- 项目是前后端分离的,后台给前台的数据均被包装为固定格式的。例如{"code":200,"message":"成功","data":null }。
data里是返回的业务数据,一般是一个json - 以前每个接口都要处理一下
@PostMapping(value = "/add")
public Result addUser(SysRoles sysRoles) {
sysRoleService.addRole(sysRoles);
return Result.success();
}
均有一个 return Result.success();的操作。
- 利用ResponseBodyAdvice统一处理后,就不用每个方法都要写一个返回Result.success()了
@RestControllerAdvice
public class RestBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter,
Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter,
MediaType mediaType,
Class<? extends HttpMessageConverter<?>> aClass,
ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse) {
if (o == null) {
return Result.success();
}
if (o instanceof Result || o instanceof File || o instanceof ResponseEntity) {
return o;
}
return Result.success(o);
}
}
- 但是当返回值是一个String时
@RequestMapping(value = "/test2")
public String test2() {
return "hee";
}
会报错:java.lang.ClassCastException: com.jianyu.domain.Result cannot be cast to java.lang.String
at org.springframework.http.converter.StringHttpMessageConverter.addDefaultHeaders(StringHttpMessageConverter.java:44) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
原因是返回值是String,Spring会使用StringHttpMessageConverter来处理返回体,但是我们定义的统一返回处理类将返回值String,变成了Result.success((String)),是一个对象。导致类型转换失败了。具体的代码是:
父类AbstractHttpMessageConverter write时,会调子类StringHttpMessageConverter的addDefaultHeaders方法,注意父类处理的是一个泛型
而子类StringHttpMessageConverter接收的是String。就会报错了(此时,接收的是Result,是一个对象)。
原因就是原来返回值是一个String,统一处理后变为了一个对象Result。导致类型转换失败了。
- 解决方案有多种,这里就选取2种来说明:
- 直接使用fastjson来序列化,fastjson处理的时候不会报错
@Bean
public HttpMessageConverters custHttpMessageConverter() {
return new HttpMessageConverters(new FastJsonHttpMessageConverter());
}
- 不想项目引入fastjson,就直接用SpringBoot自带的jackson处理,需要将jackson序列化的处理调整到最前面(可以看源码,HttpMessageConverter处理返回值值时,是根据返回的类型选取不同的处理类,FastJsonHttpMessageConverter可以处理String和对象,所以将其调整到最前面,就可以处理这种情况,而不使用StringHttpMessageConverter了。)
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new MappingJackson2HttpMessageConverter());
}
注意采取第二种做法时,需要在接口上指定produces = {"application/json;charset=utf-8"},原因时MappingJackson2HttpMessageConverter能处理的一个条件就是MediaType必须是json,可以去看源码。
如果不加produces = {"application/json;charset=utf-8"},返回String类型时,默认MediaType是text/html,导致MappingJackson2HttpMessageConverter不能处理。