Spring Boot中getServletNames()返回空,如何获取实际Servlet列表?
获取Spring Boot中实际的Servlet列表
在Spring Boot 2.7.7中,直接注入的ServletContext是Spring封装后的实例,其getServletNames()方法会返回空枚举。可以通过以下几种方式获取真实的Servlet列表:
方法一:通过WebApplicationContext获取ServletRegistrationBean
Spring Boot中注册的Servlet(包括自定义和内置的DispatcherServlet)都会以ServletRegistrationBean的形式存在于容器中,直接获取这类Bean即可得到Servlet信息:
@RestController public class HomeController { @Autowired private WebApplicationContext webApplicationContext; @GetMapping int home() { // 获取所有ServletRegistrationBean实例 Map<String, ServletRegistrationBean> servletRegBeans = webApplicationContext.getBeansOfType(ServletRegistrationBean.class); servletRegBeans.values().forEach(bean -> { System.out.println("Servlet名称:" + bean.getServletName()); System.out.println("映射路径:" + bean.getUrlMappings()); System.out.println("Servlet类:" + bean.getServlet().getClass().getName()); }); return 200; } }
方法二:通过当前请求获取原生ServletContext
当前请求对应的ServletContext是嵌入式容器(如Tomcat)提供的真实实例,能直接获取到所有注册的Servlet:
@RestController public class HomeController { @GetMapping int home() { // 获取当前请求的ServletContext ServletContext realServletContext = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .getRequest() .getServletContext(); Enumeration<String> servletNames = realServletContext.getServletNames(); while (servletNames.hasMoreElements()) { String servletName = servletNames.nextElement(); System.out.println("Servlet名称:" + servletName); // 获取对应的Servlet对象 Servlet servlet = realServletContext.getServlet(servletName); System.out.println("Servlet类:" + servlet.getClass().getName()); } return 200; } }
方法三:依赖具体嵌入式容器API(以Tomcat为例)
如果你的应用固定使用Tomcat作为嵌入式容器,可以直接通过Tomcat的API获取Servlet信息,这种方式能拿到容器层面的所有Servlet:
@RestController public class HomeController { @Autowired private TomcatServletWebServerFactory tomcatServerFactory; @GetMapping int home() { Server tomcatServer = tomcatServerFactory.getTomcat().getServer(); // 遍历Tomcat的服务、连接器、主机、上下文,获取所有Servlet for (Service service : tomcatServer.findServices()) { for (Connector connector : service.findConnectors()) { Engine engine = (Engine) connector.getContainer(); for (Host host : engine.findChildren()) { for (Context context : host.findChildren()) { Map<String, ? extends Servlet> servlets = context.getServlets(); servlets.forEach((name, servlet) -> { System.out.println("Servlet名称:" + name); System.out.println("Servlet类:" + servlet.getClass().getName()); }); } } } } return 200; } }
注意事项
- 方法一通用性最强,不依赖具体容器,推荐优先使用;
- 方法二需要在请求上下文环境中执行,无法在启动时直接调用;
- 方法三仅适用于Tomcat容器,更换容器时需要修改代码。
内容的提问来源于stack exchange,提问作者JJJohn
相关产品推荐
相关产品推荐

