【Filter】基础知识
1._Filter
JavaWeb三大组件(Servlet,Filter,Listener)之一;
与Servlet类似,用来拦截请求,不是用来处理请求的;WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。
执行地位在Servlet之前,客户端发送请求时,会先经过Filter,再到达目标Servlet中;响应时,会根据执行流程再次反向执行Filter。可以解决多个Servlet共性代码的冗余问题(例如:乱码处理、登录验证)
2._Filter的生命周期
init
:在服务器启动时会创建Filter实例,并且每个类型的Filter只创建一个实例,从此不再创建,在创建完Filter实例后,会马上调用init()方法完成初始化工作,这个方法只会被执行一次;
doFilter
:这个方法会在用户每次访问目标资源(web.xml文件配置Filter的url-pattern中的路径)时执行,如果需要“放行”,那么需要调用FilterChain的doFilter(ServletRequest,ServletResponse)方法,如果不调用FilterChain的doFilter()方法,那么目标资源将无法执行;
destroy
:服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。
修改TestFilter的代码,进行测试
public class TestFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.println("init...");
}
public void destroy() {
System.out.println("destroy...");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("filter....");
chain.doFilter(request, response);
}
}
3._Filter的配置
Filter的配置和Servlet的配置类似,分为xml和注解两种配置方式。
1,xml配置
注意和 servlet区分
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<!-- filter的名字,必须和另一组标签中的filter的名字一致 -->
<filter-name>TestFilter</filter-name>
<!-- filter的全类名 -->
<filter-class>com.qfedu.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
<!-- filter的名字,必须和另一组标签中的filter的名字一致 -->
<filter-name>TestFilter</filter-name>
<!-- 被filter拦截的资源 -->
<url-pattern>/TestServlet</url-pattern>
</filter-mapping>
</web-app>
2,注解配置
在自定义的Filter类上使用注解
@WebFilter
,注解常用属性:
- filterName:filter的名字;
- value:过滤的目标资源的地址。
如果
@WebFilter
只写了字符串,这个字符串Filter过滤目标资源的地址。
@WebFilter(filterName = "AFilter", value = "/AServlet")
public class AFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("AFilter...");
chain.doFilter(request, response);
}
}
3,过滤器路径
过滤器的过滤路径通常有三种形式:
- 精确过滤匹配 ,比如
/index.jsp
、/myservlet1
;- 后缀过滤匹配,比如
*.jsp
、*.html
、*.jpg
;- 通配符过滤匹配
/*
,表示拦截所有。注意过滤器不能使用/
匹配,/aaa/bbb/*
允许。
4,过滤器链
客户端对服务器请求之后,服务器调用Servlet之前会执行一组过滤器(多个过滤器),那么这组过滤器就称为一条过滤器链。
每个过滤器实现某个特定的功能,当第一个Filter的doFilter方法被调用时,Web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则Web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
5,过滤器优先级
在一个Web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。 优先级:
- 如果为注解的话,是按照类全名称的字符串顺序决定作用顺序;
- 如果web.xml,按照 filter-mapping注册顺序,从上往下;
- web.xml配置高于注解方式;
- 如果注解和web.xml同时配置,会创建多个过滤器对象,造成过滤多次。
关于“注解和web.xml同时配置,会创建多个过滤器对象,造成过滤多次”
4._ 基本使用
1,创建javaweb项目
2, 创建过滤器类
@WebFilter(filterName = "AFilter", value = "/AServlet")
public class AFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("AFilter...");
chain.doFilter(request, response);
}
}
3,创建被过滤的类
@WebServlet(name = "AServlet", value = "/AServlet")
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doGet...");
}
}
启动项目,访问
http://localhost:8080/javaweb__01_war_exploded/AServlet
,会先打印出"AFilter..."
然后才会执行对应的类,打印出doGet...