如何反射地获得所有控制器的列表(最好不仅有注释,而且在xml中指定),匹配您的Spring MVC应用程序中的某些特定url ?
如果只有注释,
@Autowired
private ListableBeanFactory listableBeanFactory;
...
whatever() {
Map<String,Object> beans = listableBeanFactory.getBeansWithAnnotation(RequestMapping.class);
// iterate beans and compare RequestMapping.value() annotation parameters
// to produce list of matching controllers
}
可以使用,但是在更一般的情况下,当控制器可以在spring.xml配置中指定时,该怎么办呢?如何处理请求路径参数?
从Spring 3.1开始,有了类RequestMappingHandlerMapping
,它传递了@Controller类的映射信息(RequestMappingInfo
)。
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
@PostConstruct
public void init() {
Map<RequestMappingInfo, HandlerMethod> handlerMethods =
this.requestMappingHandlerMapping.getHandlerMethods();
for(Entry<RequestMappingInfo, HandlerMethod> item : handlerMethods.entrySet()) {
RequestMappingInfo mapping = item.getKey();
HandlerMethod method = item.getValue();
for (String urlPattern : mapping.getPatternsCondition().getPatterns()) {
System.out.println(
method.getBeanType().getName() + "#" + method.getMethod().getName() +
" <-- " + urlPattern);
if (urlPattern.equals("some specific url")) {
//add to list of matching METHODS
}
}
}
}
在定义控制器的spring上下文中定义这个bean是很重要的。
通过调用HandlerMapping.getHandler(HTTPServletRequest).getHandler()
获得映射的控制器。HandlerMapping实例可以由IoC获得。如果你没有HTTPServletRequest,你可以使用MockHttpServletRequest构建请求。
@Autowired
private HandlerMapping mapping;
public Object getController(String uri) {
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
// configure your request to some mapping
HandlerExecutionChain chain = mapping.getHandler(request);
return chain.getHandler();
}
对不起,我现在读到你想要一个URL的所有控制器。这将只获得一个完全匹配的控制器。这显然不是你想要的
您可以尝试使用ListableBeanFactory接口来检索所有bean名称。
private @Autowired ListableBeanFactory beanFactory;
public void doStuff() {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
if (beanName.startsWith("env")) { // or whatever check you want to do
Object bean = beanFactory.getBean(beanName)
// .. do something with it
}
}
}
在这里查看ListableBeanFactory的文档。该接口提供了getBeansOfType()、getBeanDefinitionCount()等方法
如果这种方法没有列出@Controller注释的bean,请访问该页以查看如何做到这一点。
您需要在dispatcher servlet中为RequestMappingHandlerMapping做一个条目
<bean name="requestHandlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="useTrailingSlashMatch" value="true"></property>
</bean>
分派器servlet将查看此映射并在您的应用程序中实例化bean RequestMappingHandlerMapping
现在在任何控制器/类中你都可以使用
@Autowired
private HandlerMapping mapping;
,它应该可以正常工作。
注意:你需要注意添加bean,如果你的任何dispatcherservlet(在大型应用程序的情况下)包含这个bean,它将导致一个noUniqueBean异常和应用程序无法启动。