05、SpringBoot —— 过滤器、拦截器和监听器

SpringBoot入门05day —— 过滤器、拦截器和监听器

  • 概念

    • 开发SpringBoot项目的时候,我们常常需要对HTTP请求进行拦截和处理,以实现诸如身份验证、授权、日志记录等功能,为此,SpringBoot提供了过滤器和拦截器这两个工具
    • 我们还需要使用SpringBoot中的监听器监听特定的时间,以实现统计网站访问量、记录用户访问路径、系统启动时加载初始化信息等功能
  • 过滤器

    • 概念

      • 用于对数据进行过滤处理,包括请求和响应
      • 一个类实现了Filter接口,就能够实现自定义的过滤器
    • Filter接口待实现的方法

      • init()
        • 这是一个默认方法,实现类中可以不被重写,过滤器初始化时会调用
      • doFilter()
        • 过滤器的核心方法,在这个方法中实现过滤业务,这是一个抽象方法,必须被重写
        • 方法的FilterChain类型的参数表示过滤链对象
        • 一个项目常常配置了多个过滤器,在前一个过滤器对请求完成过滤处理后,通过调用过滤链对象的doFilter方法,即可将请求交给后一个过滤器处理
      • destroy()
        • 过滤器销毁时会调用的方法,Filter接口中的默认方法,可以不在实现类中重写
    • 配置过滤器

      • 通过FilterRegistrationBean类配置过滤器

        • 概念

          • 一个泛型类,可以配置不同类型的过滤器
        • 常用方法(其实是它继承父类以及父类。。。)

          • addUrlPatterns(String... urlPatterns)
            • 设置过滤的路径
          • setName(String name)
            • 设置过滤器名称
          • setEnabled(boolean enabled)
            • 是否启用此过滤器,默认为true
          • isEnabled
            • 该过滤器是否被启用
          • setFilter(T filter)
            • 设置要配置的过滤器对象
          • getFilter()
            • 获取已配置的过滤器对象
          • setOrder(int order)
            • 设置过滤器的优先级,值越小优先级越高,1表示顶级过滤器
          • getOrder()
            • 获取过滤器优先级
        • 示例

          LoginFilter:

          public class LoginFilter implements Filter {
          
              @Override
              public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                      throws IOException, ServletException {
                  HttpServletRequest req = (HttpServletRequest) request;
                  Object user = req.getSession().getAttribute("user");
                  if (user == null) {
                      req.getRequestDispatcher("/login").forward(request, response);
                  }else{
                      chain.doFilter(request, response);
                  }
              }
          }

          FilterConfig:

          @Configuration
          public class FilterConfig {
              @Bean
              public FilterRegistrationBean<LoginFilter> getFilter() {
                  FilterRegistrationBean<LoginFilter> bean = new FilterRegistrationBean<>();
                  bean.setFilter(new LoginFilter());
                  bean.addUrlPatterns("/test/*"); // 过滤/test下的所有子路径
                  bean.setName("loginFilter");
                  return bean;
              }
          }

          LoginController:

          @RestController
          public class LoginController {
              @RequestMapping("/test/index")
              public String index() {
                  return "欢迎访问测试页面";
              }
              @RequestMapping("/login")
              public String login() {
                  return "请先登录";
              }
          }
      • 通过@WebFilter注解配置过滤器

        • 概念

          • 该注解可以用于快速配置过滤器,只不过@WebFilter注解的功能没有FilterRegistrationBean类的功能多
          • 该注解要和@Component组合使用,否则无法被扫描器扫描到
          • urlPatterns属性表示过滤器所过滤的地址(当然,value属性功能相同)
        • 示例

          CountFilter:

          @Component
          @WebFilter(urlPatterns = "/test/index.html")
          public class CountFilter implements Filter {
          
              // 重写过滤器初始化方法
              @Override
              public void init(FilterConfig filterConfig) throws ServletException {
                  ServletContext servletContext = filterConfig.getServletContext(); // 获取上下文对象
                  servletContext.setAttribute("count", 0); // 计数器初始值为0
              }
          
              @Override
              public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
                      throws IOException, ServletException {
                  HttpServletRequest request = (HttpServletRequest) req;
                  ServletContext servletContext = request.getServletContext(); // 获取上下文对象
                  Integer count = (Integer) servletContext.getAttribute("count"); // 获取计数器的值
                  servletContext.setAttribute("count", ++count); // 让计数器自增
                  chain.doFilter(req,res);
              }
          }

          CountController:

          @RestController
          public class CountController {
              @RequestMapping("/test/index.html")
              public String index(HttpServletRequest request) {
                  ServletContext servletContext = request.getServletContext();
                  Integer count = (Integer) servletContext.getAttribute("count");
                  return "当前访问量:"+count;
              }
          }
  • 拦截器

    • 概念

      • 拦截器用于拦截用户请求并做相应的处理
      • 拦截器可以在控制器类中的方法被执行前和被执行后对请求做一些处理
      • 多个拦截器可以组成一个拦截链,链中任何一个拦截器都能中断请求,同时整个拦截链也会中断
    • 拦截器和过滤器的区别

      • 拦截器可以在控制器类中的方法被执行前和被执行后对请求做一些处理
      • 过滤器对用户通过URL地址发送的请求进行预处理,对服务器返回的数据进行后处理
    • HandlerInterceptor

      • 概念

        • 一个类如果实现了HandlerInterceptor接口,就能够实现自定义的拦截器
      • 三个默认方法

        • preHandle
          • 在控制器类中的方法被执行之前、对请求进行处理时被执行
          • 方法的返回值是布尔类型
            • true表示放行,执行控制器类中的方法
            • false表示请求中断,控制器类中的方法不会被执行
        • postHandle
          • 在控制器类中的方法被执行之后、对请求进行处理时被执行
        • afterCompletion
          • 在整个请求结束之后被执行
      • 自定义拦截器

        MyInterceptor:

        public class MyInterceptor implements HandlerInterceptor {
            @Override
            public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler)
                    throws Exception {
                if(handler instanceof HandlerMethod handlerMethod){ // 如果是HandlerMethod对象
                    System.out.println("请求访问的方法是:"+handlerMethod.getMethod().getName());
                    Object value = req.getAttribute("value"); // 读取请求的某个属性,默认为null
                    System.out.println("执行方法前:value="+value);
                    return true;
                }
                return false;
            }
        
            @Override
            public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView modelAndView)
                    throws Exception {
                Object value = req.getAttribute("value"); // 执行完请求,再读取此属性
                System.out.println("执行方法后,value="+value);
            }
        
            @Override
            public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex)
                    throws Exception {
                req.removeAttribute("value");
                System.out.println("整个请求都执行完毕,在此做一些资源释放的工作");
            }
        }

        InterceptorConfig:

        @Configuration
        public class InterceptorConfig implements WebMvcConfigurer {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                InterceptorRegistration registration = registry.addInterceptor(new MyInterceptor());
                registration.addPathPatterns("/**"); // 拦截所有地址
            }
        }

        TestController:

        @RestController
        public class TestController {
            @RequestMapping("/index")
            public String index() {
                return "index";
            }
            @RequestMapping("/login")
            public String login(HttpServletRequest request) {
                request.setAttribute("value","登录前这里保存了一些属性值");
                return "请先登录";
            }
        }

        “/*”表示匹配一层地址;“/**”表示匹配多层地址

  • 监听器

    • 概念

      • 监听器用于监听并处理指定的事件
      • 自定义的监听器类只需实现特定的监听接口并用@Componet注解予以标记即可生效
    • 8大监听接口

      • ServletRequestListener
        • 该接口可以监听请求的初始化与销毁
      • HttpSessionListener
        • 可以监听session的创建与销毁
      • ServletContextListener
        • 监听上下文的初始化与销毁
      • ServletRequestAttributeListener
        • 监听请求属性发生的增、删、改事件
      • HttpSessionAttributeListener
        • 监听session属性发生的增、删、改事件
      • ServletContextAttributeListener
        • 监听上下文属性发生的增、删、改事件
      • HttpSessionBindingListener
        • 为开发者自定义的类添加session绑定监听,当session保存或移除此类的对象时触发此监听
      • HttpSessionActivationListener
        • 为开发者自定义的类添加序列化监听,当保存在session中的自定义类对象被序列化或反序列化时触发此监听,该监听通常会配合HttpSessionBindingListener监听一起使用
          • 对象变成字节序列的过程被称为序列化(passivate,钝化、持久化)
          • 字节序列变成对象的过程被称为反序列化(active,活化)
    • 自定义监听器

      MyRequestListener:

      @Component
      public class MyRequestListener implements ServletRequestListener {
          @Override
          public void requestInitialized(ServletRequestEvent sre) {
              HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
              String ip = request.getRemoteAddr();
              String url = request.getRequestURI();
              String sessionId = request.getSession().getId();
              System.out.println("ip:" + ip + " url:" + url + " sessionId:" + sessionId);
          }
      
          @Override
          public void requestDestroyed(ServletRequestEvent sre) {
              HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
              String sessionId = request.getSession().getId();
              System.out.println("sessionId:" + sessionId+",已销毁");
          }
      }

      WelcomController:

      @RestController
      public class WelcomController {
          @RequestMapping("/index")
          public String index() {
              return "Hello World";
          }
      }
  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值