SpringBoot統(tǒng)一返回處理出現(xiàn)cannot?be?cast?to?java.lang.String異常解決
一 問題出現(xiàn)背景:
在使用 @RestControllerAdvice
和實現(xiàn) ResponseBodyAdvice
做 controller
層統(tǒng)一返回封裝時。當(dāng)返回字符串時會報 “cannot be cast to java.lang.String” 異常,返回其他類型就無任何問題。
二 解決方案
如果返回的是字符串直接手動封裝返回對象轉(zhuǎn)成json字符串返回即可。
完整代碼
@RestControllerAdvice public class ResponseResult implements ResponseBodyAdvice<Object> { /** * 支持注解@ResponseNotIntercept,使某些方法無需使用Result封裝 * * @param returnType 返回類型 * @param converterType 選擇的轉(zhuǎn)換器類型 * @return true 時會執(zhí)行beforeBodyWrite方法,false時直接返回給前端 */ @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { if (returnType.getDeclaringClass().isAnnotationPresent(ResponseNotIntercept.class)) { //若在類中加了@ResponseNotIntercept 則該類中的方法不用做統(tǒng)一的攔截 return false; } if (returnType.getMethod().isAnnotationPresent(ResponseNotIntercept.class)) { //若方法上加了@ResponseNotIntercept 則該方法不用做統(tǒng)一的攔截 return false; } return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof Result) { // 提供一定的靈活度,如果body已經(jīng)被包裝了,就不進(jìn)行包裝 return body; } if (body instanceof String) { //解決返回值為字符串時,不能正常包裝 return JSON.toJSONString(Result.success(body)); } return Result.success(body); } }
三 異常原因分析
原因:
SpringMVC
默認(rèn)會注冊一些自帶的 HttpMessageConvertor
(從先后順序排列分別為ByteArrayHttpMessageConverter、StringHttpMessageConverter、ResourceHttpMessageConverter,SourceHttpMessageConverter、AllEncompassingFormHttpMessageConverter) ,后端服務(wù)使用Restful API的形式,前后端得規(guī)范一般是json格式, SpringMVC
自帶 MappingJackson2HttpMessageConverter
,在依賴中引入 jackson
包后,容器會把 MappingJackson2HttpMessageConverter
自動注冊到 messageConverters
鏈的末尾
當(dāng)返回的數(shù)據(jù)是非字符串時使用的 MappingJackson2HttpMessageConverter
寫入返回對象。當(dāng)返回的數(shù)據(jù)是字符串時,此處得方法是要去循環(huán)遍歷 HttpMessageConverter
集,因為 StringHttpMessageConverter
會先被遍歷到,這時會認(rèn)為 StringHttpMessageConverter
可以使用,在返回 Result
是使用 ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage)
;此方法是父類方法 body
參數(shù)類型為 Object
,實際調(diào)用的為 StringHttpMessageConverter
中的 addDefaultHeaders(HttpHeaders headers, String s, @Nullable MediaType type)
方法,使用 String
類型的 s
來接收 Result
類型的 body
,類型不匹配則出現(xiàn) Result cannot be cast to java.lang.String
異常。
源碼詳細(xì)分析:
正常返回:
步驟一:遍歷 messageConverters
去判斷到 MappingJackson2HttpMessageConverter
是 GenericHttpMessageConverter
類型的 converter
;
步驟二:進(jìn)一步判斷到 MappingJackson2HttpMessageConverter
可以寫入對象類型的數(shù)據(jù)。
步驟三:調(diào)用 beforeBodyWriter
方法將原有的 TestVO
對象數(shù)據(jù)封裝到 Result
對象中。
步驟四:調(diào)用 MappingJackson2HttpMessageConverter
中的 wirte
方法(代碼中用接口類型接收的)
步驟五:通過 MappingJackson2HttpMessageConverter
繼承關(guān)系發(fā)現(xiàn)其write方法在父類 AbstractHttpMessageConverter
中,在 write
方法中調(diào)用本類中的 addDefaultHeaders
方法向輸出消息添加默認(rèn)報頭。(此處應(yīng)注意)
步驟六:將封裝好的Result對象返回給前端
返回為字符串異常
步驟一:遍歷 messageConverters
去判斷到 StringHttpMessageConverter
是null;
步驟二:進(jìn)一步判斷到 StringHttpMessageConverter
可以寫入String類型的數(shù)據(jù)。
步驟三:調(diào)用 beforeBodyWriter
方法將原有的 String
類型數(shù)據(jù)封裝到 Result
對象中。
步驟四:調(diào)用 StringHttpMessageConverter
中的 wirte
方法(代碼中用接口類型接收的)
步驟五:
調(diào)用父類 AbstractHttpMessageConverter
中的 write
方法,由于 StringHttpMessageConverter
重寫了 addDefaultHeaders
方法,故 write
中調(diào)用子類中的 addDefaultHeaders
。由于父類中參數(shù)t為對象類型,對應(yīng)子類中接收的s為String類型故會出現(xiàn)類型轉(zhuǎn)換異常 Result cannot be cast to java.lang.String
(此處應(yīng)注意)
總結(jié)
到此這篇關(guān)于SpringBoot統(tǒng)一返回處理出現(xiàn)cannot be cast to java.lang.String異常解決的文章就介紹到這了,更多相關(guān)cannot be cast to java.lang.String異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jsp+servlet實現(xiàn)簡單登錄頁面功能(附demo)
本文主要介紹了jsp+servlet實現(xiàn)簡單登錄頁面功能登錄成功跳轉(zhuǎn)新頁面,登錄失敗在原登錄界面提示登錄失敗信息,對初學(xué)者有一定的幫助,感興趣的可以了解一下2021-07-07Spring?MVC中@Controller和@RequestMapping注解使用
這篇文章主要介紹了Spring?MVC中@Controller和@RequestMapping注解使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02IDEA整合SSM框架實現(xiàn)網(wǎng)頁上顯示數(shù)據(jù)
最近做了個小項目,該項目包在intellij idea中實現(xiàn)了ssm框架的整合以及實現(xiàn)訪問,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-05-05