- 項(xiàng)目是前后端分離的,后臺(tái)給前臺(tái)的數(shù)據(jù)均被包裝為固定格式的。例如{"code":200,"message":"成功","data":null }。
data里是返回的業(yè)務(wù)數(shù)據(jù),一般是一個(gè)json - 以前每個(gè)接口都要處理一下
@PostMapping(value = "/add")
public Result addUser(SysRoles sysRoles) {
sysRoleService.addRole(sysRoles);
return Result.success();
}
均有一個(gè) return Result.success();的操作。
- 利用ResponseBodyAdvice統(tǒng)一處理后,就不用每個(gè)方法都要寫一個(gè)返回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);
}
}
- 但是當(dāng)返回值是一個(gè)String時(shí)
@RequestMapping(value = "/test2")
public String test2() {
return "hee";
}
會(huì)報(bào)錯(cuò):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會(huì)使用StringHttpMessageConverter來處理返回體,但是我們定義的統(tǒng)一返回處理類將返回值String,變成了Result.success((String)),是一個(gè)對(duì)象。導(dǎo)致類型轉(zhuǎn)換失敗了。具體的代碼是:
父類AbstractHttpMessageConverter write時(shí),會(huì)調(diào)子類StringHttpMessageConverter的addDefaultHeaders方法,注意父類處理的是一個(gè)泛型

而子類StringHttpMessageConverter接收的是String。就會(huì)報(bào)錯(cuò)了(此時(shí),接收的是Result,是一個(gè)對(duì)象)。

原因就是原來返回值是一個(gè)String,統(tǒng)一處理后變?yōu)榱艘粋€(gè)對(duì)象Result。導(dǎo)致類型轉(zhuǎn)換失敗了。
- 解決方案有多種,這里就選取2種來說明:
- 直接使用fastjson來序列化,fastjson處理的時(shí)候不會(huì)報(bào)錯(cuò)
@Bean
public HttpMessageConverters custHttpMessageConverter() {
return new HttpMessageConverters(new FastJsonHttpMessageConverter());
}
- 不想項(xiàng)目引入fastjson,就直接用SpringBoot自帶的jackson處理,需要將jackson序列化的處理調(diào)整到最前面(可以看源碼,HttpMessageConverter處理返回值值時(shí),是根據(jù)返回的類型選取不同的處理類,F(xiàn)astJsonHttpMessageConverter可以處理String和對(duì)象,所以將其調(diào)整到最前面,就可以處理這種情況,而不使用StringHttpMessageConverter了。)
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new MappingJackson2HttpMessageConverter());
}
注意采取第二種做法時(shí),需要在接口上指定produces = {"application/json;charset=utf-8"},原因時(shí)MappingJackson2HttpMessageConverter能處理的一個(gè)條件就是MediaType必須是json,可以去看源碼。
如果不加produces = {"application/json;charset=utf-8"},返回String類型時(shí),默認(rèn)MediaType是text/html,導(dǎo)致MappingJackson2HttpMessageConverter不能處理。
