过滤器的基本概念
Filter是在Servlet2.3之后增加的新功能,当需要限制用户访问某些资源或者在处理请求时提前处理某些资源时,即可使用过滤器完成。
比如:我们在有些网站需要保持用户的登录状态才能进行某些操作,这时候用户登陆后就会有一个session来存储用户的信息,以供在页面跳转后还能获取到用户信息。
比如说用户在登录页登陆后,跳转到function.jsp页,在这个页可以留言,这时候function页就会从session中获取在登陆页绑定的用户的信息。然后获取用户id和留言一起存入数据库中。
但有一种情况,如果用户没有登陆,而是在地址栏中直接输入function.jsp,这时候就会直接跳转到function页,这时候再进行留言操作就是非法的,因为获取用户session的时候发现是空。
使用过滤器之后就可以避免这种情况,使在session中没有用户数据的时候无法访问除登录页之外的页面,这就是过滤器的用法之一。具体的我们下边会详解。
过滤器是以一种组件的形式绑定到Web应用程序中的,在处理时是以”链”的方式。
定义一个过滤器,则直接让一个类实现javax.servlet.Filter接口即可,此接口定义了3个操作方法。
void destroy()
Called by the web container to indicate to a filter that it is being taken out of service.
过滤器销毁时使用void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.
完成具体的过滤操作,然后通过FilterChain让请求继续向下传递void init(FilterConfig filterConfig)
Called by the web container to indicate to a filter that it is being placed into service.
过滤器初始化(容器启动时初始化)时调用,可以通过FilterConfig去的web.xml中配置的初始化参数。
下面举个简单的例子来说明Filter的工作流程
1. 创建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 LoginFilter implements Filter { //需要实现Filter接口
String param="";
@Override
public void destroy() {
System.out.println("过滤器销毁");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain fchain) throws IOException, ServletException {
System.out.println("doFilter()之前");
fchain.doFilter(request, response);
System.out.println("doFilter()之后");
}
@Override
public void init(FilterConfig config) throws ServletException {
param=config.getInitParameter("p1");
System.out.println("过滤器初始化,获得配置参数p1:"+param);
}
}
2. 在web.xml中配置相关信息,如下
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>cn.filter.LoginFilter</filter-class>
<init-param>
<param-name>p1</param-name>
<param-value>this is one</param-value>
</init-param>
<!--可以配置多个参数-->
<init-param>
<param-name>p2</param-name>
<param-value>this is two</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
大家会发现Filter的web.xml配置文件和Servlet十分相似,其实从大方面来说Servlet可以分为简单Servlet(最常用的,完成doPost(),doGet()功能的Servlet)、过滤Servlet(Filter过滤器) 和 监听Servlet(监听器) 三种。
3. Filter的执行过程
现在这个项目中有两个文件,test.html和TestServlet.java。
在test页面有个submit button可以post方式提交表单到TestServlet。
在TestServlet中doPost()方法中有一条语句。
@WebServlet(urlPatterns="/TestServlet")
public class TextServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("This is Servlet");
}
}
所以简单的看做TestServlet是test.html的处理页就可以,我们只是来看Filter在test发出请求时是怎么执行的。
3.1 启动服务器
服务器加载配置,这时候执行Filter的init(FilterConfig config)方法开始初始化,控制台输出
过滤器初始化,获得配置参数p2:this is two
可知init方法是在启动服务器的时候就执行的了。
3.2 地址栏访问test.html页面
控制台输出
**doFilter()之前
doFilter()之后**
说明访问test.html时经过了过滤器,并且执行了doFilter()方法。
那么是什么时候执行的呢?我们可以从下边访问的Servlet中看到。
3.3 点击button提交表单到TestServlet
控制台输出
doFilter()之前
This is Servlet
doFilter()之后
这时候就很明显了,访问是在两条输出语句之间也就是fchain.doFilter(request, response)执行的。而且执行完TestServlet中的内容后又返回来继续执行后边的语句。这就体现了Filter是以链的方式执行的。
3.4 关闭服务器
关闭服务器的时候会调用destroy方法,控制台输出
过滤器销毁
以上就是过滤器的所有执行过程,后边我会讲解一下Filter的一些应用和遇到的问题。