如何在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
相关产品推荐
相关产品推荐

