过滤器是Web程序中的可重用组件,它在Servlet2.3规范中被引入,其应用十分广泛,为java Web程序的开始带来了更强大的功能。
Servlet过滤器是客户端与目标资源间的中间层组件,用于拦截客户的请求与相应信息,当WEB容器接收到一个用户的请求,Web容器判断此请求是否与过滤器对象相关联,如果相关联,容器将这一请求交给过滤器进行处理,在处理过程中过滤器可以对请求进行操作,如更改请求中的信息数据,在过滤器处理完成后,在将这一请求交个其他业务处理,当所有业务处理完成,需要对客户端进行相应时,容器又将相应交个过滤器进行很粗鲁,过滤器处理响应完成将响应发送到客户端。
在多个处理器的处理方式中,容器首先将请求交给第一个过滤器处理,处理完成后交给下一个过滤器处理,以此类推,直至最后一个过滤器处理完成,当需要对客户端回应时,将按照相反的方向对回应进行处理,直到交个第一个过滤器,最后发送给客户端回应。
过滤器API
过滤器与Servlet非常相似,他通过三个核心接口进行操作,分别是Filter接口、FilterChain接口与FilterConfig接口。
Filter接口
Filter接口位于javax.servlet包中,与Servlet接口非常类似、定义一个过滤器对象需要实现此接口,子啊Filter接口中包含三个方法:
方法 | 说明 |
public void init(FilterConfig filterConfig) | 过滤器的初始化方法,容器调用此方法完成过滤器的初始化,对于每一个Filter实例,此方法只被调用一次。 |
public void doFilter(ServletRequest request,ServlertResponse response,FilterChain chain) | 此方法与Servlet的service()方法类似,当请求以及响应交给过滤器时,过滤器调用此方法进行过滤处理。 |
public void destroy() | 在过滤器生命周期结束时调用此方法,此方法可用于释放过滤器所占用的所有资源。 |
FilterChain接口
FilterChain接口位于javax.servlet包中,此接口由容器实现,在FilterChain接口只包含一个方法,其声明如下:
void doFilter(ServletRequest request,ServletResponse response)throws IOException,ServletException
此方法用于将过滤器处理的请求或响应传递给下一个过滤器对象。在多个顾虑器的Web应用中,可以通过此方法进行传递。
FilterConfig接口。
FilterConfig接口位于javax.servlet包中,此接口由容器进行实现,用于获取过滤器初始化期间的参数信息,其方法及说明如下:
方法 | 说明 |
public String getFilterName() | 返回过滤器名称 |
public String getInitParameter(String name) | 返回初始化名称为name的参数值 |
public Enumeration getInitParameterNames() | 返回所有初始化参数名的枚举集合。 |
public ServletContext getServletContext() | 返回Servlet的上下文对象。 |
下面看一下如何通过Filter接口创建一个过滤器对象
package Filter;
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;
public class MyFilter implements Filter {
private String encoding=null;
private FilterConfig config = null;
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
配置过滤器
在创建一个过滤器对象后,需要对其进行配置才可以使用,过滤器配置方法与Servlet配置方法类似,都通过web.xml文件进行配置。其配置方法由以下两步实现:
1、 声明过滤器对象。
在web.xml文件中通过<filter>标签声明一个过滤器对象,在此标签中包含三个常用的子元素,分别是:<filter-name>、<filter-class>和<init-param>。其中<filter-name>元素用于指定过滤器名称,此名称为自定义名称。<filter-class>元素用于指定过滤器对象的完整位置,包含过滤器对象的包名和类名;<inti-param>元素用于设定过滤器的初始化参数。<init-param>元素包括两个常用的子元素,分别是<param-name>和<param-value>。其中<param-name>用于指定初始化参数的名称,<param-value>用于指定初始化参数的值。配置方法如下:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>Filter.MyFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
映射过滤器
在web.xml中声明了过滤器对象后,需要映射访问过滤器过滤的对象,此操作为<filter-mapping>标签进行配置。在<filter-mapping>标签中主要配置过滤器的名称,关联的URL样式、对应的请求方式等。其配置方法如下:
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-name>用于指定过滤器名称,此名称与<filter>标签中的<filter-name>相对应
<url-pattern>用于指定过滤器关联的URL样式,设置为/*为关联全部的url
<dispatcher>用于指定过滤器对应的请求方式
dispatcher可选值及说明如下:
可选值 | 说明 |
REQUEST | 当客户端直接请求时,则通过过滤器进行处理 |
INCLUDE | 当客户端通过RequestDispatcher对象的include()方法请求处理时,通过过滤器进行处理 |
FORWARD | 当客户端通过RequestDispatcher对象的forward()方法请求时,通过过滤器进行处理 |
ERROR | 当声明式异常产生时,则通过过滤器处理 |
下面看一个编写字符编码过滤器的具体示例:
首先创建一个字符编码过滤器类MyFilter,此类实现Filter接口,以及重写他的三个方法。代码如下:
package Filter;
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;
public class MyFilter implements Filter {
private String encoding=null;
private FilterConfig config = null;
@Override
public void init(FilterConfig config) throws ServletException {
this.config=config;
this.encoding = config.getInitParameter("encoding");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if(encoding !=null){
request.setCharacterEncoding(encoding);
response.setContentType("text/html;charset="+encoding);
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
encoding=null;
config=null;
}
}
MyFilter类的init()方法,用于读取过滤器的初始化参数,参数encoding为实例中所用到的字符编码。在doFilter()方法中,分别将request和response对象中的编码格式设置为读取到的编码格式,最后在destory()方法中将其属性设置为null,将被垃圾回收器回收。
在web.xml文件中对过滤器进行配置。关键代码如下:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>Filter.MyFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
在web.xml配置文件中需要对过滤器进行声明及验证。其中声明过程通过<init-param>指定了初始化参数的字符集编码为utf-8。
通过请求对过滤器进行验证。实例中使用表单向Servlet发送中文信息进行测试,其中表单信息放在Form.jsp页面中,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<form action="servlet/MyServlet" method = "get">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name = "password"></td>
</tr>
</table>
<input type="submit" value="提交"/>
</form>
</body>
</html>
这一请求将有Servlet对象MyServlet类进行处理,此类使用doGet()方法接受表单的请求并将表单中的username和password进行验证后,在页面输出相应的信息。其代码如下:
package Servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
//response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
String username = request.getParameter("username");
String password = request.getParameter("password");
if(username.equals(password)){
out.print(username+"欢迎你!");
}else{
out.print("您输入密码有误,请重新输入!");
}
out.flush();
out.close();
}
}