zoukankan      html  css  js  c++  java
  • springBoot的过滤器,监听器,拦截器

    概述

      在开发中,我们经常要考虑一些问题,对敏感词进行过滤,用户是否已经登录,是否需要对他的请求进行拦截,或者领导问现在在线人数有多少人?我们如何实现这些功能哪

     @WebFilter

    package com.xmlxy.firstspringbootproject;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    @WebFilter(filterName = "customFilter",urlPatterns = "/*")
    public class CustomFilter implements Filter {
    
        private static final Logger log = LoggerFactory.getLogger(CustomFilter.class);
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            log.info("===========拦截器初始化==========");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            servletRequest.setCharacterEncoding("utf-8");
            servletResponse.setCharacterEncoding("utf-8");
            log.info("doFilter请求处理");
        }
    
        @Override
        public void destroy() {
            log.info("fifter销毁");
        }
    }

    在application类中添加@ServletComponentScan注解

    package com;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    import org.springframework.context.annotation.PropertySource;
    
    @SpringBootApplication
    @ServletComponentScan
    @PropertySource(value = "classpath:jdbc.properties",encoding = "utf-8")
    public class FirstSpringbootProjectApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(FirstSpringbootProjectApplication.class, args);
        }
    
    }

    运行结果

    (笔误,应该是过滤器初始化)过滤器已经生效,但若有多个过滤器,无法指定执行顺序,我们可以通过Java类的名称,从A-L,按顺序执行。但这种方式毕竟不大靠谱,所以,有第二种写法,它提供setOrder函数,为filter设置排序值。

    package com.xmlxy.service;
    
    import com.xmlxy.firstspringbootproject.CustomFilter;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class WebFilterConfig
    {
        @Bean
        public FilterRegistrationBean someFilterRegistration1()
        {
            FilterRegistrationBean registration = new FilterRegistrationBean<>();
            System.out.println("我执行了。。。。。。。");
            registration.setFilter(new CustomFilter());
            registration.addUrlPatterns("/*");
         registration.setOrder(1);
         return registration; } }

    我们尝试写个demo,验证一下过滤器是否执行。

    用户登录对象

    User.java

    package com.xmlxy.bean;
    
    import lombok.Data;
    import org.springframework.stereotype.Component;
    
    @Data
    @Component
    public class User {
        private String user;
        private String pwd;
    }

    登录控制

    LoginController.java

    package com.xmlxy.firstspringbootproject;
    
    import com.xmlxy.bean.User;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    @RestController
    public class LoginController {
    
        @RequestMapping(value = "login",method = RequestMethod.GET)
        public String login(HttpServletRequest request)
        {
            String user = request.getParameter("user");
            String pwd = request.getParameter("pwd");
            HttpSession session = request.getSession();
            if ("admin".equals(user) && "admin".equals(pwd))
            {
                User user1 = new User();
                user1.setUser(user);
                user1.setPwd(pwd);
                session.setAttribute("user",user1);
                return "登录成功";
            }
            return "密码错误,登录失败";
        }
      @RequestMapping(value = "test",method = RequestMethod.GET)
      public String test()
      {
      return "test接口";
      }
    }

    过滤器

    CustomFilter.java

    package com.xmlxy.firstspringbootproject;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    //@WebFilter(filterName = "customFilter",urlPatterns = "/*")
    public class CustomFilter implements Filter {
    
        private static final Logger log = LoggerFactory.getLogger(CustomFilter.class);
    
        String includes[] = {"/login","register"};
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            log.info("===========过滤器初始化==========");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
        {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            servletRequest.setCharacterEncoding("utf-8");
            servletResponse.setCharacterEncoding("utf-8");
            HttpSession session = request.getSession(false);
            String uri = request.getRequestURI();
            boolean flag = isNeedFilter(uri);
            if (!flag)
            {
                filterChain.doFilter(servletRequest,servletResponse);
                System.err.printf("登录成功");
            }else {
                if (session != null && session.getAttribute("user") != null)
                {
                    filterChain.doFilter(servletRequest,servletResponse);
                }else {
                    System.err.printf("暂时未登录");
                }
            }
    
            log.info("doFilter请求处理");
        }
        public boolean isNeedFilter(String uri)
        {
            for (String include:includes)
            {
                if (include.equals(uri))
                {
                    return false;
                }
            }
            return true;
        }
        @Override
        public void destroy() {
            log.info("fifter销毁");
        }
    }

    过滤器配置

    WebFilterConfig

    package com.xmlxy.service;
    
    import com.xmlxy.firstspringbootproject.CustomFilter;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class WebFilterConfig
    {
        @Bean
        public FilterRegistrationBean someFilterRegistration1()
        {
            FilterRegistrationBean registration = new FilterRegistrationBean<>();
            System.out.println("我执行了。。。。。。。");
            registration.setFilter(new CustomFilter());
            registration.addUrlPatterns("/*");
            return registration;
        }
    }

     运行测试。。访问 127.0.0.1/test  控制台

    访问  http://127.0.0.1:8080/login?user=admin&pwd=admin,可以看到登录成功

    在次访问 127.0.0.1/test 页面显示

    所以,我们的过滤器成功过滤未登录的用户

    监听器

    正在你为自己会了过滤用户自鸣得意时,你的组长过来了,小明,你看下我们平台的在线用户有多少人。如果不知道监听器童鞋,是否会在登录接口处每次登录成功都+1,然而这种统计结果是不准确的,因为用户如果反复登录退出,那这个在值就远远大于实际值,最后就面临着,加班在加班的悲惨下场。

    CustomLister.java

    package com.xmlxy.firstspringbootproject;
    
    
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    @WebFilter
    public class CustomLister implements HttpSessionListener
    {
        public static int online = 0;
    
        @Override
        public void sessionCreated(HttpSessionEvent sessionEvent)
        {
            System.out.println("创建session,统计在线人数");
            online ++;
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent sessionEvent)
        {
            System.out.println("session已经销毁");
        }
    }

    配置监听器配置,在刚才的WebFilterConfig.java添加

    @Bean
        public ServletListenerRegistrationBean listenerRegistrationBean()
        {
            ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
            srb.setListener(new CustomLister());
            System.out.println("");
            return srb;
        }

    添加一个访问在线人数的接口

    @RequestMapping(value = "onLinePerson",method = RequestMethod.GET)
        public String onLinePerson()
        {
            StringBuffer stringBuffer = new StringBuffer("");
            stringBuffer.append(" 在线人数 ");
            stringBuffer.append(CustomLister.online);
            stringBuffer.append(" 个人 ");
            return stringBuffer.toString();
        }

    访问127.0.0.1/onLinePerson,发现被拦截器拦截了,我们先登录。在查看接口

    换个浏览器,调用下login接口,在查看

    拦截器

    拦截器,个人理解,在web上有些像是过滤器的补充,它能更精确的控制拦截哪些函数或者字段,在拦截之前或之后做一些操作。我们现在做一个敏感词的拦截,其实这个操作放在过滤器操作也是可以的,但lz因为刚才把拦截用户的操作放在过滤器了,在大规模更改,lz觉得没必要,因为都是大同小异。

    CustomInterceptor.java

    package com.xmlxy.firstspringbootproject;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.PrintWriter;
    
    public class CustomInterceptor implements HandlerInterceptor
    {
        private static final Logger log = LoggerFactory.getLogger(CustomInterceptor.class);
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {
            log.info("=======拦截器被调用=====");
            String url = request.getRequestURI();
            if (url != null && url.indexOf("seqing") != -1)
            {
                PrintWriter printWriter = response.getWriter();
                printWriter.write("ming gan ci");
                return false;
            }
            log.info("返回false 则中断请求");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
        {
            log.info("请求后调用");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception e)
        {
            log.info("视图渲染完回调");
        }
    }

    配置拦截

    package com.xmlxy.service;
    
    import com.xmlxy.firstspringbootproject.CustomFilter;
    import com.xmlxy.firstspringbootproject.CustomInterceptor;
    import com.xmlxy.firstspringbootproject.CustomLister;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class WebFilterConfig implements WebMvcConfigurer
    {
        @Bean
        public FilterRegistrationBean someFilterRegistration1()
        {
            FilterRegistrationBean registration = new FilterRegistrationBean<>();
            System.out.println("我执行了。。。。。。。");
            registration.setFilter(new CustomFilter());
            registration.addUrlPatterns("/*");
            return registration;
        }
    
        @Bean
        public ServletListenerRegistrationBean listenerRegistrationBean()
        {
            ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
            srb.setListener(new CustomLister());
            return srb;
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry)
        {
            /*拦截规则*/
            registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/*");
        }
    
    }

    现在测试访问127.0.0.1/seqing,被过滤,要求先登录。我们调用登录接口后,再次调用,发现被拦截了

    看下日志调用,可以发现,拦截器是在访问接口前被调用的

    过滤器,拦截器区别

    这里主要说下拦截器和过滤器的区别和使用场景,通过demo可以发现,它们都能实现权限的检查,日志记录这些功能,主要说下它们的区别

    1. 过滤器和拦截器触发的时机是不同的,在进入servlet之前,过滤器就进行预处理了。而拦截器是在调用Controller之前才触发执行,过滤器的范围较广,对所有的请求都起作用,而拦截起只 对action起作用

      2.拦截器可以获取IOC容器的各个bean,而过滤器就不行。因为拦截器是spring提供管理的,也因此拦截器可以使用spring的任何资源。

      3.拦截器是利用Java反射机制实现,过滤器是函数的回调。因此实现方式是不同的。

    三者使用场景

      监听器常用统计在线用户,统计网站的访问量,记录用户的访问路径

      过滤器:过滤敏感词,权限访问控制

      拦截器:权限验证,判断用户是否登录等

  • 相关阅读:
    网站安全检测
    Centos下Subversion 服务器安装配置
    报错:1130-host ... is not allowed to connect to this MySql server 开放mysql远程连接 不使用localhost
    八个免费在线网站速度测试服务-分析影响网页加载因素提高网站访问速度
    Python处理HTML转义字符
    atitit.TokenService  token服务模块的设计
    Atitit.木马 病毒 免杀 技术 360免杀 杀毒软件免杀 原理与原则 attilax 总结
    atitit.TokenService  token服务模块的设计
    Atitit.atijson 类库的新特性设计与实现 v3 q31
    Atitit.atijson 类库的新特性设计与实现 v3 q31
  • 原文地址:https://www.cnblogs.com/dslx/p/11275958.html
Copyright © 2011-2022 走看看