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

Spring中在Interceptor/Filter内获取请求对应方法并分析注解

嘿,在Spring里实现你要的这个需求完全不用自己造轮子,Spring本身就提供了现成的组件来搞定。我给你分两种场景讲,分别对应Interceptor和Filter的实现方式,优先推荐Interceptor的方案,更省心!

在Spring HandlerInterceptor中实现(首推)

因为Interceptor属于Spring MVC生命周期的一部分,当请求匹配到对应的@RequestMapping方法时,Spring会直接把目标方法封装成HandlerMethod传递给Interceptor的preHandle方法,你直接拿过来用就行,完全不用自己做路径匹配。

示例代码

首先写一个自定义Interceptor:

@Component
public class AnnotationAnalysisInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 先判断当前handler是不是@RequestMapping方法对应的HandlerMethod
        if (handler instanceof HandlerMethod handlerMethod) {
            // 获取目标方法和Controller类
            Method targetMethod = handlerMethod.getMethod();
            Class<?> controllerClass = handlerMethod.getBeanType();

            // 处理方法上的@RequireScore注解
            RequireScore requireScore = targetMethod.getAnnotation(RequireScore.class);
            if (requireScore != null) {
                Score level = requireScore.level();
                int score = requireScore.score();
                // 这里可以写你的业务逻辑,比如校验用户分数是否达标
                System.out.println("方法要求等级:" + level + ",分数:" + score);
            }

            // 处理Controller类上的@AnotherCustomAnnotation注解
            AnotherCustomAnnotation classAnnotation = controllerClass.getAnnotation(AnotherCustomAnnotation.class);
            if (classAnnotation != null) {
                String value = classAnnotation.value();
                System.out.println("Controller类注解值:" + value);
            }

            // 处理方法上的@AnotherCustomAnnotation注解
            AnotherCustomAnnotation methodAnnotation = targetMethod.getAnnotation(AnotherCustomAnnotation.class);
            if (methodAnnotation != null) {
                String value = methodAnnotation.value();
                System.out.println("方法注解值:" + value);
            }
        }
        // 返回true继续执行后续的请求流程,返回false则终止请求
        return true;
    }
}

注册Interceptor

在Spring Boot里,你可以通过WebMvcConfigurer来注册这个Interceptor:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private AnnotationAnalysisInterceptor annotationAnalysisInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(annotationAnalysisInterceptor)
                .addPathPatterns("/**"); // 指定要拦截的路径,这里是所有路径
    }
}

在Filter中实现(Servlet层面)

如果你的需求必须在Filter里处理(比如要在Spring MVC处理请求之前做一些操作),那可以借助Spring的RequestMappingHandlerMapping组件——它是Spring MVC内部存储所有@RequestMapping方法映射关系的核心Bean,我们可以用它来手动查找请求对应的方法。

示例代码

@Component
public class AnnotationAnalysisFilter implements Filter {

    // 用@Lazy避免Filter初始化时Spring上下文还没加载好这个Bean
    @Lazy
    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        try {
            // 查找当前请求对应的HandlerExecutionChain
            HandlerExecutionChain handlerChain = requestMappingHandlerMapping.getHandler(request);
            if (handlerChain != null) {
                Object handler = handlerChain.getHandler();
                // 同样判断是不是HandlerMethod类型
                if (handler instanceof HandlerMethod handlerMethod) {
                    Method targetMethod = handlerMethod.getMethod();
                    Class<?> controllerClass = handlerMethod.getBeanType();

                    // 后面的逻辑和Interceptor完全一样,这里就不重复写了
                    RequireScore requireScore = targetMethod.getAnnotation(RequireScore.class);
                    if (requireScore != null) {
                        // 你的业务逻辑
                    }
                }
            }
        } catch (Exception e) {
            // 处理查找失败的情况,比如请求是静态资源或者没有匹配到任何@RequestMapping方法
            e.printStackTrace();
        }

        // 继续执行Filter链
        chain.doFilter(servletRequest, servletResponse);
    }
}

注意事项

  • Filter是在Servlet层面执行的,比Spring MVC的Interceptor更早,所以用这种方式相当于提前做了一次路径匹配,性能上会比Interceptor稍差一点,因为Spring MVC后续还会再做一次匹配。
  • 如果你的Controller被AOP代理了,handlerMethod.getBeanType()可能返回代理类,这时候可以用handlerMethod.getMethod().getDeclaringClass()获取原始的Controller类,或者用AopUtils.getTargetClass(handlerMethod.getBean())获取目标对象的类。
  • 如果你的自定义注解没有标注@Inherited,那么子类继承父类Controller时,父类的注解不会被继承到子类,获取的时候要注意这一点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:20:31