1、什么是过滤器
自己的理解:过滤器就是用户访问servlet的时候劫持某些servlet,在根据判断条件是否重定向,或者响应该请求。
定义:Servlet 过滤器是小型的 Web 组件,它们拦截请求和响应,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据。过滤器是通常封装了一些功能的 Web 组件,这些功能虽然很重要,但是对于处理客户机请求或发送响应来说不是决定性的。典型的例子包括记录关于请求和响应的数据、处理安全协议、管理会话属性,等等。过滤器提供一种面向对象的模块化机制,用以将公共任务封装到可插入的组件中,这些组件通过一个配置文件来声明,并动态地处理。
2、创建Servlet过滤器
所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。这个接口含有3个过滤器类必须实现的方法:
- init(FileterConfig):这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。在这个方法中可以读取web.xml文件中Servelt过滤器的初始化参数。容器启动的过程中启动
- doFilter(ServletRequest,ServletResponse,FilterChain):这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain参数用于访问后续过滤器
- destroy():Servlet容器在销毁过滤器实例前调用该方法,在这个方法中可以释放Servlet过滤器占用的资源
下面是一个过滤器的例子,这个名叫NoteFilter的过滤器可以拒绝列在黑名单上的客户访问留言簿,而且能将服务器响应客户请求所花的时间写入日志。NoteFilter的源代码如下:
A、 NoteFilter.java 文件代码如下
package demo; import java.io.IOException; import java.io.PrintWriter; 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; public class NoteFilter implements Filter{ private FilterConfig config = null; private String blackList =null; public void destroy() { blackList =null; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String userName = ((HttpServletRequest) request).getParameter("username"); if(userName != null) userName = new String(userName.getBytes("ISO-8859-1"),"utf-8"); if(userName !=null && blackList.indexOf(userName)!=-1) { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<html><head></head><body>"); out.println("<h1>对不起"+userName+",你没有权限留言</h1"); out.println("</body></html>"); out.flush(); return; } long before = System.currentTimeMillis(); config.getServletContext().log("NoteFilter:before call chian.doFilter()"); chain.doFilter(request, response); config.getServletContext().log("NoteFilter:after call chain.doFilter()"); long after = System.currentTimeMillis(); String name =null; if(request instanceof HttpServletRequest) { name=((HttpServletRequest)request).getRequestURI(); } config.getServletContext().log("NoteFilter:"+name+":"+(after-before)+"ms"); } public void init(FilterConfig filterConfig) throws ServletException { this.config = filterConfig; blackList = filterConfig.getInitParameter("blacklist"); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>MyServlet</servlet-name> <servlet-class>demo.MyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/MyServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <filter> <filter-name>NoteFilter</filter-name> <filter-class>demo.NoteFilter</filter-class> <init-param> <param-name>blacklist</param-name> <param-value>phpzxh</param-value> </init-param> </filter> <filter-mapping> <filter-name>NoteFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping> </web-app>
所有的访问链接都会触发过滤器NoteFilter用个测试链接 http://localhost:8088/delop/index.jsp?username=phpzxh
结果:
对不起phpzxh,你没有权限留言
3、特性
Servlet 过滤器中结合了许多元素,从而使得过滤器成为独特、强大和模块化的 Web 组件。也就是说,
Servlet 过滤器是:
声明式的:过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明。这样允许添加和删除过滤器,而无需改动任何应用程序代码或 JSP 页面。
动态的:过滤器在运行时由 Servlet 容器调用来拦截和处理请求和响应。
灵活的:过滤器在 Web 处理环境中的应用很广泛,涵盖诸如日志记录和安全等许多最公共的辅助任务。过滤器还是灵活的,因为它们可用于对来自客户机的直接调用执行预处理和后期处理,以及处理在防火墙之后的 Web 组件之间调度的请求。最后,可以将过滤器链接起来以提供必需的功能。
模块化的:通过把应用程序处理逻辑封装到单个类文件中,过滤器从而定义了可容易地从请求/响应链中添加或删除的模块化单元。
可移植的:与 Java 平台的其他许多方面一样,Servlet 过滤器是跨平台和跨容器可移植的,从而进一步支持了 Servler 过滤器的模块化和可重用本质。
可重用的:归功于过滤器实现类的模块化设计,以及声明式的过滤器配置方式,过滤器可以容易地跨越不同的项目和应用程序使用。
透明的:在请求/响应链中包括过滤器,这种设计是为了补充(而不是以任何方式替代)servlet 或 JSP 页面提供的核心处理。因而,过滤器可以根据需要添加或删除,而不会破坏 servlet 或 JSP 页面。