• springboot-MVC 过滤器使用


    一、前言

      一下代码以SSO用户登录列子代码。完整代码https://gitee.com/xuxueli0323/xxl-sso

    二、使用

     2.1 创建过滤器

      创建一个过滤器,实现Filter 接口 

      

    public class XxlSsoTokenFilter extends HttpServlet implements Filter {
        private static Logger logger = LoggerFactory.getLogger(XxlSsoTokenFilter.class);
    
        private static final AntPathMatcher antPathMatcher = new AntPathMatcher();
    
        private String ssoServer;
        private String logoutPath;
        private String excludedPaths;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
            ssoServer = filterConfig.getInitParameter(Conf.SSO_SERVER);
            logoutPath = filterConfig.getInitParameter(Conf.SSO_LOGOUT_PATH);
            excludedPaths = filterConfig.getInitParameter(Conf.SSO_EXCLUDED_PATHS);
    
            logger.info("XxlSsoTokenFilter init.");
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
    
            // make url
            String servletPath = req.getServletPath();
    
            // excluded path check
            if (excludedPaths!=null && excludedPaths.trim().length()>0) {
                for (String excludedPath:excludedPaths.split(",")) {
                    String uriPattern = excludedPath.trim();
    
                    // 支持ANT表达式
                    if (antPathMatcher.match(uriPattern, servletPath)) {
                        // excluded path, allow
                        chain.doFilter(request, response);
                        return;
                    }
    
                }
            }
    
            // logout filter
            if (logoutPath!=null
                    && logoutPath.trim().length()>0
                    && logoutPath.equals(servletPath)) {
    
                // logout
                SsoTokenLoginHelper.logout(req);
    
                // response
                res.setStatus(HttpServletResponse.SC_OK);
                res.setContentType("application/json;charset=UTF-8");
                res.getWriter().println("{"code":"+ReturnT.SUCCESS_CODE+", "msg":""}");
    
                return;
            }
    
            // login filter
            XxlSsoUser xxlUser = SsoTokenLoginHelper.loginCheck(req);
            if (xxlUser == null) {
    
                // response
                res.setStatus(HttpServletResponse.SC_OK);
                res.setContentType("application/json;charset=UTF-8");
                res.getWriter().println("{"code":"+Conf.SSO_LOGIN_FAIL_RESULT.getCode()+", "msg":""+ Conf.SSO_LOGIN_FAIL_RESULT.getMsg() +""}");
                return;
            }
    
            // ser sso user
            request.setAttribute(Conf.SSO_USER, xxlUser);
    
    
            // already login, allow
            chain.doFilter(request, response);
            return;
        }
    
    
    }
    

      2.2 注册filter

        使用java 配置  @Configuration 注解配置 ,通过FilterRegistrationBean ,向spring容器中注入 过滤器。

     

    @Configuration
    public class XxlSsoConfig implements DisposableBean {
    
    
        @Value("${xxl.sso.server}")
        private String xxlSsoServer;
    
        @Value("${xxl.sso.logout.path}")
        private String xxlSsoLogoutPath;
    
        @Value("${xxl.sso.redis.address}")
        private String xxlSsoRedisAddress;
    
        @Value("${xxl-sso.excluded.paths}")
        private String xxlSsoExcludedPaths;
    
    
        @Bean
        public FilterRegistrationBean xxlSsoFilterRegistration() {
    
            // xxl-sso, redis init
            JedisUtil.init(xxlSsoRedisAddress);
    
            // xxl-sso, filter init
            FilterRegistrationBean registration = new FilterRegistrationBean();
    
            registration.setName("XxlSsoWebFilter");
            registration.setOrder(1);
            registration.addUrlPatterns("/*");
            registration.setFilter(new XxlSsoTokenFilter());
            registration.addInitParameter(Conf.SSO_SERVER, xxlSsoServer);
            registration.addInitParameter(Conf.SSO_LOGOUT_PATH, xxlSsoLogoutPath);
            registration.addInitParameter(Conf.SSO_EXCLUDED_PATHS, xxlSsoExcludedPaths);
    
            return registration;
        }
    
        @Override
        public void destroy() throws Exception {
    
            // xxl-sso, redis close
            JedisUtil.close();
        }
    
    }
    

      

    三、执行流程

      以springboot 为列子,看filter 是如何工作的

      3.1 bean的注入

        因为filter 以 FilterRegistrationBean 的形式 注入到spring  的容器,首先来看看这个类的结构 ,可以看到这个类实现 ServletContextInitializer 接口

            

      3.2 断点跟踪

        在FilterRegistrationBean  类中有个方法getFilter 获取的过滤器,在这里打个断点,看看spring在什么时候会来获取过滤器。

        

     启动容器,进入断点 ,观察栈信息,可以看到是在创建spring容器后创建tomcat  服务进入的断点

        

         然后拿到所有接口实现,调用

        

         看下  FilterRegistrationBean 调用 onStartup  把filter获取注册到servletContext 容器中

        

         最后 封装成 FilterMap放进org.apache.catalina.core.StandardContext#filterMaps

        

         

    3.3 前端断点

      在过滤器中打上断点,前端发起请求,进入断点

      

       找到 ApplicationFilterChain 看到过滤器在 org.apache.catalina.core.ApplicationFilterChain#filters 中  ,分析发现添加过滤器的方法 ,在此方法设置断点,前端再次发请求

      

       

      
      

       过滤器链创建完了之后 会调用 过滤器链,用里面的过滤器循环过滤

      

     

  • 相关阅读:
    print 参数
    note
    action标签的属性说明
    Cannot load JDBC driver class 'oracle.jdbc.driver.OracleDriver'
    润乾报表
    javax.naming.NameNotFoundException: Name ZKING is not bound in this Context 的问题
    Myeclipse2013安装svn插件
    Myeclipse2013的优化设置
    Myeclipse解析.classpath文件
    Struts
  • 原文地址:https://www.cnblogs.com/jonrain0625/p/14695749.html
Copyright © 2020-2023  润新知