directory=“logs”prefix=“localhost_log.”suffix=”.txt”
timestamp=“true”/>
七、过滤器的实现方式
过滤器实现方式在不保证功能前提下,从性能角度考虑有如下先后顺序:
Decorator或Proxy模式;AOP拦截器。
1,标准Servlet控制器
包装了请求和响应对象。
web容器来充当过滤管理器(FilterManager)和过滤链(FilterChain)来管理和协调过滤器。
问题:
功能覆盖范围上,也是一个scope,如果功能需求要为某个类的方法实现实现过滤,使用一个ServletFilter这样过滤器实现。
但是它对所有的Servlet请求都进行过滤,这无疑范了杀鸡取卵的错误,会造成系统性能上的损失。
2,使用Decorator模式来定制过滤器
如果过滤器是业务逻辑的一部分,而且在设计时,我们可以确定这些过滤器,进行特定指定的拦截。
Decorator模式在点上针对性相当强,特别在这个点上有一系列过滤器需要实现时。
如果某个过滤功能是很多类都需要的,会形成很多Decorator附加类,造成点形成面的情况,则升级使用AOP拦截器。
优点:
能够动态地为过滤器扩展功能。
也可以使用FilterManager和FilterChain过滤器链负责协调和管理过滤处理,这样单独的过滤器就不用和其他过滤器直接通信了。
问题:
不能以一种标准的可移植的方式支持对请求和响应对象的包装,而且不能够修改请求对象。
缺乏完善的缓存机制。
当过滤器要控制输出流的时候,还必须引入某种形式的缓存机制。
3,使用模板方法模式来定制过滤器。
可以和其他方法混用。
优点:
这种方式是基于标准的过滤器的,基本过滤器作为一个基类,封装了过滤器API的所有细节。
专注于预处理和后处理的所有逻辑。
基本过滤器声明了每个过滤器要完成的方法,每个过滤器子类来定义这些定义方法。
由超类来控制子类的控制流程。
4,使用AOP框架拦截器。
当功能不是针对某个具体类或方法(方法权限除外),而是一系列类,使用动态AOP拦截器,性能损耗也是值得的,而且是必要的。
八、过滤器的应用场合
简洁的说法:
1.认证过滤:
对用户请求进行统一认证。
2.登录和审核过滤:
对用户的访问请求进行审核和对请求信息进行日志记录。
3,数据过滤:
对用户发送的数据进行过滤,修改或替换。
4.图像转换过滤:
转换图像的格式。
5.数据压缩过滤:
对请求内容进行解压,对响应内容进行压缩。
6.加密过滤:
对请求和响应进行加密处理。
7.令牌过滤:
身份验证
8.资源访问触发事件过滤:
9.XSL/T过滤
10.Mime-type过滤
复杂的说法:
在适合使用装饰过滤器模式或者拦截器模式的任何地方,都可以使用过滤器:
加载:
对于到达系统的所有请求,过滤器收集诸如浏览器类型、一天中的时间、转发URL等相关信息,并对它们进行日志记录。
性能:
过滤器在内容通过线路传来并在到达servlet和JSP页面之前解压缩该内容,然后再取得响应内容,并在将响应内容发送到客户机机器之前将它转换为压缩格式。
安全:
过滤器处理身份验证令牌的管理,并适当地限制安全资源的访问,提示用户进行身份验证和/或将他们指引到第三方进行身份验证。
过滤器甚至能够管理访问控制列表(AccessControlList,ACL),以便除了身份验证之外还提供授权机制。
将安全逻辑放在过滤器中,而不是放在servlet或者JSP页面中,这样提供了巨大的灵活性。
在开发期间,过滤器可以关闭(在web.xml文件中注释掉)。
在生产应用中,过滤器又可以再次启用。
此外还可以添加多个过滤器,以便根据需要提高安全、加密和不可拒绝的服务的等级。
会话处理:
将servlet和JSP页面与会话处理代码混杂在一起可能会带来相当大的麻烦。
使用过滤器来管理会话可以让Web页面集中精力考虑内容显示和委托处理,而不必担心会话管理的细节。
XSLT转换:
不管是使用移动客户端还是使用基于XML的Web服务,无需把逻辑嵌入应用程序就在XML语法之间执行转换的能力都绝对是无价的。
九、MVC体系结构中的Servlet过滤器
不管过滤器处于什么位置,过滤器在处理流中的应用都是相同的。
过滤器旨在扩充MVC体系结构的请求/响应处理流。
从MVC的观点看,调度器组件(它或者包括在控制器组件中,或者配合控制器组件工作)把请求转发给适当的应用程序组件以进行处理。
这使得控制器层成为包括Servlet过滤器的最佳位置。
通过把过滤器放在控制器组件本身的前面,过滤器可以应用于所有请求,
或者通过将它放在控制器/调度器与模型和控制器之间,它可以应用于单独的Web组件。
十、应用示例或说明
1,使用过滤器认证用户:
每个过滤器也可以配置初始化参数,可以将不需要过滤的地址配置到这个Filter的配置参数中,
过滤时,如果请求地址在配置参数中,则放行,这样就避免了在程序中硬编码。
每个Filter中初始化时,都可以得到配置对象,在Filter中配置二个不需要过滤的地址,一个是登陆页面,一个是执行登陆认证的servlet;
2,登录和审核过滤的示例:
使用servlet过滤器来控制终端用户对应用程序特性的访问:
通过显示基于用户角色的用户界面来控制对应用程序特性的访问。
企业用户能够访问特定页面,但个人用户不能访问这样的页面。
应用一个过滤器来处理用户请求并返回合适的页面。
通过使用过滤器,您能够向一个基于JSP的应用程序添加这种类型的访问控制而无需更改现有的代码。
这种基于过滤器的访问控制模型也很灵活,因为把用户角色映射到特定JSP的数据存储在一个XML文件中。
因此,您可以修改映射而不用修改应用程序—不需要重新编译或重新部署。
实施:
每当用户从一个包含/controllerservlet模式的URI请求资源时就会调用AccessControlFilter的实例
当访问控制过滤器被初始化后,从映射文件读取数据,而AccessControlFilter.doFilter方法负责处理过滤事务。
在获取了用户角色和所请求页面的URL之后,doFilter把这些值与映射数据对比。
如果所请求的页面对用户角色是合适的,那么代码将调用chain.doFilter方法来调用该页面并继续正常的处理。
否则,代码将在chain.doFilter之前调用request.setAttribute,结果是ControllerServlet使用户重新进入到登录页面。
相关文件:
1、web.xml——Web部署描述符文件
AccessControlFilter
AccessControlFilter
/controllerservlet
2、Control.xml——描述事件、用户角色和JSP联系的xml文件
BUYSTOCK
buyStock
jsps/BuyStock.jsp
USER
...
CORPUPLOAD
jsps/CorporateUpload.jsp
CORP
...
CONFIGNEWSUPLOAD
configNewsUpload
jsps/UploadData.jsp
ADMIN
...
LOGIN
checkPassword
jsps/MyHome.jsp
DEFAULT
USER
CORP
ADMIN
3、AccessControlFilter.java——过滤器类
//读取Control.xml,对用户的权限做检查
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)
throwsIOException,ServletException{
HttpSessionsession=((HttpServletRequest)request).getSession();
StringeventName=request.getParameter("EVENTNAME");
if(eventName!
=null&&urlMap!
=null){
Stringrole=(String)session.getAttribute("ROLE");
if(role==null){
role="DEFAULT";
}
URLMappingevent=(URLMapping)urlMap.get(eventName);
if((event!
=null)&&(event.getRoles()!
=null)&&(event.getRoles().length>0)){
//Newsessionsonotloggedinyet.Redirecttologinpage
if(session.isNew()){
request.setAttribute("EVENTNAME","FIRSTPAGE");
}
//Ifinvalidaccess,redirecttologinpage
elseif(!
event.isValidRole(role)){
request.setAttribute("EVENTNAME","LOGINPAGE");
}
}
}else{
request.setAttribute("EVENTNAME","FIRSTPAGE");
}
//TheprivilegesaresufficienttoinvokethisURL,continuenormal
//processingoftherequest
chain.doFilter(request,response);
}
4、对请求信息进行日志记录的示例
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsServletException,IOException{
//把ServletRequest对象构造为HttpServletRequest
//从请求中提出需要的进行日志记录的信息
Stringurl=req.getRequestURI();
HttpSessionso=req.getSession();
StringcanLog=(String)so.getAttribute(url);
//如果第一次访问该页面,就进行日志处理
if(canLog==null){
so.setAttribute(url,"Y");
doLog();
}
chain.doFilter(request,response);
}
5、用过滤器来解决客户端和服务器端编码一致,防止中文乱码的问题。
publicclassCharacterEncodingFilterimplementsFilter{
protectedFilterConfigfilterConfig=null;
protectedStringencoding="";
publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)
throwsIOException,ServletException{
if(encoding!
=null){
servletRequest.setCharacterEncoding(encoding);
}
filterChain.doFilter(servletRequest,servletResponse);
}
publicvoiddestroy(){
filterConfig=null;
encoding=null;
}
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
this.filterConfig=filterConfig;
this.encoding=filterConfig.getInitParameter("encoding");
}
}
6、使Browser浏览器不缓存页面的过滤器
publicclassForceNoCacheFilterimplementsFilter{
publicvoid