SpringBoot統(tǒng)一返回結(jié)果問題
目前很多項(xiàng)目都是前后端分離,前后端會(huì)事先約定好返回格式,前端如果使用axios的話,會(huì)在全局過濾器里進(jìn)行校驗(yàn),那么后端如何做,才能優(yōu)雅的返回固定的統(tǒng)一格式呢,接下來我會(huì)帶著你一步步實(shí)現(xiàn)。
1. 直接返回結(jié)果
先看一下最基本的例子,直接將結(jié)果原封不動(dòng)返回:
@Data @AllArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class TestVo { private static final long serialVersionUID = 1L; @Schema(name = "姓名") private String name; @Schema(name = "年齡") private Integer age; }
@RestController @RequestMapping(value = "/test") public class TestApi { @GetMapping("/simple") public TestVo simple() { TestVo testVo = new TestVo("張三", 30); return testVo; } }
返回結(jié)果:
{ "name": "張三", "age": 30 }
2. 約定返回格式
假如與前端開發(fā)妹子約定好了格式,比如:
{ "code": 0, "msg": "錯(cuò)誤信息", "data": 實(shí)際返回結(jié)果 }
那么我們首先需要編寫一個(gè)封裝結(jié)果類Result,為了方便封裝,我們?cè)偬峁┮粋€(gè)success方法:
@Data @JsonInclude(JsonInclude.Include.NON_NULL) public class Result<T> implements Serializable { private static final long serialVersionUID = 1L; /** * 返回編碼 */ private Integer code; /** * 編碼描述 */ private String msg; /** * 業(yè)務(wù)數(shù)據(jù) */ private T data; /** * 返回成功結(jié)果對(duì)象 * * @param data * @param <T> * @return */ public static <T> Result<T> success(T data) { Result result = new Result(); result.setCode(0); result.setMsg("success"); result.setData(data); return result; } }
3. 返回統(tǒng)一格式結(jié)果
后臺(tái)接口代碼微調(diào)一下即可,返回值改為Result,泛型為原返回值的類型:
@RestController @RequestMapping(value = "/test") public class TestApi { @GetMapping("/withResult") public Result<TestVo> withResult() { TestVo testVo = new TestVo("張三", 30); return Result.success(testVo); } }
返回結(jié)果:
{ "code": 0, "msg": "success", "data": { "name": "張三", "age": 30 } }
至此,后端返回結(jié)果完美符合格式,但是每個(gè)接口的返回值都是Result<>,并且return的時(shí)候都要用success方法封裝一下,不夠優(yōu)雅,怎么辦?我們繼續(xù)看:
4. 切片封裝統(tǒng)一格式
編寫注解
實(shí)際使用場(chǎng)景中,并不是所有接口都能完美的統(tǒng)一格式,使用注解可以按需控制接口返回格式。
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ApiResult { String value() default ""; int successCode() default 0; String successMsg() default "success"; Class<? extends IResult> resultClass() default Result.class; }
編寫ControllerAdvice
@Order(0) @ControllerAdvice public class MyResponseBodyAdvice implements ResponseBodyAdvice { protected boolean isStringConverter(Class converterType) { return converterType.equals(StringHttpMessageConverter.class); } protected boolean isApiResult(MethodParameter returnType) { return returnType.hasMethodAnnotation(ApiResult.class); } @Override public boolean supports(MethodParameter returnType, Class converterType) { return !isStringConverter(converterType) && isApiResult(returnType); } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //關(guān)鍵 return Result.success(body); } }
這里有一點(diǎn)要注意,這個(gè)advice中supports方法中判斷返回結(jié)果類型必須為非String類型。如果返回結(jié)果為String類型,那么result要轉(zhuǎn)為json字符串后再返回,需要再寫一個(gè)advice。
接下來見證奇跡的時(shí)刻到了
@ApiResult @GetMapping("/withResultHide") public TestVo withResultHide() { TestVo testVo = new TestVo("張三", 30); return testVo; }
這段代碼與直接返回結(jié)果的一樣,僅僅加上了@ApiResult注解,我們看返回結(jié)果:
{ "code": 0, "msg": "success", "data": { "name": "張三", "age": 30 } }
大功告成!
以上只是最精簡(jiǎn)的例子,實(shí)際使用中還結(jié)合了 統(tǒng)一異常封裝、自定義返回格式 等功能。
我們注意到@ApiResult注解中,有三個(gè)參數(shù):successCode、successMsg、resultClass,就是為了自定義返回格式預(yù)留的,
下面看個(gè)例子:
5. 自定義返回格式
返回成功時(shí)code為200
如果個(gè)別接口的返回格式與默認(rèn)格式相同,但是要求code等于200代表成功,那么修改下successCode參數(shù)即可:
@ApiResult(successCode = 200, successMsg = "ok") @GetMapping("/withResultHide") public TestVo withResultHide() { TestVo testVo = new TestVo("張三", 30); return testVo; }
我們發(fā)現(xiàn),返回成功時(shí),結(jié)果中的code和msg都變?yōu)樵O(shè)置的值:
{ "code": 200, "msg": "ok", "data": { "name": "張三", "age": 30 } }
自定義返回格式
如果個(gè)別的接口返回格式不是默認(rèn)的返回格式,那么我們需要新增一個(gè)返回結(jié)果類,比如ReturnResult,里面包含returnCode、returnDesc、data三個(gè)屬性:
@Data @JsonInclude(JsonInclude.Include.NON_NULL) public class ReturnResult<T> implements Serializable { private static final long serialVersionUID = 1L; /** * 返回編碼 */ private String returnCode; /** * 編碼描述 */ private String returnDesc; /** * 業(yè)務(wù)數(shù)據(jù) */ private T data; /** * 返回成功結(jié)果對(duì)象 * * @param data * @param <T> * @return */ public static <T> ReturnResult<T> success(T data) { ReturnResult result = new ReturnResult(); result.setReturnCode(0); result.setReturnDesc("success"); result.setData(data); return result; } }
然后修改接口上的@ApiResult注解中的resultClass屬性
@ApiResult(resultClass = ReturnResult.class) @GetMapping("/withResultHide") public TestVo withResultHide() { TestVo testVo = new TestVo("張三", 30); return testVo; }
這時(shí),返回結(jié)果變?yōu)槿缦拢?/p>
{ "returnCode": "0", "returnDesc": "success", "data": { "name": "張三", "age": 30 } }
注意:以上自定義返回結(jié)果的例子需要自行根據(jù)實(shí)際情況添加,文章中的例子并不能實(shí)現(xiàn)
總結(jié)
只要按照上面一步步改造,即可實(shí)現(xiàn)統(tǒng)一返回結(jié)果,既規(guī)范、又優(yōu)雅,也可根據(jù)自己所需添加對(duì)應(yīng)的屬性和數(shù)據(jù)。還等什么,搞起來吧~
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot統(tǒng)一數(shù)據(jù)返回格式的實(shí)現(xiàn)示例
- SpringBoot如何統(tǒng)一處理返回結(jié)果和異常情況
- 詳解SpringBoot中的統(tǒng)一結(jié)果返回與統(tǒng)一異常處理
- Springboot設(shè)置統(tǒng)一的返回格式的方法步驟
- SpringBoot返回結(jié)果統(tǒng)一處理實(shí)例詳解
- 淺析SpringBoot統(tǒng)一返回結(jié)果的實(shí)現(xiàn)
- SpringBoot全局處理統(tǒng)一返回類型方式
- 詳解SpringBoot如何統(tǒng)一處理返回的信息
- SpringBoot統(tǒng)一返回格式的方法詳解
- SpringBoot統(tǒng)一數(shù)據(jù)返回的幾種方式
相關(guān)文章
Java中Elasticsearch 實(shí)現(xiàn)分頁(yè)方式(三種方式)
Elasticsearch是用Java語(yǔ)言開發(fā)的,并作為Apache許可條款下的開放源碼發(fā)布,是一種流行的企業(yè)級(jí)搜索引擎,這篇文章主要介紹了Elasticsearch實(shí)現(xiàn)分頁(yè)的3種方式,需要的朋友可以參考下2022-07-07Java中將一個(gè)列表拆分為多個(gè)較小列表的三種不同方法
有時(shí)候我們需要將大集合按指定的數(shù)量分割成若干個(gè)小集合,這篇文章主要給大家介紹了關(guān)于Java中將一個(gè)列表拆分為多個(gè)較小列表的三種不同方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09