注入Servlet、Filter、Listener的两种方式

注入Servlet、Filter、Listener

官方文档

文档:
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-web-applications.embedded-container.servlets-filters-listeners

基本介绍

  1. 考虑到实际开发业务非常复杂和兼容,Spring-Boot 支持将Servlet、Filter、Listener 注入Spring 容器, 成为Spring bean。
  2. 也就是说明Spring-Boot 开放了和原生WEB 组件(Servlet、Filter、Listener)的兼容。

应用实例1-使用注解方式注入

需求:

演示通过注解方式注入Servlet、Filter、Listener

应用实例-实现

1.创建com/nlc/usersys/servlet/Servlet_.java

/**
 * 解读
 * 1. 通过继承 HttpServlet 来开发原生的Servlet
 * 2. @WebServlet 标识将 Servlet_ 对象/bean注入到容器
 * 3. (urlPatterns = {"/servlet01","/servlet02"} ,是映射路径,对servlet配置了url-pattern
 * 4. 提示: 注入的原生的Servlet_ 不会被spring-boot的拦截器拦截
 * 5. 对于开发的原生的Servlet ,需要使用 @ServletComponentScan指定要扫描的原生Servlet包, 才会注入到spring 容器.
 */
@WebServlet(urlPatterns = {"/servlet01","/servlet02"})//映射两个路径
public class Servlet_ extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 	{
        resp.getWriter().write("hello,Servlet_!");
    }
}
  1. 修改com/nlc/usersys/Application.java , 加入@ServletComponentScan
//要求扫描com.nlc.springboot 包/子包下的原生方式注入的Servlet
@ServletComponentScan(basePackages = "com.nlc.springboot")
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext ioc =
                SpringApplication.run(Application.class, args);
        System.out.println("hello");
    }
}
  1. 完成测试, 浏览器http://localhost:8080/servlet01

image-20230818154132148

  1. 创建com/nlc/usersys/servlet/Filter_.java
/**
 * 开发Filter 并注入
 * 解读
 * 1. @WebFilter 表示Filter_是一个过滤器,并注入容器
 * 2. urlPatterns = {"/css/*", "/images/*"} 当请求  /css/目录资源或者 /images/目录下资源的时候,会经过该过滤器
 * 3. 这里是直接放行后,在经过拦截器, 拦截器是否拦截要根据拦截器的拦截规则
 * 4. 过滤器配置的urlPatterns 也会经过Spring-Boot 拦截器
 */
@Slf4j
@WebFilter(urlPatterns = {"/css/*", "/images/*"})
public class Filter_ implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("--Filter_ init--");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("--Filter_ doFilter--");
        //为了方便观察过滤器处理的资源,我们输出一个uri
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        log.info("过滤器处理的uri={}", httpServletRequest.getRequestURI());
        //我们直接放行-实际开发中,根据自己的业务来决定如何处理
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        log.info("--Filter_ destroy--");
    }
}
  1. 创建static/css/t.css, 作为测试文件

image-20230818154757801

  1. 完成测试, 注意观察后台, 浏览器输入: http://localhost:8080/css/t.css

image-20230818154951645

  1. 创建com/nlc/usersys/servlet/Listener_.java
@Slf4j
@WebListener
//@WebListener 表示Listener_是web监听器,并注入容器
public class Listener_ implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {

        //这里可以加入项目初始化的相关业务代码
        log.info("Listener_ contextInitialized 项目初始化OK~");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //这里可以加入相应代码...
        log.info("Listener_ contextDestroyed 项目销毁");
    }
}
  1. 完成测试, 启动项目,观察后台输出

image-20230818161433443

注意:

过滤器配置的urlPatterns 也会经过Spring-Boot 拦截器(根据拦截器的规则),所以为了看到效果,请在拦截器配置放行/css/ **
在servlet 匹配全部是/*, 在Spring-Boot 是/**

image-20230818160954820

应用实例2-使用RegistrationBean 方式注入

需求:

演示使用RegistrationBean 注入Servlet、Filter、Listener

应用实例-实现

  1. 创建com/nlc/usersys/config/RegisterConfig_.java
/**
 * RegisterConfig_: 是一个配置类
 * proxyBeanMethods = true : 默认是单例返回bean[保证每个@Bean 方法被调用多少次返回的组件都是 单实例的, 是代理方式]
 */
@Configuration(proxyBeanMethods = true)
public class RegisterConfig_ {

    //以使用RegistrationBean方式注入
    //注入Servlet
    @Bean
    public ServletRegistrationBean servlet_() {
        //创建原生的Servlet对象
        Servlet_ servlet_ = new Servlet_();
        //把servlet_对象关联到 ServletRegistrationBean 对象
        //"/servlet01", "/servlet02" 就是注入的Servlet的url-pattern
        return new ServletRegistrationBean(servlet_, "/servlet01", "/servlet02");
    }

    //注入filter
    @Bean
    public FilterRegistrationBean filter_() {
        Filter_ filter_ = new Filter_();//创建原生的filter
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter_);
        //设置filter的url-pattern
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/css/*", "/images/*"));
        return filterRegistrationBean;
    }
    //注入Listener
    @Bean
    public ServletListenerRegistrationBean listener_() {
        //创建原生的Listener对象
        Listener_ listener_ = new Listener_();
        return new ServletListenerRegistrationBean(listener_);
    }
}
  1. 去掉相关的注解,再次完成测试

image-20230818162143796

image-20230818162207047

image-20230818162239960

image-20230818162946588

注意事项和细节说明

请求Servlet 时,不会到达DispatherServlet, 因此也不会达到拦截器

原因分析

​ 1.注入的Servlet 存在Spring 容器中

​ 2.DispatherServlet 也存在Spring 容器

image-20230818164239223

说明

1.多个Servlet都能处理到同一层路径,精确优先原则/最长前缀匹配原则。

2.使用当/servlet01时,就会直接匹配到注入的servlet。

3.Tomcat 对Servlet url 匹配的原则, 多个servlet 都能处理到同一层路径, 精确优先原则/最长前缀匹配原则.

4.spring 容器的debug 图.

image-20230818165130914

image-20230818165158330

  1. 在SpringBoot 中, 去调用@Controller 目标方法是按照DispatherServlet 分发匹配的机制。

源码分析

  1. DispatcherServletAutoConfiguration 完成对DispatcherServlet 自动配置
  2. 下面执行流程分析

image-20230819181637978

image-20230819181722753
image-20230819181827155

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨犀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值