Web开发

【九】Web原生组件注入(Servlet、Filter、Listener)

一、使用Servlet API

@ServletComponentScan(basePackages = “com.achang.admin.servlet”):指定原生Servlet组件都放在哪里;在SpringBoot主程序上写

@WebServlet(urlPatterns = “/myServlet”):效果:直接响应没有经过Spring的拦截器?

@WebFilter(urlPatterns={"/css/*","/images/*"})

@WebListener

@ServletComponentScan(basePackages = "com.achang.admin.servlet")
@SpringBootApplication
public class Boot05AdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(Boot05AdminApplication.class, args);
    }
    
}
@Slf4j
@WebListener
public class MyServletContextListenner implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        log.info("ServletContextListener初始化完成");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        log.info("ServletContextListener销毁完成");
    }
}
@Slf4j
@WebFilter(urlPatterns = {"/css/*","/images/*"})
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("MyFilter初始化");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("MyFilter工作");
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
        log.info("MyFilter销毁");
    }
    
}
@WebServlet(urlPatterns = "/myServlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().write("8888");
    }
    
}

扩展:DispatchServlet 如何注册进来

  • 容器中自动配置了 DispatcherServlet 属性绑定到 WebMvcProperties;对应的配置文件配置项是 spring.mvc。
  • 通过 ServletRegistrationBean< DispatcherServlet > 把 DispatcherServlet 配置进来。
  • 默认映射的是 / 路径。

Tomcat-Servlet

多个Servlet都能处理到同一层路径,精确优选原则

A: /my/

B: /my/1【会来到这】

image.png

二、使用RegistrationBean方式

ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean


@Configuration
public class MyRegistConfig {
    @Bean
    public ServletRegistrationBean myServlet(){
        MyServlet myServlet = new MyServlet();
        return new ServletRegistrationBean(myServlet,"/myServlet");
    }
    @Bean
    public FilterRegistrationBean myFilter(){

        MyFilter myFilter = new MyFilter();
//        return new FilterRegistrationBean(myFilter,myServlet());
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
        return filterRegistrationBean;
    }
    @Bean
    public ServletListenerRegistrationBean myListener(){
        MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();
        return new ServletListenerRegistrationBean(mySwervletContextListener);
    }
}

.

【十】嵌入式Servlet容器

一、切换嵌入式Servlet容器

  • 默认支持的webServer

    • Tomcat, Jetty, or Undertow
    • ServletWebServerApplicationContext 容器启动寻找ServletWebServerFactory 并引导创建服务器
  • 切换服务器

image.png

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • 原理

    • SpringBoot应用启动发现当前是Web应用。web场景包-导入tomcat
    • web应用会创建一个web版的ioc容器 ServletWebServerApplicationContext
    • ServletWebServerApplicationContext 启动的时候寻找 ServletWebServerFactory(Servlet 的web服务器工厂---> Servlet 的web服务器)
    • SpringBoot底层默认有很多的WebServer工厂;TomcatServletWebServerFactory, JettyServletWebServerFactory, or UndertowServletWebServerFactory
    • 底层直接会有一个自动配置类。ServletWebServerFactoryAutoConfiguration
    • ServletWebServerFactoryAutoConfiguration导入了ServletWebServerFactoryConfiguration(配置类)
    • ServletWebServerFactoryConfiguration 配置类 根据动态判断系统中到底导入了那个Web服务器的包。(默认是web-starter导入tomcat包),容器中就有 TomcatServletWebServerFactory
    • TomcatServletWebServerFactory 创建出Tomcat服务器并启动;TomcatWebServer 的构造器拥有初始化方法initialize---this.tomcat.start();
    • 内嵌服务器,就是手动把启动服务器的代码调用(tomcat核心jar包存在)

二、定制Servlet容器方式

1、实现 WebServerFactoryCustomizer< ConfigurableServletWebServerFactory >

作用:把配置件的值和ServletWebServerFactory 进行绑定

xxxxxCustomize:定制化器,可以改变xxxx的默认规则

@Component
//类名随机叫,xxxxxCustomize
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
    @Override
    public void customize(ConfigurableServletWebServerFactory server) {
        server.setPort(9000);//修改相关属性
    }

}

2、修改applicationContext配置文件 server.xxx【推荐方式】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B7eJJcNm-1609915106436)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210106140039369.png)]

3、直接自定义 ConfigurableServletWebServerFactory

在配置类下配置自定义,并放入ioc容器

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.setPort(9000);
    factory.setSessionTimeout(10, TimeUnit.MINUTES);
    factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
    return factory;
}

.

【十一】、定制化原理

一、定制化的常见方式 【要求掌握】

  • 修改配置文件;—【推荐
  • **xxxxxCustomizer;**实现 WebServerFactoryCustomizer< ConfigurableServletWebServerFactory >
  • 编写自定义的配置类 xxxConfiguration;+ @Bean替换、增加容器中默认组件;视图解析器
  • 编写一个配置类,实现 WebMvcConfigurer + @Bean给容器中再扩展一些组件—【推荐
@Configuration
public class AdminWebConfig implements WebMvcConfigurer
  • @EnableWebMvc + WebMvcConfigurer —— @Bean 可以全面接管SpringMVC,所有规则全部自己重新配置; 实现定制和扩展功能

原理【@EnableWebMvc + WebMvcConfigurer】

1、WebMvcAutoConfiguration 默认的SpringMVC的自动配置功能类。静态资源、欢迎页…

2、一旦使用 @EnableWebMvc 。会 @Import(DelegatingWebMvcConfiguration.class)

3、DelegatingWebMvcConfiguration 的 作用,只保证SpringMVC最基本的使用

  • 把所有系统中的 WebMvcConfigurer 拿过来。所有功能的定制都是这些 WebMvcConfigurer 合起来一起生效
  • 自动配置了一些非常底层的组件。RequestMappingHandlerMapping、这些组件依赖的组件都是从容器中获取
  • public classDelegatingWebMvcConfiguration extends WebMvcConfigurationSupport

4、WebMvcAutoConfiguration 里面的配置要能生效 必须 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

5、@EnableWebMvc 里有 DelegatingWebMvcConfiguration,而DelegatingWebMvcConfiguration 继承WebMvcConfigurationSupport ,因此导致了 WebMvcAutoConfiguration 没有生效

二、原理分析套路

引入场景starter - xxxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties – 绑定配置文件项

感谢尚硅谷!!!

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