.1)什么是过滤器
servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。简单说,就是可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理。
.2)filter工作原理
先来看看filter原理图:
当客户端向Web资源发出请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。
在上面的描述中,提到了过滤链(FilterChain)的问题,需要特别指出的是,多个过滤器执行的顺序是由配置在web.xml中的顺序决定的。
Filter的创建和销毁是由WEB服务器负责的,在应用启动的时候装载Filter类并创建对象实例,然后调用init()方法,接着被Web容器保存进应用级的集合容器中,等待用户访问资源;当用户访问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了);当应用服务被停止或重新装载了,则会执行Filter的destroy方法,Filter对象销毁。
注意:init方法与destroy方法只会直接一次。
.4)filter API
servlet对过滤器提供了3个接口,分别是:filter,filterChain,filterConfig
filter接口,主要提供下面3个方法:
init() Init 方法在 Filter 生命周期中仅执行一次,web 容器在创建了filter对象实例后调用
destory() 在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
doFilter() Filter 链的执行 控制
filterChain接口,提供了doFilter()方法,主要进行链的控制
filterConfig接口,检索过滤器名、初始化参数以及活动的Servlet上下文 ,提供下面4个方法:
getFilterName() 返回web.xml部署文件中定义的该过滤器的名称。
getServletContext() 返回调用者所处的servlet上下文。
getlnitParameter()返回过滤器初始化参数值的字符串形式,当参数不存在时,返回nul1.name是初始化参数名。
getlnitParameterNames() 以Enumeration形式返回过滤器所有初始化参数值,如果没有初始化参数,返回为空。
.5)使用场景
过滤器主要使用场景有以下几点:
(2)统计web应用的访问量,和访问的命中率,报告
(3)实现web应用的日志、乱码处理功能
(4)实现数据压缩功能
(5)对传输的数据进行加密
(6)实现XML文件的XSLT转换
.6)filter使用
创建HelloServlet,有请求就输出Hello字符串
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = -1430231096992328970L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
PrintWriter pw=resp.getWriter();
pw.print("Hello");
}
}
创建EncodingFilter,过滤servlet请求并设置编码为utf-8
public class EncodingFilter implements Filter {
private String encoding;
// 项目结束时就已经进行销毁
public void destroy() {
System.out.println("do destroy()");
encoding = null;
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
System.out.println("before encoding " + encoding + " filter!");
req.setCharacterEncoding(encoding);
chain.doFilter(req, resp);
System.out.println("after encoding " + encoding + " filter!");
}
// 项目启动时就已经进行读取
public void init(FilterConfig config) throws ServletException {
System.out.println("init HelloFilter");
encoding = config.getInitParameter("encoding");
}
}
web.xml配置servlet及filter
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>JustT</display-name>
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>com.test.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
<filter>
<filter-name>setCharacterEncoding</filter-name>
<filter-class>com.test.servlet.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>