2012-12-24 46 views
12

如何在Spring MVC應用程序中匹配某些特定網址,從而反射性地獲取所有控制器的列表(最好如果不僅註釋,而且還在xml中指定)?反思性地獲取匹配特定網址的Spring MVC控制器列表

在註釋只的情況下,

@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配置指定控制器怎麼辦?以及如何處理請求路徑參數?

+0

您打算如何使用這些信息? Spring Tool Suite會在IDE中爲您提供這些信息。否則,這裏是我寫的一個實用程序:https://github.com/kdgregory/pathfinder(我將在本週晚些時候合併一些更新) – kdgregory

+0

我正在嘗試爲我的web應用程序實現動態菜單系統。我不需要靜態分析源代碼(我的想法已經做得很好),我需要反思性地分析它的運行時間。 –

+0

您如何計劃在XML配置中查找相關控制器?也許你可以在運行時訪問'org.springframework.web.bind.annotation.support.HandlerMethodResolver.getHandlerMethods()'並處理返回的方法。 –

回答

23

自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 
      } 
     } 
    }  
} 

重要的是,這個bean是在其中控制器被限定的彈簧上下文中定義。

+0

我沒有面對類型爲RequestMappingHandlerMapping的bean。在自動裝配之前誰將會使用這個bean?你能幫我嗎? –

3

您可以嘗試使用ListableBeanFactory接口來檢索所有的bean名稱。的ListableBeanFactory here

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 
     } 
    } 
} 

查看文檔。 該接口提供了一些方法,如getBeansOfType(),getBeanDefinitionCount()等

如果這種方法沒有列出@Controller的豆visit this頁面,看看如何可以做到的。

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所有控制器。這將使您只有一個完全匹配的控制器。顯然不是你想要的。

1

你需要做你的調度的servlet

<bean name="requestHandlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> 
     <property name="useTrailingSlashMatch" value="true"></property> 
    </bean> 

調度servlet將考慮這個映射RequestMappingHandlerMapping一個條目,並在你的應用實例化一個bean RequestMappingHandlerMapping

現在在你的任何控制器/你可以使用的類

@Autowired 
private HandlerMapping mapping; 

它應該可以正常工作。

注意:如果有任何dispatcherservlet(如果是大型應用程序)包含此bean,則需要照顧添加bean,否則將導致noUniqueBean異常並且應用程序無法啓動。