Filter

1.Filter 过滤器

1.1 过滤器简介

1、Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:==Servlet 程序==、==Listener 监听器==、==Filter 过滤器==

2、Filter 过滤器它是 JavaEE 的规范。也就是接口

3、Filter 过滤器它的作用是:拦截请求,过滤响应。

拦截请求常见的应用场景有

1、权限检查

2、日记操作

3、事务管理

……等等

==通过类比了解过滤器作用==

①坐地铁

img001.e0262273

②登录检查

img002.7d95df39

==过滤器三要素==

①拦截

过滤器之所以能够对请求进行预处理,关键是对请求进行拦截,把请求拦截下来才能够做后续的操作。而且对于一个具体的过滤器,它必须明确它要拦截的请求,而不是所有请求都拦截。

②过滤

根据业务功能实际的需求,看看在把请求拦截到之后,需要做什么检查或什么操作,写对应的代码即可。

③放行

过滤器完成自己的任务或者是检测到当前请求符合过滤规则,那么可以将请求放行。所谓放行,就是让请求继续去访问它原本要访问的资源。

友情提示:将来学习SpringMVC时,会学习SpringMVC中的『拦截器』,同样具备三要素。

Filter 的工作流程图

2022-09-25_151039

Filter 过滤器的使用步骤

1、编写一个类去实现 Filter 接口

2、实现过滤方法 doFilter()

3、到 web.xml 中去配置 Filter 的拦截路径

Filter 的代码

public class AdminFilter implements Filter { 
    /*** doFilter 方法,专门用于拦截请求。可以做权限检查 */ 
    @Override 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 
        HttpSession session = httpServletRequest.getSession(); 
        Object user = session.getAttribute("user"); 
        // 如果等于 null,说明还没有登录 
        if (user == null) { 
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse); 
            return; } else { 
            // 让程序继续往下访问用户的目标资源 
            filterChain.doFilter(servletRequest,servletResponse); 
        } 
    } 
}

web.xml:

<filter> 
    <!--给 filter 起一个别名--> 
    <filter-name>AdminFilter</filter-name> 
    <!--配置 filter 的全类名--> 
    <filter-class>com.imooc.filter.AdminFilter</filter-class> 
