SpringBoot的嵌入式Servlet容器自动配置原理1

    科技2022-08-16  118

    目录

     

    前言

    一、如何定制和修改Servlet容器的相关配置

    二、注册Servlet三大组件【Servlet、Filter、Listener】

    1、先来看ServletRegistrationBean

    2、接下来是FilterRegistrationBean

    3、最后一个是ServletListenerRegistrationBean

    三、举例

    四、知识扩充


    前言

    我们知道SpringBoot默认使用Tomcat作为嵌入式的Servlet容器

    我们可以从pom文件中右键查看依赖图:

    既然是嵌入式的容器了,于是不禁思考:我们该如何定制和修改Servlet容器的相关参数呢?

    一、如何定制和修改Servlet容器的相关配置

    1、修改和server有关的配置(ServerProperties【也是EmbeddedServletContainerCustomizer】)例如:

    server.port=8081 server.context-path=/crud

     

    我们进入到ServerProperties类中,它来绑定和服务器相关的配置,可以看到还能配置tomcat:

    于是我们可以大致总结:通用的Servlet容器设置为server.xxx,那么Tomcat的设置则为server.tomcat.xxx

     

    查看tomcat:

    2、编写一个EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器。它也可以用来修改Servlet容器的配置。

    2.x版源码中的类已经没有EmbeddedServletContainerCustomizer:

    1.x版本是WebServerFactoryCustomizer类,这个类是个接口:

    需要注意的是,在此处是规定了一个泛型,否则不能设置服务器属性,对比如下图,下方的方法才是正确的。另外我们需要注意,要想让这个方法起作用,就需要在方法头部加上@Bean,这样springboot才知道它的存在

    编写完成后我们启动项目看看,发现端口号的确是配置后的8081:

     

    二、注册Servlet三大组件【Servlet、Filter、Listener】

    由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,没有web.xml文件。而非是创建一个标准的web应用的目录结构,如果是的话,那应该在src下的main里面有个webapp,其下有META-INF,其下还有web.xml,把所有插件注册到web.xml。

    如果不是注册到web.xml里面,那是否有其他办法呢?于是引入注册组件这一解决工具:

    注册三大组件用以下方式

    ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean

    1、先来看ServletRegistrationBean

    我们先创建一个ServletRegistrationBean类型的方法,

    我们可以点进ServletRegistrationBean看看,发现里面有一个有参构造器,里面的参数,一个是我们可以直接传一个servlet,另一个则是映射路径

    运行程序,打开浏览器,输入url,http://localhost:8080/crud/myServlet

    2、接下来是FilterRegistrationBean

    其实实现模式一样:先创建一个实现了Filter(注意是javax.servlet)的类MyFilter,我们在doFilter()方法中除了做一些输出,还需要放行

     

     

    感兴趣可以点进FilterRegistrationBean看看,

    而后就是编写FilterRegistrationBean类型的方法。这个方法里面我们设置对哪些servlet进行拦截过滤,并且对映射地址做出设置

    如果我们在这里把路径写错了,少了斜杠

    则会报错:

    项目成功启动后,我们访问http://localhost:8080/crud/myServlet

    此时查看控制台,输出了我们起初设置的内容

     

    3、最后一个是ServletListenerRegistrationBean

    先实现一个实现了ServletContextListener接口的类。里面有两个方法,一个是初始化,一个是销毁

    之后就是编写一个ServletListenerRegistrationBean类型的方法

    注意这里是个泛型:

    之后我们运行程序,注意看,在控制台输出了如下信息:

    之后我们再点击exit。注意!如下是正常的程序关闭按钮

    于是我们发现控制台又有输出信息:

     

    不过切记哟,不可以点以下这两个,(尽管我们基本上都会习惯性点这两个)这样的操作相当于直接拔电源了!

        

     

    三、举例

    最好的一个例子就是SpringBoot在帮我们自动SpringMVC的时候,自动的注册SpringMVC的前端控制器:DispatcherServlet。

    我们进入DispatcherServletAutoConfiguration看看:

    这里我们看到getPath()方法:

    点进去看看

    这个path是什么呢?看下图:

    即默认拦截所有路径的,包括静态资源,但是不拦截jsp请求

    而以往我们也接触过/*,它是会拦截jsp请求的。同时我们也知道,可以通过server.servletPath来修改SpringMVC前端控制器默认拦截的请求路径

     

    四、知识扩充

    使用其他servlet容器

    Jetty:长连接

    Undertow :不支持JSP

    我们可以在代码中看看ConfigurableWebServerFactory的继承树,ctrl+h

    替换为其他嵌入式Servlet容器

    默认支持:

    Tomcat(默认使用)

    <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>    引入web模块默认就是使用嵌入式的Tomcat作为Servlet容器; </dependency>

    jetty

    <!-- 引入web模块 --> <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>    <exclusions>       <exclusion>          <artifactId>spring-boot-starter-tomcat</artifactId>          <groupId>org.springframework.boot</groupId>       </exclusion>    </exclusions> </dependency> <!--引入其他的Servlet容器--> <dependency>    <artifactId>spring-boot-starter-jetty</artifactId>    <groupId>org.springframework.boot</groupId> </dependency>

    Undertow

    <!-- 引入web模块 --> <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>    <exclusions>       <exclusion>          <artifactId>spring-boot-starter-tomcat</artifactId>          <groupId>org.springframework.boot</groupId>       </exclusion>    </exclusions> </dependency> <!--引入其他的Servlet容器--> <dependency>    <artifactId>spring-boot-starter-undertow</artifactId>    <groupId>org.springframework.boot</groupId> </dependency>
    Processed: 0.016, SQL: 9