2012-12-24 15 views
12

Jak uzyskać refleksyjnie listę wszystkich kontrolerów (najlepiej, jeśli nie tylko adnotowanych, ale także określonych w xml), pasujących do jakiegoś konkretnego adresu URL w aplikacji Spring MVC?Odzyskiwanie listy kontrolerów Spring MVC pasujących do określonego adresu URL

W przypadku odnotowany tylko,

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

mogą być używane, ale co zrobić w bardziej ogólnym przypadku, gdy kontrolery mogą być określony w spring.xml config? A co zrobić z parametrami ścieżki żądania?

+0

Jak zamierzasz wykorzystać te informacje? Spring Tool Suite da ci te informacje w IDE. W przeciwnym razie, oto narzędzie, które napisałem: https://github.com/kdgregory/pathfinder (będę scalać niektóre aktualizacje później w tym tygodniu) – kdgregory

+0

Próbuję wdrożyć dynamiczny system menu dla mojej aplikacji internetowej.Nie muszę statycznie analizować kodów źródłowych (mój pomysł tak dobrze już działa), muszę go analizować w czasie rzeczywistym. –

+0

Jak planujesz znaleźć odpowiednie kontrolery w konfiguracji XML? Może mógłbyś uzyskać dostęp do 'org.springframework.web.bind.annotation.support.HandlerMethodResolver.getHandlerMethods()' w czasie wykonywania i przetworzyć zwrócone metody. –

Odpowiedz

23

Od wiosny 3.1, istnieje klasa RequestMappingHandlerMapping, dostarcza informacji o mapowaniu (RequestMappingInfo) klas @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 
      } 
     } 
    }  
} 

Ważne jest, że fasola jest określony w kontekście sprężyny, gdy sterownik jest zdefiniowany.

+0

Nie widzę fasoli typu RequestMappingHandlerMapping. Kto zakończy tę fasolę przed autowiringiem. Czy możesz mi w tym pomóc? –

3

Możesz spróbować użyć interfejsu ListableBeanFactory w celu pobrania wszystkich nazw fasoli.

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

Zobacz dokumentację ListableBeanFactory here. Interfejs ten udostępnia kilka metod, takich jak getBeansOfType(), getBeanDefinitionCount() itd

Jeśli takie podejście nie wymienia @Controller Opatrzone komentarzem fasolę visit this stronę, aby zobaczyć, jak to można zrobić.

5

Otrzymujesz mapowanego kontrolera, dzwoniąc pod numer HandlerMapping.getHandler(HTTPServletRequest).getHandler(). Instancja HandlerMapping może zostać nabyta przez IoC. Jeśli nie masz HTTPServletRequest, możesz zbudować swój wniosek za pomocą 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(); 
} 

Niestety, czytam teraz, że chcesz wszystkie kontrolery do adresu URL. To będzie oznaczać tylko jednego dokładnie dopasowanego kontrolera. Oczywiście, nie chcesz tego.

1

trzeba zrobić wpis dla RequestMappingHandlerMapping w dyspozytora serwletu

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

dyspozytor aplet będzie wyglądać w tym mapowaniu i instancji RequestMappingHandlerMapping fasoli w aplikacji

teraz w dowolnym kontrolerze/klasa, której możesz używać:

@Autowired 
private HandlerMapping mapping; 

i powinna działać poprawnie.

Uwaga: musisz zająć się dodaniem komponentu bean, jeśli którykolwiek z twoich dispatcherserlet (w przypadku dużych aplikacji) zawiera ten komponent, spowoduje to wyjątek noUniqueBean, a aplikacja nie zostanie uruchomiona.

Powiązane problemy