• 个人博客开发之blogapi项目统一结果集api封装


    前言

    由于返回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格式返回

    关注公众号猿小叔获取更多干货分享

  • 相关阅读:
    addEventListener事件委托
    ES6的解构赋值
    JavaScript 中最​​重要的保留字
    HTML 5 Web 存储
    Node.js 里的 process.nextTick(),简单理解
    实现多层DIV叠加的js事件穿透
    touch事件中的touches、targetTouches和changedTouches详解
    Promise.all( ) 的使用
    js 中的五种迭代方法
    迭代
  • 原文地址:https://www.cnblogs.com/kenx/p/15018583.html
Copyright © 2020-2023  润新知