springboot 关于servlet容器配置修改及原理 组件注册 容器切换 使用外部tomcat流程及原理

1.嵌入式Servlet容器配置修改

    • 1.通过全局配置文件修改
      • 可以通过server.xxx 来进行web服务配置, 没有带服务器名称的则是通用配置
      • 通过带了具体的服务器名称则是单独对该服务器进行设置,比如 server.tomcat.xxx 就是专门针对tomcat的配置
    • 2.通过WebServerFactoryCustomizer的Bean修改
      • 修改server.xxx 配置的相关内容
      • 会跟配置文件形成互补
@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        factory.setContextPath("/abc");
    }
}

2.注册servlet三大组件 servlet   listener   filter

方式一:servlet3.0规范提供的注解方式注册  需要使用  @ServletComponentScan 扫描才能生效

    •   @WebServlet
    •   @WebListener
    •   @WebFilter
复制代码
@WebServlet(name="HelloServlet",urlPatterns = "/HelloServlet")
//@WebFilter 使用方式相似
//@WebListener 使用方式相似
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.println("hello world 3333");
    }
}
复制代码
@SpringBootApplication
@ServletComponentScan
public class SpringbootservletApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootservletApplication.class, args);
    }
}

方式二:springboot 方式

public class BeanServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.println("hello BeanServlet!");
    }
}
复制代码
@Configuration
public class SpringBootServlet {
    /**
     * SpringBoot提供的注册:
     *         ServletRegistrationBean
     *         FilterRegistrationBean
     *         ServletListenerRegistrationBean
     */
    @Bean
    public ServletRegistrationBean myServlet(){
        ServletRegistrationBean<Servlet> servletServletRegistrationBean = new ServletRegistrationBean<>();
        servletServletRegistrationBean.setServlet(new BeanServlet());
        servletServletRegistrationBean.setName("BeanServlet");
        servletServletRegistrationBean.addUrlMappings("/BeanServlet");
        return servletServletRegistrationBean;
    }
}
复制代码

 

3.切换其他嵌入式Servlet容器

  • Spring Boot包含对嵌入式TomcatJettyUndertow服务器的支持
  • tomcat(默认)
  • Jetty(socket)
  • Undertow(响应式)
  • 复制代码
    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <!--1.排除tomcat 要想使用jetty 或者 undertow 必须排除tomcat-->
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-tomcat</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
            <!--2.依赖jetty
            <dependency>
                <artifactId>spring-boot-starter-jetty</artifactId>
                <groupId>org.springframework.boot</groupId>
            </dependency>-->
    
            <!--3.依赖undertow
            <dependency>
                <artifactId>spring-boot-starter-undertow</artifactId>
                <groupId>org.springframework.boot</groupId>
            </dependency>-->
    复制代码

 

4.使用外部Servlet容器

1. 下载tomcat服务 springboot3.1.2 对应 Tomcat10.1.11  版本不对应会有问题,访问不了

2.设置当前maven项目的打包方式

<!--打包方式 默认是jar-->
<packaging>war</packaging>

3.让tomcat相关的依赖不参与打包部署 ,因为外置tomcat服务器已经有这些jar包  

<!--让它不参与打包部署-->
<dependency>
  <artifactId>spring-boot-starter-tomcat</artifactId>
  <groupId>org.springframework.boot</groupId>
  <scope>provided</scope>
</dependency>

 

4. 为了让它支持springboot需要加上一下代码: 才能启动springboot应用

public class TomcatStartSpringBoot extends SpringBootServletInitializer{

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(SpringbootservletApplication.class);
    }
}

 

5.servlet容器的自动配置原理、

1.servlet自动配置类, 依赖任何一个servlet容器 ServletRequest 都会生效,若是没有任何servlet容器,ServletRequest 就会是红色的失效状态

如 排除了tomcat 容器 还没有加载其他容器,ServletRequest 就是红色的

复制代码
@AutoConfiguration(after = SslAutoConfiguration.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
//配置任何servlet容器,该类都会生效,否则不生效
@ConditionalOnClass(ServletRequest.class)
//指定类型未servlet类型,若ServletRequest生效,一定是servlet类型
@ConditionalOnWebApplication(type = Type.SERVLET)
//配置属性类 启用类所有server.xxx的配置信息绑定到 ServerProperties类上面
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
    //一下是导入对应的依赖包才能生效的内嵌容器 ServletWebServerFactoryConfiguration.EmbeddedTomcat.
class, ServletWebServerFactoryConfiguration.EmbeddedJetty.class, ServletWebServerFactoryConfiguration.EmbeddedUndertow.class }) public class ServletWebServerFactoryAutoConfiguration { }
复制代码

 

ServletWebServerFactoryCustomizer 和 TomcatServletWebServerFactoryCustomizer 都是实现了
customize 接口进行的属性注入,那么谁调用的 customize()接口呢 。就是
BeanPostProcessorsRegistrar 并注册了
WebServerFactoryCustomizerBeanPostProcessor

 

 

 6.外部tomcat启动springboot原理

tomcat不会主动去启动springboot应用 ,, 所以tomcat启动的时候肯定调用了SpringBootServletInitializer 的 SpringApplicationBuilder , 就会启动springboot

 符合servlet 的spi规范

 

大概: 当servlet容器启动时候 就会去META-INF/services 文件夹中找到javax.servlet.ServletContainerInitializer, 这个文件里面肯定绑定一个ServletContainerInitializer. 当servlet容器启动时候就会去该文件中找到ServletContainerInitializer的实现类,从而创建它的实例调用onstartUp

 

  • @HandlesTypes(WebApplicationInitializer.class).
    • @HandlesTypes传入的类为ServletContainerInitializer感兴趣的
    • 容器会自动在classpath中找到 WebApplicationInitializer 会传入到onStartup方法的webAppInitializerClasses中
    • Set<class<?>> webAppInitializerClasses 这里面也包括之前定义的TomcatStartSpringBoot

复制代码
/**
 * 外部tomcat启动 springboot 的配置文件
 */
public class TomcatStartSpringBoot extends SpringBootServletInitializer{
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(SpringbootservletApplication.class);
    }
}
复制代码

代码关系图

 

SpringServletContainerInitializer的 onStartup 方法调用
SpringBootServletInitializer的 onStartup 方法

 

 

 最后是通过run 方法启动的

 注意springmvc 里在web.xml配置的 DispatcherServlet 和 ContextLoaderListener 也是

 

 例如:ContextLoaderListener 

 

   

posted @   花开如梦  阅读(723)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2020-08-04 连redis 连不上怎么办!
点击右上角即可分享
微信分享提示