JavaWeb中 Filter使用

在一个Web应用中,每个Web组件都用于响应特定的客户请求,不过,在这些Web组件响应客户请求的过程中,可能都会完成一些相同的操作。比如都要先检查客户的IP地址是否位于预定义的拒绝IP地址范围内,如果满足这一条件,就直接向客户端返回拒绝响应客户请求的信息,而不会继续执行后续操作。

如果在多个Web组件中编写完成同样操作的程序代码,显然会导致重复编码,从而降低开发效率和软件的可维护性。

为了解决上述问题,过滤器应运而生,它是在JavaServlet 2.3规范中出现的技术。过滤器能够对一部分客户请求先进行预处理操作,然后再把请求转发给相应的Web组件,等到Web组件生成了响应结果后,过滤器还能对响应结果进行检查和修改,然后再把修改后的响应结果发送给客户。各个Web组件的相同操作可以放到同一个过滤器中来完成,这样就能减少重复编码。

过滤器能够对Servlet容器传给Web组件的ServletRequest对象和ServletResponse对象进行检查和修改。过滤器本省并不生成ServletRequest和ServletResponse对象,它只作为Web组件提供如下过滤功能:

·  过滤器能够在Web组件被调用之前检查ServletRequest对象,修改请求头和请求正文的内容,或者对请求进行预处理操作。

过滤器能够在Web组件被调用之后检查ServletResponse对象,修改响应头和响应正文。

过滤器负责过滤的Web组件可以是Servlet、JSP或HTML文件。过滤器的过滤过程如下图:

过滤器既有以下特点:

·  过滤器可以检查ServletRequest和ServletResponse对象,并且利用ServletRequestWrapper和ServletResponseWrapper包装类来修改ServletRequest和ServletResponse对象。

·  ·可以在web.xml文件中为过滤器映射特定的URL。当客户请求访问此URL时,Servlet容器就会先触发过滤器工作。

·  过滤器是JavaServlet 2.3规范的一部分,因此所有实现Java Servlet 2.3规范及其以上版本的Servlet容器都支持过滤器。

·  多个过滤器可以被串联在一起,协同为Web组件过滤请求对象和响应对象。

创建过滤器

所有自定义的过滤器都必须实现javax.servlet.Filter接口,这个接口含有以下3个过滤器类必须实现的方法。

·  init(FilterConfig config):这是过滤器的初始化方法。在Web应用启动时,Servlet容器先创建包含了过滤器配置信息的FilterConfig对象,然后创建Filter对象,接着调用Filter对象的init(FilterConfig config)方法,在这个方法中可通过config参数来读取web.xml文件中为过滤器配置的初始化参数。

·  doFilter(ServletRequest req , ServletResponse res , FilterChainchain):这个方法完成实际的过滤操作。当客户请求访问的URL与为过滤器映射的URL匹配时,Servletrongqi先调用过滤器的doFilter()方法。FilterChain参数用于访问后续过滤器或者Web组件。

·  destroy():Servlet容器在销毁过滤器对象前调用该方法,在这个方法中可以释放过滤器占用的资源。

过滤器由Servlet容器创建,在它的生命周期中包含以下阶段。

·  初始化阶段:当Web应用启动时,Servlet容器会加载过滤器类,创建过滤器配置对象(FilterConfig)和过滤器对象,并调用过滤器对象的init(FilterConfig config)方法。

·  运行时阶段:当客户请求访问的URL与为过滤器映射的URL匹配时,Servlet容器将先调用过滤器的doFilter()方法。

·  销毁阶段:当Web应用终止时,Servlet容器将先调用个过滤器对象的destroy()方法,然后销毁过滤器对象。

发布过滤器

在发布过滤器时,必须在web.xml文件中加入<filter>元素和<filter-mapping>元素。<filter>元素用来定义一个过滤器:

<filter>
	<filter-name>CommonFilter</filter-name>
	<filter-class>dis.geo.demo.filter.CommonFilter</filter-class>
	<init-param>
	<param-name>ipblock</param-name>
	<param-value>221.45</param-value>
</init-param>
	<init-param>
	<param-name>blacklist</param-name>
	<param-value>捣蛋鬼</param-value>
</init-param>
</filter>
<filter-mapping>
	<filter-name>CommonFilter</filter-name>
	<filter-pattern>/note</filter-pattern>
</filter-mapping>

串联过滤器

多个过滤器可以串联起来协同工作,Servlet容器将根据它们在web.xml中定义的先后顺序,依次调用它们的doFilter()方法。自定义过滤器的doFilter()方法中一般会有这样的代码:chain.doFilter(),chain就是链的意思,也就是说在应用中可以将过滤器串起来,就像是净化水一样一步一步的进行过滤直至满足需求。

