【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...

posted @ 2022-04-02 09:46  coderwcb  阅读(10)  评论(0编辑  收藏  举报