异常通知处理和返回值统一封装
返回值结果集类
@ToString
@Data
public class Result<T> implements Serializable {
private int code;
private String message;
private T data;
public Result(ResultCode resultCode, T data) {
this.code = resultCode.code();
this.message = resultCode.message();
this.data = data;
}
/**
* 返回成功
*/
public static Result<Object> success() {
return new Result<>(ResultCode.SUCCESS, null);
}
public static<T> Result<T> success(T data) {
return new Result<>(ResultCode.SUCCESS, data);
}
/**
* 失败
* @param resultCode 错误码
* @return 结果集
*/
public static Result<Object> fail(ResultCode resultCode) {
return new Result<>(resultCode, null);
}
/**
* 失败
* @param resultCode 错误码
* @param data 错误数据
* @return 结果集
*/
public static<T> Result<Object> fail(ResultCode resultCode, T data) {
return new Result<>(resultCode, data);
}
}
返回值码
public enum ResultCode {
/**
* 成功
*/
SUCCESS(200, "success"),
SYS_ERROR(500, "系统错误");
private Integer code;
private String message;
ResultCode(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer code() {
return code;
}
public String message() {
return message;
}
}
指定注解 @ResponseResult
/**
* 结果集包装处理
* @author xiaou
* @date 2022/4/1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
public @interface ResponseResult {}
测试 Controller
@RestController
@ResponseResult
public class TestController {
@GetMapping(value = "test", produces = {"application/json;charset=utf-8"})
public String test(String id) {
if (Objects.isNull(id)) {
throw new IllegalArgumentException("参数出现错误");
}
return "111";
}
}
出现异常 java.lang.ClassCastException: xiaou.Entity.Result cannot be cast to java.lang.String
。
有两种解决方案。
第一种是直接使用 fastjson 来序列化,fastjson 处理的时候不会报错
@Bean
public HttpMessageConverters custHttpMessageConverter() {
return new HttpMessageConverters(new FastJsonHttpMessageConverter());
}
第二种方案不想项目引入 fastjson,就直接用 SpringBoot 自带的 jackson 处理,需要将 jackson 序列化的处理调整到最前面。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new MappingJackson2HttpMessageConverter());
}
}
> 注意采取第二种做法时,需要在接口上指定 produces = {"application/json;charset=utf-8"}
统一处理
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
ResponseResult attribute = (ResponseResult) request.getAttribute(ResponseResultInterceptor.RESPONSE_RESULT_ANN);
return !Objects.isNull(attribute);
}
@Override
public 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);
}
/**
* 参数异常处理
* @return Result<Object>
*/
@ExceptionHandler(value = IllegalArgumentException.class)
@ResponseBody
public Result<Object> argumentException() {
return Result.fail(ResultCode.SYS_ERROR);
}
}
效果
// http://localhost:8080/test
{
"code": 500,
"message": "系统错误",
"data": null
}
// http://localhost:8080/test
{
"code": 200,
"message": "success",
"data": "111"
}