如何在自定义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>
(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; 
    } 
}
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;
    }
}

三、小结

(1)通过解决这个问题,学会了filter的init-param该怎么玩
(2)后续可以直接复用这个代码了,静态资源的放行直接在web.xml中配置。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/15529.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论