前言
由于返回json api 格式接口,所以我们需要通过java bean封装一个统一数据返回格式,便于和前端约定交互,
状态码枚举ResultCode
1package cn.soboys.core.ret; 2 3 4import lombok.Getter; 5 6/** 7 * @author kenx 8 * @version 1.0 9 * @date 2021/6/17 15:35 10 * 响应码枚举,对应HTTP状态码 11 */ 12@Getter 13public enum ResultCode { 14 15 SUCCESS(200, "成功"),//成功 16 //FAIL(400, "失败"),//失败 17 BAD_REQUEST(400, "Bad Request"), 18 UNAUTHORIZED(401, "认证失败"),//未认证 19 NOT_FOUND(404, "接口不存在"),//接口不存在 20 INTERNAL_SERVER_ERROR(500, "系统繁忙"),//服务器内部错误 21 METHOD_NOT_ALLOWED(405,"方法不被允许"), 22 23 /*参数错误:1001-1999*/ 24 PARAMS_IS_INVALID(1001, "参数无效"), 25 PARAMS_IS_BLANK(1002, "参数为空"); 26 /*用户错误2001-2999*/ 27 28 29 private Integer code; 30 private String message; 31 32 ResultCode(int code, String message) { 33 this.code = code; 34 this.message = message; 35 } 36} 37
结果体Result
1package cn.soboys.core.ret; 2 3import lombok.Data; 4 5import java.io.Serializable; 6 7/** 8 * @author kenx 9 * @version 1.0 10 * @date 2021/6/17 15:47 11 * 统一API响应结果格式封装 12 */ 13@Data 14public class Result<T> implements Serializable { 15 16 private static final long serialVersionUID = 6308315887056661996L; 17 private Integer code; 18 private String message; 19 private T data; 20 21 22 public Result setResult(ResultCode resultCode) { 23 this.code = resultCode.getCode(); 24 this.message = resultCode.getMessage(); 25 return this; 26 } 27 28 public Result setResult(ResultCode resultCode, T data) { 29 this.code = resultCode.getCode(); 30 this.message = resultCode.getMessage(); 31 this.setData(data); 32 return this; 33 } 34 35 36} 37
响应结果方法工具类
1package cn.soboys.core.ret; 2 3/** 4 * @author kenx 5 * @version 1.0 6 * @date 2021/6/17 16:30 7 * 响应结果返回封装 8 */ 9public class ResultResponse { 10 private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS"; 11 12 // 只返回状态 13 public static Result success() { 14 return new Result() 15 .setResult(ResultCode.SUCCESS); 16 } 17 18 // 成功返回数据 19 public static Result success(Object data) { 20 return new Result() 21 .setResult(ResultCode.SUCCESS, data); 22 23 24 } 25 26 // 失败 27 public static Result failure(ResultCode resultCode) { 28 return new Result() 29 .setResult(resultCode); 30 } 31 32 // 失败 33 public static Result failure(ResultCode resultCode, Object data) { 34 return new Result() 35 .setResult(resultCode, data); 36 } 37 38 39 40} 41
自定义解析controller拦截
注解@ResponseResult
1package cn.soboys.core.ret; 2 3import java.lang.annotation.*; 4 5/** 6 * @author kenx 7 * @version 1.0 8 * @date 2021/6/17 16:43 9 * 统一包装接口返回的值 Result 10 */ 11@Target({ElementType.TYPE, ElementType.METHOD}) 12@Retention(RetentionPolicy.RUNTIME) 13@Documented 14public @interface ResponseResult { 15} 16
请求拦截ResponseResultInterceptor
1package cn.soboys.core.ret; 2 3import org.springframework.web.method.HandlerMethod; 4import org.springframework.web.servlet.HandlerInterceptor; 5 6import javax.servlet.http.HttpServletRequest; 7import javax.servlet.http.HttpServletResponse; 8import java.lang.reflect.Method; 9 10/** 11 * @author kenx 12 * @version 1.0 13 * @date 2021/6/17 17:10 14 * 请求拦截 15 */ 16public class ResponseResultInterceptor implements HandlerInterceptor { 17 18 //标记名称 19 public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN"; 20 21 @Override 22 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 23 //请求方法 24 if (handler instanceof HandlerMethod) { 25 final HandlerMethod handlerMethod = (HandlerMethod) handler; 26 final Class<?> clazz = handlerMethod.getBeanType(); 27 final Method method = handlerMethod.getMethod(); 28 //判断是否在对象上加了注解 29 if (clazz.isAnnotationPresent(ResponseResult.class)) { 30 //设置此请求返回体需要包装,往下传递,在ResponseBodyAdvice接口进行判断 31 request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class)); 32 //方法体上是否有注解 33 } else if (method.isAnnotationPresent(ResponseResult.class)) { 34 //设置此请求返回体需要包装,往下传递,在ResponseBodyAdvice接口进行判断 35 request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class)); 36 } 37 } 38 return true; 39 } 40} 41 42
请求全局解析ResponseResultHandler
1package cn.soboys.core.ret; 2 3import cn.soboys.core.utils.HttpContextUtil; 4import com.alibaba.fastjson.JSON; 5import lombok.extern.slf4j.Slf4j; 6import org.springframework.core.MethodParameter; 7import org.springframework.http.MediaType; 8import org.springframework.http.converter.HttpMessageConverter; 9import org.springframework.http.server.ServerHttpRequest; 10import org.springframework.http.server.ServerHttpResponse; 11import org.springframework.web.bind.annotation.ControllerAdvice; 12import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; 13 14import javax.servlet.http.HttpServletRequest; 15 16/** 17 * @author kenx 18 * @version 1.0 19 * @date 2021/6/17 16:47 20 * 全局统一响应返回体处理 21 */ 22@Slf4j 23@ControllerAdvice 24public class ResponseResultHandler implements ResponseBodyAdvice<Object> { 25 26 public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN"; 27 28 /** 29 * @param methodParameter 30 * @param aClass 31 * @return 此处如果返回false , 则不执行当前Advice的业务 32 * 是否请求包含了包装注解 标记,没有直接返回不需要重写返回体, 33 */ 34 @Override 35 public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) { 36 HttpServletRequest request = HttpContextUtil.getRequest(); 37 //判断请求是否有包装标志 38 ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN); 39 return responseResultAnn == null ? false : true; 40 } 41 42 /** 43 * @param body 44 * @param methodParameter 45 * @param mediaType 46 * @param aClass 47 * @param serverHttpRequest 48 * @param serverHttpResponse 49 * @return 处理响应的具体业务方法 50 */ 51 @Override 52 public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { 53 if (body instanceof Result) { 54 return body; 55 } else if (body instanceof String) { 56 return JSON.toJSONString(ResultResponse.success(body)); 57 } else { 58 return ResultResponse.success(body); 59 } 60 } 61}
具体详细内容请参考我这边文章 Spring Boot 无侵入式 实现RESTful API接口统一JSON格式返回