示例:黑名单及屏蔽字符串

应用中时常会出现“黑名单”的概念,使用过滤器实现就是检查请求中的特定参数,与指定参数匹配时禁止使用应用中的部分功能。而文字屏蔽更常见,在网上经常会出现某些敏感字符禁止出现的情况,比如马化腾变成***或XXX……

首先需要定义一个过滤器,在过滤器中先判断客户是否在黑名单中,如果在则停止响应或是返回一个拒绝服务的提示。不在黑名单中的客户在进行发布评论等操作时,将过滤掉敏感字符,替换成***,在示例中将屏蔽“夏洛克”、“福尔摩斯”、“华生”这三个字符。正常情况下,应该是有一个屏蔽库,这里使用简单的数组进行模拟。

public class CommonFilter implements Filter{
	private String[] strs;
	public void destroy() {
		System.out.println("===== commonFilter#destroy =====");

	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("===== commonFilter#doFilter =====");
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;
		String loginusername = req.getParameter("loginusername");
		if(loginusername != null&&!loginusername.equals("xiaoming")){
			//屏蔽敏感字符
			String note = req.getParameter("note");
			if(note != null && !note.equals("")){
				for(String str:strs){
					note = note.replaceAll(str, "***");
				}
			}
			req.setAttribute("note", note);
			chain.doFilter(req, res);
		}else{
			//拒绝服务
			res.setContentType("text/html;charset=utf-8");
			PrintWriter out = res.getWriter();
			out.println("<b><hr/></b><h1 align='center'>拒绝服务...</h1>");
		}
	}

	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("===== commonFilter#init =====");
		this.strs  = new String[]{"夏洛克" , "福尔摩斯" , "华生"};
	}
}

在web.xml文件中配置过滤器:

 <filter>
  	<filter-name>commonFilter</filter-name>
  	<filter-class>dis.geo.demos.filter.CommonFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>commonFilter</filter-name>
  	<url-pattern>/hello.jsp</url-pattern>
  </filter-mapping>

login.jsp文件内容:

<body>
	<br />
	<form name="loginForm" method="POST" action="hello.jsp">
		<table>
			<tr>
				<td><div align="right"><ml:content key="login.user" />:</div></td>
				<td><input type="text" name="loginusername" /></td>
			</tr>
			<tr>
				<td><div align="right"><ml:content key="login.note" />:</div></td>
				<td><textarea rows="5" cols="20" name="note"></textarea></td>
			</tr>
			<tr>
				<td></td>
				<td>
					<input type="submit" name="submit" value=<ml:content key="login.submit"/>>
					<input type="reset" name="reset" value=<ml:content key="login.reset"/>>
				</td>
			</tr>
		</table>
	</form>
</body>

hello.jsp:

<body>
	<b><ml:content key="hello.hi"/> :${param.loginusername}</b>
	<br/>
	<p><ml:content key="login.note"/> :<%=request.getAttribute("note") %></p>
</body>

启动服务器,按照下面的步骤进行实验:

(1)      访问login.jsp输入用户名“张华”,评论“I‘m 夏洛克·福尔摩斯的得力助手——Dr.华生!!!”点击提交,可以看到访问后页面内容中“夏洛克、福尔摩斯、华生”都被替换成“***”;

(2)      再访问login.jsp输入用户名“xiaoming”,评论“I‘m 夏洛克·福尔摩斯的得力助手——Dr.华生!!!”点击提交,访问后的页面内容为:拒绝访问…

上面的示例中模拟了使用过滤器完成黑名单功能和敏感字符替换功能。修改以下过滤器doFilter方法的代码,在chain.doFilter(req , res);代码行后添加如下代码:

chain.doFilter(req, res);

req.setAttribute("note",
"123456");

res.setStatus(404);

System.out.println("===== After doFilter =====");

打开网页的调试窗口,进行步骤(1),可以看到页面中内容没有发生变化,也就是说在chain.doFilter(req , res)之后对req的修改是无效的,而在网页的调试窗口看到响应的状态为404,也就是说在chain.doFilter(req , res)之后对响应的修改起作用了。而且在控制台看到语句输出===== After doFilter =====。然后把上面res.setStatus(404)修改为res.sendError(404);再进行步骤(1)就可以看到通常情况下的404错误:

上面的步骤中可以看到在chain.doFilter(req , res)之后的代码继续执行,但是此时req对象已经被过滤完毕,传递给了请求目标,再对其进行修改,将不会起作用;但是此时响应还没有被过滤,因此对响应的修改仍然有效。

