SpringBoot全局Controller返回值格式統(tǒng)一
一、返回值格式統(tǒng)一
1.返回值介紹
在使用controller對(duì)外提供服務(wù)的時(shí)候,很多時(shí)候都需要統(tǒng)一返回值格式,例如
{
"status": true,
"message": null,
"code": "200",
"data": {
"name": "json",
"desc": "json返回值"
}
}
如果不使用全局統(tǒng)一返回,就需要寫一個(gè)工具類,然后controller返回對(duì)應(yīng)的對(duì)象
@Data
public class ResponseData {
private boolean status;
private String message;
private String code;
private Object data;
}
@RequestMapping("/foo")
public ResponseData foo() {
// 或者使用工具類返回,根據(jù)業(yè)務(wù)設(shè)置值
return new ResponseData();
}
除了上述方法,可以對(duì)返回值進(jìn)行統(tǒng)一處理,不需要對(duì)所有controller都使用一個(gè)返回值,controller只需要返回原始值,處理器會(huì)對(duì)返回值進(jìn)行封裝
同時(shí)也可以添加自定義注解,此注解用于忽略返回值封裝,按照controller原始值返回
2.基礎(chǔ)類功能
org.springframework.web.method.support.HandlerMethodReturnValueHandler
- 使用不同策略處理從調(diào)用處理程序方法的返回值
- 策略處理頂層接口,自定義返回值格式需要實(shí)現(xiàn)此接口
- supportsReturnType:設(shè)置支持返回值類型
- handleReturnValue:處理返回值基礎(chǔ)參數(shù)

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
- 請(qǐng)求映射處理適配,包含了參數(shù)、返回值處理器等信息
- HandlerMethodReturnValueHandlerComposite內(nèi)部維護(hù)了HandlerMethodReturnValueHandler列表


可以自定義注解,用于類或者方法級(jí)別忽略返回值封裝
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreResponseWrapper {
}
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
- 屬于HandlerMethodReturnValueHandler子類
- 主要功能是對(duì)請(qǐng)求和響應(yīng)體的做處理的方法
- 所有屬于RequestResponseBodyMethodProcessor的子類都需要替換為自定義返回值處理
實(shí)現(xiàn)原理就是,在bean初始化的時(shí)候,獲取到所有處理器數(shù)組,然后將所有是RequestResponseBodyMethodProcessor處理器子類對(duì)返回值處理的過程替換為自定義處理器
處理這樣當(dāng)調(diào)用對(duì)應(yīng)返回值處理器時(shí),將會(huì)使用到自定義的返回值處理器,也就是所有返回值都會(huì)按照規(guī)定的進(jìn)行處理
3.基礎(chǔ)實(shí)現(xiàn)
創(chuàng)建普通springboot項(xiàng)目,項(xiàng)目創(chuàng)建在此不做說明
創(chuàng)建類實(shí)現(xiàn)HandlerMethodReturnValueHandler接口,主要用于實(shí)現(xiàn)自定義返回值內(nèi)容,不需要注入容器
import com.codecoord.unifyreturn.annotation.IgnoreResponseWrapper;
import com.codecoord.unifyreturn.domain.ResponseBase;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
public class ResponseBodyWrapHandler implements HandlerMethodReturnValueHandler {
private final HandlerMethodReturnValueHandler delegate;
public ResponseBodyWrapHandler(HandlerMethodReturnValueHandler delegate) {
this.delegate = delegate;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return delegate.supportsReturnType(returnType);
}
@Override
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
// 如果類或者方法含有不包裝注解則忽略包裝
IgnoreResponseWrapper wrapper = returnType.getDeclaringClass().getAnnotation(IgnoreResponseWrapper.class);
if (wrapper != null) {
delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
return;
}
wrapper = returnType.getMethodAnnotation(IgnoreResponseWrapper.class);
if (wrapper != null) {
delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
return;
}
// 自定義返回格式
ResponseBase responseBase = new ResponseBase();
responseBase.setStatus(true);
responseBase.setCode("200");
responseBase.setData(returnValue);
delegate.handleReturnValue(responseBase, returnType, mavContainer, webRequest);
}
}
創(chuàng)建類實(shí)現(xiàn)InitializingBean,在初始化時(shí)調(diào)用,需要注入到容器中,否則Spring無法管理
import java.util.ArrayList;
import java.util.List;
@Component
public class ResponseBodyWrapFactoryBean implements InitializingBean {
private final RequestMappingHandlerAdapter adapter;
@Autowired
public ResponseBodyWrapFactoryBean(RequestMappingHandlerAdapter adapter) {
this.adapter = adapter;
}
@Override
public void afterPropertiesSet() throws Exception {
List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
if (returnValueHandlers.size() > 0) {
// 將內(nèi)置的返回值處理器進(jìn)行替換
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(returnValueHandlers);
decorateHandlers(handlers);
adapter.setReturnValueHandlers(handlers);
}
}
/**
* 將所有RequestResponseBodyMethodProcessor返回值處理器替換為自定義的返回值處理器
*
* @author tianxincode@163.com
* @since 2020/10/12
*/
private void decorateHandlers(List<HandlerMethodReturnValueHandler> handlers) {
for (HandlerMethodReturnValueHandler handler : handlers) {
if (handler instanceof RequestResponseBodyMethodProcessor) {
// 替換為自定義返回值處理器
ResponseBodyWrapHandler decorator = new ResponseBodyWrapHandler(handler);
int index = handlers.indexOf(handler);
handlers.set(index, decorator);
break;
}
}
}
}
創(chuàng)建controller信息,例如此處map不需要封裝,按照原來格式響應(yīng)
@RestController
@RequestMapping("/unify")
public class UnifyReturnValueController {
@RequestMapping("string")
public String stringHandler(){
return "接收成功了";
}
@RequestMapping("/json")
public JSONObject jsonHandler(){
JSONObject object = new JSONObject();
object.put("name", "json");
object.put("desc", "json返回值");
return object;
}
@RequestMapping("/map")
@IgnoreResponseWrapper
public Map<String, Object> mapHandler(){
Map<String, Object> map = new HashMap<>(10);
map.put("name", "map");
map.put("desc", "map返回值");
return map;
}
@RequestMapping("/list")
public List<Object> listHandler(){
List<Object> data = new ArrayList<>();
data.add(100);
data.add(95);
data.add(99);
return data;
}
}
4.測(cè)試信息 測(cè)試json(有封裝)
{
"status": true,
"message": null,
"code": "200",
"data": {
"name": "json",
"desc": "json返回值"
}
}
測(cè)試map(無封裝)
{
"name": "map",
"desc": "map返回值"
}
別的方法測(cè)試一樣
二、附錄說明
項(xiàng)目結(jié)構(gòu)參考紅框部分,別的忽略

