Filter和Listener是Servlet规范中的两个高级特性,不同于servlet,他们不用于处理客户端的请求,只用于request,response进行修改,或者对context、session、request事件进行监听,为我们servlet提供一些额外的辅助性功能,帮助我们简化开发。
一、Filter的概述
Filter也称之为过滤器,Filter是Servlet技术中最激动人心的技术。Filter可以管理WEB服务器中所有的WEB资源,可以对JSP,Servlet,HTML,以及图片文件等进行拦截和过滤,因此常用与实现一些特殊的功能,比如:访问权限控制,敏感词汇的过滤,乱码的处理等。Filter其实就是一个特殊的Servlet。
Servlet API提供了Filter接口,在WEB项目中,一个Java类实现了Filter接口,那这个Java类他就是Filter过滤器,Filter其实就是在用户访问目标资源之前,对请求和响应进行拦截过滤和处理。
Filter的作用
在HttpServletRequest和HttpServletResponse到达Servlet之前,拦截客户的HttpServletRequest和HttpServletResponse,根据要求检查HTTPServletRequest和HttpServletResponse,也可以修改HttpServletResponse和HttpServletResponse。
二、Filter的简单案例
开发步骤:
在WEB项目中创建一个Java类,让该类实现javax.servlet.Filter接口
在该类中实现Filter接口的所有方法
在WEB.xml中进行相关的配置
创建Java类实现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 FilterDemo implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
//放行的方法,如果满足条件,就会调用下面的doFilter方法,
//将request和response对象传给Servlet的service()方法执行
arg2.doFilter(arg0,arg1);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
配置文件的设置:
<filter>
<filter-name>FilterDemo</filter-name>
<filter-class>com.itheima.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<url-pattern>/*</url-pattern><!-- 拦截资源的路径,/*代表拦截所有web资源 -->
</filter-mapping>
创建一个jsp文件进行访问:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>hello filter</h1>
</body>
</html>
Filter的入门案例
注意:
(1)filter是一个特殊的Servlet,所以他的配置和Servlet是一样的,两者的本质区别是,filter不能产生一个请求或者响应,只能修改摸一个资源的请求或者响应
(2)必须实现javax.servlet.Filter接口,需要在web.xml中进行配置才能生效
(3)Filter和特定的url关联,当用户请求访问次url时,才会触发filter调用doFilter这个方法。
三、Filter的生命周期
创建:
Filter对象在WEB服务器启动的时候,由WEB服务器帮我们创建,调用init()方法
销毁:
Filter对象在WEB服务器关闭的时候会被销毁,调用destroy()方法
下面我们来测试一下Filter的生命周期:
首先创建一个Filter,可以使用Eclipse直接创建
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 FilterDemo2 implements Filter {
public FilterDemo2() {
// TODO Auto-generated constructor stub
System.out.println("FilterDemo2的构造方法执行了");
}
public void destroy() {
// TODO Auto-generated method stub
System.out.println("FilterDemo2的destroy执行了");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
// pass the request along the filter chain
chain.doFilter(request, response);
System.out.println("FilterDemo2的doFilter方法执行了");
}
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
System.out.println("FilterDemo2的init方法执行了");
}
}
然后修改配置文件:
将拦截路径url-pattern修改一下,改为“/*”。
最后访问demo01.jsp进行测试:
我们可以发现,在重启tomcat的过程中,会输出“FilterDemo2的构造方法执行了”和“FilterDemo2的init方法执行了”,每次访问页面,控制台都会输出一次“FilterDemo2的doFilter方法执行”,最后当我们关闭tomcat的时候,控制台会输出FilterDemo2的destroy执行了。
四、Filter链
在同一个WEB应用中,可以开发编写多个Filter,那这多个Filter组成了一个链子,这个链子我们就称之为Filter链,WEB服务器在执行Filter链的时候,会根据Filter在web.xml文件中的配置顺序来执行,如果有任何一个Filter没有放行,那么页面就不会输出。
示例:
如果我们将上面两个案例中配置文件信息都写入web.xml,修改第一个案例中的doFilter方法:
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
System.out.println("FilterDemo执行了");
//放行的方法,如果满足条件,就会调用下面的doFilter方法,
//将request和response对象传给Servlet的service()方法执行
arg2.doFilter(arg0,arg1);
}
访问demo01.jsp后,我们发现浏览器输出了内容,控制台也输出了两条信息“FilterDemo执行了”和“FilterDemo2的doFilter方法执行”,说明我们的两个Filter都放行了,最后jsp文件可以执行;
如果我们将上面doFilter方法中的doFilter方法注释掉:
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
System.out.println("FilterDemo执行了");
//放行的方法,如果满足条件,就会调用下面的doFilter方法,
//将request和response对象传给Servlet的service()方法执行
//arg2.doFilter(arg0,arg1);
}
这时我们会发现,页面没有输出“hello filter”,同时控制台只输出了“FilterDemo执行了”,说明我们的访问在第一个Filter处被拦截了,后面的访问都无法执行。
五、获取Filter的初始化参数
在web.xml文件中,可以通过<init-param>标签来为Filter配置初始化参数,WEB服务器在创建Filter对象的时候,会调用Filter对象的init方法,并且将封装了Filter初始化参数的FilterConfig对象传递进去。在Filter的init方法中,就可以通过FilterConfig对象来获取Filter的初始化参数,参数在服务器打开的时候就会被获取到。
配置文件
<filter>
<display-name>FilterDemo3</display-name>
<filter-name>FilterDemo3</filter-name>
<filter-class>com.itheima.FilterDemo3</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>zhangsan</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FilterDemo3</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
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 FilterDemo3 implements Filter {
public FilterDemo3() {
// TODO Auto-generated constructor stub
}
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
// pass the request along the filter chain
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
String username = fConfig.getInitParameter("username");
String password = fConfig.getInitParameter("password");
System.out.println(username);
System.out.println(password);
}
}
控制台信息
网友评论