美文网首页
SpringBoot学习笔记(八)SpringBoot_Web开

SpringBoot学习笔记(八)SpringBoot_Web开

作者: 啊_6424 | 来源:发表于2019-03-20 23:20 被阅读0次

    一、配置嵌入式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文件夹里注册这三个组件
    没有这一文件夹我们可以利用ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean完成注册
    对这些组件的相关设置也可以直接在方法里面设置
    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<MyListener> 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<MultipartConfigElement> 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(默认使用)默认使用的原因:

    <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>
    

    四、嵌入式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?

    六、使用外部Servlet容器&JSP支持

    七、外部Servlet容器启动SpringBoot应用原理

    相关文章

      网友评论

          本文标题:SpringBoot学习笔记(八)SpringBoot_Web开

          本文链接:https://www.haomeiwen.com/subject/psxxvqtx.html