栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java实现自定义包装注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java实现自定义包装注解

java实现自定义包装注解的方式不少,可以采用aop方式,还可以单纯采用拦截器配合ResponseBodyAdvice(响应结果处理)方式。这篇文章我用到的是第二种。

1. 自定义一个注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@documented
public @interface ResponseResult {

}

作用:自定义的包装注解,可在controller类/具体接口方法上添加,最后实现效果就是检测到有这个注解标记的话,可对范围内的接口返回值进行统一格式包装。

2. 定义一个拦截器处理@ResponseResult注解

@Component
@Slf4j
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();
      log.info("拦截该请求接口,判断方法或该方法所在的类上是否有统一包装的注解@ResponseResult:{}->{}",clazz.getSimpleName(),method.getName());
      //判断是否在类对象上面加了注解
      if (clazz.isAnnotationPresent(ResponseResult.class)){
        //设置此请求返回体,需要包装,往下传递,在ResponseAdvice接口进行判断
        request.setAttribute(RESPONSE_RESULT_ANN,clazz.getAnnotation(ResponseResult.class));
        //方法体上是否有注解
      }else if (method.isAnnotationPresent(ResponseResult.class)){
        //设置此请求返回体,需要包装,往下传递,在ResponseAdvice接口进行判断
        request.setAttribute(RESPONSE_RESULT_ANN,method.getAnnotation(ResponseResult.class));
      }
    }
    return true;
  }
}

注:HandlerInterceptor接口是必须要实现的,是spring web中的拦截器接口。而提到的ResponseAdvice接口是在下一步完成。

3. 注册自定义的拦截器
拦截器要想生效需要被注册。

@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {

  @Autowired
  private ResponseResultInterceptor responseResultInterceptor;

  
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    //  针对@ResponseResult注解的拦截器
    registry.addInterceptor(responseResultInterceptor).addPathPatterns("
  public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";

  @Autowired
  private ObjectMapper objectMapper;


  
  @Override
  public boolean supports(MethodParameter returnType,
      Class> converterType) {
    ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder
        .getRequestAttributes();
    assert sra != null;
    HttpServletRequest request = sra.getRequest();
    //判断请求 是否有包装标记
    ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN);
    return responseResultAnn != null;
  }

  @SneakyThrows
  @Override
  public Object beforeBodyWrite(Object body, MethodParameter returnType,
      MediaType selectedContentType, Class> selectedConverterType,
      ServerHttpRequest request, ServerHttpResponse response) {
    if (body instanceof String) {
      return objectMapper.writevalueAsString(Result.ok(body));
    }
    log.info("有包装注解,拦截返回接口数据成功,封装成统一返回格式");
    return Result.ok(body);
  }


}

注:
1.@RestControllerAdvice是需要处理的范围,一般指定controller层
2.自定义的包装注解是否存在的判断是通过定义的标记名称来实现
3.这个类要想生效,需要在controller层中调用方法上加入@RequstMapping和@ResponseBody
4.文中的Result.ok()是我自定义的返回格式,可根据需求自行定义。
5.加上

    if (body instanceof String) {
      return objectMapper.writevalueAsString(Result.ok(body));
    }

的目的是因为可能对返回类型是String的话可能无法识别解析。

最终效果:

只要加了该注解,就会对接口的返回类型进行统一包装,不用重复劳动,写上类似return Result.ok(JsonUtil.json2Map(response));
这种代码。
后续也可在此基础上实现同一异常处理。

ps:因为目前所在公司属于个人任务时间充裕那种,所以我不用像之前那样已赶紧做出来为主,更多的思考,优化,造轮子才是有成就感。希望看到的朋友一起共进步,讨论。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/423965.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号