SpringBoot對Spring MVC都做了哪些事?(四)
環境:Springboot2.4.12
上一篇:《??SpringBoot對Spring MVC都做了哪些事?(三)??》
JAX-RS(Jersey)支持
?JAX-RS是JAVA EE6 引入的一個新技術。 JAX-RS即Java API for RESTful Web Services,是一個Java 編程語言的應用程序接口,支持按照表述性狀態轉移(REST)架構風格創建Web服務。JAX-RS使用了Java SE5引入的Java注解來簡化Web服務的客戶端和服務端的開發和部署。
Jersey RESTful Web Services框架是開源,生產質量的,用于在Java中開發RESTful Web服務的框架,該框架提供對JAX-RS API的支持,并充當JAX-RS( JSR 311和JSR 339 )參考實現。 Jersey框架不只是JAX-RS參考實現。 Jersey提供了自己的API,使用其他功能和實用程序擴展了JAX-RS工具包,以進一步簡化RESTful服務和客戶端開發。
如果你更喜歡REST端點的JAX-RS編程模型,那么可以使用一種可用的實現,而不是Spring MVC。Jersey和Apache CXF在開箱即用的情況下工作得很好。CXF要求您在應用程序上下文中將其Servlet或過濾器注冊為@Bean。Jersey有一些本機的Spring支持,因此我們也在 Spring Boot中為其提供自動配置支持,以及一個啟動器。簡單說就是如果你就是想使用JAX-RS那么SpringBoot為其提供了自動配置的支持。
在SpringBoot中使用的流程:
- 引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jersey</artifactId></dependency>
- 自定義Endpoint
"/hello")public class Endpoint { public String message() { return "Hello"; }}(
- 資源配置
class JerseyConfig extends ResourceConfig { public JerseyConfig() { register(Endpoint.class); }}
以上配置完成后就可以通過http://xxx:port/hello進行方法接口了。
因為端點是一個Spring @Component,它的生命周期由Spring管理,你可以使用@Autowired注釋來注入依賴項,并使用@Value注釋來注入外部配置。默認情況下,Jersey servlet被注冊并映射到/*。您可以通過添加@ApplicationPath到你的ResourceConfig來更改映射。
// 訪問路徑:http://xxx:port/api-a/hello@ApplicationPath("/api-a")public class JerseyConfig extends ResourceConfig { public JerseyConfig() { register(Endpoint.class); }}
Servlets, Filters, Listeners
當使用嵌入式servlet容器時,你可以通過使用Spring bean或掃描Servlet組件,從Servlet規范中注冊Servlet、Filter和所有Listener(例如HttpSessionListener)。
任何作為Spring bean的Servlet、Filter或Servlet *Listener實例都被注冊到嵌入式容器中。如果您想要引用應用程序中的值,這將非常方便。在配置屬性。
默認情況下,如果上下文只包含單個Servlet,它將被映射到/。在有多個servlet bean的情況下,bean名被用作路徑前綴。過濾器映射到/*。這什么意思,看如下示例:
class ServletConfig { public Servlet1 s1() { return new Servlet1() ; } // 如果不定義訪問路徑,那么會將該bean的名稱作為訪問路徑 // http://xxx:port/servlet1 @Bean public ServletRegistrationBean<Servlet1> servlet1(Servlet1 s1) { ServletRegistrationBean<Servlet1> servlet = new ServletRegistrationBean<>(s1) ; return servlet ; }}
可以通過:ServletRegistrationBean, FilterRegistrationBean, andServletListenerRegistrationBean分別注冊Servlet,Filter,Listener。
通常情況下,讓Filter bean處于無序狀態是安全的。如果需要特定的順序,您應該用@Order注釋Filter,或者讓它實現Ordered。您不能通過使用@Order注釋其bean方法來配置Filter的順序。如果您不能更改Filter類以添加@Order或實現Ordered,那么您必須為Filter定義一個FilterRegistrationBean,并使用setOrder(int)方法設置注冊bean的訂單。避免配置在Ordered讀取請求體的Filter。HIGHEST_PRECEDENCE,因為它可能違反應用程序的字符編碼配置。如果Servlet篩選器包裝了請求,那么它應該配置一個小于或等于OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER的順序。
Servlet上下文初始化
嵌入的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的適配器。
當使用嵌入式容器時,可以通過使用@ServletComponentScan來啟用帶有@WebServlet、@WebFilter和@WebListener注釋的類的自動注冊。
ServletWebServerApplicationContext
在內部,Spring Boot使用了不同類型的ApplicationContext來嵌入servlet容器支持。ServletWebServerApplicationContext是一種特殊類型的WebApplicationContext,它通過搜索單個ServletWebServerFactory bean來引導自己。通常TomcatServletWebServerFactory,JettyServletWebServerFactory,或UndertowServletWebServerFactory已經被自動配置。
如果需要通過編程方式配置嵌入式servlet容器,可以注冊一個實現WebServerFactoryCustomizer接口的Spring bean。WebServerFactoryCustomizer提供對ConfigurableServletWebServerFactory的訪問,其中包括許多定制setter方法。下面的例子顯示了如何通過編程方式設置端口:
class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> { public void customize(ConfigurableServletWebServerFactory server) { server.setPort(9000); }}
TomcatServletWebServerFactory,JettyServletWebServerFactory和UndertowServletWebServerFactory是ConfigurableServletWebServerFactory的專用變體,分別為Tomcat, Jetty和Undertow提供額外的定制setter方法。下面的例子展示了如何自定義TomcatServletWebServerFactory來提供對tomcat特定配置選項的訪問:
class TomcatServerCustomizerExample implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { public void customize(TomcatServletWebServerFactory server) { server.addConnectorCustomizers((tomcatConnector) -> { tomcatConnector.setAsyncTimeout(Duration.ofSeconds(20).toMillis()); tomcatConnector.setURIEncoding("UTF-8"); tomcatConnector.setPort(8088); }); }}