美文网首页
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