Spring Boot非常適合web應用程序開發。可以使用嵌入式Tomcat、Jetty、Undertow或Netty創建自包含的HTTP服務器。大多數web應用程序使用spring-boot-starter-web模塊來快速啟動和運行。您還可以選擇使用spring-boot-starter-webflux模塊來構建反應性web應用程序。
1.Spring Web MVC框架
Spring Web MVC框架(通常簡稱為“Spring MVC”)是一個豐富的“模型-視圖-控制器”Web框架。Spring MVC允許您創建特殊的@Controller或@RestController bean來處理傳入的HTTP請求。控制器中的方法通過使用@RequestMapping注釋映射到HTTP。
以下是示例:
@RestController @RequestMapping(value="/users") public class MyRestController { @RequestMapping(value="/{user}", method=RequestMethod.GET) public User getUser(@PathVariable Long user) { //@PathVariable 將 URL 中占位符參數綁定到控制器處理方法的入參中:URL 中的 {xxx} 占位符可以通過@PathVariable(“xxx“) 綁定到操作方法的入參中。 // ... } @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) { // ... } }
1.1Spring MVC 自動配置
Spring Boot為Spring MVC提供了自動配置,可以很好地與大多數應用程序配合使用。
自動配置在Spring的默認設置之上添加了以下特性:
a.包含contentatingviewresolver和BeanNameViewResolver bean。
b.支持為靜態資源提供服務,包括對webjar的支持(本文檔后面將介紹)。
c.轉換器、GenericConverter和格式化器bean的自動注冊。
d.支持HttpMessageConverters(本文檔后面將介紹)。
e.MessageCodesResolver的自動注冊(本文檔后面將介紹)。
f.靜態index . html的支持。
g.自定義的Favicon支持(稍后將在本文檔中介紹)。
h.自動使用ConfigurableWebBindingInitializer bean(稍后將在本文檔中介紹)。
如果您希望保留Spring Boot MVC功能,並且希望添加額外的MVC配置(攔截器、格式化器、視圖控制器和其他功能),您可以添加自己的WebMvcConfigurer類型的@Configuration類,但是不需要@EnableWebMvc。如果希望提供RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定義實例,可以聲明WebMvcRegistrationsAdapter實例來提供此類組件。
如果你想完全控制Spring MVC,你可以用@EnableWebMvc添加你自己的@Configuration注解。
1.2HttpMessageConverters(http消息轉換器)
Spring MVC使用HttpMessageConverter接口來轉換HTTP請求和響應。合理的默認值是開箱即用的。例如,可以將對象自動轉換為JSON(通過使用Jackson庫)或XML(通過使用Jackson XML擴展(如果可用),或者通過使用JAXB(如果Jackson XML擴展不可用)。默認情況下,字符串是用UTF-8編碼的。
如果需要添加或自定義轉換器,可以使用Spring Boot的HttpMessageConverters類,如下面的清單所示:
import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.context.annotation.*; import org.springframework.http.converter.*; @Configuration(proxyBeanMethods = false) public class MyConfiguration { @Bean public HttpMessageConverters customConverters() { HttpMessageConverter<?> additional = ... //添加額外的轉換器 HttpMessageConverter<?> another = ... return new HttpMessageConverters(additional, another); } }
上下文中出現的任何HttpMessageConverter bean都將添加到轉換器列表中。您還可以以相同的方式覆蓋默認轉換器。
1.3定制JSON的序列化(Serializers)和反序列化(Deserializers)
如果你使用Jackson來序列化和反序列化Json數據,你可能想寫你自己的JsonSerializer和
JsonDeserializer類。定制序列化器通常通過模塊在Jackson中注冊,但是Spring Boot提供了一個替代的@JsonComponent注釋,使得直接注冊Spring bean更加容易。
您可以直接在JsonSerializer、JsonDeserializer或KeyDeserializer實現上使用@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和JsonObjectDeserializer基類,它們在序列化對象時為標准Jackson版本提供了有用的替代方法。有關詳細信息,請參閱Javadoc中的JsonObjectSerializer和JsonObjectDeserializer。
如果我們想靈活一些,可以分別定義序列化類(繼承JsonSerializer<T>或JsonObjectSerializer<T>)和反序列化類(繼承JsonDeSerializer<T>或JsonObjectDeserializer<T>)。然后通過注解@JsonSerialize(using=MyJsonSerializer.class)和@JsonDeSerialize(using=MyJsonDeSerializer.class)來指向屬性。還有其他的屬性上的注解(忽略屬性/日期轉換等等@JsonSerialize @JsonIgnoreProperties @JsonIgnore @JsonFormat等等),可以參考:https://www.cnblogs.com/guxia/p/6598174.html
package org.springframework.boot.jackson; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; /** * Helper base class for {@link JsonSerializer} implementations that serialize objects. * * @param <T> the supported object type * @author Phillip Webb * @since 1.4.0 * @see JsonObjectDeserializer */ public abstract class JsonObjectSerializer<T> extends JsonSerializer<T> { @Override public final void serialize(T value, JsonGenerator jgen, SerializerProvider provider) throws IOException { try { jgen.writeStartObject(); serializeObject(value, jgen, provider); jgen.writeEndObject(); } catch (Exception ex) { if (ex instanceof IOException) { throw (IOException) ex; } throw new JsonMappingException(jgen, "Object serialize error", ex); } } /** * Serialize JSON content into the value type this serializer handles. * @param value the source value * @param jgen the JSON generator * @param provider the serializer provider * @throws IOException on error */ protected abstract void serializeObject(T value, JsonGenerator jgen, SerializerProvider provider) throws IOException; }
1.4.MessageCodesResolver(消息代碼解析器)
Spring MVC有一個從綁定錯誤中生成錯誤代碼的策略:MessageCodesResolver。如果你設置了spring.mvc.message-codes-resolver-format屬性PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE, Spring Boot為您創建了一個(參見DefaultMessageCodesResolver.Format中的枚舉)。
1.5.靜態目錄
默認情況下,Spring Boot從類路徑中名為/static(或/public或/resources或/META-INF/resources)的目錄或ServletContext的根目錄提供靜態內容。它使用來自Spring MVC的ResourceHttpRequestHandler,因此您可以通過添加自己的WebMvcConfigurer並覆蓋addResourceHandlers方法來修改行為。 參考:https://www.cnblogs.com/panxuejun/p/6737031.html
在獨立的web應用程序中,還啟用了容器中的缺省servlet,並充當備用機制,如果Spring決定不處理它,則從ServletContext的根目錄提供內容。大多數情況下,這不會發生(除非修改默認的MVC配置),因為Spring總是可以通過DispatcherServlet處理請求。
默認情況下,資源映射在/**上,但是您可以使用spring.mvc對其進行調優。static-path-pattern財產。例如,將所有資源重新分配到/resources/**可以實現如下:
spring.mvc.static-path-pattern=/resources/**
您還可以使用spring.resources.static-locations自定義靜態資源位置(替換默認的目錄)。the root Servlet上下文路徑“/”也被自動添加為一個位置。
除了前面提到的“標准”靜態資源位置之外,webjar內容還有一個特殊的情況。任何在/webjars/**中有路徑的資源都可以從jar文件中獲得,前提是它們是以webjars格式打包的。
注:如果您的應用程序打包為jar,那么不要使用src/main/webapp目錄。雖然這個目錄是一個通用的標准,但是它只適用於war打包,如果您生成一個jar,那么大多數構建工具都會忽略它。
Spring Boot還支持Spring MVC提供的高級資源處理特性,允許使用例如破壞緩存的靜態資源或為webjar使用版本不可知的url。
注:如果使用JBoss,則需要聲明webjar -locator- JBoss -vfs依賴項,而不是webjar -locator-core。否則,所有webjar都將解析為404。
由於ResourceUrlEncodingFilter是為Thymeleaf和FreeMarker自動配置的,所以在運行時可以在模板中重寫到資源的鏈接。使用jsp時應該手動聲明此篩選器。其他模板引擎目前還不被自動支持,但是可以使用自定義模板宏/助手和ResourceUrlProvider。
當使用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”),而其他資源仍然使用內容策略(<link href=“/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css”/>)
1.6.歡迎頁面
Spring Boot同時支持靜態和模板化歡迎頁面。它首先在配置的靜態內容位置中查找index.html文件。如果沒有找到,則查找索引模板。如果找到其中之一,它將自動用作應用程序的歡迎頁面。
1.7.自定義圖標
與其他靜態資源一樣,Spring Boot在配置的靜態內容位置中查找favicon.ico。如果存在這樣的文件,它將自動用作應用程序的favicon。
1.8.路徑匹配和內容協商
Spring MVC可以通過查看請求路徑並將其與應用程序中定義的映射(例如,@GetMapping對控制器方法的注釋)匹配,從而將傳入的HTTP請求映射到處理程序。
默認情況下,Spring Boot選擇禁用后綴模式匹配,這意味着像“GET /projects/ Spring - Boot.json”這樣的請求,將不會與@GetMapping(“/projects/spring-boot”)映射匹配。這被認為是Spring MVC應用程序的最佳實踐。這個功能主要是有用的在過去的HTTP客戶端沒有發送正確的“接受”請求頭;我們需要確保將正確的內容類型發送到客戶機。如今,內容協商更加可靠。
還有其他方法可以處理不一致發送正確的“Accept”請求頭的HTTP客戶端。我們可以使用一個查詢參數來確保諸如“GET /projects/spring-boot?”format=json"將被映射到@GetMapping("/projects/spring-boot"):
spring.mvc.contentnegotiation.favor-parameter=true # We can change the parameter name, which is "format" by default: # spring.mvc.contentnegotiation.parameter-name=myparam # We can also register additional file extensions/media types with: spring.mvc.contentnegotiation.media-types.markdown=text/markdown
如果您理解這些警告,並且仍然希望您的應用程序使用后綴模式匹配,則需要進行以下配置:
spring.mvc.contentnegotiation.favor-path-extension=true spring.mvc.pathmatch.use-suffix-pattern=true
另外,與其開放所有后綴模式,不如只支持注冊后綴模式更安全:
spring.mvc.contentnegotiation.favor-path-extension=true spring.mvc.pathmatch.use-registered-suffix-pattern=true # You can also register additional file extensions/media types with: # spring.mvc.contentnegotiation.media-types.adoc=text/asciidoc
1.9.ConfigurableWebBindingInitializer(可配置的Web綁定初始化器)
Spring MVC使用WebBindingInitializer來初始化特定請求的WebDataBinder。如果你創建了自己的ConfigurableWebBindingInitializer @Bean, Spring Boot會自動配置Spring MVC來使用它。
1.10.模板引擎
除了REST web服務,您還可以使用Spring MVC來提供動態HTML內容。Spring MVC支持多種模板技術,包括Thymeleaf、FreeMarker和jsp。此外,許多其他模板引擎也包含自己的Spring MVC集成。
BasicErrorController可以用作自定義ErrorController的基類。如果您希望為新的內容類型添加處理程序(默認情況下是專門處理文本/html,並為其他所有內容提供回退),這尤其有用。為此,擴展BasicErrorController,添加一個帶有@RequestMapping(具有produces屬性)的公共方法,並創建一個新類型的bean。
您還可以定義一個帶有@ControllerAdvice注釋的類,以自定義JSON文檔以返回特定的控制器和/或異常類型,如下面的示例所示:
@ControllerAdvice(basePackageClasses = AcmeController.class) public class AcmeControllerAdvice 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); } }
在前面的示例中,如果與AcmeController在同一個包中定義的控制器拋出了YourException,則使用CustomErrorType POJO的JSON表示,而不是ErrorAttributes表示。
自定義錯誤頁面
如果您想要顯示給定狀態碼的自定義HTML錯誤頁,可以將文件添加到/error文件夾。錯誤頁面可以是靜態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.ftlh
+- <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方法和@ControllerAdvice。然后ErrorController獲取任何未處理的異常。
映射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")); } }
注:如果您注冊了一個ErrorPage,其路徑最終由一個過濾器處理(這在一些非spring web框架中很常見,如Jersey和Wicket),那么過濾器必須顯式地注冊為一個錯誤調度程序,如下面的示例所示:
@Bean public FilterRegistrationBean myFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); ... registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); return registration; }
注意,默認的FilterRegistrationBean不包含錯誤調度程序類型。
注意:當部署到servlet容器時,Spring Boot使用其錯誤頁面過濾器將帶有錯誤狀態的請求轉發到適當的錯誤頁面。如果尚未提交響應,則只能將請求轉發到正確的錯誤頁面。默認情況下,WebSphere Application Server 8.0及以后在成功完成servlet的服務方法后提交響應。您應該通過設置com.ibm.ws.webcontainer.invokeFlushAfterService為false來禁用此行為。
1.12.Spring HATEOAS
如果您開發一個利用超媒體的RESTful API, Spring Boot將為Spring HATEOAS提供自動配置,這在大多數應用程序中都能很好地工作。自動配置取代了使用@EnableHypermediaSupport的需要,並注冊了許多bean來簡化構建基於超媒體的應用程序,包括一個LinkDiscoverers(用於客戶端支持)和一個ObjectMapper(配置為正確地將響應封入所需的表示)。ObjectMapper是通過設置各種spring.jackson.*定制的屬性,如果存在屬性,則由Jackson2ObjectMapperBuilder bean創建。
您可以使用@EnableHypermediaSupport來控制Spring HATEOAS的配置。注意,這樣做會禁用前面描述的ObjectMapper定制。
1.13.CORS 支持
跨源資源共享(Cross-origin resource sharing, CORS)是由大多數瀏覽器實現的W3C規范,它允許您以靈活的方式指定授權的跨域請求類型。,而不是使用一些不太安全、不太強大的方法,如IFRAME或JSONP。
從4.2版開始,Spring MVC就支持CORS。在Spring啟動應用程序中使用帶有@CrossOrigin注釋的控制器方法CORS配置不需要任何特定的配置。通過使用定制的addcorsm(CorsRegistry)方法注冊WebMvcConfigurer bean,可以定義全局CORS配置。
@Configuration(proxyBeanMethods = false) public class MyConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } }; } }
2.Spring WebFlux框架
Spring WebFlux是Spring framework 5.0中引入的新的反應性web框架。與Spring MVC不同,它不需要Servlet API,是完全異步和非阻塞的,並且通過反應器項目實現了反應式流規范。
Spring WebFlux有兩種風格:功能性和基於注釋的。基於注解的模式非常接近於Spring MVC模式,如下例所示:
@RestController @RequestMapping("/users") public class MyRestController { @GetMapping("/{user}") public Mono<User> getUser(@PathVariable Long user) { // ... } @GetMapping("/{user}/customers") public Flux<Customer> getUserCustomers(@PathVariable Long user) { // ... } @DeleteMapping("/{user}") public Mono<User> deleteUser(@PathVariable Long user) { // ... } }
“WebFlux.fn”是函數變量,它將路由配置與請求的實際處理分離開來,如下例所示:
@Configuration(proxyBeanMethods = false) public class RoutingConfiguration { @Bean public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) { return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser) .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers) .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser); } } @Component public class UserHandler { public Mono<ServerResponse> getUser(ServerRequest request) { // ... } public Mono<ServerResponse> getUserCustomers(ServerRequest request) { // ... } public Mono<ServerResponse> deleteUser(ServerRequest request) { // ... } }
WebFlux是Spring框架的一部分,詳細的信息可以在它的參考文檔中找到。
您可以定義任意數量的RouterFunction bean來模塊化路由器的定義。如果需要應用優先級,可以對bean進行排序。
首先,將spring-boot-starter-webflux模塊添加到您的應用程序中。
在您的應用程序中同時添加Spring - Boot -starter-web和Spring - Boot -starter- WebFlux模塊會在Spring Boot中自動配置Spring MVC,而不是WebFlux。之所以選擇這種行為,是因為許多Spring開發人員將Spring -boot-starter-webflux添加到他們的Spring MVC應用程序中,以使用反應性的WebClient。您仍然可以通過將選擇的應用程序類型設置為SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)來強制執行您的選擇。
2.1.Spring WebFlux 自動配置
Spring Boot為Spring WebFlux提供了自動配置,可以很好地與大多數應用程序配合使用。
自動配置在Spring的默認設置之上添加了以下特性:
為HttpMessageReader和HttpMessageWriter實例配置編解碼器(稍后將在本文檔中描述)。
支持為靜態資源提供服務,包括對webjar的支持(稍后將在本文中描述)。
如果你想保持Spring啟動WebFlux特性,你想添加額外的WebFlux配置,你可以添加你自己的WebFluxConfigurer類型的@Configuration類,但是不需要@EnableWebFlux.
2.2.帶有httpmessagereader和httpmessagewriter的HTTP編解碼器
Spring WebFlux使用HttpMessageReader和HttpMessageWriter接口來轉換HTTP請求和響應。它們配置了CodecConfigurer,通過查看類路徑中可用的庫來設置合理的默認值。
Spring Boot為編解碼器提供了專用的配置屬性,Spring .codec.*。它還通過使用CodecCustomizer實例應用進一步的定制。例如,spring.jackson。配置鍵應用於傑克遜編解碼器。
如果需要添加或自定義CodecCustomizer,可以創建自定義CodecCustomizer組件,如下所示
import org.springframework.boot.web.codec.CodecCustomizer; @Configuration(proxyBeanMethods = false) public class MyConfiguration { @Bean public CodecCustomizer myCodecCustomizer() { return codecConfigurer -> { // ... }; } }
您還可以利用Boot的定制JSON序列化器和反序列化器。
2.3.靜態目錄
默認情況下,Spring Boot從類路徑中名為/static(或/public或/resources或/META-INF/resources)的目錄提供靜態內容。它使用來自Spring WebFlux的ResourceWebHandler,因此您可以通過添加自己的WebFluxConfigurer並覆蓋addResourceHandlers方法來修改行為。
默認情況下,資源被映射到/**上,但是您可以通過設置spring.webflux來調整它。static-path-pattern財產。例如,將所有資源重新分配到/resources/**可以實現如下:
spring.webflux.static-path-pattern=/resources/**
您還可以使用spring.resources.static-locations自定義靜態資源位置。這樣做將用目錄位置列表替換默認值。如果這樣做,默認的歡迎頁面檢測將切換到您的自定義位置。因此,如果在啟動時在您的任何位置有index.html,它就是應用程序的主頁。
除了前面列出的“標准”靜態資源位置之外,Webjars內容還有一個特殊的情況。任何在/webjars/**中有路徑的資源都可以從jar文件中獲得,前提是它們是以webjars格式打包的。
注:Spring WebFlux應用程序並不嚴格依賴於Servlet API,所以它們不能作為war文件部署,也不使用src/main/webapp目錄。
2.4.模板引擎
除了REST web服務,您還可以使用Spring WebFlux來提供動態HTML內容。Spring WebFlux支持多種模板技術,包括Thymeleaf、FreeMarker和Mustache。
Spring Boot包含對下列模板引擎的自動配置支持:FreeMarker、Thymeleaf和Mustache。
當您使用這些帶有默認配置的模板引擎之一時,您的模板將自動從src/main/resources/templates中獲取。
2.5.異常處理
要更改錯誤處理行為,可以實現ErrorWebExceptionHandler並注冊該類型的bean定義。因為WebExceptionHandler是相當底層的,Spring Boot還提供了一個方便的AbstractErrorWebExceptionHandler,讓您以WebFlux函數的方式處理錯誤,如下面的例子所示:
public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler { // Define constructor here @Override protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { return RouterFunctions .route(aPredicate, aHandler) .andRoute(anotherPredicate, anotherHandler); } }
對於更完整的圖片,您還可以直接子類化DefaultErrorWebExceptionHandler並覆蓋特定的方法。
2.6.Web過濾器
Spring WebFlux提供了一個WebFilter接口,可以實現它來過濾HTTP請求-響應交換。在應用程序上下文中找到的WebFilter bean將自動用於篩選每個交換。
如果過濾器的順序很重要,那么它們可以實現Ordered或使用@Order注釋。Spring Boot自動配置可以為您配置web過濾器。當它這樣做時,將使用下表中顯示的訂單:
Web Filter | Order |
---|---|
|
|
|
|
|
|
3.JAX-RS和Jersey
如果您喜歡REST端點的JAX-RS編程模型,您可以使用其中一個可用的實現來代替Spring MVC。Jersey和Apache CXF的開箱即用效果非常好。CXF要求您在應用程序上下文中將其Servlet或過濾器注冊為@Bean。Jersey有一些本機Spring支持,因此我們還在Spring Boot中為其提供了自動配置支持,以及一個啟動器。
要開始使用Jersey,首先要包含spring-boot-starter-jersey作為一個依賴項,然后需要一個ResourceConfig類型的@Bean來注冊所有的端點,如下例所示:
@Component public class JerseyConfig extends ResourceConfig { public JerseyConfig() { register(Endpoint.class); } }
對於更高級的定制,您還可以注冊實現ResourceConfigCustomizer的任意數量的bean。
所有注冊的端點都應該是帶有HTTP資源注解的@Components (@GET等),如下例所示:
@Component @Path("/hello") public class Endpoint { @GET public String message() { return "Hello"; } }
因為端點是一個Spring @Component,所以它的生命周期是由Spring管理的,您可以使用@Autowired注解注入依賴項,使用@Value注解注入外部配置。默認情況下,Jersey servlet被注冊並映射到/*。您可以通過將@ApplicationPath添加到您的ResourceConfig來更改映射。
默認情況下,Jersey被設置為名為jerseyServletRegistration的@Bean類型的servletregiationbean中的Servlet。默認情況下,servlet是惰性初始化的,但是您可以通過設置spring.jersey.servlet.load-on-startup來定制該行為。您可以通過創建自己的同名bean來禁用或覆蓋該bean。您還可以通過設置spring.jersey來使用過濾器而不是servlet。type=filter(在這種情況下,要替換或覆蓋的@Bean是jerseyFilterRegistration)。過濾器有一個@Order,您可以使用spring. jersei .filter.order來設置它。servlet和過濾器注冊都可以通過使用spring. jersei .init.*指定屬性的映射來獲得初始化參數。
4.嵌入式Servlet容器支持
Spring Boot包含對嵌入式Tomcat、Jetty和Undertow服務器的支持。大多數開發人員使用適當的“Starter”來獲得完全配置的實例。默認情況下,嵌入式服務器監聽端口8080上的HTTP請求。
4.1.Servlet、Filters和listeners
在使用嵌入式servlet容器時,可以通過使用Spring bean或掃描servlet組件,從servlet規范注冊servlet、過濾器和所有偵聽器(如HttpSessionListener)。
將servlet、過濾器和偵聽器注冊為Spring bean
作為Spring bean的任何Servlet、過濾器或Servlet *Listener實例都將注冊到嵌入的容器中。如果您希望引用應用程序中的值,這將特別方便。在配置屬性。
默認情況下,如果上下文只包含一個Servlet,則將其映射到/。對於多個servlet bean, bean名用作路徑前綴。過濾器映射到/*。
如果基於約定的映射不夠靈活,可以使用ServletRegistrationBean、FilterRegistrationBean和ServletListenerRegistrationBean類來完成控制。
通常把過濾器Beans放得亂七八糟是安全的。如果需要特定的順序,您應該使用@Order注釋過濾器,或者讓它實現Ordered。您不能通過使用@Order注釋其bean方法來配置篩選器的順序。如果您不能更改過濾器類以添加@Order或實現Ordered,則必須為過濾器定義FilterRegistrationBean,並使用setOrder(int)方法設置注冊bean的訂單。避免配置按順序讀取請求主體的篩選器。highest_priority,因為它可能與應用程序的字符編碼配置相沖突。如果Servlet篩選器包裝了請求,則應該使用小於或等於OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER的訂單對其進行配置。
注:要查看應用程序中每個過濾器的順序,請為web日志組啟用調試級別日志記錄(logging.level.web=debug)。注冊過濾器的詳細信息,包括它們的順序和URL模式,將在啟動時被記錄下來。
注:注冊過濾器bean時要小心,因為它們在應用程序生命周期中很早就初始化了。如果需要注冊一個與其他bean交互的過濾器,可以考慮使用一個DelegatingFilterProxyRegistrationBean
.
4.2.Servlet上下文初始化
嵌入式servlet容器並不直接執行servlet 3.0+ javax.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口。這是一個有意的設計決策,目的是為了降低在war中運行的第三方庫可能會破壞Spring啟動應用程序的風險。
如果您需要在SpringBoot應用中執行servlet上下文初始化,您應該注冊一個實現org.springframework.boot.web.servlet.ServletContextInitializer接口。單一的onStartup方法提供了對ServletContext的訪問,如果需要,可以輕松地用作現有WebApplicationInitializer的適配器。
掃描servlet、過濾器和偵聽器
在使用嵌入式容器時,可以通過使用@ServletComponentScan啟用@WebServlet、@WebFilter和@WebListener注釋的類的自動注冊。
@ServletComponentScan在獨立容器中沒有作用,而是使用容器的內置發現機制。
4.3ServletWebServerApplicationContext
在底層,Spring Boot使用不同類型的ApplicationContext來支持嵌入式servlet容器。ServletWebServerApplicationContext是一種特殊類型的WebApplicationContext,它通過搜索單個ServletWebServerFactory bean來引導自己。通常,TomcatServletWebServerFactory、JettyServletWebServerFactory或UndertowServletWebServerFactory是自動配置的。
您通常不需要知道這些實現類。大多數應用程序是自動配置的,適當的ApplicationContext和ServletWebServerFactory是代表您創建的。
4.4.定制嵌入的Servlet容器
可以使用Spring環境屬性來配置通用的servlet容器設置。通常,您需要在application.properties文件中定義屬性。
常見的服務器設置包括:
網絡設置:監聽傳入HTTP請求的端口(server.port),接口地址綁定到server.address,等等。
a.會話設置:會話是否持久(server.servlet.session.persistent)、會話超時(server.servlet.session.timeout)、會話數據的位置(server.servlet.session.store-dir)、會話cookie配置(server.servlet.session.cookie.*)。
b.錯誤管理:錯誤頁面的位置(server.error.path)等。
c.SSL
d.HTTP壓縮
Spring Boot盡可能多地嘗試公開公共設置,但這並不總是可能的。對於這些情況,專用名稱空間提供特定於服務器的自定義(參見server.tomcat和server.undertow)。例如,可以使用嵌入式servlet容器的特定功能來配置訪問日志。
編程定制
如果需要以編程方式配置嵌入的servlet容器,可以注冊一個實現WebServerFactoryCustomizer接口的Spring bean。WebServerFactoryCustomizer提供對ConfigurableServletWebServerFactory的訪問,其中包含許多定制setter方法。下面的例子顯示了以編程方式設置端口:
import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.stereotype.Component; @Component public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> { @Override public void customize(ConfigurableServletWebServerFactory server) { server.setPort(9000); } }
注:TomcatServletWebServerFactory、JettyServletWebServerFactory和UndertowServletWebServerFactory是ConfigurableServletWebServerFactory的專用變體,它們分別為Tomcat、Jetty和Undertow提供了額外的定制setter方法。
自定義ConfigurableServletWebServerFactory
如果前面的定制技術太有限,您可以自己注冊TomcatServletWebServerFactory、JettyServletWebServerFactory或UndertowServletWebServerFactory bean。
@Bean public ConfigurableServletWebServerFactory webServerFactory() { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); factory.setPort(9000); factory.setSessionTimeout(10, TimeUnit.MINUTES); factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html")); return factory; }
為許多配置選項提供了setter。如果您需要做一些更奇特的事情,還提供了幾個受保護的方法“掛鈎”。有關詳細信息,請參閱源代碼文檔。
4.5.JSP的局限性
在運行使用嵌入式servlet容器(並打包為可執行歸檔文件)的Spring引導應用程序時,JSP支持存在一些限制。
a.對於Jetty和Tomcat,如果使用war打包,它應該可以工作。一個可執行的war在使用java -jar啟動時可以工作,並且可以部署到任何標准容器中。使用可執行jar時不支持jsp。
b.Undertow不支持jsp。
c.創建自定義error.jsp頁面不會覆蓋默認的錯誤處理視圖。應該使用自定義錯誤頁面。
5.嵌入式反應服務器支持
Spring Boot包含對以下嵌入式反應性web服務器的支持:Reactor Netty、Tomcat、Jetty和Undertow。大多數開發人員使用適當的“Starter”來獲得完全配置的實例。默認情況下,嵌入式服務器監聽端口8080上的HTTP請求。
6.服務器資源配置
在自動配置反應器Netty或Jetty服務器時,Spring Boot將創建特定的bean,為服務器實例提供HTTP資源:ReactorResourceFactory或JettyResourceFactory。
默認情況下,這些資源也將與反應器Netty和Jetty客戶端共享,以獲得最佳性能,具體如下:
a.服務器和客戶機使用相同的技術
b.客戶端實例是使用WebClient構建的。Builder bean由Spring Boot自動配置
開發人員可以通過提供定制的ReactorResourceFactory來覆蓋Jetty和Reactor Netty的資源配置