Controller 层优化四步曲
前言
在开发过程中,Controller
层作为系统与外界交互的桥梁,承担着接收请求、解析参数、调用业务逻辑、处理异常等职责。
然而,随着业务复杂度的增加,Controller
层的代码往往会变得臃肿且难以维护。
为了提升代码的可读性、可维护性以及系统的健壮性,我们可以通过以下四个步骤对 Controller
层进行改造:
- 统一返回结构
- 统一包装处理
- 参数校验
- 自定义异常与统一拦截异常
1.统一返回结构
在前后端分离的架构中,统一的返回结构能够显著提升接口的可读性和可维护性。
通过定义统一的返回格式,前端开发人员可以更清晰地判断接口调用是否成功,而不需要依赖返回值的具体内容。
定义返回数据结构
首先,我们可以定义一个通用的返回结构,包含状态码、状态信息以及返回的数据。
以下是一个示例:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {private Integer code;private String message;private T data;public static <T> Result<T> success(T data) {return new Result<>(200, "操作成功", data);}public static <T> Result<T> error(String message) {return new Result<>(500, message, null);}
}
在这个结构中,code
表示状态码,message
表示状态信息,data
则是具体的返回数据。
通过这种方式,所有的接口都可以返回统一的格式,便于前端处理。
2.统一包装处理
为了进一步简化 Controller
层的代码,我们可以使用 Spring
提供的 ResponseBodyAdvice
来统一处理返回值的包装。
这样,Controller
层只需要返回业务数据,而不需要手动封装返回结构。
使用 ResponseBodyAdvice
进行统一包装
@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {if (body instanceof Result) {return body;}return Result.success(body);}
}
通过这种方式,所有的 Controller
返回值都会被自动包装成 Result
对象,减少了重复代码。
3. 参数校验
参数校验是保证系统健壮性的重要手段。通过将参数校验逻辑从业务代码中剥离出来,不仅可以减少代码的耦合度,还能提升代码的可读性。
使用 @Validated
进行参数校验
Spring
提供了 @Validated
注解,可以方便地对请求参数进行校验。
我们可以在 DTO
对象中定义校验规则,并在 Controller
方法中使用 @Validated
注解进行校验。
@Data
public class UserDTO {@NotBlank(message = "用户名不能为空")private String username;@NotBlank(message = "密码不能为空")@Length(min = 6, max = 20, message = "密码长度必须在6到20之间")private String password;@Email(message = "邮箱格式不正确")private String email;
}@RestController
@RequestMapping("/user")
public class UserController {@PostMapping("/register")public Result<String> register(@RequestBody @Validated UserDTO userDTO) {// 业务逻辑return Result.success("注册成功");}
}
通过这种方式,参数校验的逻辑与业务逻辑完全解耦,代码更加清晰。
自定义异常与统一拦截异常
在实际开发中,系统可能会抛出各种异常。
为了提升系统的健壮性,我们可以自定义异常,并通过统一的异常拦截器来处理这些异常。
自定义异常
我们可以根据业务需求定义不同的异常类,例如 BusinessException
和 ForbiddenException
:
public class BusinessException extends RuntimeException {public BusinessException(String message) {super(message);}
}public class ForbiddenException extends RuntimeException {public ForbiddenException(String message) {super(message);}
}
统一异常拦截
通过 @RestControllerAdvice
和 @ExceptionHandler
,我们可以统一处理系统中的异常,并返回统一的错误信息。
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public Result<String> handleBusinessException(BusinessException ex) {return Result.error(ex.getMessage());}@ExceptionHandler(ForbiddenException.class)public Result<String> handleForbiddenException(ForbiddenException ex) {return Result.error("无权访问");}@ExceptionHandler(Exception.class)public Result<String> handleException(Exception ex) {return Result.error("系统异常,请稍后重试");}
}
通过这种方式,所有的异常都会被统一处理,并返回给前端统一的错误格式。
总结
通过对 Controller
层的改造,我们可以显著提升代码的可读性、可维护性以及系统的健壮性。
统一的返回结构、自动化的参数校验、自定义异常与统一拦截异常,这些措施不仅减少了重复代码,还使得代码更加清晰和易于维护。
在实际开发中,我们可以根据具体的业务需求,进一步优化和扩展这些策略。
– 欢迎点赞、关注、转发、收藏【我码玄黄】,各大平台同名。