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

如何在Spring Boot中获取所有已创建请求映射并监听其变化?

解决方案:Spring 中监听请求映射的初始化与动态变化

要实现你需要的请求映射元数据管理组件,核心是利用 Spring MVC 的核心管理类 RequestMappingHandlerMapping——它负责维护所有请求映射的注册信息。下面分两部分给出具体实现方案:

一、初始化时抓取所有已存在的请求映射

在 @PostConstruct 方法中,直接注入 RequestMappingHandlerMapping,就能一次性获取所有已注册的 Controller 请求映射:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.PostConstruct;
import java.util.Map;

@Component
public class RequestMappingMetadataHolder {

    private final RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Autowired
    public RequestMappingMetadataHolder(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    @PostConstruct
    public void initRequestMappings() {
        // 获取所有已注册的请求映射键值对
        Map<String, Object> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
        
        // 遍历提取元数据(示例:打印请求路径、处理方法信息)
        handlerMethods.forEach((key, value) -> {
            // key 格式类似 {GET [/api/users]},包含请求方法和路径
            // value 是 HandlerMethod 对象,可获取处理类、方法签名等信息
            System.out.println("初始化发现请求映射:" + key);
            // 这里可将元数据存入自定义存储(比如内存Map、数据库)
        });
    }
}

这段代码会在组件初始化完成后,自动抓取所有启动时就存在的请求映射。

二、监听请求映射的动态新增/移除

要捕获后续的请求映射变化,我们需要扩展 RequestMappingHandlerMapping,在它的注册/注销逻辑中触发自定义事件,再让元数据组件监听这些事件来实时更新。

步骤1:自定义可观测的 RequestMappingHandlerMapping

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;

public class ObservableRequestMappingHandlerMapping extends RequestMappingHandlerMapping implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher eventPublisher;

    @Override
    protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
        super.registerHandlerMethod(handler, method, mapping);
        // 发布请求映射新增事件
        eventPublisher.publishEvent(new RequestMappingAddedEvent(this, mapping, handler, method));
    }

    @Override
    protected void unregisterHandlerMethod(Object handler, Method method) {
        RequestMappingInfo mapping = getMappingForMethod(method, handler.getClass());
        super.unregisterHandlerMethod(handler, method);
        if (mapping != null) {
            // 发布请求映射移除事件
            eventPublisher.publishEvent(new RequestMappingRemovedEvent(this, mapping, handler, method));
        }
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.eventPublisher = applicationEventPublisher;
    }
}

步骤2:定义自定义事件类

import org.springframework.context.ApplicationEvent;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;

import java.lang.reflect.Method;

// 请求映射新增事件
public class RequestMappingAddedEvent extends ApplicationEvent {
    private final RequestMappingInfo mappingInfo;
    private final Object handler;
    private final Method method;

    public RequestMappingAddedEvent(Object source, RequestMappingInfo mappingInfo, Object handler, Method method) {
        super(source);
        this.mappingInfo = mappingInfo;
        this.handler = handler;
        this.method = method;
    }

    // getter 方法
    public RequestMappingInfo getMappingInfo() { return mappingInfo; }
    public Object getHandler() { return handler; }
    public Method getMethod() { return method; }
}

// 请求映射移除事件
public class RequestMappingRemovedEvent extends ApplicationEvent {
    private final RequestMappingInfo mappingInfo;
    private final Object handler;
    private final Method method;

    public RequestMappingRemovedEvent(Object source, RequestMappingInfo mappingInfo, Object handler, Method method) {
        super(source);
        this.mappingInfo = mappingInfo;
        this.handler = handler;
        this.method = method;
    }

    // getter 方法
    public RequestMappingInfo getMappingInfo() { return mappingInfo; }
    public Object getHandler() { return handler; }
    public Method getMethod() { return method; }
}

步骤3:替换默认的 RequestMappingHandlerMapping

通过配置类让 Spring 使用我们自定义的实现:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@Configuration
public class WebMvcConfig {

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        return new ObservableRequestMappingHandlerMapping();
    }
}

步骤4:在元数据组件中监听事件

修改 RequestMappingMetadataHolder,让它监听自定义事件来实时更新元数据:

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class RequestMappingMetadataHolder implements ApplicationListener<RequestMappingAddedEvent>, ApplicationListener<RequestMappingRemovedEvent> {

    // 保留之前的注入和 initRequestMappings 方法...

    @Override
    public void onApplicationEvent(RequestMappingAddedEvent event) {
        RequestMappingInfo mappingInfo = event.getMappingInfo();
        // 提取新增的请求映射元数据,更新存储
        System.out.println("新增请求映射:" + mappingInfo.getPatternsCondition());
    }

    @Override
    public void onApplicationEvent(RequestMappingRemovedEvent event) {
        RequestMappingInfo mappingInfo = event.getMappingInfo();
        // 移除对应的元数据
        System.out.println("移除请求映射:" + mappingInfo.getPatternsCondition());
    }
}

补充说明

  • 这个方案支持动态注册/注销 Controller的场景(比如通过 BeanDefinitionRegistry 动态添加 Controller、或用 @RefreshScope 刷新 Controller)。
  • RequestMappingInfo 包含了请求映射的完整元数据:请求路径、请求方法、请求参数、媒体类型等,可按需提取使用。
  • 若使用 Spring Boot,无需额外配置 DispatcherServlet,自定义的 RequestMappingHandlerMapping 会自动被容器识别替换默认实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:19:11