一、配置嵌入式Servlet容器
SpringBoot默认使用的是嵌入式的Servlet容器(Tomcat)
使用嵌入式的Servlet容器,那我们可以考虑几个问题
- 1.如何定制和修改Servlet容器的相关配置(使用外置的话,可以从配置文件里改,内置的该从哪改呢?)
答:
1).在配置文件(application.properties / application.yaml)里修改与server相关的配置(ServerProperties),这种属于通用的Servlet容器设置
server.port=8081 修改端口号
2).编写一个定制器
参考:https://blog.csdn.net/l1336037686/article/details/81047312 - 2.SpringBoot能不能支持其他的Servlet容器
二、注册Servlet三大组件(Servlet、Filter、Listener)
SpringBoto创建的项目默认是以jar的方式启动默认的Tomcat,这不是一个标准的web项目
因为标准web项目会有一个webapp文件夹,在webapp/WEB-INF/pom.xml文件夹里注册这三个组件
没有这一文件夹我们可以利用ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean完成注册
对这些组件的相关设置也可以直接在方法里面设置
MyServerConfig .java
@Configuration
public class MyServerConfig {
@Bean //把他加在容器中,一定要做
public ServletRegistrationBean myServlet(){
//注册三大组件
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet");
return servletRegistrationBean;
}
}
MyServlet.java
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello!MyServlet");
}
}
其他两个类似
MyServerConfig.java
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
return registrationBean;
}
MyServerConfig.java
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean registrationBean = new ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}
SpringBoot帮我们自动SpringMVC的时候,自动的注册SpringMVC的前端控制器;
DispatcherServletAutoConfiguration中:
protected static class DispatcherServletRegistrationConfiguration {
private final WebMvcProperties webMvcProperties;
private final MultipartConfigElement multipartConfig;
public DispatcherServletRegistrationConfiguration(WebMvcProperties webMvcProperties, ObjectProvider multipartConfigProvider) {
this.webMvcProperties = webMvcProperties;
this.multipartConfig = (MultipartConfigElement)multipartConfigProvider.getIfAvailable();
}
@Bean(
name = {"dispatcherServletRegistration"}
)
@ConditionalOnBean(
value = {DispatcherServlet.class},
name = {"dispatcherServlet"}
)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet) {
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, this.webMvcProperties.getServlet().getPath());
//默认拦截: / 所有请求;包静态资源,但是不拦截jsp请求; /*会拦截jsp
//可以通过server.servletPath来修改SpringMVC前端控制器默认拦截的请求路径
registration.setName("dispatcherServlet");
registration.setLoadOnStartup(this.webMvcProperties.getServlet().getLoadOnStartup());
if (this.multipartConfig != null) {
registration.setMultipartConfig(this.multipartConfig);
}
return registration;
}
}
三、切换其他嵌入式Servlet容器(Jetty、Undertow)
Jetty,适合用于开发长连接的应用,如聊天
Undertow,不支持jsp,但是它的并发性能非常好
Tomcat(默认使用)默认使用的原因:
org.springframework.boot
spring-boot-starter-web
引入web模块默认就是使用嵌入式的Tomcat作为Servlet容器;
改为Jetty
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-tomcat
org.springframework.boot
spring-boot-starter-jetty
org.springframework.boot
改为Undertow
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-tomcat
org.springframework.boot
spring-boot-starter-undertow
org.springframework.boot
四、嵌入式Servlet容器自动配置原理
为何通过修改dependency就能修改Servlet容器?--- 探索源码
根据引入的依赖,去判断使用哪个Servlet容器
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties({ServerProperties.class})
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
public EmbeddedWebServerFactoryCustomizerAutoConfiguration() {
}
@Configuration
@ConditionalOnClass({Undertow.class, SslClientAuthMode.class})
public static class UndertowWebServerFactoryCustomizerConfiguration {
public UndertowWebServerFactoryCustomizerConfiguration() {
}
@Bean
public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
}
}
@Configuration
@ConditionalOnClass({Server.class, Loader.class, WebAppContext.class})
public static class JettyWebServerFactoryCustomizerConfiguration {
public JettyWebServerFactoryCustomizerConfiguration() {
}
@Bean
public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
return new JettyWebServerFactoryCustomizer(environment, serverProperties);
}
}
@Configuration
@ConditionalOnClass({Tomcat.class, UpgradeProtocol.class})//判断当前是否引入Tomcat依赖
public static class TomcatWebServerFactoryCustomizerConfiguration {
public TomcatWebServerFactoryCustomizerConfiguration() {
}
@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}
...
}
那么,我们修改容器的配置是怎么生效的?
修改容器有两种方式:
- 1)在配置文件中修改相关属性,它与serverProperties绑定
-
2)通过定制器ConfigurableServletWebServerFactory
定义一些属性的设置方法
public interface ConfigurableWebServerFactory extends WebServerFactory, ErrorPageRegistry {
void setPort(int port);
void setAddress(InetAddress address);
void setErrorPages(Set extends ErrorPage> errorPages);
void setSsl(Ssl ssl);
void setSslStoreProvider(SslStoreProvider sslStoreProvider);
void setHttp2(Http2 http2);
void setCompression(Compression compression);
void setServerHeader(String serverHeader);
}
五、嵌入式Servlet容器启动原理
什么时候创建嵌入式的Servlet容器工厂?
什么时候获取嵌入式的Servlet容器并启动Tomcat?