How to Turn Bloated Spring Controllers into Clean, Maintainable Code

The article compares messy Spring MVC controllers packed with try‑catch, field checks, and business logic to concise, well‑structured versions that use @Valid, service delegation, and global exception handling, and provides a step‑by‑step refactoring guide.

Architect
Architect
Architect
How to Turn Bloated Spring Controllers into Clean, Maintainable Code

Problem: Overly Complex Controllers

Controllers that contain thousands of lines, repetitive if checks, extensive try‑catch blocks, and inline business logic are hard to read, test and maintain.

Refactored (Graceful) Controller

By delegating validation to Spring and moving business logic to services, the controller size can be reduced by roughly 50%.

@RestController
@RequestMapping("/user/test")
public class UserController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserService userService;
    @Autowired
    private AuthService authService;

    @PostMapping("/userRegistration")
    public CommonResult userRegistration(@RequestBody @Valid UserVo userVo) {
        userService.registerUser(userVo.getUsername());
        return CommonResult.ok();
    }

    @PostMapping("/login")
    @PermitAll
    @ApiOperation("使用账号密码登录")
    public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
        return success(authService.login(reqVO));
    }
}
All validation and error handling are now centralized, making the controller concise and testable.

Validation with @Valid

Apply @Valid on request‑body parameters and annotate the fields of the VO (Value Object) with Bean Validation constraints.

@ApiModel(value = "管理后台 - 账号密码登录 Request VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthLoginReqVO {
    @ApiModelProperty(value = "账号", required = true, example = "user")
    @NotEmpty(message = "登录账号不能为空")
    @Length(min = 4, max = 16, message = "账号长度为 4-16 位")
    @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
    private String username;

    @ApiModelProperty(value = "密码", required = true, example = "password")
    @NotEmpty(message = "密码不能为空")
    @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
    private String password;
}

When a POST request arrives, Spring automatically validates the object. If validation succeeds, the method proceeds; otherwise a MethodArgumentNotValidException is thrown.

Why use @Valid ?

Eliminates verbose if checks.

Improves readability and keeps controller responsibilities focused on routing.

Related annotations

@NotEmpty

, @Length, @Pattern – define constraints on individual fields.

Difference between @Valid and @Validated

@Validated

supports validation groups, allowing selective validation of fields, while @Valid validates all constraints on the object.

Global Exception Handling

A centralized @RestControllerAdvice captures validation errors and any uncaught exceptions, returning a uniform CommonResult response.

@ResponseBody
@RestControllerAdvice
public class ExceptionHandlerAdvice {
    private static final Logger logger = LoggerFactory.getLogger(ExceptionHandlerAdvice.class);

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult<Object> handleValidationExceptions(MethodArgumentNotValidException ex) {
        logger.error("[handleValidationExceptions]", ex);
        StringBuilder sb = new StringBuilder();
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String field = ((org.springframework.validation.FieldError) error).getField();
            sb.append(field).append(":").append(error.getDefaultMessage()).append(";");
        });
        return CommonResult.error(sb.toString());
    }

    @ExceptionHandler(Exception.class)
    public CommonResult<?> defaultExceptionHandler(Throwable ex) {
        logger.error("[defaultExceptionHandler]", ex);
        return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
    }
}
This approach ensures that validation failures and unexpected errors are reported consistently.

Benefits of the Refactor

Business logic is isolated in service layers, improving reuse.

Controller methods stay under 80–100 lines, aligning with common style guides.

Code is easier to read, test, and maintain.

Centralized validation and exception handling reduce duplication.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Exception HandlingSpring Boot@ValidController RefactoringCode Cleanliness
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.