6、SpringBoot之Web原生组件注入(Servlet、Filter、Listener)

1、使用Servlet API

  • 注入Servlet:
@ServletComponentScan(basePackages = "com.atguigu.admin") :指定原生Servlet组件都放在那里
@WebServlet(urlPatterns = "/my"):效果:直接响应,没有经过Spring的拦截器?
/* 步骤: 使用@WebServlet注解并设置匹配的路径 + @ServletComponentScan扫描Servlet组件 继承HttpServlet类并重写方法 */ @WebServlet(urlPatterns = "/my") public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("666"); } }

@ServletComponentScan(basePackages = "com.atguigu.admin")//扫描Servlet组件 @SpringBootApplication public class Boot05WebAdminApplication {public static void main(String[] args) { SpringApplication.run(Boot05WebAdminApplication.class, args); }}

  • 注入Filter:@WebFilter(urlPatterns={"/css/*","/images/*"})
/* 步骤: 使用@WebFilter注解并设置拦截路径 实现Filter接口并重写方法 */ @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销毁。。。。。。。。。"); } }

  • 注入Listener:@WebListener
/* 步骤: 使用@WebListener注解 实现ServletContextListener接口并实现方法 */ @Slf4j @WebListener public class MyListener implements ServletContextListener { //项目 一运行就执行这个方法 @Override public void contextInitialized(ServletContextEvent sce) { log.info("MyListener监听到项目初始化完成"); }//项目真正被停掉后才执行方法(点idea里的红色小正方形按钮没有效) @Override public void contextDestroyed(ServletContextEvent sce) { log.info("MyListener监听到项目被终止了"); } }

推荐可以这种方式:
2、使用RegistrationBean ServletRegistrationBean, FilterRegistrationBean, ServletListenerRegistrationBean
先把@WebServlet,@WebFilter,@WebListener这三个注解注释掉
@Slf4j //@WebServlet(urlPatterns = "/my") public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { log.info("servlet执行"); resp.getWriter().write("666"); } }

@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销毁。。。。。。。。。"); } }

@Slf4j //@WebListener public class MyListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { log.info("MyListener监听到项目初始化完成"); }@Override public void contextDestroyed(ServletContextEvent sce) { log.info("MyListener监听到项目被终止了"); } }

//将这个类标注为配置类,并保证每个@Bean方法被调用多少次返回的组件都是单实例的 @Configuration(proxyBeanMethods = true) public class MyRegistConfig { @Bean public ServletRegistrationBean myservlet(){ MyServlet myServlet = new MyServlet(); return new ServletRegistrationBean(myServlet,"/my","/my2"); }@Bean public FilterRegistrationBean myFilter(){ MyFilter myFilter = new MyFilter(); //第一种写法 //Servlet拦截的是什么路径,我Filter就拦截什么路径 //return new FilterRegistrationBean(myFilter,myservlet()); /* * 第二种写法 * 可以自己设置拦截什么路径 * */ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter); filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*")); return filterRegistrationBean; }@Bean public ServletListenerRegistrationBean myListener(){ MyListener myListener = new MyListener(); return new ServletListenerRegistrationBean(myListener); }

执行顺序: 执行Listener的contextInitialized容器初始化方法->执行Filter的init初始化方法 ->执行Filter的doFilter方法->执行Servlet的doGet或doPost方法 ->执行Filter的destroy方法->执行Listener的contextDestroyed销毁方法

扩展:DispatchServlet 如何注册进来
  • 容器中自动配置了 DispatcherServlet, 属性绑定到 WebMvcProperties 类;对应的配置文件配置项(prefix前缀)是 spring.mvc。
  • 通过 ServletRegistrationBean 把 DispatcherServlet 配置进来。
  • 默认映射的是 / 路径。所以项目下的所有请求都来到DispatchServlet 处理
以前使用Tomcat做原生的Servlet开发的时候:
多个Servlet都能处理到同一层路径时,使用精确优选原则
A: /my/如果发的是/my/请求,他会先来到A处理 B: /my/1如果发的是/my/1请求,他会先来到b处理

【6、SpringBoot之Web原生组件注入(Servlet、Filter、Listener)】6、SpringBoot之Web原生组件注入(Servlet、Filter、Listener)
文章图片

总结:DispatchServlet 如何注册进来?使用RegistrationBean把DispatchServlet 它映射 / 路径注册进来的。

    推荐阅读