Java Web 从入门到退坑 第十三章 Filter 过滤器


Java Web 从入门到退坑 —— 第十三章 Filter 过滤器


By: -gregPerlinLi-


1. 什么是 Filter 过滤器

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

​ 2. Filter 过滤器是 JavaEE 的规范,也就是接口。

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

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

​ 1. 权限检查

​ 2. 日记操作

​ 3. 事务管理

​ ……

2. Filter 的初体验

​ 要求:在 Web 工程下,有个 admin 目录,这个目录下的所有资源(HTML 页面,JPG 图片,jsp 页面)都必须是用户登录之后才允许访问。

思考: 根据之前学过的内容可知,在用户登录之后,都会把用户信息保存到 Session 域中,所以要检查用户是否登陆可以判断 Session 中是否包含有用户登录的信息即可

方法1(仅适用于 jsp 页面):


    <%
        Object user = session.getAttribute("user");
        // If it is null, it means that you have not logged in
        if (user == null) {
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;
        }
    %>
    

I'm a.jsp file

方法2(使用 Filter 过滤器):

​ Filter 过滤器的原理:

FilterPrinciple

​ 在 web.xml 配置 Filter 过滤器

<!-- Configure Filter -->
<filter>
    <!-- Give Filter an alias -->
    <filter-name>AdminFilter</filter-name>
    <!-- Configure the full class name of the Filter -->
    <filter-class>com.gregperlinli.Filter.AdminFilter</filter-class>
</filter>
<!-- Filter of intercepting path configuration -->
<filter-mapping>
    <!-- Indicates the current interception path to the Filter to use -->
    <filter-name>AdminFilter</filter-name>
    <!--
        Configure interception path
        The / slash indicates that the request address is http://ip:port/projctName/
        Map to webapp directory in IDEA
        /admin/* Indicates that the request address is: http://ip:port/projctName/admin/*
     -->
    <url-pattern>/admin/*</url-pattern>
</filter-mapping>

​ 示例代码:

    /**
     * doFilter() method is designed to intercept requests,and it can do permission checking
     * @param request request
     * @param response response
     * @param chain chain
     * @throws IOException e
     * @throws ServletException e
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException &#123;
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpSession session = httpServletRequest.getSession();

        Object user = session.getAttribute("username");
        // If it is null, it means that you have not logged in
        if (user == null) &#123;
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;
        &#125; else &#123;
            // Let the program continue to access the user's target resource
            chain.doFilter(request, response);
        &#125;
    &#125;

​ Filter 过滤器的使用步骤:

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

​ 2. 实现过滤方法 doFilter()

​ 3. 到 web.xml 中去配置 Filter 的拦截路径(也可以使用以下注解来进行配置)

@WebFilter(filterName = "AdminFilter", value = "/admin/*")

3. Filter 的生命周期

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

​ 1. 构造器方法

​ 2. init 初始化方法

​ 3. doFilter 过滤方法

​ 4. destroy 销毁方法

​ 第1,2步,在 Web 工程启动的时候执行(Filter 已经创建)

​ 第3步在每次拦截到请求的时候就会执行

​ 第4步在停止 Web 工程的时候就会执行(停止 Web 工程,也会销毁 Filter 过滤器)

4. FilterConfig

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

​ Tomcat 每次创建 Filter 的时候也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。

FilterConfig 类的作用是获取 Filter 过滤器的配置内容

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

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

​ 3. 获取 ServletContext 对象

示例代码:

@WebFilter(filterName = "AdminFilter", value = "/admin/*",
        initParams = &#123;
        @WebInitParam(name = "username", value = "root"),
        @WebInitParam(name = "url", value = "jdbc:mysql://localhost:3306/test") &#125;)
public class AdminFilter implements Filter &#123;
        @Override
        public void init(FilterConfig filterConfig) throws ServletException &#123;
            System.out.println("2. Filter initialize method");
            // 1. Get the name of filter and the content of filter-name
            System.out.println("filter-name: " + filterConfig.getFilterName());
            // 2. Get the init-param initialization parameter configured in the filter
            System.out.println("Initialize parameter username: " + filterConfig.getInitParameter("username"));
            System.out.println("Initialize parameter url: " + filterConfig.getInitParameter("url"));
            // 3. Get the ServletContext object
            System.out.println(filterConfig.getServletContext());
        &#125;
&#125;

5. FilterChain 过滤器链

Filter: 过滤器 &nbsp;&nbsp; Chain: 链,链条

FilterChain 就是过滤器链(多个过滤器如何一起工作)

FilterChain

FilterChain.doFilter() 方法的作用:

​ 1. 执行下一个 Filter 过滤器(如果有 Filter)

​ 2. 执行目标资源(如果没有 Filter)

示例代码:

Filter1.java

@WebFilter(filterName = "Filter1", value = "/admin/target.jsp")
public class Filter1 implements Filter &#123;
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException &#123;
        System.out.println("Prefix code of Filter1");
        chain.doFilter(request, response);
        System.out.println("Post code of Filter1");
    &#125;
&#125;

Filter2.java

@WebFilter(filterName = "Filter2", value = "/admin/target.jsp")
public class Filter2 implements Filter &#123;
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException &#123;
        System.out.println("Prefix code of Filter2");
        chain.doFilter(request, response);
        System.out.println("Post code of Filter2");
    &#125;
&#125;

注意⚠️:在多个 Filter 过滤器执行的时候,对于使用 web.xml 来配置的 Filter 过滤器来说,它们执行的优先顺序是由它们在中从上到下配置的顺序决定的;而对于使用注解 @WebFilter() 配置的 FIlter 过滤器,则是按照 Filter 名字的顺序(不区分大小写)来决定的!

​ 多个 Filter 过滤器执行的特点:

​ 1. 所有 Filter 和目标资源默认都执行在同一个线程中

​ 2. 以上多个 Filter 共同执行的时候,它们都是用同一个 Request 对象

6. Filter 的拦截路径

6.1. 精确匹配

<url-pattern>/target.jsp</url-pattern>
@WebFilter(filterName = "Filter", value = "/target.jsp")

​ 以上配置的路径,表示请求地址必须为:http://ip:port/projectName/target.jsp

6.2. 目录匹配

<url-pattern>/target/*</url-pattern>
@WebFilter(filterName = "Filter", value = "/target/*")

​ 以上配置的路径表示请求地址必须为:http://ip:port/projectName/target/*(也就是该目录下的全部资源)

6.3. 后缀名匹配

<url-pattern>*.html</url-pattern>
@WebFilter(filterName = "Filter", value = "*.html")

​ 以上配置的路径表示请求地址必须以 .html 结尾(即以 html 作为后缀名)才会拦截到

注意⚠️:Filter 过滤器只关心请求的地址是否匹配,不关心请求的路径是否存在!



文章作者: gregPerlinLi
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 gregPerlinLi !
  目录