• SpringBoot中使用Servlet,Filter,Listener


      项目最近在替换之前陈旧的框架,改用SpringBoot进行重构,初接触,暂时还没有用到Servlet,Filter,Listener的地方,但在之前回顾Servlet的生命周期时,https://www.cnblogs.com/qq931399960/p/10283952.html,想到SpringBoot如何使用原生Servlet,故简单调查了下。

      目前SpringBoot官网GA版本为2.1.2,在官方文档中有对Servlet,Filter,Listener的具体描述

      可以通过将Servlet, Filter,Listener注册为Spring Bean或者使用@ServletComponentScan注解扫描Servlet组件

    一、注册Spring Bean方式使用Servlet,Filter,Listener

    自定义Servlet

    package com.demo.webtest.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    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 {
            System.out.println("do service"); 
        }
    
        @Override
        public void destroy() {
            System.out.println("destory servlet");
        }
    
        @Override
        public void init() throws ServletException {
            System.out.println("init servlet");
        }
    
    }

    自定义Filter

    package com.demo.webtest.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class MyFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
    
            System.out.println("do filter");
            // 使请求继续执行
            chain.doFilter(request, response);
        }
    
        
    }

    自定义Listener(以ServletRequestListener为例)

    package com.demo.webtest.servlet;
    
    import javax.servlet.ServletRequestEvent;
    import javax.servlet.ServletRequestListener;
    
    public class MyRequestListener implements ServletRequestListener {
    
        @Override
        public void requestDestroyed(ServletRequestEvent sre) {
            System.out.println("destory request");
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent sre) {
            System.out.println("init request");
        }
    
    }

    将自定义Servlet,Filter,Listener注册为Spring Bean

    package com.demo.webtest.servletbean;
    
    import javax.servlet.Filter;
    import javax.servlet.Servlet;
    import javax.servlet.ServletRequestListener;
    
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
    import org.springframework.boot.web.servlet.ServletRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;
    
    import com.demo.webtest.servlet.MyFilter;
    import com.demo.webtest.servlet.MyRequestListener;
    import com.demo.webtest.servlet.MyServlet;
    
    @Component
    public class ServletBean {
    
        @Bean
        public ServletRegistrationBean<Servlet> registerServlet() {
            ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<Servlet>(new MyServlet(),
                    "/myservlet");
            // 设置服务启动时初始化该servlet
            servletRegistrationBean.setLoadOnStartup(1);
            return servletRegistrationBean;
        }
    
        @Bean
        public FilterRegistrationBean<Filter> registerFilter() {
            FilterRegistrationBean<Filter> filter = new FilterRegistrationBean<>();
            filter.setFilter(new MyFilter());
            filter.addUrlPatterns("/*");
            return filter;
        }
    
        @Bean
        public ServletListenerRegistrationBean<ServletRequestListener> registerRequestListener() {
            ServletListenerRegistrationBean<ServletRequestListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>();
            servletListenerRegistrationBean.setListener(new MyRequestListener());
            return servletListenerRegistrationBean;
        }
    
    }

    启动服务

      MyServlet设置了loadOnStartup,且其值大于等于0,故服务启动初始化MyServlet,调用了其init方法,页面访问http://localhost:8080/myservlet

    上面日志省略。。。
    2019-01-20 09:29:02.308  WARN 12592 --- [           main] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
    init servlet
    2019-01-20 09:29:02.710  INFO 12592 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2019-01-20 09:29:02.712  INFO 12592 --- [           main] com.demo.webtest.WebtestApplication      : Started WebtestApplication in 3.032 seconds (JVM running for 3.47)
    init request
    do filter
    do service
    destory request

    1、程序启动,初始化Servlet

    2、页面访问Servlet,初始化request

    3、过滤器过滤请求

    4、执行Servlet业务

    5、销毁request

    清空日志,再次访问http://localhost:8080/myservlet

    init request
    do filter
    do service
    destory request

    1、初始化request

    2、过滤器过滤请求

    3、执行Servlet业务

    4、销毁request

    以上测试时使用的为ServletRequestListener ,LIstener还有其他多种形式,比如HttpSessionListener,HttpSessionBindingListener等,但比较重要的有一个ServletContextListener,在springmvc官网的配置文件中,配置了一个ContextLoaderListener,该Listener实现了ServletContextListener接口,并重写了contextInitialized和contextDestroyed方法,在contextInitialized中初始化了WebApplicationContext,服务器启动后,无论servlet是否配置有loadStartup,也不论该值是什么,contextInitialized始终都在servlet的初始化方法之前执行。每个应用只有一个ServletContext

    二、使用注解扫描Servlet组件

    删除或注释掉ServletBean类

    修改自定义Servlet,Filter,Listener,添加Servlet相关组件注解

    自定义Servlet,为与上面区分,将url将映射到/my

    package com.demo.webtest.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet(urlPatterns = "/my", loadOnStartup = 0)
    public class MyServlet extends HttpServlet {
         ...
    }

    自定义Filter

    package com.demo.webtest.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    
    @WebFilter(urlPatterns="/*")
    public class MyFilter implements Filter {
         ...    
    }

    自定义Listener

    package com.demo.webtest.servlet;
    
    import javax.servlet.ServletRequestEvent;
    import javax.servlet.ServletRequestListener;
    import javax.servlet.annotation.WebListener;
    
    @WebListener(value="/*")
    public class MyRequestListener implements ServletRequestListener {
         ...
    }

    启动类添加Servlet组件扫描

    package com.demo.webtest;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    
    @SpringBootApplication
    @ServletComponentScan
    public class WebtestApplication {
    
        public static void main(String[] args) {
            SpringApplication springApplication = new SpringApplication(WebtestApplication.class);
            springApplication.run(args);
        }
    }

    服务启动,也会先进行servlet初始化,页面访问http://localhost:8080/my,日志输出与上述注册Spring Bean方式一致

  • 相关阅读:
    [刷题] 1016 部分A+B (15分)
    [刷题] 1022 D进制的A+B (20分)
    [刷题] 1021 个位数统计 (15分)
    [刷题] 1020 月饼 (25分)
    洛谷&BZOJ [POI2016]Korale
    反演魔术---二项式反演
    毒瘤养成记1: 如何卡hash
    多项式全家桶
    [CQOI]排序机械臂
    后缀自动机感性理解
  • 原文地址:https://www.cnblogs.com/qq931399960/p/10294134.html
Copyright © 2020-2023  润新知