Java 如何在SpringMVC中找到所有控制器?

Java 如何在SpringMVC中找到所有控制器?,java,spring,spring-mvc,controller,Java,Spring,Spring Mvc,Controller,为了提供一些运行时生成的API文档,我想迭代所有SpringMVC控制器。所有控制器都使用Spring@Controller注释进行注释。目前我是这样做的: for (final Object bean: this.context.getBeansWithAnnotation( Controller.class).values()) { ...Generate controller documentation for the bean... } 但是这个代码的第一个调用

为了提供一些运行时生成的API文档,我想迭代所有SpringMVC控制器。所有控制器都使用Spring@Controller注释进行注释。目前我是这样做的:

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

但是这个代码的第一个调用是极其缓慢的。我想知道Spring是否迭代类路径中的所有类,而不仅仅是检查定义的bean。当上面的代码运行时,控制器已经加载,日志显示了所有控制器及其请求映射,因此Spring MVC必须已经知道所有控制器,并且必须有一种更快的方法来获取它们的列表。但是如何实现呢?

我在几个月前也遇到过这样的需求,我使用下面的代码片段实现了它

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());
        }
您也可以使用控制器执行类似操作

更新了代码段。删除了不必要的代码,只显示控制器的类名,以便更好地理解。
希望这对你有帮助。干杯。

我喜欢@Japs建议的方法,但也想推荐另一种方法。 这是基于您的观察,即Spring已经扫描了类路径,并且配置了控制器和请求映射方法,该映射在
handlerMapping
组件中维护。如果您使用的是Spring 3.1,那么这个
handlerMapping
组件就是RequestMappingHandlerMapping的一个实例,您可以查询它来查找handlerMappedMethods和相关的控制器,大致如下(如果您使用的是旧版本的Spring,您应该能够使用类似的方法):

我在这个url上提供了更多的细节


这是基于Spring Source的Rossen Stoyanchev在Spring 3.1上的演示。

我想知道,既然您在做
@Controller
(s)的注释,为什么需要这些信息无论如何,他在问题中已经非常清楚地提到,他希望为这些控制器生成文档。我提供的答案也可以实现这一点。很好的代码片段(+1)。但是我觉得这个水平太低了。我的意思是这个扫盲班。我认为
getBeansWithAnnotation()
实现应该在内部使用scanner。也许你是对的。但他想要一个更快的方法来实现这一点。我已经使用了上面的代码片段,对我来说并不慢。这就是我提出这个建议的原因。这个scanner类是由Spring本身提供的,所以据我所知,它的级别并不低。它比getBeansWithAnnotation()工作得更好,速度更快。谢谢这真是太棒了。我会使用/定义@Autowired private-RequestMappingHandlerMapping-handlerMapping-handlerMapping;在类中也可以工作,而不是定义final并将其作为参数传递并在构造函数中初始化,稍后如果您使用自定义的用户创建的对象(显然不是控制器)进行初始化。这可能是个问题
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());
 } 
}