SpringBoot之統(tǒng)一數(shù)據(jù)返回格式的實(shí)現(xiàn)示例
之前我們實(shí)現(xiàn)的圖書管理系統(tǒng),函數(shù)的返回值格式都不統(tǒng)一,如果將這些函數(shù)的返回值格式都進(jìn)行統(tǒng)一,將方便后續(xù)的返回和接收,但是如果我們挨個(gè)修改這些函數(shù)的返回值格式,有些麻煩,那么有沒有別的好的辦法呢?----有,就是下面我們要講解的"SpringBoot之統(tǒng)一數(shù)據(jù)返回格式"。
統(tǒng)一數(shù)據(jù)返回格式
使用
統(tǒng)?的數(shù)據(jù)返回格式使? @ControllerAdvice 和 ResponseBodyAdvice 的?式實(shí)現(xiàn)
@ControllerAdvice 表?控制器通知類。
定義類 ResponseAdvice , 實(shí)現(xiàn) ResponseBodyAdvice 接?, 并在類上添加
@ControllerAdvice 注解。
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof Result){
return body;
}
return Result.success(body);
}
}運(yùn)行結(jié)果:

定義測(cè)試接口
@RequestMapping("/test")
@RestController
public class TestController {
@RequestMapping("/t1")
public String t1(){
return "string";
}
@RequestMapping("/t2")
public Integer t2(){
return 1;
}
@RequestMapping("/t3")
public Boolean t3(){
return true;
}
}運(yùn)行結(jié)果
t2返回結(jié)果:

t3返回結(jié)果:

t1返回結(jié)果:


為什么其他方法都能夠正常返回,而返回類型為String時(shí)卻不能正常返回,而且還拋出了ClassCastException異常,這是為什么呢?
問(wèn)題解答(結(jié)合源碼)
根據(jù)IDEA控制臺(tái)打印的堆棧信息,我們首先看看StringHttpMessageConverter和AbstractHttpMessageConverter這兩個(gè)類,特別是StringHttpMessageConverter的addDefaultHeaders方法和AbstractHttpMessageConverter的write方法,其中StringHttpMessageConverter是繼承了AbstractHttpMessageConverter并重寫了幾個(gè)方法,特別是addDefaultHeaders方法,下面通過(guò)Debug方式運(yùn)行:


再繼續(xù)運(yùn)行,會(huì)捕獲到異常

由此我們知道,是因?yàn)榉祷亟Y(jié)果為String類型的"string"被轉(zhuǎn)換成了Result類型,但是在執(zhí)行AbstractHttpMessageConverter的write方法時(shí),因?yàn)锳bstractHttpMessageConverter的派生類StringHttpMessageConverter重寫了addDefaultHeaders方法,此時(shí)會(huì)調(diào)用StringHttpMessageConverter的addDefaultHeaders方法,但是StringHttpMessageConverter的addDefaultHeaders方法要求 t 的類型是String類型,但是無(wú)法從自定義的Result類型轉(zhuǎn)換成String類型,因此拋出了ClassCastException異常。

那么問(wèn)題來(lái)了,上面的三個(gè)測(cè)試接口,走的都是Result.success()方法,為什么卻有不一樣的結(jié)果,通過(guò)調(diào)試:
對(duì)于返回類型為String類型,在AbstractMessageConverterMethodProcessor里面的writeWithMessageConverters()方法時(shí),在經(jīng)過(guò)下圖所示過(guò)程中,String類型會(huì)被轉(zhuǎn)換成Result類型的結(jié)果,而且后面走的是StringHttpMessageConverter的addDefaultHeaders方法,其中StringHttpMessageConverter重寫了AbstractHttpMessageConverter的addDefaultHeaders方法;


而返回值類型不是String類型時(shí),經(jīng)過(guò)和剛剛同樣的步驟時(shí),直接走的是AbstractHttpMessageConverter的addDefaultHeaders方法,而沒有走StringHttpMessageConverter的addDefaultHeaders方法。

解決方法:對(duì)返回類型為String類型的字符串進(jìn)行序列化
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import springbook.model.Result;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@SneakyThrows
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof Result){
return body;
}
if (body instanceof String){
return objectMapper.writeValueAsString(Result.success(body));
}
return Result.success(body);
}
}運(yùn)行結(jié)果:

優(yōu)點(diǎn)
1. ?便前端程序員更好的接收和解析后端數(shù)據(jù)接?返回的數(shù)據(jù)
2. 降低前端程序員和后端程序員的溝通成本, 按照某個(gè)格式實(shí)現(xiàn)就可以了, 因?yàn)樗薪?都是這樣返回的.
3. 有利于項(xiàng)?統(tǒng)?數(shù)據(jù)的維護(hù)和修改.
4. 有利于后端技術(shù)部?的統(tǒng)?規(guī)范的標(biāo)準(zhǔn)制定, 不會(huì)出現(xiàn)稀奇古怪的返回內(nèi)容.
到此這篇關(guān)于SpringBoot之統(tǒng)一數(shù)據(jù)返回格式的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot 統(tǒng)一數(shù)據(jù)返回格式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java shiro實(shí)現(xiàn)退出登陸清空緩存
本篇文章主要介紹了java shiro實(shí)現(xiàn)退出登陸清空緩存,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
Springboot啟動(dòng)停止命令的.sh腳本編寫方式
這篇文章主要介紹了Springboot啟動(dòng)停止命令的.sh腳本編寫方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
詳解SpringBoot+SpringSecurity+jwt整合及初體驗(yàn)
這篇文章主要介紹了詳解SpringBoot+SpringSecurity+jwt整合及初體驗(yàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-06-06
Java實(shí)現(xiàn)短信驗(yàn)證碼的示例代碼
Java是一種流行的編程語(yǔ)言,驗(yàn)證碼是一種常用的網(wǎng)絡(luò)安全技術(shù)。Java發(fā)展至今,網(wǎng)上也出現(xiàn)了各種各樣的驗(yàn)證碼,下面是用Java實(shí)現(xiàn)短信驗(yàn)證碼的總結(jié),感興趣的可以了解一下2023-03-03
Java子線程無(wú)法獲取Attributes的解決方法(最新推薦)
在Java多線程編程中,子線程無(wú)法直接獲取主線程設(shè)置的Attributes是一個(gè)常見問(wèn)題,本文探討了這一問(wèn)題的原因,并提供了兩種解決方案,對(duì)Java子線程無(wú)法獲取Attributes的解決方案感興趣的朋友一起看看吧2025-01-01
SpringBoot導(dǎo)入mail依賴報(bào)錯(cuò)問(wèn)題解決
這篇文章主要介紹了SpringBoot導(dǎo)入mail依賴報(bào)錯(cuò)問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
淺析JAVA常用JDBC連接數(shù)據(jù)庫(kù)的方法總結(jié)
本篇文章是對(duì)在JAVA中常用JDBC連接數(shù)據(jù)庫(kù)的方法進(jìn)行了詳細(xì)的總結(jié)分析,需要的朋友參考下2013-07-07
IDEA連接postgressql數(shù)據(jù)庫(kù)操作
這篇文章主要介紹了IDEA連接postgressql數(shù)據(jù)庫(kù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Java實(shí)現(xiàn)簡(jiǎn)單無(wú)界面五子棋
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單無(wú)界面五子棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05

