1.filter简介
Flter中文意思为过滤器。顾名思义,过滤器可在浏览器以及目标资源之间起到一个过滤的作用。例如:水净化器,可以看成是生活中的一个过滤器,他可以将污水中的杂质过滤,从而使进入的污水变成净水。
对于WEB应用来说,过滤器是一个驻留在服务器中的WEB组件,他可以截取客户端和WEB资源之间的请求和响应信息。
WEB资源可能包括Servlet、JSP、HTML页面等。
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:
Filter是Tomcat容器内的过滤器,在请求到达容器是先会调用过滤器,再调用我们的servlet或者jsp
当服务器收到特定的请求后,会先将请求交给过滤器,程序员可以在过滤器中对请求信息进行读取修改等操作,然后将请求信息再发送给目标资源。目标资源作出响应后,服务器会再次将响应转交给过滤器,在过滤器中同样可以对响应信息做一些操作,然后再将响应发送给浏览器。
2.Filter过滤器的介绍
Filter过滤器是JavaWeb三大组件之一,其余组件是:Servlet程序、Listener监听器
Filter过滤器是JavaEE规范,也就是一个接口
Filter过滤器的作用是:拦截请求、过滤响应
3.Filter请求和响应
Filter是可以转换请求或响应的标头和内容 (或两者) 的对象。Filter与 web 组件的区别在于, Filter本身通常不会创建响应。相反, Filter提供了可 "附加" 到任何类型的 web 资源的功能。因此, Filter不应依赖于它充当其Filter的 web 资源。这样, 它可以由多种类型的 web 资源组成。
Filter可以执行的主要任务如下所示:
查询请求并采取相应的操作。
阻止请求和响应对通过任何进一步。
修改请求标头和数据。您可以通过提供请求的自定义版本来执行此操作。
修改响应标头和数据。您可以通过提供响应的自定义版本来执行此操作。
与外部资源交互。
Filter的应用包括身份验证、日志记录、图像转换、数据压缩、加密、令牌流、XML 转换等。
您可以将 web 资源配置为按特定顺序按零、一个或多个Filter链进行筛选。此链是在部署包含该组件的 web 应用程序时指定的, 并且在 web 容器加载组件时实例化。
4.filter的实现
编写Filter和编写Servlet类似,都需要实现接口。
编写Filter需要实现Filter接口,我们来看一下Filter接口的主要方法:
Filter
init(FilterConfig): void
doFilter(ServletRequest, ServletResponse, FilterChain) : void
destroy() : void
Filter接口,实现Filter需要实现该接口
init0方法用于初始化Filter
doFilter()作用和service()方法类似,是过滤请求和响应的主要方法。
destroy()用于在Filter对象被销毁前做一些收尾工作。如:释放资源等
FilterConfig
getFilterName() : String
getSenvletContext() : ServletContext
getinitParameter(String) : String
getinitParameterNames() : Enumeration
FilterConfig对象在服务器调用init()方法时传递进来
getFilterName() 获取Filter的名字
getServletContext() 获取ServletContext对象(即application)
getInitParameter() 获取Filter的初始化参数
getlnitParameterNames() 获取所有初始化参数的名字
5.Filter过滤器的生命周期
构造方法
init初始化方法
doFilter方法(其中有filterChain.doFilter方法)
destroy方法
其中:
①1和2在web工程启动的时候执行(即在创建Filter过滤器)
②第三步,符合拦截路径的请求发送到服务器的时候,自动的执行,若请求不属于拦截路径,则不会执行
③第四步,停止web工程的时候执行(停止web工程,也会销毁Filter过滤器)
6.FilterConfig类
FilterConfig类是Filter过滤器的配置文件类,每次创建Filter的时候,也会创建一个FilterConfig
类,其中包含了Filter配置文件的配置信息
FilterConfig类的作用是获取Filter过滤器的配置文件内容:
⑴获取Filter的名称,即web.xml文件中标签的值:
filterConfig.getFilterName(;
⑵获取web.xml文件中标签的值(写在filter标签中,可写多),如:
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
⑶获取ServletContext对象: filterConfig.getServletContext()
7.FilterChain过滤器链
作用: 解决多个过滤器如何一起工作
注意:
上述两个Filter拦截的资源路径相同,代表一定会执行两个Filter过滤器的doFilter方法,但因为手动注释不一定执行其中的chain.doFilter方法
如果两Flter栏戴资源不同,且栏截资源符合Filter1,不符合Flter2,则会执行Flter1 的doFiter方法,且执行其中的chain.doFiter方法时,不会去执行Filter2的doFiter方法,直接去访问资源,之后执行Filter1的后置代码(在chain.doFilter之后的均是后置代码)
如果请求的资源不符合过滤器1和2的拦截路径,两个doFilter方法都不执行
前置代码、chain.doFilter方法、后置代码都在doFilter方法中
8.Filter过滤器的使用
1.Filter过滤器的使用步骤:
编写一个类实现Filter接口 (导入的包为:javax.servlet.Filter)
实现三个方法:
实现过滤方法doFilter(),此方法中的:
filterChain.doFilter(servletRequest,servletResponse);
只有执行此方法,才可以访问拦截路径中的资源,若未执行此方法则代表拦截
实现init()方法
实现destroy()方法
到web.xml中配置Filter的拦截路径
2.Filter过滤器的工作流程:
3.案例:在web目录下有一个Admin目录,此目录下的所有资源都必须用户登录之后才可访问,若没有登录,则跳转到登录页面
分析: 用户登录之后会把登录信息保存到Session域中,所以检查用户是否登录,可以判断Session 中是否包含用户的登录信息即可
代码演示:创建MyFilter程序
package com.zhao.filter;
import com.zhao.bean.User;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebFilter("/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter...init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter...执行过滤");
//先把ServletRequest、ServletResponse、转换为HttSpervletRequest和HttServletResponse
HttpServletRequest request=(HttpServletRequest) servletRequest;
HttpServletResponse response=(HttpServletResponse) servletResponse;
//1.获取请求的资源名称
String path = request.getServletPath();
System.out.println(path);
//2.从session中获取登录的用户信息----session中有用户信息表示已登录,没有用户信息表示未登录
HttpSession session=request.getSession();
User user=(User) session.getAttribute("user");
//index.jsp、login.jsp、error.jsp、register.jsp、login、register这些页面或地址请求放行
if(path.equals("/index.jsp") || path.equals("/login.jsp") || path.equals("/register.jsp") || path.equals("/error.jsp") ||
path.equals("/login") || path.equals("/register")){
filterChain.doFilter(servletRequest,servletResponse);
}else if (user!=null){
//session中有用户信息表示已登录,没有用户信息表示未登录,已登录则放行
filterChain.doFilter(servletRequest,servletResponse);//放行
}else {
response.sendRedirect("login.jsp");
}
}
@Override
public void destroy() {
System.out.println("Filter...destroy");
}
}