除了對(duì)返回值進(jìn)行全局統(tǒng)一,也可以對(duì)異常進(jìn)行全局處理和按照統(tǒng)一格式返回
到此這篇關(guān)于SpringBoot全局Controller返回值格式統(tǒng)一的文章就介紹到這了,更多相關(guān)SpringBoot返回值格式統(tǒng)一內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot統(tǒng)一數(shù)據(jù)返回格式的實(shí)現(xiàn)示例
- Spring Boot 統(tǒng)一數(shù)據(jù)返回格式的解決方案
- springboot統(tǒng)一接口返回?cái)?shù)據(jù)的實(shí)現(xiàn)
- SpringBoot統(tǒng)一返回處理出現(xiàn)cannot?be?cast?to?java.lang.String異常解決
- springboot配置Jackson返回統(tǒng)一默認(rèn)值的實(shí)現(xiàn)示例
- 詳解SpringBoot如何統(tǒng)一后端返回格式
- Spring?Boot如何實(shí)現(xiàn)統(tǒng)一數(shù)據(jù)返回
相關(guān)文章
Java Cmd運(yùn)行Jar出現(xiàn)亂碼的解決方案
這篇文章主要介紹了Java Cmd運(yùn)行Jar出現(xiàn)亂碼的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
Spring?Data?JPA?映射VO/DTO對(duì)象方式
這篇文章主要介紹了Spring?Data?JPA?映射VO/DTO對(duì)象方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
java String[]字符串?dāng)?shù)組自動(dòng)排序的簡(jiǎn)單實(shí)現(xiàn)
下面小編就為大家?guī)硪黄猨ava String[]字符串?dāng)?shù)組自動(dòng)排序的簡(jiǎn)單實(shí)現(xiàn)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09
SpringBoot Mybatis如何配置多數(shù)據(jù)源并分包
這篇文章主要介紹了SpringBoot Mybatis如何配置多數(shù)據(jù)源并分包,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
Java實(shí)戰(zhàn)員工績效管理系統(tǒng)的實(shí)現(xiàn)流程
只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+Mysql+Maven+HTML實(shí)現(xiàn)一個(gè)員工績效管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2022-01-01
Java采用setAsciiStream方法檢索數(shù)據(jù)庫指定內(nèi)容實(shí)例解析
這篇文章主要介紹了Java采用setAsciiStream方法檢索數(shù)據(jù)庫指定內(nèi)容,是比較實(shí)用的功能,需要的朋友可以參考下2014-08-08
Spring Web MVC和Hibernate的集成配置詳解
這篇文章主要介紹了Spring Web MVC和Hibernate的集成配置詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下2017-12-12

