WebFilter-SpringBoot 过滤器注解实例讲解

本贴最后更新于 2108 天前,其中的信息可能已经时异事殊

v2a0ed46ccaa50311b2b8c435ef1277639hd.jpg

简介

Filter 也称之为过滤器,它是 Servlet 技术中最让人激动的技术,Web 开发人员通过 Filter 技术,对 Web 服务器管理的所有 Web 资源:例如 JSP,Servlet,静态图片文件或静态 HTML 文件等进行拦截,从而实现一些特殊的功能,例如实现 URL 级别的权限访问控制,过滤敏感词汇,压缩响应信息等一些高级功能。
可以在 web.xml 中配置过滤器的生效 URL 地址,它会过滤指定的 URL 地址经过的数据”/*”代表过滤所有的 URL 地址请求数据。
这样做的好处有什么呢,可以直接配置过滤所有的请求编码都设置为 UTF-8,在 response 的时候也可以将响应编码也设置为 UTF-8,这样就省去了写相同代码的步骤,优化代码。

Filter 链

在一个 Web 应用中,可以开发编写多个 Filter,这些 Filter 组合起来称之为一个 Filter 链。
Web 服务器根据 Filter 在 web.xml 文件中的注册顺序,决定先调用哪个 Filter,当第一个 Filter 的 dofilter 方法被调用时,web 服务器会创建一个代表 filter 链的 FilterChain 对象传递给该方法,在 doFilter() 方法中,开发人员如果调用 FilterChain 对象的 doFilter() 方法,则 Web 服务器会检查 FilterChain 对象中是否还有 Filter,如果有,则调用第二个 Filter,如果没有,则调用目标资源。

Filter 匹配

精确匹配:

/路径/资源名

如:/index.html 、/hello/index.jsp 、 /client/LoginServlet

精确匹配只要在请求地址完全一样时才会调用 Filter

路径匹配:

/路径名/*

如:/hello/* 、/*

路径匹配只要是所请求的资源是在设置的路径下就会调用 Filter

如:/hello/* 只要访问 项目根目录/hello/ 下的任意资源就会调用 Filter

如: /* 只要访问 项目根目录下的资源就会调用 Filter

后缀匹配:

*.后缀名

如:*.jsp 、 *.html

后缀匹配只要访问的资源路径是以指定后缀结尾就会调用 Filter

Filter 的生命周期

Filter 的创建好销毁都由 Web 服务器负责,Web 应用程序启动时,Web 服务器将创建 Filter 的实例化对象,并调用其 init() 方法,完成对象的初始化功能,从而为后续的用户请求做好拦截的准备工作,Filter 对象只会创建一次,init() 方法也只会执行一次。通过 init() 方法的参数,可获得代表当前 Filter 配置信息的 FilterConfig 的对象。

Web 容器调用 destroy() 方法销毁 Filter,destroy() 方法在 Filter 的生命周期中仅执行一次;在 destroy() 方法中,可以释放过滤器使用的资源。

FilterConfig 接口

用户在配置 Filter 时,可以使用 <init-param> 为 Filter 配置一些初始化参数,当 Web 容器实例化 Filter 对象,调用其 init() 方法时,会把封装了 Filter 初始化参数的 filterConfig 对象传递进来。因此开发人员在编写 Filter 时,通过 filterConfig 对象的方法,就可获得:

String getFilterName()

得到 Filter 的名称。

String getInitParameter(String name)

返回在部署描述中指定名称的初始化参数的值。如果不存在返回 null

Enumeration getInitParameterNames()

返回过滤器的所有初始化参数的名字的枚举集合。

public ServletContext getServletContext()

返回 Servlet 上下文对象的引用。

使用

Filter 的声明方式有两种:
第一种是使用注解的方式声明
第二种是在 web.xml 中使用标签的方式进行声明

注解 Filter

使用 @WebFilter(filterName = "过滤器名字", urlPatterns = "过滤地址", description = "描述")

举个栗子

    @Controller
    @WebFilter(filterName = "TestFilter", urlPatterns = "/*.do")
    public class TestFilter implements Filter {

        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println("开始过滤2");
            chain.doFilter(req, resp);
        }

        public void init(FilterConfig config) throws ServletException {
            System.out.println("创建filter对象2");
        }

        public void destroy() {
            System.out.println("filter已经被销毁2");
        }
    }

    @Controller
    @WebFilter(filterName = "TestFilter2", urlPatterns = "/*.do")
    public class TestFilter2 implements Filter {

        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println("开始过滤1");
            chain.doFilter(req, resp);
        }

        public void init(FilterConfig config) throws ServletException {
            System.out.println("创建filter对象1");
        }

        public void destroy() {
            System.out.println("filter已经被销毁1");
        }
    }

通过注解的方式配置 Filter 过滤器

如果在 SpringBoot 里最好加上一个 @Controller 标签,Filter 的执行顺序可以使用 @Order(i) 决定 Filter 的执行顺序i 的值越大执行顺序越靠前。

在 web.xml 里配置的 Filter 是由上下顺序决定的。

web.xml 配置 Filter

再举个栗子

    <!-- Filter文件配置 -->
    <filter>
        <filter-name>TestFilter</filter-name>
        <filter-class>cn.zlys.service.TestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>TestFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- Filter的执行顺序和配置的顺序有关 -->
    <filter>
        <filter-name>TestFilter2</filter-name>
        <filter-class>cn.zlys.service.TestFilter2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>TestFilter2</filter-name>
        <url-pattern>/*.do</url-pattern>
    </filter-mapping>

在 web.xml 中配置的好处是在项目发布后可以不更改项目源码就可以更改 Filter 执行的 URL 地址或者是 Filter 的 class 路径。并且通过 web.xml 配置 Filter 还可以选择过滤的方式,比如只过滤请求或者过滤 ERROR。

使用 dispatcher 标签决定过滤的方式,一共有 REQUEST、ERROR、FORWARD、INCLUDE,分别是 请求错误转发包含,包含是 JSP 里的 include 标签。

在 Filter 中也有 init-param 标签,可以在项目初始化时获取数据,比如说在 init-param 标签里配置编码格式为 UTF-8 格式,这样的话就可以使项目的编码动态的更改,如果想要在项目发布后更改项目的编码格式,直接更改 web.xml 中 init-param 里的数据就可以了。

总结

Filter 的发明真的是便利的我们的生活,可以省略不必要的代码,如果是请求的编码确认可以不用写很多遍,因为如果 Serlvet 过多时,在每个 Servlet 都要写设置编码格式,如果想要更改编码格式的时候就需要每个 Servlet 都重写一遍,但是有了 Filter 就可以只写一遍,就实现了在每个 Servlet 里都更改了请求编码格式和响应编码格式。

Filter 不仅可以通过 url-pattern 来拦截指定 url 地址匹配的资源,而且还可以通过 servlet-name 来指定拦截哪个指定的 servlet(专门为某个 servlet 服务,servlet-name 对应 Servlet 相关配置)

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3190 引用 • 8214 回帖 • 1 关注
  • 代码
    467 引用 • 586 回帖 • 9 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...