应用中的多数页面可能是需要用户登录后才能使用的,如果在每个页面中进行判断,将会产生大量的重复代码,此时可以将此任务交给过滤器完成。用户登录后将用户信息保存在session中,如果用户没有登录而直接输入登录后才能使用网页地址,将被拦截到登录页面,可以在应用中增加LoginFilter过滤器

该示例见博客http://blog.csdn.net/goskalrie/article/details/51202741使用Cookie模拟自动登录部分。

时间: 2024-09-29 02:17:44

JavaWeb中 Filter使用的相关文章

JavaWeb中filter的详解及应用案例

一:Filter介绍 Filter可认为是Servlet的一种“变种”,它主要用于对用户请求(HttpServletRequest)进行预处理,也可以对服务器响应(HttpServletResponse)进行后处理,是个典型的处理链.它与Servlet的区别在于:它不能直接向用户生成响应.完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理. 二:Filter的几个用处 在HttpServletRequest到达

JAVA学习篇--javaweb之Filter详解

在DRP项目中,多次提到了Filter,它解决了字符集的统一设置以及统一控制简单WebCache,从中我们可以体会到,它给我们带来的好处不仅仅是减少代码量这么简单,它的出现避免了我们每个页面重复的编写相同的代码,减少了我们的工作量,而且给维护带来了极大的便利,那么它是如何实现统一管理的呢?既然它能统一管理某些重复的操作,那么它和AOP有什么关系呢? Filter简介 ServletAPI中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过

MVC的设计模式在JavaWeb中的实现

JSP开发模式 jsp开发模式的发展 1.模式1:(适合小型项目的技术的开发) a.第一版本,纯jsp(封装数据,处理数据,显示数据) b.第二版本,Jsp+JavaBean. jsp:收集数据,显示数据 JavaBean:封装.处理 2.模式2:servlet+Jsp+JavaBean(是mvc在java中的具体的实现,是java技术实现的具体的内容) a.servlet:负责协调jsp和javabean,获得数据,处理数据(业务逻辑),封装到javabean中,选择jsp去显示数据. b.j

javaweb之Filter详解

一.概念:Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等一些高级功能. 二.Filter简介Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filte

vuex中filter的使用 &amp;&amp; 快速判断一个数是否在一个数组中

vue中filter的使用 computed: mapState({ items: state => state.items.filter(function (value, index, arr) { return index < 5 }) }), 如上所示,对于vuex,我们在使用mapState获取state时, 可以使用filter来过滤其中的元素,在filter的回调函数中接受三个参数,第一个是value,即每一个元素的值: 第二个是index, 即每一个元素所在的index, 第三个

JSP中filter详解以及应用实例(转载)

filter功能.它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.换种说法,filter其实是一个”servlet chaining”(servlet 链). 一个filter 包括: 1. 在servlet被调用之前截获; 2. 在servlet被调用之前检查servlet reques

个人对JavaWeb中MVC与三层架构的区别理解

JavaWeb中MVC是指B/S结构开发中的一种设计模式,能够将Web页面与业务逻辑以及数据库操作之间的耦合性降到最低点,易于代码的重用以及后期维护.而三层架构的概念在JavaWeb中则是指Web层,业务层,数据层.但三层架构中却是把MVC中的Model,也就是JavaBeans分成业务层和数据层,而把Controller控制器以及View视图合并成Web层.二者之间最大的区别在于MVC只限于JavaWeb,而三层架构则能够实现在非Web应用平台之上,只需替换掉Web层足以,而业务层与数据层依旧

了解IE中filter属性的应用!

在设置不透明属性时,经常用opacity来增加层次感或者增加用户体验,但这个属性是css3属性,对于低级浏览器的兼容性来说就达不到预期的效果. 一般而言,我们都尽可能少用一些浏览私有属性-webkit,-moz,-ms,-o,但这也仅仅解决了市面上很多浏览器的问题,面对IE,特别是IE9-版本的,也是显得有气无力. 如果要使得市面上的浏览器达到统一的近类似效果,那么是非常有必要写上IE私有属性,触发IE hasLayout 特性,比如这样: .opacity{ opacity:0.5; filt

关于JS中数组splice,concat的用法和AngularJs中filter的补充知识

一 JS数组相关操作 1. splice函数,可做插入,删除,替换操作 1 <script> 2 "use strict" 3 var arr = ['z3']; 4 arr.splice(1,0,'l4'); 5 alert(arr); //z3,l4 6 arr.splice(1,1,'w5'); 7 alert(arr); //z3,w5 8 arr.splice(1,1); 9 alert(arr); //z3 10 arr.splice(10,1,'l4','w5