zoukankan      html  css  js  c++  java
  • 如何在自定义Filter中优雅的实现静态资源放行

            在javaweb开发中,过滤器Filter比较常用于类似登录的拦截等场景。但是,当过滤器的配置不当时就会把所有的请求都拦截,静态资源也会被拦截掉,导致静态页面加载不出来。
    一般的解决方案是在过滤器代码中对所有的静态资源放行,但这样硬编码的方式特别不灵活,代码复用性也不高。下面说个更优雅点的方案。

    一、解决方案

            如果将静态资源放行的功能做成在web.xml中可以直接配置的话,就比较方便了。因此我们可以采用配置Filter的init-param的方式来配置那些资源不需要过滤器拦截,然后在过滤器Filter中的init方法去取这个配置的init-param。 具体的还是直接上代码吧。

    二、代码

    (1)web.xml中Filter的配置代码片段如下
            这里的重点是配置了一个init-param
      <!--身份验证、登录、权限-->
      <filter>
        <filter-name>authorityFilter</filter-name>
        <filter-class>com.hk.uc.client.filter.RestAuthorizeFilter</filter-class>
        <init-param>
        	<!-- 配置不需要被登录过滤器拦截的链接,只支持配后缀、前缀 及全路径,多个配置用逗号分隔 -->
        	<param-name>excludedPaths</param-name>
        	<param-value>/pages/*,*.html,*.js,*.ico</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>authorityFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    x
    14
    1
      <!--身份验证、登录、权限-->
    2
      <filter>
    3
        <filter-name>authorityFilter</filter-name>
    4
        <filter-class>com.hk.uc.client.filter.RestAuthorizeFilter</filter-class>
    5
        <init-param>
    6
            <!-- 配置不需要被登录过滤器拦截的链接,只支持配后缀、前缀 及全路径,多个配置用逗号分隔 -->
    7
            <param-name>excludedPaths</param-name>
    8
            <param-value>/pages/*,*.html,*.js,*.ico</param-value>
    9
        </init-param>
    10
      </filter>
    11
      <filter-mapping>
    12
        <filter-name>authorityFilter</filter-name>
    13
        <url-pattern>/*</url-pattern>
    14
      </filter-mapping>
    (2)自定义Filter的代码如下
            代码解释如下:
        • 首先我声明了excludedPaths用来接收web.xml中配置的init-param
        • init()方法中把init-param的值赋值给excludedPaths
        • 写一个方法用来判断是否是直接放行的请求,这里写了isFilterExcludeRequest()这个方法
        • doFilter()这个方法中,先调用isFilterExcludeRequest()这个方法,判断是否应该直接放行。如果不是直接放行才走我们的逻辑代码
    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import com.kangxiinfo.framework.common.util.StringUtils;
    
    /**
     * 身份认证过滤器
     * @author ZENG.XIAO.YAN
     * @time   2018-10-19 14:07:44
     * @version  v1.0
     */
    public class RestAuthorizeFilter implements Filter {
    	/**
    	 * 不需要被过滤器拦截的页面 ,主要用于静态资源的放行
    	 * 在web.xml中配置filter的init-param
    	 */    
    	private String excludedPaths; 
    	private String [] excludedPathArray;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
        	// 初始化时读取web.xml中配置的init-param
        	excludedPaths = filterConfig.getInitParameter("excludedPaths");
        	if(!StringUtils.isNullOrBlank(excludedPaths)){
        		excludedPathArray = excludedPaths.split(",");
        	}
        }
        
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            // 判断是否是直接放行的请求
    		if (!isFilterExcludeRequest(request)) {
    			// TODO 这里写你的过滤器处理逻辑
    		}
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
        }
    
        /**
         * 判断是否是 过滤器直接放行的请求
         * <br/>主要用于静态资源的放行
         * @param url
         * @return
         */
        private boolean isFilterExcludeRequest(HttpServletRequest request) {
        	if(null != excludedPathArray && excludedPathArray.length > 0) {
        		String url = request.getRequestURI();
            	for (String ecludedUrl : excludedPathArray) {
    				if (ecludedUrl.startsWith("*.")) {
    					// 如果配置的是后缀匹配, 则把前面的*号干掉,然后用endWith来判断
    					if(url.endsWith(ecludedUrl.substring(1))){
    						return true;
    					}
    				} else if (ecludedUrl.endsWith("/*")) {
    					if(!ecludedUrl.startsWith("/")) {
    						// 前缀匹配,必须要是/开头
    						ecludedUrl = "/" + ecludedUrl;
    					}
    					// 如果配置是前缀匹配, 则把最后的*号干掉,然后startWith来判断
    					String prffixStr = request.getContextPath() + ecludedUrl.substring(0, ecludedUrl.length() - 1);
    					if(url.startsWith(prffixStr)) {
    						return true;
    					}
    				} else {
    					// 如果不是前缀匹配也不是后缀匹配,那就是全路径匹配
    					if(!ecludedUrl.startsWith("/")) {
    						// 全路径匹配,也必须要是/开头
    						ecludedUrl = "/" + ecludedUrl;
    					}
    					String targetUrl = request.getContextPath() + ecludedUrl;
    					if(url.equals(targetUrl)) {
    						return true;
    					}
    				}
    			}
        	}
        	return false;
        }
    }
    
    94
     
    1
    import java.io.IOException;
    2
    import javax.servlet.Filter;
    3
    import javax.servlet.FilterChain;
    4
    import javax.servlet.FilterConfig;
    5
    import javax.servlet.ServletException;
    6
    import javax.servlet.ServletRequest;
    7
    import javax.servlet.ServletResponse;
    8
    import javax.servlet.http.HttpServletRequest;
    9
    import javax.servlet.http.HttpServletResponse;
    10
    import com.kangxiinfo.framework.common.util.StringUtils;
    11
    12
    /**
    13
     * 身份认证过滤器
    14
     * @author ZENG.XIAO.YAN
    15
     * @time   2018-10-19 14:07:44
    16
     * @version  v1.0
    17
     */
    18
    public class RestAuthorizeFilter implements Filter {
    19
        /**
    20
         * 不需要被过滤器拦截的页面 ,主要用于静态资源的放行
    21
         * 在web.xml中配置filter的init-param
    22
         */    
    23
        private String excludedPaths; 
    24
        private String [] excludedPathArray;
    25
    26
        @Override
    27
        public void init(FilterConfig filterConfig) throws ServletException {
    28
            // 初始化时读取web.xml中配置的init-param
    29
            excludedPaths = filterConfig.getInitParameter("excludedPaths");
    30
            if(!StringUtils.isNullOrBlank(excludedPaths)){
    31
                excludedPathArray = excludedPaths.split(",");
    32
            }
    33
        }
    34
        
    35
        @Override
    36
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
    37
                             FilterChain filterChain) throws IOException, ServletException {
    38
            HttpServletRequest request = (HttpServletRequest) servletRequest;
    39
            HttpServletResponse response = (HttpServletResponse) servletResponse;
    40
            // 判断是否是直接放行的请求
    41
            if (!isFilterExcludeRequest(request)) {
    42
                // TODO 这里写你的过滤器处理逻辑
    43
            }
    44
            filterChain.doFilter(servletRequest, servletResponse);
    45
        }
    46
    47
        
    48
        @Override
    49
        public void destroy() {
    50
            // TODO Auto-generated method stub
    51
        }
    52
    53
        /**
    54
         * 判断是否是 过滤器直接放行的请求
    55
         * <br/>主要用于静态资源的放行
    56
         * @param url
    57
         * @return
    58
         */
    59
        private boolean isFilterExcludeRequest(HttpServletRequest request) {
    60
            if(null != excludedPathArray && excludedPathArray.length > 0) {
    61
                String url = request.getRequestURI();
    62
                for (String ecludedUrl : excludedPathArray) {
    63
                    if (ecludedUrl.startsWith("*.")) {
    64
                        // 如果配置的是后缀匹配, 则把前面的*号干掉,然后用endWith来判断
    65
                        if(url.endsWith(ecludedUrl.substring(1))){
    66
                            return true;
    67
                        }
    68
                    } else if (ecludedUrl.endsWith("/*")) {
    69
                        if(!ecludedUrl.startsWith("/")) {
    70
                            // 前缀匹配,必须要是/开头
    71
                            ecludedUrl = "/" + ecludedUrl;
    72
                        }
    73
                        // 如果配置是前缀匹配, 则把最后的*号干掉,然后startWith来判断
    74
                        String prffixStr = request.getContextPath() + ecludedUrl.substring(0, ecludedUrl.length() - 1);
    75
                        if(url.startsWith(prffixStr)) {
    76
                            return true;
    77
                        }
    78
                    } else {
    79
                        // 如果不是前缀匹配也不是后缀匹配,那就是全路径匹配
    80
                        if(!ecludedUrl.startsWith("/")) {
    81
                            // 全路径匹配,也必须要是/开头
    82
                            ecludedUrl = "/" + ecludedUrl;
    83
                        }
    84
                        String targetUrl = request.getContextPath() + ecludedUrl;
    85
                        if(url.equals(targetUrl)) {
    86
                            return true;
    87
                        }
    88
                    }
    89
                }
    90
            }
    91
            return false;
    92
        }
    93
    }
    94

    三、小结

    (1)通过解决这个问题,学会了filter的init-param该怎么玩
    (2)后续可以直接复用这个代码了,静态资源的放行直接在web.xml中配置。
  • 相关阅读:
    python中的编码问题
    CVPR2018 Tutorial 之 Visual Recognition and Beyond
    hdu 1376 Octal Fractions
    hdu 1329 Hanoi Tower Troubles Again!
    hdu 1309 Loansome Car Buyer
    hdu 1333 Smith Numbers
    hdu 1288 Hat's Tea
    hdu 1284 钱币兑换问题
    hdu 1275 两车追及或相遇问题
    hdu 1270 小希的数表
  • 原文地址:https://www.cnblogs.com/zeng1994/p/638bcf0b5278b3658da9435d84058db8.html
Copyright © 2011-2022 走看看