Tomcat、Jetty、Undertow 与 Servlet 关系
- Tomcat、Jetty、Undertow 都属于 Servlet 容器
- 一个程序中可以由多个 Servlet 组成,Servlet 必须跑在 Servlet 容器中
- spring-boot-starter-web 默认使用 tomcat 作为 Servlet 容器,利用通过配置切换 Servlet
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!‐‐排除默认tomcat‐‐>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!‐‐引入其他的Servlet容器‐‐>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐jetty</artifactId>
</dependency>
配置 Servlet 容器
1. ServerProperties
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
/**
* Server HTTP port.
*/
private Integer port;
/**
* Network address to which the server should bind.
*/
private InetAddress address;
@NestedConfigurationProperty
private final ErrorProperties error = new ErrorProperties();
/**
* Whether X-Forwarded-* headers should be applied to the HttpRequest.
*/
private Boolean useForwardHeaders;
- 服务器相关所有配置都是以 "server"开头
2. 通过编写 EmbeddedServletContainerCustomizer 配置
@Bean
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
//定制嵌入式的Servlet容器相关的规则
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(8083);
}
};
}
注册 Servlet 三大组件:Servlet、Filter、Listener
- Servlet
//注册三大组件
@Bean public ServletRegistrationBean myServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet");
return registrationBean;
}
- Filter
@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
return registrationBean;
}
- Listener
@Bean
public ServletListenerRegistrationBean myListener() {
ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}
Servlet 自动加载原理
EmbeddedServletContainerAutoConfiguration 自动配置
- 注册容器工厂 TomcatEmbeddedServletContainerFactory
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration @ConditionalOnWebApplication @Import(BeanPostProcessorsRegistrar.class)
//导入BeanPostProcessorsRegistrar:Spring注解版;给容器中导入一些组件
//导入了EmbeddedServletContainerCustomizerBeanPostProcessor:
//后置处理器:bean初始化前后(创建完对象,还没赋值赋值)执行初始化工作
public class EmbeddedServletContainerAutoConfiguration {
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })//判断当前是否引入了Tomcat依赖;
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
//判断当前容器没有用户自己定义EmbeddedServletContainerFactory:嵌入式的 Servlet容器工厂;作用:创建嵌入式的Servlet容器
public static class EmbeddedTomcat {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}
}
}
- EmbeddedServletContainerFactory 创建 Servlet 容器
@Override
public EmbeddedServletContainer getEmbeddedServletContainer( ServletContextInitializer... initializers) {
// 创建一个Tomcat
Tomcat tomcat = new Tomcat();
// 配置Tomcat的基本环节
File baseDir = (this.baseDirectory != null ? this.baseDirectory: createTempDir("tomcat")); tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
// 将配置好的Tomcat传入进去,返回一个EmbeddedServletContainer;并且启动Tomcat服务器
return getTomcatEmbeddedServletContainer(tomcat);
}
- Spring Java 类继承 BeanPostProcessor::postProcessBeforeInitialization 会在Bean被实例化后会被调用
EmbeddedServletContainerCustomizer 实现 BeanPostProcessor,当 Servlet 容器实例化后对 Servlet 初始化设置