目錄
1. 對所有返回類型方法進行統一數據返回類型處理
2.?部分返回類型方法存在的問題
3. 對兩種有誤的方法進行處理
仍以圖書管理系統為例。
創建Result對后端返回給前端的數據進行封裝,增加業務狀態碼與錯誤信息,將原本的數據作為data部分:
package com.example.bookmanagementsystem.model;import com.example.bookmanagementsystem.enums.ResultCode;
import lombok.Data;@Data
public class Result<T> {
// 業務狀態碼:0-成功, -1-失敗, -2未登錄;private ResultCode code;
// 錯誤信息;private String errMsg;
// 數據private Object data;public static <T> Result<T> success(T data){Result result=new Result();result.setCode(ResultCode.SUCCESS);result.setErrMsg("");result.setData(data);return result;}public static <T> Result<T> fail(String errMsg,Object data){Result result=new Result();result.setCode(ResultCode.FAIL);result.setErrMsg(errMsg);result.setData(data);return result;}public static <T> Result<T> fail(String errMsg){Result result=new Result();result.setCode(ResultCode.FAIL);result.setErrMsg(errMsg);result.setData(null);return result;}public static <T> Result<T> unlogin(){Result result=new Result();result.setCode(ResultCode.UNLOGIN);result.setErrMsg("用戶未登錄");result.setData(null);return result;}
}
將getBookListByPage方法的返回值修改為Result:
@RequestMapping("/getBookListByPage")public Result getBookListByPage(PageRequest pageRequest, HttpSession session){log.info("接收到查詢翻頁信息:pageRequest:{}",pageRequest);// 校驗成功if(pageRequest.getPageSize()<0 || pageRequest.getCurrentPage()<1) {return Result.fail("參數校驗失敗");}PageResult<BookInfo> bookInfoPageResult=null;try{bookInfoPageResult = bookService.selectBookInfoByPage(pageRequest);return Result.success(bookInfoPageResult);}catch (Exception e){log.error("查詢翻頁信息錯誤:e{}",e);return Result.fail(e.getMessage());}}
?為了實現后端方法返回給前端的數據都被封裝為Result類型,若逐個修改封裝會非常麻煩,接下來采用統一數據返回對現有方法進行處理。
1. 對所有返回類型方法進行統一數據返回類型處理
在config包下創建一個ResponseAdvice類,表示控制器通知類:
package com.example.bookmanagementsystem.config;import com.example.bookmanagementsystem.model.Result;
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;@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 返回前需要執行的操作:封裝return Result.success(body);}
}
1、控制器通知類需要使用@ControllerAdvice注解,并實現ResponseBodyAdvice接口;
2、控制器通知類需要重寫supports方法和beforeBodyWrite方法:
(1)supports方法:返回值為布爾類型,表示是否執行beforeBodyWrite方法:
若返回值為true表示執行,false表示不執行;
(2)beforeBodyWrite方法:對response方法進行具體操作;
2.?部分返回類型方法存在的問題
1、當返回類型為Result時:(Result類型已進行返回類型的封裝)
登錄后,測試getBookListByPage方法:
body就是返回的結果,但success方法已經進行了封裝,故而導致兩遍封裝:
2、當返回類型為String時:
登錄后,對updateBook方法進行測試:
可見HTTP狀態碼為500,表示服務器內部執行有誤。但此時采用的統一數據返回形式卻將業務狀態碼置為SUCCESS,出現錯誤;
綜上:
當前統一數據返回格式處理對于兩種返回類型的方法存在錯誤:
(1)返回類型為Result時出現嵌套封裝;
(2)返回類型為String時無法正確處理;
3. 對兩種有誤的方法進行處理
修改ResponseAdvice類:
package com.example.bookmanagementsystem.config;import com.example.bookmanagementsystem.model.Result;
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;@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Autowiredprivate ObjectMapper objectMapper;@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@SneakyThrows // lombok提供的處理異常的注解:編譯后處理為try catch;@Overridepublic 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);}
}
(1)對于返回類型為Result的方法進行處理,當body為Result時直接返回body即可,無需進行統一數據返回;
(2)對于返回類型為String類型的方法進行處理,此時需使用jackson的ObjectMapper類,實例化對象后調用writeValueAsString方法進行處理;
使用postman進行測試:
1、使用getBookListByPage方法(返回值為Result類型)進行測試:
2、使用updateBook方法(返回值為String類型)進行測試: