• Spring boot 集成 servlet、监听器、过滤器、拦截器


    Spring boot 集成 servlet

    Web 开发使用 Controller 基本上可以完成大部分需求,但是我们还可能会用到 Servlet、Filter、Listener、Interceptor 等等。
    当使用 Spring-Boot 时,嵌入式 Servlet 容器通过扫描注解的方式注册 Servlet、Filter 和 Servlet 规范的所有监听器(如HttpSessionListener 监听器)。
    Spring boot 的主 Servlet 为 DispatcherServlet,其默认的 url-pattern 为“/”。也许我们在应用中还需要定义更多 的 Servlet,该如何使用SpringBoot 来完成呢?

    在 spring boot 中添加自己的 Servlet 有两种方法,代码注册 Servlet 和注解自动注册(Filter 和 Listener 也是如此)。
    一、代码注册通过 ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得
    控制。也可以通过实现 ServletContextInitializer 接口直接注册。
    二、在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通 过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

    maven依赖

    		<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
    • 1
    • 2
    • 3
    • 4

    方式一、代码注册

    1、创建一个MyServlet2 类,继承HttpServlet ,重写doGet方法

    public class MyServlet2 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("myservlet2正在运行。。。。。。。。");
            resp.setContentType("text/html;charset=utf-8");
            resp.setCharacterEncoding("UTF-8");
            PrintWriter out = resp.getWriter();
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Hello World</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>这是:MyServlet2</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2、在启动类中是实例化ServletRegistrationBean并注入自定义的servlet

    public class ServletApplication {
    
        @Bean
        public ServletRegistrationBean registerMyServlet(){
           return new ServletRegistrationBean(new MyServlet2(),"/myservlet2/*");
        }
    
        public static void main(String[] args) {
            SpringApplication.run(ServletApplication.class,args);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    方式二、注解注册

    1、创建一个MyServlet1 类,继承HttpServlet ,重写doGet方法,并使用@WebServlet注解,填写访问路径,和servlet名称

    @WebServlet(urlPatterns = "/myservlet1/*",name = "myservlet1")
    public class MyServlet1 extends HttpServlet {
    
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
            System.out.println("myservlet1正在运行。。。。。。。。");
            resp.setContentType("text/html;charset=utf-8");
            resp.setCharacterEncoding("UTF-8");
            PrintWriter out = resp.getWriter();
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Hello World</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>这是:MyServlet1</h1>");
            out.println("</body>");
            out.println("</html>");
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2、使用@ServletComponentScan注解自动注册

    @SpringBootApplication
    @ServletComponentScan
    public class ServletApplication {
    
        @Bean
        public ServletRegistrationBean registerMyServlet(){
           return new ServletRegistrationBean(new MyServlet2(),"/myservlet2/*");
        }
    
        public static void main(String[] args) {
            SpringApplication.run(ServletApplication.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Spring boot 集成 Fliter 和 Linstener

    过滤器(Filter)和监听器(Listener)的注册方法和 Servlet 一 样;
    下面将直接使用@WebFilter 和@WebListener 的方式,完成一个Filter 和一个 Listener;使用注解@ServletComponentScan//这个就是扫描相应的 Servlet 包;

    监听器

    import lombok.extern.slf4j.Slf4j;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    @Slf4j
    @WebListener
    public class MyListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            log.info("监听器:listener=====>contextInitialized");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            log.info("监听器:listener=====>contextDestroyed");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    过滤器

    import lombok.extern.slf4j.Slf4j;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    /**
     * 过滤器是要什么,拦截器是不要什么
     */
    @Slf4j
    @WebFilter(urlPatterns = "/*",filterName = "myFilter")
    public class MyFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) {
            log.info("过滤器:filter=====>init");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            log.info("过滤器:filter=====>doFilter");
            log.info("过滤器:filter=====>before filter");
            filterChain.doFilter(servletRequest,servletResponse);
            log.info("过滤器:filter=====>after filter");
        }
    
        @Override
        public void destroy() {
            log.info("过滤器:filter=====>destroy");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    打印结果:
    在这里插入图片描述
    以上可见,监听器执行初始化,之后进行过滤器的初始化,然后执行过滤器的filterChain.doFilter,再执行servlet方法

    Spring boot 拦截器 HandlerInterceptor

    过滤器属于 Servlet 范畴的 API,与 Spring 没什么关系。
    Web 开发中,我们除了使用 Filter 来过滤请 web 求外,还可以使用 Spring 提供的 HandlerInterceptor(拦 截器)。
    HandlerInterceptor 的功能跟过滤器类似,但是提供更精细的的控制能力:在 request 被响应之前request 被响
    应之后
    视图渲染之前以及 request 全部结束之后。我们不能通过拦截器修改 request 内容,但是可以通过抛出
    异常(或者返回 false)来暂停 request 的执行。(意思是:不能修改request内容,但是可以获取request内容后进行判断是否需要停止此次request的执行)
    实现 UserRoleAuthorizationInterceptor 的拦截器有:
    ConversionServiceExposingInterceptor
    CorsInterceptor
    LocaleChangeInterceptor
    PathExposingHandlerInterceptor
    ResourceUrlProviderExposingInterceptor
    ThemeChangeInterceptor
    UriTemplateVariablesHandlerInterceptor
    UserRoleAuthorizationInterceptor
    其中 LocaleChangeInterceptor 和 ThemeChangeInterceptor 比较常用。

    配 置 拦 截 器 也很简单, Spring 为什么提供了 基 础 类 WebMvcConfigurerAdapter ,我们 只 需 要 重 写
    addInterceptors 方法添加注册拦截器。 实现自定义拦截器只需要 3 步:
    1、创建我们自己的拦截器类并实现 HandlerInterceptor 接口。
    2、创建一个 Java 类继承 WebMvcConfigurer,并重写 addInterceptors 方法。实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在 addInterceptors 方法中添加)
    3、创建controller类进行测试

    拦截器

    1、创建一个MyInterceptor自定义类

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    @Slf4j
    @Component
    public class MyInterceptor implements HandlerInterceptor {
    
        /**
         * 在将请求发送到控制器controller之前执行操作,若返回true就进入控制器,若返回false就不进入控制器了。
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("拦截器======》preHandle");
            return true;
        }
    
        /**
         * 用于在将响应发送到客户端之前执行操作,就是控制器执行完之后返回数据时执行。
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("拦截器======》postHandle");
        }
    
        /**
         * 在完成请求和响应后执行操作。
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("拦截器======》afterCompletion");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    2、创建WebMvcConfigurer接口的实现类,重写addInterceptors方法

    import com.lcj.interceptor.MyInterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    import javax.annotation.Resource;
    
    @Configuration
    public class MyWebMvcConfig implements WebMvcConfigurer {
        //引入自定义拦截器对象
        @Resource
        private MyInterceptor myInterceptor;
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //addInterceptor方法向拦截器注册器添加拦截器,addPathPatterns方法添加拦截路径匹配规则("/**"是拦截所有),excludePathPatterns方法是设置白名单,放行哪些路径
            // 对于order的顺序:拦截器的preHandle方法是顺序执行,
            registry.addInterceptor(myInterceptor).addPathPatterns("/**");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3、创建controller类测试

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @Slf4j
    @RestController
    @RequestMapping
    public class MyController {
    
        @RequestMapping("/test")
        public String test(){
    
        log.info("进入=====》test");
    
        return "你成功啦";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试结果:
    在这里插入图片描述
    总结:拦截器和过滤器是不同的,
    1、一个是spring提供的,一个是servlet的范畴的API,
    2、拦截器只能作用于controller层,而过滤器可以过来所有客户端发送过来的请求,包括使用原生servlet方式。
    3、拦截器不能修改request中的内容,但是可以获取request中的参数进行判断时候需要停止此次的request请求,主要是对request请求内容的拦截预判断,过滤器主要是针对请求的路径进行过滤,判断这个请求能否通过

  • 相关阅读:
    springboot+vue+elementui农村村务管理信息系统
    冯诺依曼体系结构、操作系统的认识
    嵌入式linux系统中UART子系统基本实现
    【操作系统-进程】进程的概念
    数据库锁及批量更新死锁处理
    【图像分类】2022-CMT CVPR
    事务隔离级别和MVCC
    HDI激光钻孔和常见问题
    P 进阶_(eval 函数)
    MTK Camera自定义Vendor Tag
  • 原文地址:https://blog.csdn.net/weixin_44740485/article/details/124946163