美文网首页
Controller优化2:统一Json格式返回(注解实现)

Controller优化2:统一Json格式返回(注解实现)

作者: 最爱下雨天呢 | 来源:发表于2020-03-11 22:25 被阅读0次

    Controller优化1:统一Json格式响应定义

    等等,经过上述实现,我们可以在Controller层直接返回业务实体,但是这样的话注意到上面的supports方法,这样所有的响应都将进行包装,这可能并不是我们想要的。为此 我们引入自定义注解+拦截器

    实现思路:通过注解标识需要被包装的类或方法。我们在请求进入时候拦截,为其打上注解标签,在返回时候进行标签验证,如果有才进行body重写,否则直接返回即可。

    自定义注解 ResponseJsonFormat

    /**
     * 返回格式-注解 
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Documented
    public @interface ResponseJsonFormat {
    }
    

    响应格式控制拦截器 ResponseFormatJsonInterceptor

    /**
     * 响应格式-自定义注解拦截处理
     */
    @Slf4j
    @Component
    public class ResponseFormatJsonInterceptor implements HandlerInterceptor {
        public static final String RESPONSE_FORMAT_FLAG = "RESPONSE_JSON_FLAG";
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 请求里面添加注解@ResponseJsonFormat的标志,为了返回响应时拦截进行处理
            if (handler instanceof HandlerMethod) {
                final HandlerMethod handlerMethod = (HandlerMethod) handler;
                final Class<?> clazz = handlerMethod.getBeanType();
                final Method method = handlerMethod.getMethod();
                if (clazz.isAnnotationPresent(ResponseFormat.class)) {
                    request.setAttribute(RESPONSE_FORMAT_FLAG, 
                                         clazz.getAnnotation(ResponseJsonFormat.class));
                } else if (method.isAnnotationPresent(ResponseFormat.class)) {
                    request.setAttribute(RESPONSE_FORMAT_FLAG, 
                                         method.getAnnotation(ResponseJsonFormat.class));
                }
            }
            return true;
        }
    }
    

    当然,需要注意该拦截器需要注册到系统内,springboot2.0使用实现WebMvcConfigurer进行配置,此处略过...

    然后,我们在需要改写ResponseJsonFormatHandlersupport方法,判断注解标志

    @Slf4j
    @ControllerAdvice
    public class ResponseJsonFormatHandler implements ResponseBodyAdvice<Object> { 
        /**
         * 标记位
         */
        public static final String RESPONSE_FORMAT_FLAG = "RESPONSE_JSON_FLAG";
        @Override
        public boolean supports(MethodParameter methodParameter,
                                Class<? extends HttpMessageConverter<?>> aClass) {
            // 判断请求是否需要包装,默认true
            // 判断请求是否包含了注解标记
            ServletRequestAttributes sra = 
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = sra.getRequest();
            ResponseJsonFormat responseFlag = 
                (ResponseJsonFormat) request.getAttribute(RESPONSE_FORMAT_FLAG);
            return null != responseFlag; 
        }
    
        @Override
        public Object beforeBodyWrite(Object o, MethodParameter methodParameter,
                                      MediaType mediaType,
                                      Class<? extends HttpMessageConverter<?>> aClass,
                                      ServerHttpRequest serverHttpRequest,
                                      ServerHttpResponse serverHttpResponse) {
            log.info("进入返回体重写过程,封装code msg data...");   
            if (null == o) { 
                return ResponseJson.ok();       //成功执行但无数据返回,返回code,msg
            } else if (o instanceof ResponseJson) { 
                return o;                       //已经在controller封装完成,直接返回
            } 
            return ResponseJson.ok(o);          // 尚未包装的成功数据,此处封装code msg data
        }
    }
    

    当然我们在Controller层也要发生小小的变化,在该类上添加注解@ResponseJsonFormat,

    标识该类下所有方法都要进行响应包装,当然也可以加在方法上,即指定某一个方法需要进行响应包装

    @Slf4j
    @ResponseJsonFormat 
    @RestController
    @RequestMapping("/test")
    public class TestController {  
    
        @GetMapping("/hello")
        public String sayHello() {
            log.info("进入方法...")
            return "what’s happening to you?";   
        }
    }
    

    下一篇:Controller优化3:统一异常处理

    相关文章

      网友评论

          本文标题:Controller优化2:统一Json格式返回(注解实现)

          本文链接:https://www.haomeiwen.com/subject/deekjhtx.html