• SpringBoot2.0(过滤器,监听器,拦截器)


    一,过滤器

    1.1,自定义Filter

    1. 使用Servlet3.0的注解进行配置
    2. 启动类里面增加 @ServletComponentScan ,进行扫描
    3. 新建一个Filter类,implements Filter ,并实现对应接口
    4. @WebFilter 标记一个类为Filter,被spring进行扫描
    5. urlPatterns:拦截规则,支持正则
    6. 控制chain.doFilter的方法的调用,来实现是否通过放行,
      不放行的话,web应用resp.sendRedirect(“/index.html”)
      场景:权限控制,用户登录(非前端后端分离场景)等

    1.2,启动类代码

    package com.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    
    @SpringBootApplication
    @ServletComponentScan  // 扫描select的注解
    public class DemoApplication {
    
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class,args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    1.2,创建filter类和LoginFilter包

    在这里插入图片描述

    1.2.1,编写loginFilter类 过滤器代码

    package com.demo.filter;
    
    import org.springframework.core.Ordered;
    import org.springframework.core.annotation.Order;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    
    @WebFilter(urlPatterns = {"/*"})
    @Order(Ordered.HIGHEST_PRECEDENCE)    // 设置过滤器的排序,int类型
    public class LoginFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("初始化过滤器");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("doFilter");
    //        servletResponse.setCharacterEncoding("UTF-8");
            // 设置响应的字符编码为UTF-8
            servletResponse.setCharacterEncoding("UTF-8");
            // 设置响应的内容类型为text/plain;charset=UTF-8
            servletResponse.setContentType("text/plain;charset=UTF-8");
            // 登录过滤器 有两种情况,需要放行
            // 1,登录请求要放行
            // 2. 不是登录请求,但是有登录token
    
            String uri = ((HttpServletRequest)servletRequest).getRequestURI();
            System.out.println(uri);
            if (uri.startsWith("/login/")){  // 判断是否以 /login/ 开头
                // 放行
                filterChain.doFilter(servletRequest,servletResponse);
            }else {
                // 从请求中获取token
                String token = ((HttpServletRequest)servletRequest).getParameter("token");
                if (token != null && !"".equals(token)){
                    // 其实还需要进行解码,现在是只要有token就放行
                    filterChain.doFilter(servletRequest,servletResponse);
                }else {
                    PrintWriter pw = servletResponse.getWriter();
                    pw.flush();
                    pw.write("请先登录");
                    pw.close();
                }
            }
    
    
        }
    
        @Override
        public void destroy() {
            System.out.println("销毁过滤器");
        }
    }
    
    • 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
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    1.2.2,创建二个Controller类

    看看是不是以login开头的放行

    第一个controller类为LoginController

    package com.demo.controller;
    
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    
    @RestController
    @RequestMapping("/login")
    public class LoginController {
    
        @RequestMapping("/doLogin")
        public Object doLogin(){
            return "登录接口";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    第二个controller类为HelloController

    看看不是以login会不会过滤

    package com.demo.controller;
    
    import com.demo.bean.Person;
    import com.demo.config.BootProperties;
    import com.demo.config.SysProperties;
    import com.demo.util.ResultUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.core.env.Environment;
    import org.springframework.util.ClassUtils;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.xml.crypto.Data;
    import java.io.File;
    import java.io.IOException;
    import java.util.Date;
    import java.util.UUID;
    
    
    @RestController
    public class HelloController {
    
        @Autowired
        private BootProperties bootProperties;
    
        @RequestMapping("/test6")
        public Object test6(){
            return sysProperties.getParam1()+sysProperties.getParam2();
        }
    }
    // 整个之前的代码试试
    
    • 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

    在这里插入图片描述
    证明过滤了,试试登录后

    在这里插入图片描述

    二,监听器

    2.1,自定义监听器

    1. 自定义Listenter(常用监听器
      servletContextListenter,
      httpSessionListenter,
      HTTPSessionAttributeListenter,
      servletRequestListenter)

    2.2,创建listenter包和MyListenter类

    在这里插入图片描述

    2.2.1,编写MyListenter类 监听器代码

    package com.demo.listener;
    
    import javax.servlet.ServletRequestEvent;
    import javax.servlet.ServletRequestListener;
    import javax.servlet.annotation.WebListener;
    
    
    @WebListener
    public class MyListener implements ServletRequestListener {
        @Override
        public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
            System.out.println("请求被销毁");
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent servletRequestEvent) {
            System.out.println("请求被初始化创建");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    三,拦截器

    3.1,创建自定义拦截器配置类

    @Configuration
    继承WebMvcConfigurationAdapter(SpringBoot2.X之前旧版本)
    SpringBoot2.X新版本配置拦截器 implements WebMvcConfigurer

    3.2,创建配置包config和配置类MyWebMvcConfigurer

    在这里插入图片描述

    package com.demo.config;
    
    import com.demo.interceptor.Logininterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration  // 添加了Configuration的类,我们称之为配置类
    public class MyWebMvcConfigurer implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new Logininterceptor()).addPathPatterns("/login/**");
            WebMvcConfigurer.super.addInterceptors(registry);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.3,创建拦截器包interceptor和Logininterceptor类

    在这里插入图片描述

    Logininterceptor类代码

    package com.demo.interceptor;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    public class Logininterceptor implements HandlerInterceptor {
        // 调用Controller某个方法之前,判断是否要不要处理
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            return false; // false是拦截, true是不拦截
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("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

    在这里插入图片描述

    四,按顺序进行拦截,先注册,先被拦截

    拦截器不生效的常见问题

    1. 是否有加@Configuration
    2. 拦截器是否有路径问题 ** 和 *
    3. 拦截器最后路径一定要 " /** " ,如果是目录的话则是 /*/

    Filter
    是基于函数回调 doFilter(),而lnterceptor则是基于AOP思想
    Filter在只在Servlet前后起作用,而lnterceptor够深入到方法前后,异常抛出前后等

    依赖于Servlet容器即web应用中,而lnterceptor不依赖于Servlet容器所以可以运行在多种环境。

    在接口调用的声明周期里,lnterceptor可以被多次调用,而Filter只能在容器中初始化调用一次。

    Filter和lnterceptor的执行顺序
    过滤前 --> 拦截前 --> action(handler) --> 执行 --> 拦截后 --> 过滤后

  • 相关阅读:
    mac无法读取移动硬盘怎么办?mac怎么使用ntfs硬盘
    线程同步(解决线程安全问题)
    <6>【深度学习 × PyTorch】概率论知识大汇总 | 实现模拟骰子的概率图像 | 互斥事件、随机变量 | 联合概率、条件概率、贝叶斯定理 | 附:Markdown 不等于符号、无穷符号
    机器学习入门(1)
    当mybatisPlus与tk.mybatis遇到更新
    ArcGIS加载的各类地图怎么去除服务署名水印
    17.重定向(redirect)和请求转发(forward)
    解决mac运行scrcpy报错库找不到的问题
    第二章:25+ Python 数据操作教程(第十六节PYTHON 列表理解:通过示例学习)持续更新中
    《钻石王牌》:热血青春·棒球1号位
  • 原文地址:https://blog.csdn.net/H20031011/article/details/132823284