在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中配置。

如何在自定义Filter中优雅的实现静态资源放行的更多相关文章

  1. springboot 项目中css js 等静态资源无法访问的问题

    目录 问题场景 问题分析 问题解决 问题场景 今天在开发一个springboot 项目的时候突然发现 css js 等静态资源竟然都报404找不到,折腾了好久终于把问题都解决了,决定写篇博客,纪录总结 ...

  2. Spring Boot 中的静态资源到底要放在哪里?

    当我们使用 SpringMVC 框架时,静态资源会被拦截,需要添加额外配置,之前老有小伙伴在微信上问松哥Spring Boot 中的静态资源加载问题:"松哥,我的HTML页面好像没有样式?& ...

  3. Spring Boot中的静态资源文件

    Spring Boot中的静态资源文件 1.SSM中的配置 2.Spring Boot 中的配置 2.1 整体规划 2.2 源码解读 2.3 自定义配置 2.3.1 application.prope ...

  4. 在Salesforce中使用静态资源

    静态资源 静态资源是Salesforce中默认的一种数据类型,用户可以上传各种文件,比如zip文件.jpg文件.css文件.图像文件等. 在Visualforce页面.Lightning框架的开发过程 ...

  5. DirectX:在graph自动连线中加入自定义filter(graph中遍历filter)

    为客户提供的视频播放的filter的测试程序中,采用正向手动连接的方式(http://blog.csdn.net/mao0514/article/details/40535791),由于不同的视频压缩 ...

  6. Python中自定义filter用法

    django中新建项目,在项目中新建app,自定义filter一般放到app中.结构目录如下: 1.先在APP中新建一个templatetags的django文件夹,文件夹中新建一个filter的py ...

  7. Asp.net mvc自定义Filter简单使用

    自定义Filter的基本思路是继承基类ActionFilterAttribute,并根据实际需要重写OnActionExecuting,OnActionExecuted,OnResultExecuti ...

  8. Jinja2模版语言自定义filter的使用

    Jinja2模版语言,自带有一些filter,能够在前端的模版中控制数据按照相应的方式显示.比如以下两种filter,分别能在前端控制数字的近似精度显示和根据字符串长度补齐: round(value, ...

  9. HBase笔记--自定义filter

    自定义filter需要继承的类:FilterBase 类里面的方法调用顺序   方法名 作用 1 boolean filterRowKey(Cell cell) 根据row key过滤row.如果需要 ...

随机推荐

  1. Android项目实战(四十):Andoird 7.0+ 安装APK适配

    首先看一下安装apk文件的代码 /** * 通过隐式意图调用系统安装程序安装APK */ public static void install(Context context) { Intent in ...

  2. php get接口,并在浏览器中以json格式返回查找到的数据

    php查询数据有6个步骤,分别为: 连接数据库服务器,使用的命令为:mysql_connect("服务器名称","用户名","密码") 选择 ...

  3. sublime使用Package Control不能正常使用的解决办法

    标签: Sublime作为一款非常优秀的编辑器,套用中学语文课本里一篇讲梁启超的文章里形容梁启超的一句话,就是“短小精悍”.说它“短小”,是因为它的轻量级:说它“精悍”,则得益于它那包罗万象以适用于任 ...

  4. C#多线程图片爬虫

    写了个简单的多线程图片爬虫,整理一下.数据已经爬下来了,图片URL需要自行拼接,首先从Lawyers表中取的RawData字段,RawData中有一个list字段是json格式的数据,需要的只是lis ...

  5. Linux 无线网卡配置

    无线网卡常见的配置选项 某TL-WR842N路由器无线配置选项含义: 无线名称 路由器的无线(Wi-Fi)名称.无线密码 无线加密使用WPA2-PSK/WPA-PSK加密方式.AES加密算法,无线密码 ...

  6. ssh-keygen的学习总结

    ssh-keygen介绍   维基百科上关于ssh-keygen的介绍如下:     ssh-keygen is a standard component of the Secure Shell (S ...

  7. CSS margin 外边距 属性的位置关系

    padding:内边距 margin :外边距 margin:10px; 所有 4 个外边距都是 10px ******************************************* ma ...

  8. 【转】JSF中的三大核心组件 UI标签的详细介绍和使用举例

    JSF提供了大量的UI标签来简化创建视图.这些UI标签类似于ASP.NET中的服务器组件.使用这些标签,可以通过其value,binding,action,actionListener等属性直接绑定到 ...

  9. MSSQL中 数值类型转换为千分号的解决方案

    转自:http://www.maomao365.com/?p=4797 前言:最近需要将报表中关于数值部分的数据,采用千分号的形式展现给用户,下面将讲解如何制作1 将数值类型转换为 money类型2 ...

  10. EOS智能合约开发(三):EOS创建和管理账号

    没有看前面文章的小伙伴可以看一下 EOS智能合约开发(一):EOS环境搭建和启动节点 EOS智能合约开发(二):EOS创建和管理钱包 创建好钱包.密钥之后,接下来你就可以创建账号了,账号是什么?账号保 ...