如何在自定义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.YAN15
* @time 2018-10-19 14:07:4416
* @version v1.017
*/18
public class RestAuthorizeFilter implements Filter {19
/**20
* 不需要被过滤器拦截的页面 ,主要用于静态资源的放行21
* 在web.xml中配置filter的init-param22
*/ 23
private String excludedPaths; 24
private String [] excludedPathArray;25
26
27
public void init(FilterConfig filterConfig) throws ServletException {28
// 初始化时读取web.xml中配置的init-param29
excludedPaths = filterConfig.getInitParameter("excludedPaths");30
if(!StringUtils.isNullOrBlank(excludedPaths)){31
excludedPathArray = excludedPaths.split(",");32
}33
}34
35
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
49
public void destroy() {50
// TODO Auto-generated method stub51
}52
53
/**54
* 判断是否是 过滤器直接放行的请求55
* <br/>主要用于静态资源的放行56
* @param url57
* @return58
*/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中配置。
作者:zeng1994
出处:http://www.cnblogs.com/zeng1994/
本文版权归作者和博客园共有,欢迎转载!但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接!

浙公网安备 33010602011771号