今天給大家帶來的是Spring Boot API 統一回傳格式封裝,我們在做專案的時候API 介面回傳是需要統一格式的,只有這樣前端的同學才可對介面回傳的資料做統一處理,也可以使前后端分離
模式的開發中,只關注于業務,而無需考慮對每一個回傳結果做處理,中心思想是,所有結果封裝為json,錯誤資訊通過例外拋出,統一捕捉處理后回傳前端,舉例:如果插入一條用戶資訊,而
這個用戶已經在系統中存在,則回傳插入失敗,我們用列舉定義一個回傳資訊,通過例外拋出,
**說明:本人沒有公眾號,只要這個博客,也會對博客進行持續更新,如果對您有幫助,希望您持續關注**
原始碼地址https://gitee.com/zgc005/resut
廢話少說 上代碼
先講專案結構
├── LICENSE
├── demo.iml
├── pom.xml
├── re
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── result
│ │ └── demo
│ │ ├── DemoApplication.java
│ │ ├── common
│ │ │ └── config
│ │ ├── global
│ │ │ ├── advice
│ │ │ │ ├── ExceptionResultAdvice.java ———— 例外捕捉,處理,
│ │ │ │ └── ResponseResultAdvice.java ———— 介面回傳統一封裝
│ │ │ ├── annotation
│ │ │ │ └── ResponseResult.java ———— 自定義標簽 用來驗證介面是否需要包裝回傳 并且驗證介面是否存在
│ │ │ ├── config
│ │ │ │ └── GlobalConfig.java ———— 全域配置,讀取*.yml 組態檔資訊
│ │ │ ├── enums
│ │ │ │ └── ResultCode.java ———— api例外列舉
│ │ │ ├── exception
│ │ │ │ └── BizException.java
│ │ │ ├── filterLists
│ │ │ │ ├── FilterConfig.java ———— Filter 配置
│ │ │ │ └── SignAuthFilter.java ———— 介面請求驗簽等操作
│ │ │ ├── interceptor
│ │ │ │ ├── ResponseResultInterceptor.java 用來處理回傳資料是否需要封裝
│ │ │ │ └── WebConfigurer.java
│ │ │ ├── result
│ │ │ │ ├── EnumInterface.java
│ │ │ │ └── Result.java
│ │ │ └── sign
│ │ │ ├── BodyReaderHttpServletRequestWrapper.java ————對請求流處理
│ │ │ ├── HttpUtils.java
│ │ │ └── SignUtil.java
│ │ ├── modules
│ │ │ ├── goods
│ │ │ │ ├── controller
│ │ │ │ │ └── GoodsController.java
│ │ │ │ ├── dao
│ │ │ │ │ └── GoodsDao.java
│ │ │ │ ├── entity
│ │ │ │ │ ├── Goods.java
│ │ │ │ │ ├── GoodsBrandBean.java
│ │ │ │ │ ├── GoodsImage.java
│ │ │ │ │ ├── ProductEntity.java
│ │ │ │ │ └── TestName.java
│ │ │ │ └── service
│ │ │ │ ├── GoodsService.java
│ │ │ │ └── impl
│ │ │ │ └── GoodsServiceImpl.java
│ │ │ ├── order
│ │ │ │ ├── controller
│ │ │ │ ├── dao
│ │ │ │ ├── entity
│ │ │ │ └── service
│ │ │ ├── user
│ │ │ │ ├── controller
│ │ │ │ ├── dao
│ │ │ │ ├── entity
│ │ │ │ └── service
│ │ │ └── util
│ │ │ └── JsonTOpagaData.java
│ │ ├── scheduled
│ │ │ ├── ScheduledMachine.java
│ │ │ └── ScheduledProduct.java
│ │ └── test
│ │ ├── Demo.java
│ │ └── Test.java
│ └── resources
│ ├── application-dev.yml
│ ├── application-pro.yml
│ ├── application-test.yml
│ ├── application.yml
│ └── mapper
│ ├── goods
│ │ └── GoodsDao.xml
│ ├── machine
│ │ └── MachineDao.xml
│ ├── order
│ └── user
└── test
└── java
└── com
└── result
└── demo
└── DemoApplicationTests.java
以下是幾個核心的類
- ExceptionResultAdvice :所有的例外都會通個這個類進行捕捉,處理,如果有新增加的Exception 只需要新增方法即可,如新增一個XXXException的方法
@ExceptionHandler(value = https://www.cnblogs.com/onehm/archive/2020/11/09/XXXException.class)
public Result XXXexceptionHandler(XXXException xxxexception){
log.info("系統例外處理:{}",xxxexception);
return Result.error();
}
- ResponseResultAdvice: 重寫回傳資料,這個類主要是對回傳結果進行封裝,而不需要在每一個Controller 里的方法進行封裝,簡化代碼,做到只關注業務,
這里有一個坑:ResponseBodyAdvice 回傳型別如果是String 的話會報錯,原因大家可以自行查看,所以這個地方要對String 型別的資料進行處理
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
log.info("進入回傳提重寫格式 處理中,,,,,,");
Result result = new Result();
// 包含Result 說明是例外
if (body instanceof Result) {
return body;
}
if (body instanceof String) {
String str = JSON.toJSONString(Result.success(body));
return str;
}
return Result.success(body);
}
- ResponseResult: 這個是自定義的標簽,主要是用來判斷Controller 類的回傳資料是否需要封裝用法如下
@Slf4j
@RestController
@RequestMapping(value = "https://www.cnblogs.com/api")
@ResponseResult
public class Test {
}
在ResponseResultInterceptor 類里會對這個標簽進行判斷處理,
public class ResponseResultInterceptor implements HandlerInterceptor {
public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";
/**
* 此代碼核心思想,就是獲取此請求,是否需要回傳值包裝,設定一個屬性標記,
*
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 方法校驗
if (handler instanceof HandlerMethod) {
final HandlerMethod handlerMethod = (HandlerMethod) handler;
final Class<?> clazz = handlerMethod.getBeanType();
final Method method = handlerMethod.getMethod();
if (clazz.isAnnotationPresent(ResponseResult.class)) {
request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class));
} else if (method.isAnnotationPresent(ResponseResult.class)) {
request.setAttribute(RESPONSE_RESULT_ANN, method.getAnnotation(ResponseResult.class));
}
return true;
} else {
return initResponse(response, ResultCode.API_NOT_EXIST);
}
}
private boolean initResponse(HttpServletResponse response,ResultCode resultCode) throws IOException {
response.setCharacterEncoding("utf-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", resultCode.getCode());
jsonObject.put("message", resultCode.getMessage());
jsonObject.put("data", null);
writer.write(jsonObject.toString());
return false;
}
小結:對于面向物件編程的邏輯思維要始終貫穿于整個專案,物件的封裝也是必然,一個類是物件,多個類組成的模塊也是物件,甚至在龐大的系統中,每一個子系統都是一個物件,這也就是OOP的核心 ,一切皆物件,所以沒有物件的同學要抓緊時間找個物件,只有這樣你才會知道如何面向物件!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/207968.html
標籤:其他
