18

如何反射性地获取所有控制器的列表(如果不仅有注释,而且在 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 配置中指定控制器时该怎么办?以及如何处理请求路径参数?

4

4 回答 4

32

从 Spring 3.1 开始,有 class RequestMappingHandlerMapping,它提供有关RequestMappingInfo@Controller 类的映射 () 的信息。

@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 很重要。

于 2012-12-25T21:05:51.980 回答
5

您可以通过调用来获得映射的控制器HandlerMapping.getHandler(HTTPServletRequest).getHandler()。IoC 可以获取 HandlerMapping 实例。如果您没有 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 的所有控制器。这将只为您提供一个完全匹配的控制器。这显然不是你需要的。

于 2012-12-28T13:16:04.867 回答
3

您可以尝试使用 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 ,请访问此页面以查看如何完成。

于 2012-12-28T12:21:17.093 回答
0

您需要在调度程序 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 异常并且应用程序将无法启动。

于 2016-07-07T09:52:22.017 回答