Spring - 学习 - 嵌入式 Servlet 容器

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 自动配置

  1. 注册容器工厂 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();
            }
        }
}

  1. 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);
    }
  1. Spring Java 类继承 BeanPostProcessor::postProcessBeforeInitialization 会在Bean被实例化后会被调用
    EmbeddedServletContainerCustomizer 实现 BeanPostProcessor,当 Servlet 容器实例化后对 Servlet 初始化设置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值