目前很多項目都是前后端分離,前后端會事先約定好返回格式。那么后端如何做,才能優雅的返回統一格式呢,接下來,請大家跟著我,一步步來實現。
1. 直接返回結果
先看一下最基本的例子,直接將結果原封不動返回:
@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;
}
}
返回結果:
{
"name": "張三",
"age": 30
}
2. 約定返回格式
假如已經與前端開發妹子約定好了格式,比如:
{
"code": 0,
"msg": "錯誤信息",
"data": 實際返回結果
}
那么我們首先需要編寫一個封裝結果類Result。為了方便封裝,在這個類中增加一個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;
/**
* 業務數據
*/
private T data;
/**
* 返回成功結果對象
*
* @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. 返回統一格式結果
后臺接口代碼微調一下,返回值改為Result,泛型為原返回值的類型:
@RestController
@RequestMapping(value = "/test")
public class TestApi {
@GetMapping("/withResult")
public Result< TestVo > withResult() {
TestVo testVo = new TestVo("張三", 30);
return Result.success(testVo);
}
}
返回結果:
{
"code": 0,
"msg": "success",
"data": {
"name": "張三",
"age": 30
}
}
至此,返回結果完美符合格式。
但是這樣的代碼并不算簡潔:每個接口的返回值都必須是Result<>,并且return的時候都要用Result.success()方法封裝一下。
那么,有沒有更優雅的方法?我們繼續往下看:
4. 切片封裝統一格式
編寫注解
實際使用場景中,并不是所有接口都需要統一格式。我們這里使用一個注解作為開關,按需控制接口返回格式。
@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
@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) {
//關鍵
return Result.success(body);
}
}
這里有一點要 注意 ,這個advice中supports方法中判斷返回結果類型必須為非String類型。如果返回結果為String類型,那么result要轉為json字符串后再返回,需要再寫一個advice。
見證奇跡的時刻到了
@ApiResult
@GetMapping("/withResultHide")
public TestVo withResultHide() {
TestVo testVo = new TestVo("張三", 30);
return testVo;
}
這段代碼與最開始一樣,并沒有返回Result,僅僅加上了@ApiResult注解,我們看返回結果:
{
"code": 0,
"msg": "success",
"data": {
"name": "張三",
"age": 30
}
}
大功告成!
以上只是最精簡的例子,實際使用中還結合了 統一異常封裝、自定義返回格式 等功能。我們注意到@ApiResult注解中,有三個參數:successCode、successMsg、resultClass,就是為了自定義返回格式預留的,下面再看兩個場景:
5. 自定義返回格式
場景1:返回成功時code為200
如果個別接口的返回格式與默認格式相同,但是要求code等于200時才代表成功,那么修改下successCode參數即可:
@ApiResult(successCode = 200, successMsg = "ok")
@GetMapping("/withResultHide")
public TestVo withResultHide() {
TestVo testVo = new TestVo("張三", 30);
return testVo;
}
返回成功時,結果中的code和msg都變為設置的值:
{
"code": 200,
"msg": "ok",
"data": {
"name": "張三",
"age": 30
}
}
場景2:自定義返回格式
如果某個接口的返回格式不是默認的返回格式,比如約定返回returnCode、returnDesc、data(對應默認的code、msg、data)。那么則需要新增一個返回結果類,比如ReturnResult:
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ReturnResult< T > implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 返回編碼
*/
private String returnCode;
/**
* 編碼描述
*/
private String returnDesc;
/**
* 業務數據
*/
private T data;
/**
* 返回成功結果對象
*
* @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;
}
這時,返回結果就變為想要的格式了:
{
"returnCode": "0",
"returnDesc": "success",
"data": {
"name": "張三",
"age": 30
}
}
小結
只要按照上面一步步改造,即可實現統一返回格式,既簡潔、又優雅。
-
接口
+關注
關注
33文章
8497瀏覽量
150835 -
代碼
+關注
關注
30文章
4748瀏覽量
68355
發布評論請先 登錄
相關推薦
評論