【问题标题】:Reflectively getting list of Spring MVC controllers matching specific url反射性地获取与特定 url 匹配的 Spring MVC 控制器列表
【发布时间】:2012-12-11 03:25:55
【问题描述】:

如何反射性地获取所有控制器的列表(最好不仅是带注释的,而且在 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 Tool Suite 将在 IDE 中为您提供此信息。否则,这是我写的一个实用程序:github.com/kdgregory/pathfinder(我将在本周晚些时候合并一些更新)
  • 我正在尝试为我的 Web 应用程序实现动态菜单系统。我不需要静态分析源代码(我的想法已经做得很好了),我需要在运行时进行反思。
  • 您打算如何在 XML 配置中找到相关的控制器?也许您可以在运行时访问org.springframework.web.bind.annotation.support.HandlerMethodResolver.getHandlerMethods() 并处理返回的方法。
  • Ralph 的回答没有给您想要的吗?我的想法是扫描您的 bean 以查找 DefaultAnnotationHandlerMapping,然后拉出它的映射图,但由于我没有尝试过,所以这不是答案。另一种方法是检查已注册的 bean 的注释,但这有一些曲折。

标签: java spring spring-mvc reflection


【解决方案1】:

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

【讨论】:

  • 我没有遇到 RequestMappingHandlerMapping 类型的 bean。在自动装配之前谁会吃掉这个 bean..你能帮帮我吗?
【解决方案2】:

您可以尝试使用 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 here 的文档。 该接口提供了getBeansOfType()、getBeanDefinitionCount()等方法。

如果这种方法没有列出@Controller 注释的bean visit this 页面,看看如何做到这一点。

【讨论】:

    【解决方案3】:

    您可以通过调用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 的所有控制器。这将只为您提供一个完全匹配的控制器。这显然不是你需要的。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-16
        • 2023-04-02
        • 2015-05-30
        • 1970-01-01
        • 1970-01-01
        • 2016-10-17
        • 1970-01-01
        • 2016-07-27
        相关资源
        最近更新 更多