【问题标题】:How to find all controllers in Spring MVC?如何在 Spring MVC 中查找所有控制器?
【发布时间】:2012-06-09 12:21:33
【问题描述】:

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

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

但此代码的第一次调用非常慢。我想知道 Spring 是否会遍历类路径中的 ALL 类,而不仅仅是检查定义的 bean。运行上述代码时,控制器已经加载,日志显示所有控制器及其请求映射,因此 Spring MVC 必须已经知道它们,并且必须有更快的方法来获取它们的列表。但是怎么做呢?

【问题讨论】:

  • 我想知道你为什么需要这些信息,因为你正在做 @Controller (s) 的注释
  • 他在问题中非常清楚地提到他想为那些控制器生成文档。
  • 我提供的答案here也可以做到这一点。

标签: java spring spring-mvc controller


【解决方案1】:

我喜欢@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 Source 的 Rossen Stoyanchev 关于 Spring 3.1 的演示。

【讨论】:

  • 这太棒了。我会选择这个
  • 使用/定义 @Autowired 私有 RequestMappingHandlerMapping handlerMapping;在类中也可以工作,而不是定义 final 并且必须将其作为参数传递并在构造函数中对其进行初始化,稍后如果您使用自定义用户制作的对象(显然不是控制器)进行初始化。这可能是个问题
【解决方案2】:

几个月前我也遇到过这样的要求,我使用以下代码 sn-p 实现了它。

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());
        }

你也可以用你的控制器做这样的事情。

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

【讨论】:

  • 良好的 sn-p (+1)。但我认为它的水平太低了。我的意思是这个扫描。我相信getBeansWithAnnotation() 的实现应该在里面使用扫描仪。
  • 也许你是对的。但他想要一种更快的方法来实现这一目标。 Ans 我已经使用了上面的代码 sn-p 并且对我来说并不慢。这就是我建议这个的原因。而且这个扫描器类是由 Spring 本身提供的,所以在我看来它不是低级的。
  • 工作得很好,而且比 getBeansWithAnnotation() 快得多。谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-04-25
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 2011-11-10
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
相关资源
最近更新 更多