</filter>
<!--filter-mapping 配置 Filter 过滤器的拦截路径--> 
<filter-mapping> 
    <!--filter-name 表示当前的拦截路径给哪个 filter 使用--> 
    <filter-name>AdminFilter</filter-name> 
    <!--url-pattern 配置拦截路径 
	/ 表示请求地址为:http://ip:port/工程路径/ 映射到 IDEA 的 web 目录 
	/admin/* 表示请求地址为:http://ip:port/工程路径/admin/* --> 
    <url-pattern>/admin/*</url-pattern> 
</filter-mapping>

1.2 HelloWorld

1、思路

img003.c60d667c

  1. Filter也属于Servlet规范

  2. Filter开发步骤:新建类实现Filter接口,然后实现其中的三个方法:initdoFilterdestroy,配置Filter,可以用注解@WebFilter,也可以使用xml文件 <filter> <filter-mapping>

  3. Filter在配置时,和servlet一样,也可以配置通配符,例如 @WebFilter("*.do")表示拦截所有以.do结尾的请求

  4. 过滤器链 1)执行的顺序依次是: A B C demo03 C2 B2 A2 2)如果采取的是注解的方式进行配置,那么过滤器链的拦截顺序是按照全类名的先后顺序排序的 3)如果采取的是xml的方式进行配置,那么按照配置的先后顺序进行排序

    01.Filter

1.3 Filter生命周期

和Servlet生命周期类比,Filter生命周期的关键区别是:在Web应用启动时创建对象

Filter 的生命周期包含几个方法

  1. 构造器方法

  2. init 初始化方法

    • 第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建)
  3. doFilter 过滤方法

    • 第 3 步,每次拦截到请求,就会执行
  4. destroy 销毁

    • 第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)
生命周期阶段执行时机执行次数
创建对象Web应用启动时一次
初始化创建对象后一次
拦截请求接收到匹配的请求多次
销毁Web应用卸载前一次

1.4 FilterConfig 类

FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。

Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。FilterConfig 类的作用是获取 filter 过滤器的配置内容

1、获取 Filter 的名称 filter-name 的内容

2、获取在 Filter 中配置的 init-param 初始化参数

3、获取 ServletContext 对象

java 代码:

@Override 
public void init(FilterConfig filterConfig) throws ServletException { 
    System.out.println("2.Filter 的 init(FilterConfig filterConfig)初始化"); 
    // 1、获取 Filter 的名称 filter-name 的内容 
    System.out.println("filter-name 的值是:" + filterConfig.getFilterName()); 
    // 2、获取在 web.xml 中配置的 init-param 初始化参数 
    System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username")); 
    System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url")); 
    // 3、获取 ServletContext 对象 
    System.out.println(filterConfig.getServletContext()); 
}

web.xml 配置:

<!--filter 标签用于配置一个 Filter 过滤器--> 
<filter> 
    <!--给 filter 起一个别名--> 
    <filter-name>AdminFilter</filter-name> 
    <!--配置 filter 的全类名-->
    <filter-class>com.imooc.filter.AdminFilter</filter-class> 
    <init-param> 
        <param-name>username</param-name> 
        <param-value>root</param-value> 
    </init-param> 
    <init-param> 
        <param-name>url</param-name> 
        <param-value>jdbc:mysql://localhost3306/test</param-value> 
    </init-param> 
</filter>

1.5 过滤匹配规则

本节要探讨的是在filter-mapping中如何将Filter同它要拦截的资源关联起来。

Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在。

==1、精确匹配==

指定被拦截资源的完整路径:

<!-- 配置Filter要拦截的目标资源 -->
<filter-mapping>
    <!-- 指定这个mapping对应的Filter名称 -->
    <filter-name>Target01Filter</filter-name>

    <!-- 通过请求地址模式来设置要拦截的资源 -->
    <url-pattern>/Target01Servlet</url-pattern>
</filter-mapping>

==2、模糊匹配==

相比较精确匹配,使用模糊匹配可以让我们创建一个Filter就能够覆盖很多目标资源,不必专门为每一个目标资源都创建Filter,提高开发效率。

①前杠后星(目录匹配)

在我们配置了url-pattern为/user/*之后,请求地址只要是/user开头的那么就会被匹配。

<filter-mapping>
    <filter-name>Target02Filter</filter-name>

    <!-- 模糊匹配:前杠后星 -->
    <!--
        /user/Target02Servlet
        /user/Target03Servlet
        /user/Target04Servlet
    -->
    <url-pattern>/user/*</url-pattern>
</filter-mapping>

极端情况:/*匹配所有请求

②前星后缀(后缀名匹配)

下面我们使用png图片来测试后缀拦截的效果,并不是只能拦截png扩展名。

[1]创建一组img标签

    <img th:src="@{/./https://chunqiurusi-1304032293.cos.ap-chengdu.myqcloud.com/images/Java/img017.png}"/><br/>
    <img th:src="@{/./https://chunqiurusi-1304032293.cos.ap-chengdu.myqcloud.com/images/Java/img018.png}"/><br/>
    <img th:src="@{/./https://chunqiurusi-1304032293.cos.ap-chengdu.myqcloud.com/images/Java/img019.png}"/><br/>
    <img th:src="@{/./https://chunqiurusi-1304032293.cos.ap-chengdu.myqcloud.com/images/Java/img020.png}"/><br/>
    <img th:src="@{/./https://chunqiurusi-1304032293.cos.ap-chengdu.myqcloud.com/images/Java/img024.png}"/><br/>
    <img th:src="@{/./https://chunqiurusi-1304032293.cos.ap-chengdu.myqcloud.com/images/Java/img025.png}"/><br/>

[2]创建Filter

③前杠后缀,星号在中间

配置方式如下:

<url-pattern>/*.png</url-pattern>

按照这个配置启动Web应用时会抛出异常:

java.lang.IllegalArgumentException: Invalid /*.png in filter mapping

结论:请求地址不能以/开头,这么配是不允许的!

<url-pattern>.html</url-pattern>

以上配置的路径,表示请求地址必须以.html 结尾才会拦截到

<url-pattern>*.do</url-pattern>

以上配置的路径,表示请求地址必须以.do 结尾才会拦截到

<url-pattern>*.action</url-pattern>

以上配置的路径,表示请求地址必须以.action 结尾才会拦截到

==3、匹配Servlet名称[了解]==

<filter-mapping>
    <filter-name>Target05Filter</filter-name>
    <!-- 根据Servlet名称匹配 -->
    <servlet-name>Target01Servlet</servlet-name>
</filter-mapping>

12.5 过滤器链

==1、概念==

  • 多个Filter的拦截范围如果存在重合部分,那么这些Filter会形成Filter链
  • 浏览器请求重合部分对应的目标资源时,会依次经过Filter链中的每一个Filter。
  • Filter链中每一个Filter执行的顺序是由web.xml中filter-mapping配置的顺序决定的。

img004.962f5d5c

<filter-mapping>
    <filter-name>TargetChain03Filter</filter-name>
    <url-pattern>/Target05Servlet</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>TargetChain02Filter</filter-name>
    <url-pattern>/Target05Servlet</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>TargetChain01Filter</filter-name>
    <url-pattern>/Target05Servlet</url-pattern>
</filter-mapping>

2022-09-25_153505