💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 27\. 开发Web应用程序 Spring Boot非常适合Web应用程序开发。 您可以使用嵌入式Tomcat,Jetty或Undertow轻松创建自包含的HTTP服务器。 大多数Web应用程序将使用spring-boot-starter-web模块快速启动和运行。 如果您尚未开发Spring Boot Web应用程序,则可以按照“Hello World!”示例进行操作。 在“[入门](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#getting-started-first-application)”部分中的示例。 ### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#271-spring-web-mvc框架)27.1 “Spring Web MVC框架” Spring Web MVC框架(通常简称为“Spring MVC”)是一个丰富的“模型视图控制器”Web框架。 Spring MVC允许您创建特殊的@Controller或@RestController bean来处理传入的HTTP请求。 您的控制器中的方法将使用@RequestMapping注释映射到HTTP。 以下是@RestController用于提供JSON数据的典型示例: ``` @RestController @RequestMapping(value="/users") public class MyRestController { @RequestMapping(value="/{user}", method=RequestMethod.GET) public User getUser(@PathVariable Long user) { // ... } @RequestMapping(value="/{user}/customers", method=RequestMethod.GET) List<Customer> getUserCustomers(@PathVariable Long user) { // ... } @RequestMapping(value="/{user}", method=RequestMethod.DELETE) public User deleteUser(@PathVariable Long user) { // ... } } ``` Spring MVC是Spring Framework的一部分,详细信息可在[参考文档](http://docs.spring.io/spring/docs/4.3.7.RELEASE/spring-framework-reference/htmlsingle#mvc)中找到。 [Spring.io/guide](https://spring.io/guides)中还有几个指南可供Spring MVC使用。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2711-spring-mvc自动配置)27.1.1 Spring MVC自动配置 Spring Boot提供了适用于大多数应用程序的Spring MVC的自动配置。 自动配置在Spring的默认值之上添加以下功能: * 包含ContentNegotiatingViewResolver和BeanNameViewResolver bean。 * 支持提供静态资源,包括对WebJars的支持(见下文)。 * Converter,GenericConverter,Formatter beans的自动注册。 * 支持HttpMessageConverters(见下文)。 * 自动注册MessageCodesResolver(见下文)。 * 静态index.html支持。 * 自定义Favicon支持(见下文)。 * 自动使用ConfigurableWebBindingInitializer bean(见下文)。 如果要保留Spring Boot MVC功能,并且您只需要添加其他[MVC配置](http://docs.spring.io/spring/docs/4.3.7.RELEASE/spring-framework-reference/htmlsingle#mvc)(interceptors, formatters, view, controllers等),你可以添加自己的WebConfigurerAdapter类型的@Configuration类,但不能使用@EnableWebMvc。 如果要提供自定义的RequestMappingHandlerMapping,RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver实例,您可以声明一个提供此类组件的WebMvcRegistrationsAdapter实例。 如果要完全控制Spring MVC,可以使用@EnableWebMvc添加您自己的@Configuration注释。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2712-httpmessageconverters)27.1.2 HttpMessageConverters Spring MVC使用HttpMessageConverter接口转换HTTP请求和响应。 包括一些开箱即用的合理配置,例如对象可以自动转换为JSON(使用Jackson库)或XML(使用Jackson XML扩展,如果可用,否则使用JAXB)。 字符串默认使用UTF-8进行编码。 如果需要添加或自定义转换器,可以使用Spring Boot HttpMessageConverter类: ``` import org.springframework.boot.autoconfigure.web.HttpMessageConverters; import org.springframework.context.annotation.*; import org.springframework.http.converter.*; @Configuration public class MyConfiguration { @Bean public HttpMessageConverters customConverters() { HttpMessageConverter<?> additional = ... HttpMessageConverter<?> another = ... return new HttpMessageConverters(additional, another); } } ``` 上下文中存在的任何HttpMessageConverter bean将被添加到转换器列表中。 您也可以以这种方式覆盖默认转换器。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2713-自定义json序列化器和反序列化器)27.1.3 自定义JSON序列化器和反序列化器 如果您使用Jackson序列化和反序列化JSON数据,则可能需要编写自己的JsonSerializer和JsonDeserializer类。 自定义序列化程序通常[通过一个模块注册到Jackson](http://wiki.fasterxml.com/JacksonHowToCustomDeserializers),但是Spring Boot提供了一个备用的@JsonComponent注释,可以更容易地直接注册Spring Bean。 您可以直接在JsonSerializer或JsonDeserializer实现中使用@JsonComponent。 您也可以将它用于包含序列化器/解串器的类作为内部类。 例如: ``` import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import org.springframework.boot.jackson.*; @JsonComponent public class Example { public static class Serializer extends JsonSerializer<SomeObject> { // ... } public static class Deserializer extends JsonDeserializer<SomeObject> { // ... } } ``` ApplicationContext中的所有@JsonComponent bean将自动注册到Jackson,并且由于@JsonComponent是使用@Component进行元注解的,所以常规的组件扫描规则适用。 Spring Boot还提供了[JsonObjectSerializer](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot/src/main/java/org/springframework/boot/jackson/JsonObjectSerializer.java)和[JsonObjectDeserializer](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot/src/main/java/org/springframework/boot/jackson/JsonObjectDeserializer.java)基类,它们在序列化对象时为标准的Jackson版本提供了有用的替代方法。 有关详细信息,请参阅Javadoc。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2714-messagecodesresolver)27.1.4 MessageCodesResolver Spring MVC有一个生成错误代码的策略,用于从绑定错误中提取错误消息:MessageCodesResolver。 Spring Boot将为您创建一个错误代码,如果您设置spring.mvc.message-codes-resolver.format属性PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE(请参阅DefaultMessageCodesResolver.Format中的枚举)。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2715-静态内容)27.1.5 静态内容 默认情况下,Spring Boot将从类路径或ServletContext的根目录中的名为/static(或/ public或/resources或/META-INF/resources)的目录提供静态内容。 它使用Spring MVC中的ResourceHttpRequestHandler,因此您可以通过添加自己的WebMvcConfigurerAdapter并覆盖addResourceHandlers方法来修改该行为。 在独立的Web应用程序中,来自容器的默认servlet也被启用,并且作为后备,如果Spring决定不处理它,则从ServletContext的根目录提供内容。 大多数情况下,这不会发生(除非您修改默认的MVC配置),因为Spring将始终能够通过DispatcherServlet处理请求。 默认情况下,资源映射到/** ,但可以通过spring.mvc.static-path-pattern调整。 例如,将所有资源重定位到 /resources/**可以配置如下: ``` spring.mvc.static-path-pattern=/resources/** ``` 您还可以使用spring.resources.static-locations(使用目录位置列表替换默认值)来自定义静态资源位置。 如果这样做,默认欢迎页面检测将切换到您的自定义位置,因此,如果在启动时任何位置都有一个index.html,它将是应用程序的主页。 除了上述“标准”静态资源位置之外,还提供了一个特殊情况,用于[Webjars内容](http://www.webjars.org/)。 任何具有/ webjars / **中路径的资源都将从jar文件中提供,如果它们以Webjars格式打包。 如果您的应用程序将被打包为jar,请不要使用 src/main/webapp 目录。 虽然这个目录是一个通用的标准,但它只适用于war包,如果生成一个jar,它将被大多数构建工具忽略。 Spring Boot还支持Spring MVC提供的高级资源处理功能,允许使用例如缓存静态资源或使用Webjars的版本无关的URL。 要为Webjars使用版本无关的URL,只需添加webjars-locator依赖关系即可。然后声明您的Webjar,以jQuery为例,如“/webjars/jquery/dist/jquery.min.js”,这将产生“/webjars/jquery/xyz/dist/jquery.min.js”,其中xyz是Webjar版本 。 > 如果您使用JBoss,则需要声明webjars-locator-jboss-vfs依赖关系而不是webjars-locator; 否则所有Webjars都将解析为404。 要使用缓存清除功能,以下配置将为所有静态资源配置缓存清除解决方案,从而有效地在URL中添加内容哈希值,例如&lt;link href=“/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css”/&gt;: ``` spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/** ``` > 链接资源在运行时在模板中被重写,这归功于自动配置为Thymeleaf和FreeMarker的ResourceUrlEncodingFilter。 使用JSP时,应手动声明此过滤器。 其他模板引擎现在不会自动支持,但可以使用自定义模板宏/帮助程序和使用[ResourceUrlProvider](http://docs.spring.io/spring/docs/4.3.7.RELEASE/javadoc-api/org/springframework/web/servlet/resource/ResourceUrlProvider.html)。 当使用例如JavaScript模块加载器动态加载资源时,重命名文件不是一个选项。这就是为什么其他策略也得到支持并可以合并的原因。 “固定(fixed)”策略将在URL中添加静态版本字符串,而不更改文件名: ``` spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/** spring.resources.chain.strategy.fixed.enabled=true spring.resources.chain.strategy.fixed.paths=/js/lib/ spring.resources.chain.strategy.fixed.version=v12 ``` 使用此配置,位于“/js/lib/”下的JavaScript模块将使用固定版本策略“/v12/js/lib/mymodule.js”,而其他资源仍将使用内容&lt;link href =“/css/“spring-2a2d595e6ed9a0b24f027f2b63b134d6.css”/&gt;。 有关更多支持的选项,请参阅[ResourceProperties](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java)。 > 此功能已在专门的[博客文章](https://spring.io/blog/2014/07/24/spring-framework-4-1-handling-static-web-resources)和Spring Framework[参考文档](http://docs.spring.io/spring/docs/4.3.7.RELEASE/spring-framework-reference/htmlsingle/#mvc-config-static-resources)中进行了详细描述。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2716-自定义图标)27.1.6 自定义图标 Spring Boot在配置的静态内容位置和类路径的根目录(按顺序)中查找favicon.ico。 如果文件存在,它将被自动用作应用程序的图标。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2717-configurablewebbindinginitializer)27.1.7 ConfigurableWebBindingInitializer Spring MVC使用WebBindingInitializer为特定请求初始化WebDataBinder。 如果您用@Bean创建自己的ConfigurableWebBindingInitializer @Bean,Spring Boot将自动配置Spring MVC以使用它。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2718-模板引擎)27.1.8 模板引擎 除了REST Web服务,您还可以使用Spring MVC来提供动态HTML内容。 Spring MVC支持各种模板技术,包括Thymeleaf,FreeMarker和JSP。 许多其他模板引擎也运行自己的Spring MVC集成。 Spring Boot包括对以下模板引擎的自动配置支持: * [FreeMarker](http://freemarker.org/docs/) * [Groovy](http://docs.groovy-lang.org/docs/next/html/documentation/template-engines.html#_the_markuptemplateengine) * [Thymeleaf](http://www.thymeleaf.org/) * [Mustache](https://mustache.github.io/) > 如果可能,应避免使用JSP,当使用嵌入式servlet容器时,JSP有几个[已知的限制](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#boot-features-jsp-limitations)。 当您使用默认配置的模板引擎之一时,您的模板将从 src/main/resources/templates 自动获取。 > IntelliJ IDEA根据运行应用程序的方式对类路径进行不同的排序。 通过main方法在IDE中运行应用程序将导致使用Maven或Gradle打包的jar运行应用程序时的不同顺序。这可能会导致Spring Boot找不到类路径上的模板。 如果您受此问题的影响,您可以重新排序IDE中的类路径,以放置模块的类和资源。 或者,您可以配置模板前缀以搜索类路径上的每个模板目录:`classpath*:/templates/`。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2719-错误处理)27.1.9 错误处理 默认情况下,Spring Boot提供 /error 映射,以合理的方式处理所有错误,并在servlet容器中注册为“global”错误页面。 对于机器客户端,它将产生JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。 对于浏览器客户端,有一个'whitelabel'错误视图,以HTML格式呈现相同的数据(定制它只需添加一个解析“error”的视图)。 要完全替换默认行为,您可以实现ErrorController并注册该类型的bean定义,或者简单地添加一个类型为ErrorAttributes的bean来使用现有机制,但只是替换内容。 > BasicErrorController可以用作自定义ErrorController的基类。 如果要添加新内容类型的处理程序(默认情况下是专门处理text/html并为其他内容提供备选),这一点尤其有用。 要做到这一点,只需扩展BasicErrorController并添加一个带有@RequestMapping的公共方法,并创建一个新类型的bean。 您还可以定义一个@ControllerAdvice来自定义为特定控制器 and/or 异常类型返回的JSON文档。 ``` @ControllerAdvice(basePackageClasses = FooController.class) public class FooControllerAdvice extends ResponseEntityExceptionHandler { @ExceptionHandler(YourException.class) @ResponseBody ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) { HttpStatus status = getStatus(request); return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status); } private HttpStatus getStatus(HttpServletRequest request) { Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); if (statusCode == null) { return HttpStatus.INTERNAL_SERVER_ERROR; } return HttpStatus.valueOf(statusCode); } } ``` 在上面的示例中,如果由FooController在同一个包中定义的控件抛出了YourException,则将使用CustomerErrorType POJO的json表示法而不是ErrorAttributes表示形式。 ##### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#自定义错误页面)自定义错误页面 如果要显示给定状态代码的自定义HTML错误页面,请将文件添加到/error文件夹。 错误页面可以是静态HTML(即添加在任何静态资源文件夹下)或使用模板构建。 该文件的名称应该是确切的状态代码或一个序列掩码。 例如,要将404映射到静态HTML文件,您的文件夹结构将如下所示: ``` src/ +- main/ +- java/ | + <source code> +- resources/ +- public/ +- error/ | +- 404.html +- <other public assets> ``` 要使用FreeMarker模板映射所有5xx错误,使用如下结构: ``` src/ +- main/ +- java/ | + <source code> +- resources/ +- templates/ +- error/ | +- 5xx.ftl +- <other templates> ``` 对于更复杂的映射,您还可以添加实现ErrorViewResolver接口的bean。 ``` public class MyErrorViewResolver implements ErrorViewResolver { @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { // Use the request or status to optionally return a ModelAndView return ... } } ``` 您还可以使用常规的Spring MVC功能,如[@ExceptionHandler方法](http://docs.spring.io/spring/docs/4.3.7.RELEASE/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers)和[@ControllerAdvice](http://docs.spring.io/spring/docs/4.3.7.RELEASE/spring-framework-reference/htmlsingle/#mvc-ann-controller-advice)。 然后,ErrorController将接收任何未处理的异常。 ##### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#映射spring-mvc之外的错误页面)映射Spring MVC之外的错误页面 对于不使用Spring MVC的应用程序,可以使用ErrorPageRegistrar接口来直接注册ErrorPages。这个抽象直接与底层的嵌入式servlet容器一起工作,即使没有Spring MVC DispatcherServlet也可以工作。 ``` @Bean public ErrorPageRegistrar errorPageRegistrar(){ return new MyErrorPageRegistrar(); } // ... private static class MyErrorPageRegistrar implements ErrorPageRegistrar { @Override public void registerErrorPages(ErrorPageRegistry registry) { registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400")); } } ``` N.B. 如果您注册一个最终由Filter过滤的路径的ErrorPage(例如,像一些非Spring Web框架,例如Jersey和Wicket一样),则必须将Filter显式注册为ERROR dispatcher,例如。 ``` @Bean public FilterRegistrationBean myFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); ... registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); return registration; } ``` (默认的FilterRegistrationBean不包括ERROR dispatcher 类型)。 ##### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#websphere-application-server上的错误处理)WebSphere Application Server上的错误处理 当部署到servlet容器时,Spring Boot会使用其错误页面过滤器将具有错误状态的请求转发到相应的错误页面。 如果响应尚未提交,则该请求只能转发到正确的错误页面。 默认情况下,WebSphere Application Server 8.0及更高版本在成功完成servlet的服务方法后提交响应。 您应该通过将[com.ibm.ws](http://com.ibm.ws).webcontainer.invokeFlushAfterService设置为false来禁用此行为 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#27110-spring-hateoas)27.1.10 Spring HATEOAS 如果您正在开发一种利用超媒体的RESTful API,Spring Boot可以为Spring HATEOAS提供自动配置,适用于大多数应用程序。 自动配置取代了使用@EnableHypermediaSupport的需求,并注册了一些Bean,以便轻松构建基于超媒体的应用程序,包括LinkDiscoverers(用于客户端支持)和配置为将响应正确地组织到所需表示中的ObjectMapper。 ObjectMapper将根据spring.jackson。*属性或Jackson2ObjectMapperBuilder bean(如果存在)进行自定义。 您可以使用@EnableHypermediaSupport控制Spring HATEOAS配置。 请注意,这将禁用上述ObjectMapper定制。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#27111-cors-支持)27.1.11 CORS 支持 [跨原始资源共享](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing/)(CORS)是[大多数浏览器](http://note.youdao.com/)实现的[W3C规范](http://caniuse.com/#feat=cors),允许您以灵活的方式指定什么样的跨域请求被授权,而不是使用一些不太安全和不太强大的方法,如IFRAME或JSONP。 从版本4.2起,Spring MVC支持CORS开箱即用。 在Spring Boot应用程序中的controller方法使用@CrossOrigin注解的CORS配置不需要任何特定的配置。 可以通过使用自定义的addCorsMappings(CorsRegistry)方法注册WebMvcConfigurer bean来定义全局CORS配置: ``` @Configuration public class MyConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } }; } } ``` ### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#272-jax-rs-和-jersey)27.2 JAX-RS 和 Jersey 如果您喜欢JAX-RS编程模型的REST endpoints ,您可以使用一个可用的实现而不是Spring MVC。 如果您刚刚在应用程序上下文中注册了一个@Bean的Servlet或Filter,那么Jersey 1.x和Apache CXF的功能非常出色。 Jersey2.x有一些本地Spring支持,所以我们也提供自动配置支持它在Spring Boot与启动器。 要开始使用Jersey 2.x,只需将spring-boot-starter-jersey作为依赖项,然后您需要一个@Bean类型ResourceConfig,您可以在其中注册所有端点(endpoints): ``` @Component public class JerseyConfig extends ResourceConfig { public JerseyConfig() { register(Endpoint.class); } } ``` > Jersey对扫描可执行档案的包是相当有限的。 例如,当运行可执行的war文件时,它无法扫描在WEB-INF/classes中找到的包中的端点(endpoints)。 为了避免这种限制,不应使`packages`方法,并且应使用上述寄存器方法单独注册(register)端点。 您还可以注册任意数量的ResourceConfigCustomizer的实现bean,以实现更高级的自定义。 所有注册的端点都应为具有HTTP资源注解(@GET等)的@Components,例如。 ``` @Component @Path("/hello") public class Endpoint { @GET public String message() { return "Hello"; } } ``` 由于Endpoint是一个Spring @Component,所以Spring的生命周期由Spring管理,您可以使用@Autowired依赖关系并使用@Value注入外部配置。 默认情况下,Jersey servlet将被注册并映射到/ *。 您可以通过将@ApplicationPath添加到ResourceConfig来更改映射。 默认情况下,Jersey将通过@Bean以名为jerseyServletRegistration的ServletRegistrationBean类型在Servlet进行设置。 默认情况下,servlet将被初始化,但是您可以使用spring.jersey.servlet.load-on-startup进行自定义。您可以通过创建一个自己的同名文件来禁用或覆盖该bean。 您也可以通过设置spring.jersey.type = filter(在这种情况下,@Bean来替换或替换为jerseyFilterRegistration),使用Filter而不是Servlet。 servlet有一个@Order,您可以使用spring.jersey.filter.order设置。 可以使用spring.jersey.init.* 给出Servlet和过滤器注册的init参数,以指定属性的映射。 有一个[Jersey示例](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-samples/spring-boot-sample-jersey),所以你可以看到如何设置。 还有一个[Jersey1.x示例](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-samples/spring-boot-sample-jersey1)。 请注意,在Jersey1.x示例中,spring-boot maven插件已经被配置为打开一些Jersey jar,以便它们可以被JAX-RS实现扫描(因为示例要求它们在Filter注册中进行扫描) 。 如果您的任何JAX-RS资源作为嵌套的jar打包,您可能需要执行相同操作。 ### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#273-嵌入式servlet容器支持)27.3 嵌入式servlet容器支持 Spring Boot包括对嵌入式Tomcat,Jetty和Undertow服务器的支持。 大多数开发人员将简单地使用适当的“Starter”来获取完全配置的实例。 默认情况下,嵌入式服务器将监听端口8080上的HTTP请求。 > 如果您选择在CentOS上使用Tomcat,请注意,默认情况下,临时目录用于存储已编译的JSP,文件上传等。当您的应用程序正在运行导致故障时,该目录可能会被tmpwatch删除。 为了避免这种情况,您可能需要自定义tmpwatch配置,以便tomcat.*目录不被删除,或配置server.tomcat.basedir,以便嵌入式Tomcat使用不同的位置 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2731-servlets-filters-和-listeners)27.3.1 Servlets, Filters 和 listeners 当使用嵌入式servlet容器时,可以使用Spring bean或通过扫描Servlet组件(例如HttpSessionListener)注册Servlet规范中的Servlet,过滤器和所有监听器。 将Servlets,过滤器和监听器注册为Spring bean 任何Servlet,Filter或Servlet Listener 实例都会作为Spring bean注册到嵌入式容器中。 可以非常方便地在配置过程中引用您的application.properties中的值。 默认情况下,如果容器中只包含一个Servlet,它将映射到/。 在多个Servlet bean的情况下,bean名称将作为路径前缀。 过滤器(Filters)将映射到/*,默认过滤所有请求。 如果基于惯例的映射不够灵活,可以使用ServletRegistrationBean,FilterRegistrationBean和ServletListenerRegistrationBean类来完成控制。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2732-servlet-context-初始化)27.3.2 Servlet Context 初始化 嵌入式servlet容器不会直接执行Servlet 3.0+ javax.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口。 这样设计的目的旨在降低在war中运行的第三方库破坏Spring Boot应用程序的风险。 如果您需要在Spring Boot应用程序中执行servlet context 初始化,则应注册一个实现org.springframework.boot.context.embedded.ServletContextInitializer接口的bean。 单个onStartup方法提供对ServletContext的访问,并且如果需要,可以轻松地用作现有WebApplicationInitializer的适配器。 扫描Servlet,过滤器和监听器 使用嵌入式容器时,可以使用@ServletComponentScan启用@WebServlet,@WebFilter和@WebListener注解类的自动注册。 > @ServletComponentScan在独立容器中不起作用,在该容器中将使用容器的内置发现机制。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2733-embeddedwebapplicationcontext)27.3.3 EmbeddedWebApplicationContext 在Spring Boot引导下,将会使用一种新类型的ApplicationContext来支持嵌入式的servlet容器。 EmbeddedWebApplicationContext是一种特殊类型的WebApplicationContext,它通过搜索单个EmbeddedServletContainerFactory bean来引导自身。 通常,TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory将被自动配置。 > 您通常不需要知道这些实现类。 大多数应用程序将被自动配置,并将代表您创建适当的ApplicationContext和EmbeddedServletContainerFactory。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2734-定制嵌入式servlet容器)27.3.4 定制嵌入式servlet容器 可以使用Spring Environment属性配置常见的servlet容器设置。 通常您可以在application.properties文件中定义属性。 常用服务器设置包括: * 网络设置:侦听端口的HTTP请求(server.port),接口地址绑定到server.address等。 * 会话设置:会话是否持久化(server.session.persistence),会话超时(server.session.timeout),会话数据的位置(server.session.store-dir)和session-cookie配置(server.session.cookie.*)。 * 错误管理:错误页面的位置(server.error.path)等 * [SSL](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#howto-configure-ssl) * [HTTP压缩](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#how-to-enable-http-response-compression) Spring Boot尽可能地尝试公开常见设置,但并不总是可能的。 对于这些情况,专用命名空间提供服务器特定的定制(请参阅server.tomcat和server.undertow)。 例如,可以使用嵌入式servlet容器的特定功能来配置[访问日志](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#howto-configure-accesslogs)。 > 有关完整列表,请参阅 [ServerProperties](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java) 类。 用程序定制 如果需要以编程方式配置嵌入式servlet容器,您可以注册一个实现EmbeddedServletContainerCustomizer接口的Spring bean。 EmbeddedServletContainerCustomizer提供对ConfigurableEmbeddedServletContainer的访问,其中包含许多自定义设置方法。 ``` import org.springframework.boot.context.embedded.*; import org.springframework.stereotype.Component; @Component public class CustomizationBean implements EmbeddedServletContainerCustomizer { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.setPort(9000); } } ``` 直接自定义ConfigurableEmbeddedServletContainer 如果上述定制技术有太多限制,您可以自己注册TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory bean。 ``` @Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); factory.setPort(9000); factory.setSessionTimeout(10, TimeUnit.MINUTES); factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html")); return factory; } ``` setter方法提供了许多配置选项。 如果您需要做更多的自定义,还会提供几种保护方法“钩子”。 有关详细信息,请参阅源代码文档。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2735-jsp限制)27.3.5 JSP限制 当运行使用嵌入式servlet容器(并打包为可执行文档)的Spring Boot应用程序时,对JSP支持有一些限制。 * 可以使用Tomcat和war包,即可执行的war将会起作用,并且也可以部署到标准容器(不限于但包括Tomcat)中。 由于Tomcat中的硬编码文件模式,可执行的jar将无法正常工作。 * 可以使用Jetty和war包,即可执行的war将会起作用,并且也可以部署到任何标准的容器,它应该可以工作。 * Undertow不支持JSP。 * 创建自定义的error.jsp页面将不会覆盖默认视图以进行[错误处理](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#boot-features-error-handling),而应使用[自定义错误页面](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#boot-features-error-handling-custom-error-pages)。