SpringBoot統(tǒng)一返回處理遇到的問題cannot be cast to java.lang.String

  • 項(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è)泛型


image.png

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


image.png

原因就是原來返回值是一個(gè)String,統(tǒng)一處理后變?yōu)榱艘粋€(gè)對(duì)象Result。導(dǎo)致類型轉(zhuǎn)換失敗了。

  • 解決方案有多種,這里就選取2種來說明:
  1. 直接使用fastjson來序列化,fastjson處理的時(shí)候不會(huì)報(bào)錯(cuò)
@Bean
public HttpMessageConverters custHttpMessageConverter() {
    return new HttpMessageConverters(new FastJsonHttpMessageConverter());
}
  1. 不想項(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不能處理。


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容