You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AnnotationUtils获取GetMapping路径为空的问题及更优方案问询

优化Spring MVC拦截器中获取请求路径的方案

问题背景

在Spring MVC拦截器中,控制器接口存在两种定义方式:

  1. 使用@GetMapping/@PostMapping等HTTP动词组合注解
  2. 使用原生@RequestMapping注解

直接调用AnnotationUtils.findAnnotation(method, RequestMapping.class)无法获取组合注解的路径值(因为组合注解的路径属性是自身定义的,并非元注解@RequestMapping的属性),原方案通过switch-case逐一检查各组合注解的方式不够简洁,需要优化。

优化方案

方案一:利用Spring原生RequestMappingInfo(推荐)

Spring内部会将所有请求注解(包括组合注解和原生@RequestMapping)统一解析为RequestMappingInfo,包含完整的路径、请求方法、参数等映射信息。通过RequestMappingHandlerMapping可以直接获取该对象,无需手动处理各类注解。

代码示例:

@Component
public class MyOwnInterceptor implements HandlerInterceptor {

    private final RequestMappingHandlerMapping requestMappingHandlerMapping;

    // 构造注入RequestMappingHandlerMapping
    public MyOwnInterceptor(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取当前方法的RequestMappingInfo
            RequestMappingInfo mappingInfo = requestMappingHandlerMapping.getMappingForMethod(
                    handlerMethod.getMethod(), 
                    handlerMethod.getBeanType()
            );
            
            if (mappingInfo != null) {
                // 获取合并后的完整请求路径(包含类上@RequestMapping的前缀)
                Set<String> pathPatterns = mappingInfo.getPatternsCondition().getPatterns();
                String requestPath = pathPatterns.iterator().next();
                // 这里添加你的业务逻辑,比如打印路径
                System.out.println("请求路径:" + requestPath);
            }
        }
        return true;
    }
}

优势:

  • 自动处理类和方法级别的路径合并,无需手动拼接
  • 统一解析所有请求注解类型,无需逐个判断
  • 能获取到请求方法、参数条件等更多映射信息,扩展性强

方案二:反射统一处理请求注解

如果不想依赖RequestMappingHandlerMapping,可以通过反射批量检查所有请求注解类型,统一提取路径属性。

代码示例:

@Component
public class MyOwnInterceptor implements HandlerInterceptor {

    // 定义所有需要检查的请求注解类型
    private static final List<Class<? extends Annotation>> REQUEST_ANNOTATIONS = Arrays.asList(
            GetMapping.class, PostMapping.class, PutMapping.class,
            DeleteMapping.class, PatchMapping.class, RequestMapping.class
    );

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            String requestPath = getRequestPath(handlerMethod.getMethod());
            if (requestPath != null) {
                // 业务逻辑处理
                System.out.println("请求路径:" + requestPath);
            }
        }
        return true;
    }

    private String getRequestPath(Method method) {
        for (Class<? extends Annotation> annoClass : REQUEST_ANNOTATIONS) {
            Annotation annotation = AnnotationUtils.findAnnotation(method, annoClass);
            if (annotation == null) {
                continue;
            }
            try {
                // 反射获取注解的value属性
                Method valueMethod = annoClass.getMethod("value");
                String[] values = (String[]) valueMethod.invoke(annotation);
                if (values.length > 0 && !values[0].isEmpty()) {
                    return values[0];
                }
            } catch (ReflectiveOperationException e) {
                // 忽略注解属性获取异常,继续检查下一个注解
                continue;
            }
        }
        return null;
    }
}

优势:

  • 代码简洁,新增请求注解只需添加到列表中
  • 不依赖Spring的映射处理器,轻量化

注意事项

  • 方案一的RequestMappingInfo会自动处理路径中的占位符(如/{id})、路径前缀合并等场景,比方案二更可靠
  • 如果控制器类上存在@RequestMapping前缀,方案二需要额外处理类级别的注解,才能得到完整路径

内容的提问来源于stack exchange,提问作者user3309305

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 00:01:00