前言
由于傳回
json api
格式接口,是以我們需要通過java bean封裝一個統一資料傳回格式,便于和前端約定互動,
狀态碼枚舉ResultCode
package cn.soboys.core.ret;
import lombok.Getter;
/**
* @author kenx
* @version 1.0
* @date 2021/6/17 15:35
* 響應碼枚舉,對應HTTP狀态碼
*/
@Getter
public enum ResultCode {
SUCCESS(200, "成功"),//成功
//FAIL(400, "失敗"),//失敗
BAD_REQUEST(400, "Bad Request"),
UNAUTHORIZED(401, "認證失敗"),//未認證
NOT_FOUND(404, "接口不存在"),//接口不存在
INTERNAL_SERVER_ERROR(500, "系統繁忙"),//伺服器内部錯誤
METHOD_NOT_ALLOWED(405,"方法不被允許"),
/*參數錯誤:1001-1999*/
PARAMS_IS_INVALID(1001, "參數無效"),
PARAMS_IS_BLANK(1002, "參數為空");
/*使用者錯誤2001-2999*/
private Integer code;
private String message;
ResultCode(int code, String message) {
this.code = code;
this.message = message;
}
}
結果體Result
package cn.soboys.core.ret;
import lombok.Data;
import java.io.Serializable;
/**
* @author kenx
* @version 1.0
* @date 2021/6/17 15:47
* 統一API響應結果格式封裝
*/
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 6308315887056661996L;
private Integer code;
private String message;
private T data;
public Result setResult(ResultCode resultCode) {
this.code = resultCode.getCode();
this.message = resultCode.getMessage();
return this;
}
public Result setResult(ResultCode resultCode, T data) {
this.code = resultCode.getCode();
this.message = resultCode.getMessage();
this.setData(data);
return this;
}
}
響應結果方法工具類
package cn.soboys.core.ret;
/**
* @author kenx
* @version 1.0
* @date 2021/6/17 16:30
* 響應結果傳回封裝
*/
public class ResultResponse {
private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
// 隻傳回狀态
public static Result success() {
return new Result()
.setResult(ResultCode.SUCCESS);
}
// 成功傳回資料
public static Result success(Object data) {
return new Result()
.setResult(ResultCode.SUCCESS, data);
}
// 失敗
public static Result failure(ResultCode resultCode) {
return new Result()
.setResult(resultCode);
}
// 失敗
public static Result failure(ResultCode resultCode, Object data) {
return new Result()
.setResult(resultCode, data);
}
}
自定義解析controller攔截
注解@ResponseResult
package cn.soboys.core.ret;
import java.lang.annotation.*;
/**
* @author kenx
* @version 1.0
* @date 2021/6/17 16:43
* 統一包裝接口傳回的值 Result
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseResult {
}
請求攔截ResponseResultInterceptor
package cn.soboys.core.ret;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* @author kenx
* @version 1.0
* @date 2021/6/17 17:10
* 請求攔截
*/
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)) {
//設定此請求傳回體需要包裝,往下傳遞,在ResponseBodyAdvice接口進行判斷
request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class));
//方法體上是否有注解
} else if (method.isAnnotationPresent(ResponseResult.class)) {
//設定此請求傳回體需要包裝,往下傳遞,在ResponseBodyAdvice接口進行判斷
request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class));
}
}
return true;
}
}
請求全局解析ResponseResultHandler
package cn.soboys.core.ret;
import cn.soboys.core.utils.HttpContextUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
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;
import javax.servlet.http.HttpServletRequest;
/**
* @author kenx
* @version 1.0
* @date 2021/6/17 16:47
* 全局統一響應傳回體處理
*/
@Slf4j
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";
/**
* @param methodParameter
* @param aClass
* @return 此處如果傳回false , 則不執行目前Advice的業務
* 是否請求包含了包裝注解 标記,沒有直接傳回不需要重寫傳回體,
*/
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
HttpServletRequest request = HttpContextUtil.getRequest();
//判斷請求是否有包裝标志
ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN);
return responseResultAnn == null ? false : true;
}
/**
* @param body
* @param methodParameter
* @param mediaType
* @param aClass
* @param serverHttpRequest
* @param serverHttpResponse
* @return 處理響應的具體業務方法
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if (body instanceof Result) {
return body;
} else if (body instanceof String) {
return JSON.toJSONString(ResultResponse.success(body));
} else {
return ResultResponse.success(body);
}
}
}
具體詳細内容請參考我這篇文章Spring Boot 無侵入式 實作RESTful API接口統一JSON格式傳回
關注公衆号猿小叔擷取更多幹貨分享