Как найти все контроллеры в Spring MVC?

Чтобы предоставить некоторую документацию по API, созданную во время выполнения, я хочу перебрать все контроллеры Spring MVC. Все контроллеры снабжены аннотацией Spring @Controller. В настоящее время я делаю это так:

for (final Object bean: this.context.getBeansWithAnnotation(
        Controller.class).values())
{
    ...Generate controller documentation for the bean...
}

Но первый вызов этого кода ОЧЕНЬ медленный. Интересно, перебирает ли Spring классы ВСЕ в пути к классам, а не просто проверяет определенные bean-компоненты. Контроллеры уже загружены, когда приведенный выше код запущен, журнал отображает их все с их сопоставлениями запросов, поэтому Spring MVC должен уже знать их все, и должен быть более быстрый способ получить их список. Но как?


person kayahr    schedule 05.06.2012    source источник
comment
Интересно, зачем вам эта информация, если вы все равно делаете аннотацию @Controller (s)   -  person ant    schedule 05.06.2012
comment
Он очень четко упомянул в вопросе, что хочет создать документацию для этих контроллеров.   -  person Japan Trivedi    schedule 05.06.2012
comment
Ответ, который я предоставил здесь можно и этого добиться.   -  person Jose Quijada    schedule 28.11.2020


Ответы (2)


Я также столкнулся с таким требованием за несколько месяцев, и я выполнил его, используя следующий фрагмент кода.

ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(Controller.class));
        for (BeanDefinition beanDefinition : scanner.findCandidateComponents("com.xxx.yyy.controllers")){
            System.out.println(beanDefinition.getBeanClassName());
        }

Вы также можете сделать что-то подобное с вашими контроллерами.

Обновил фрагмент кода. Удален ненужный код и просто отображено имя класса контроллеров для лучшего понимания. Надеюсь, это поможет вам. Ваше здоровье.

person Japan Trivedi    schedule 05.06.2012
comment
Хороший фрагмент (+1). Но я думаю, что это слишком низкий уровень. Я имею в виду, что этот сканирует классы. Я считаю, что реализация getBeansWithAnnotation() должна использовать сканер внутри. - person AlexR; 05.06.2012
comment
Возможно, вы правы. Но он хочет более быстрый способ добиться этого. Ответ: Я использовал приведенный выше фрагмент кода, и для меня это не медленно. Вот почему я предложил это. И этот класс сканера предоставляется самой Spring, поэтому, по моему мнению, это не низкий уровень. - person Japan Trivedi; 05.06.2012
comment
Отлично работает и НАМНОГО быстрее, чем getBeansWithAnnotation(). Спасибо! - person kayahr; 05.06.2012

Мне нравится подход, предложенный @Japs, но я также хотел бы порекомендовать альтернативный подход. Это основано на вашем наблюдении, что путь к классам уже был просканирован Spring, а контроллеры и методы сопоставления запросов настроены, это сопоставление поддерживается в компоненте handlerMapping. Если вы используете Spring 3.1, этот компонент handlerMapping является экземпляром RequestMappingHandlerMapping, который вы можете запросить, чтобы найти handlerMappedMethods и связанные с ним контроллеры, в следующих строках (если вы используете более старую версию Spring, вы должны иметь возможность использовать аналогичный подход):

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@Controller
public class EndpointDocController {
 private final RequestMappingHandlerMapping handlerMapping;
 
 @Autowired
 public EndpointDocController(RequestMappingHandlerMapping handlerMapping) {
  this.handlerMapping = handlerMapping;
 }
  
 @RequestMapping(value="/endpointdoc", method=RequestMethod.GET)
 public void show(Model model) {
  model.addAttribute("handlerMethods", this.handlerMapping.getHandlerMethods());
 } 
}

Я предоставил более подробную информацию по этому адресу http://biju-allandsundry.blogspot.com/2012/03/endpoint-documentation-controller-for.html

Это основано на презентации Spring 3.1 Россена Стоянчева из Spring Source.

person Biju Kunjummen    schedule 05.06.2012
comment
это довольно круто. я бы пошел с этим - person Sean Patrick Floyd; 05.06.2012
comment
Использование/определение @Autowired private RequestMappingHandlerMapping handlerMapping; В классе также работает вместо определения final и необходимости передавать его в качестве аргумента и инициализировать в конструкторе. Позже, если вы используете пользовательский объект, созданный пользователем (очевидно, не контроллер) для инициализации. Это может быть проблемой - person Merv; 04.04.2018