• 如何在自定义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中配置。
  • 相关阅读:
    HDU 4901 The Romantic Hero
    COGS8 备用交换机
    POJ 1466 Girls and Boys
    bzoj3442 学习小组
    bzoj2054 疯狂的馒头
    POJ2135 Farm Tour
    POJ 1149 PIGS
    Html5 Canvas学习之路(五)
    关于跨域简单总结
    vue-baidu-map 进入页面自动定位的解决方案!
  • 原文地址:https://www.cnblogs.com/zeng1994/p/638bcf0b5278b3658da9435d84058db8.html
Copyright © 2020-2023  润新知