SpringBoot + RestControllerAdvice + ResponseBodyAdvice
背景: 在Springboot项目开发中,接口异常基本都会使用全局异常类处理,核心就是底层AOP代理了controller,封装了入参及异常的处理,使我们不再重复处理每一个接口方法,减少样板代码。如果异常场景都可被全局处理,那正常场景是否可以同样全局封装呢?下面将介绍个人在项目中常用的完整的全局处理方式。
博客内容精选:
1、Servlet请求体重复读&修改新姿势
2、根据请求获取后端接口详情
3、封装Springboot项目的starter-sdk新方式
4、Springboot全局处理完整版
5、itextpdf读取文本时上下行位置错乱
6、JAVA读取PDF表格内容
7、JAVA读取PDF出现内容错乱
直接贴代码:
@Slf4j
@RestControllerAdvice
public class GlobalInvokeHandler implements ResponseBodyAdvice<Object> {
@Autowired
// 序列化用
private ObjectMapper objectMapper;
// 异常方法封装
@ResponseBody
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Result<Object> globalExceptionHandler(Exception exception) {
log.error("Request[{}] {} type error, detail {}", ....);
String errMsg = ".......";
return Result.newErrorResponse(errMsg);
}
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
//根据需求修改,一般直接默认true即可
return true;
}
// 全局实体封装
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 接口方法返回字符串对象场景较为特殊,需要手工封装实体后重新序列化成字符串
if (body instanceof String) {
return objectMapper.writeValueAsString(Result.newOkResponse(body));
}
// 此块用于处理全局异常封装后的响应实体,其中Result为个人自定义响应封装静态类
if (body instanceof Result) {
// 已异常封装,直接返回
return body;
}
// 此块用于封装所有接口除字符串类型外的其他所有响应,不需要序列化
return Result.newOkResponse(body);
}
}
总结:
1、RestControllerAdvice:见名知意,控制权全局切面类,该注解还被@ControllerAdvice、
@ResponseBody两注解修饰。
2、@ExceptionHandler:全局异常封装注解,可指定异常类
– 2.1、@ResponseBody:异常全局封装实体响应处理
– 2.2、@ResponseStatus:接口HTTP状态码
3、ResponseBodyAdvice: 全局响应处理接口,需要自定义实现beforeBodyWrite方法,该方法可处理所有接口的返回内容,包含异常场景,具体说明见代码
看看,只需要上述这一点代码,即可完全托管接口响应的封装,不用重复在每个接口方法中使用静态方法封装了,感谢Spring的给力支持。