27.4 Embedded Servlet Container Support

Spring Boot包括对嵌入式TomcatJettyUndertow服务器的支持. 大多数开发人员使用适当的“Starters”获得一个完全配置实例.默认情况下,嵌入式服务器在端口8080上侦听HTTP请求。

Warning

如果您选择在CentOS上使用Tomcat,请注意,在默认情况下,一个临时目录用于存储编译的jsp文件,上传的文件等等.这个目录可能在应用程序运行时被tmpwatch删除,这将导致运行失败. 为了避免这种情况,你可能想要定制tmpwatch配置确保tomcat.*目录不被删除或配置server.tomcat.basedir使得嵌入的Tomcat使用不同的路径.

Servlets,Filters,and Listeners

当使用一个内嵌的servlet容器时,你可以按照servlet规范注册servlet,filters(过滤器)和所有的listeners(监听器)(如HttpSessionListener),可通过使用Spring实例或servlet组件扫描方式.

Registering Servlets,Filters,and Listeners as Spring Beans

任何Servlet,Filter或Servlet *Listener实例都将随嵌入式容器注册为Spring实例.在配置属性时,引用application.properties中的属性值时将显得特别方便.

默认情况下,如果上下文只包含单例Servlet,则将其映射到/.对于多个servlet实例,实例名称将作为路径前缀,过滤器将被映射到/*.

如果基于约定的映射配置不够灵活,您可以使用ServletRegistrationBean,FilterRegistrationBeanServletListenerRegistrationBean类完全定制.

Spring Boot附带了许多自动配置可定义过滤器实例.这里有一些过滤器和各自顺序(低阶值意味着更高的优先级)的例子:  

Servlet Filter Order
OrderedCharacterEncodingFilter Ordered.HIGHEST_PRECEDENCE
WebMvcMetricsFilter Ordered.HIGHEST_PRECEDENCE + 1
ErrorPageFilter Ordered.HIGHEST_PRECEDENCE + 1
HttpTraceFilter Ordered.LOWEST_PRECEDENCE - 10

通常安全的做法是让过滤器Bean实例无序.

如果需要特定的顺序,你应该避免配置一个过滤器使用Ordered.HIGHEST_PRECEDENCE顺序值读取请求主体,因为它可能会不利于您的应用程序字符编码配置. 如果一个Servlet过滤器包装请求,该过滤器配置的顺序值应该小于或等于FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER值.

Servlet Context Initialization

嵌入的servlet容器不会直接执行Servlet 3.0+规范的javax.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口. 这是一个故意设计决策旨在降低第三方库在war中运行可能会破坏Spring Boot应用的风险.

如果需要在Spring Boot应用中执行servlet上下文初始化,您应该注册一个实现org.springframework.boot.web.servlet.ServletContextInitializer接口的Bean实例. 该接口单一的onStartup方法提供对ServletContext的访问,并且,如果需要的话,很容易用作现有WebApplicationInitializer的适配器.

Scanning for Servlets, Filters, and listeners

使用嵌入式容器时,使用@WebServlet,@WebFilter,@WebListener注解的自动注册类可通过@ServletComponentScan扫描启用.

Tip

@ServletComponentScan在一个独立的容器中没有影响,因为容器的内置发现机制默认替代了该使用方式.

The ServletWebServerApplicationContext

根据容器引擎不同,Spring Boot使用不同类型的ApplicationContext支持嵌入servlet容器.ServletWebServerApplicationContext是特殊类型的WebApplicationContext, 它通过搜索单例的ServletWebServerFactory来启动上下文.通常TomcatServletWebServerFactory,JettyServletWebServerFactoryUndertowServletWebServerFactory是自动配置的.

Note

您通常不需要关注这些实现类.大多数应用程序是自动配置的且适当的ApplicationContextServletWebServerFactory将根据你的行为创建.

Customizing Embedded Servlet Containers

可以使用Spring环境属性配置公共servlet容器设置.通常,你会在application.properties文件中定义属性.

常见的服务器设置包括:

  • 网络设置:监听HTTP请求的端口(server.port), 接口地址绑定在server.address等等.
  • Session设置:session是否持久化(server.servlet.session.persistence),session超时(server.servlet.session.timeout),session数据保存路径(server.servlet.session.store-dir)以及session-cookie配置(server.servlet.session.cookie.*).
  • 错误管理:错误页面的路径(server.error.path)等等.
  • SSL.
  • HTTP连接.

Spring Boot尝试尽可能多地暴露这些公共设置,但这并不总是可能的.在某些情况下,专用名称空间提供特定于服务器的定制(见server.tomcatserver.undertow). 例如,访问日志可以为特定功能的嵌入servlet容器配置.

Tip

查看ServerProperties来获取完整参数列表.

Programmatic Customization

如果你需要以编程方式配置嵌入servlet容器,你可以注册一个实现WebServerFactoryCustomizer接口的Spring Bean实例. WebServerFactoryCustomizerConfigurableServletWebServerFactory提供访问接入点,其中包括许多定制的setter方法.Tomcat、Jetty和Undertow都有专用的变量.下面的例子展示了以编程方式设置端口:

  1. import org.springframework.boot.web.server.WebServerFactoryCustomizer;
  2. import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
  6. @Override
  7. public void customize(ConfigurableServletWebServerFactory server) {
  8. server.setPort(9000);
  9. }
  10. }
Customizing ConfigurableServletWebServerFactory Directly

如果上述的配置技术太过于局限,你可以创建你自己的TomcatServletWebServerFactory,JettyServletWebServerFactory,UnderowServletWebServerFactory Bean实例进行注册:

  1. @Bean
  2. public ConfigurableServletWebServerFactory webServerFactory() {
  3. TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
  4. factory.setPort(9000);
  5. factory.setSessionTimeout(10, TimeUnit.MINUTES);
  6. factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
  7. return factory;
  8. }

许多配置选项都提供了setter.大量的保护方法“钩子”也提供,便于你需要作更多奇异的更改.有关详细信息,请参阅源代码文档.

JSP Limitations

当使用嵌入式servlet容器运行Spring Boot应用程序(或打包为一个可执行归档)时,在JSP支持上存在如下限制:

  • 对于Tomcat,如果您使用war包,则应该可以运行.换言之,一个可执行的war包也可部署到一个标准容器(不限于,但包括Tomcat).由于Tomcat的硬编码的文件模式,一个可执行jar不能正常工作.
  • 对于Jetty来说,如果您使用war包,则应该可以运行.换言之,一个可执行的war包也可部署到一个标准容器.
  • Undertow不支持jsp.
  • 创建一个自定义的error.jsp页面不会覆盖错误处理的默认视图.应该使用自定义的错误页面.

可参阅JSP示例,获取如何设置.