等等,经过上述实现,我们可以在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
进行配置,此处略过...
然后,我们在需要改写ResponseJsonFormatHandler
的 support
方法,判断注解标志
@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?";
}
}
网友评论