Java Web开发中,自定义过滤器被执行两次的原因分析及解决办法 - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 网站建设 >

Java Web开发中,自定义过滤器被执行两次的原因分析及解决办法

发表时间:2012-6-8

发布人:葵宇科技

浏览次数:37

本文出处:http://blog.csdn.net/chaijunkun/article/details/7646338,转载请注明。由于本人不定期会整理相关博文,会对相应内容作出完善。因此强烈建议在原始出处查看此文。
在Java Web开发过程中,我们可以使用过滤器和Spring框架提供的拦截器来对请求进行处理,从而实现对整个Web应用的权限控制。在这里我简单介绍一下我在使用过滤器实现权限验证方面的经验。
过滤器作为传统的Web开发技术,不受使用了第三方框架的束缚,所有符合标准的Servlet容器都支持这项技术。URL字符编码过滤器是我们经常使用的,而权限控制过滤器则是过滤器轻量级应用的常见场景。目前我所开发的一个项目中就使用了这项技术,然而在开发时遇到了过滤器被调用了两次的问题,下面说一下我的配置:

在web.xml中我指定了过滤器:

<!--权限过滤器 -->
	<filter>
		<filter-name>permissionFilter</filter-name>
		<filter-class>blog.csdn.net.chaijunkun.PermissionFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>permissionFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

下面是过滤器的实现代码:

package blog.csdn.net.chaijunkun;

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 org.apache.log4j.Logger;

public class PermissionFilter implements Filter {

	private Logger logger= Logger.getLogger(PermissionFilter.class);

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain filterChain) throws IOException, ServletException {
		HttpServletRequest request= (HttpServletRequest) req;
		    logger.info("过滤器被调用");
		    filterChain.doFilter(request, resp);
		}
		
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
	}

}

结果当我访问了一个接口后,在控制台显示了两条“过滤器被调用”的提示。后来在网上寻找原因,偶然看到了有人问同样的问题:http://topic.csdn.net/u/20110930/22/d8741022-53eb-4df1-ace0-357f6edabee1.html
按照“xiaobluesky”说的方法,打印了一下请求的URL地址:System.out.println(request.getRequestedURI());
发现两次打印的内容不一样:
第一次打印的是我请求的Servlet,第二次打印的是/favicon.ico,此时才恍然大悟,很多浏览器都支持“站点图标”的功能。例如我当前正在编辑这篇文章,使用的是Chrome浏览器,标签页上就显示了一个这样的CSDN的图标:

CSDN图标

根据规范,这个图标的位置就是在站点根目录下,命名也必须为favicon.ico。
过滤器被执行两次的情况仅限于使用Servlet容器既提供静态访问支持、又提供动态访问支持的情况,当采用动静态分离的场合(例如apache+tomcat,apache将静态请求拦截自己处理,tomcat只处理动态内容),这种问题自然而然就消失了,因为该请求不会到达Servlet容器。


既然知道了原理,解决起来就好办了,写几个正则表达式,按照requestURI的规划进行合理的分配,不同的访问URL采用不同的权限过滤机制即可。但是这种方法并不能阻止doFilter方法被调用两次,只是代码在按照我们指定的请求逻辑上运行。也许,这就是过滤器的不足之处。


也许写到这里你会问,为什么在web.xml配置文件中url-pattern一定要写成"/*"这种形式呢?写成“/*.do”这种形式不是更好么?我又何尝不想这样呢,查了资料并实践后才知道,这样写是不符合JSR-315规范的。有兴趣的朋友可以参阅帖子:
http://topic.csdn.net/u/20100525/12/41569c26-350b-45f9-abc0-2019cbb4641b.html
读一下JSR 315 12.2 节的原文

相关案例查看更多