Servlet过滤器是一种小型的、可插入的Web组件,其提供了对Web应用程序的前期处理和后期处理的逻辑控制,可以拦截请求和响应,以便查看、提取 或以某种方式操作正在客户端和服务器之间进行交换的数据。Servlet过滤器具有动态、灵活、透明、模块化、可移植、可重用等性质,是一种自包含的,模 块化的组件,可以在使用时将其添加到请求/响应链中,也可以被删除而不影响到应用程序的其他Web组件。Servlet过滤器应用非常广泛,有拦截的地方 一般都可以用到过滤器,其也和Servlet类似,也需要在Web应用配置文件(即Web.xml)中进行配置部署。
过滤器并不是servlet,他们并不实际创建一个请求。他们是请求到达一个servlet前的预处理程序,和/或响应离开servlet后的后处理程序。一个过滤器能够:
1.在一个servlet被调用前截获该调用
2.在一个servlet被调用前检查请求
3.修改在实际请求中提供了可定制请求对象的请求头和请求数据
4.修改在实际响应中提供了可定制响应对象的响应头和响应数据
过滤器类必须要实现Filter接口,这个接口在javax.servlet包中。该接口有三个方法如下:
1.void init(FilterConfig config) throws ServletException:在过滤器执行service前被调用,以设置过滤器的配置对象。服务器调用一次init(FilterConfig) 以为服务准备过滤器,然后在请求需要使用过滤器的任何时候调用doFilter()。FilterConfig接口检索过滤器名、初始化参数以及活动的 servlet上下文。
2.void doFilter(ServletRequest req,ServletResponse res,FilterChain chain) throws IOException,ServletException;执行实际的过滤工作。在doFilter()方法中,每个过滤器都接受当前的请求和响应,而 FilterChain包含的过滤器则仍然必须被处理。doFilter()方法中,过滤器可以对请求和响应做它想做的一切。过滤器调用 chain.doFilter()将控制权传送给下一个过滤器。当这个调用返回后,过滤器可以在它的doFilter()方法的最后对响应做些其他的工 作;例如,它能记录响应的信息。如果过滤器想要终止请求的处理或或得对响应的完全控制,则他可以不调用下一个过滤器。
3.void destroy();在过滤器执行service后被调用。服务器调用destory()以指出过滤器已结束服务。
下面是一个很经典的例子,记录请求所持续的时间。
import java.io. * ;
import javax.servlet. * ;
import javax.servlet.http. * ;
public class TimerFilter implements Filter
{
private FilterConfig config = null ;
public void init(FilterConfig config) throws ServletException // 初始化
{
this .config = config;
}
public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException, ServletException
{
long before = System.currentTimeMillis(); // 请求处理前获取系统时间
chain.doFilter(request, response); // 将请求转发到过滤器链上的其他对象
long after = System.currentTimeMillis(); // 请求处理后获取系统时间
String name = "" ;
if (request instanceof HttpServletRequest)
{
name = ((HttpServletRequest)request).getRequestURI(); // 获取发出请求的URI
}
config.getServletContext().log(name + " : " + (after - before) + " ms " ); // 记录信息
}
public void destroy() // 结束服务
{
config = null ;
}
}
前面说过,过滤器要在Web.xml文件中部署,部署跟Servlet部署非常相似,就是把Servlet部署中的标签中servlet改为filter就可以了。
< filter >
< filter-name > timerFilter </ filter-name >
< filter-class > TimerFilter </ filter-class >
</ filter >
< filter-mapping >
< filter-name > timerFilter </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
一、字符编码的过滤器 /** *//** public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException public void destroy() public void init(FilterConfig filterConfig) throws ServletException } 二、使浏览器不缓存页面的过滤器 /** *//** public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException public void destroy() { public void init(FilterConfig filterConfig) throws ServletException {
/** *//**
* redirectURL 如果用户未登录,则重定向到指定的页面,URL不包括 ContextPath * notCheckURLList 不做检查的URL列表,以分号分开,并且 URL 中不包括 ContextPath */ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException HttpSession session = request.getSession(); public void destroy() private boolean checkRequestURIIntNotFilterList(HttpServletRequest request) public void init(FilterConfig filterConfig) throws ServletException String notCheckURLListStr = filterConfig.getInitParameter("notCheckURLList"); if(notCheckURLListStr != null) 四、资源保护过滤器 import javax.servlet.Filter; /** *//** //the logger object //a set of restricted resources /** *//** /** *//** String contextPath = ((HttpServletRequest)req).getContextPath(); this.logger.debug("contextPath = " + contextPath); if (this.contains(requestUri, contextPath) && !this.authorize((HttpServletRequest)req)) { public void destroy() {} private boolean contains(String value, String contextPath) { while (ite.hasNext()) { if ((contextPath + restrictedResource).equalsIgnoreCase(value)) { return false; private boolean authorize(HttpServletRequest req) { //处理用户登录 if (user != null && user.getLoggedIn()) { 五 利用Filter限制用户浏览权限 在一个系统中通常有多个权限的用户。不同权限用户的可以浏览不同的页面。使用Filter进行判断不仅省下了代码量,而且如果要更改的话只需要在Filter文件里动下就可以。 import java.io.IOException;
public class RightFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain arg2) throws IOException, ServletException { } public void init(FilterConfig arg0) throws ServletException { } } 在web.xml中加入Filter的配置,如下: <!-- 判断页面的访问权限 --> <filter-name>EncodingAndCacheflush</filter-name> 要传递参数的时候最好使用form进行传参,如果使用链接的话当中文字符的时候过滤器转码是不会起作用的,还有就是页面上 form的method也要设置为post,不然过滤器也起不了作用。 |