2022.5.10 Filter 过滤器

Filter 过滤器

什么是Filter过滤器

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

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

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

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

  • 权限检查

  • 日记操作

  • 事务管理 ……等等

Filter 的初体验

要求:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必 须是用户登录之后才允许访问。

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

Filter 的工作流程图:

Filter 的代码:

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import javax.servlet.http.HttpServletRequest;
 5 import javax.servlet.http.HttpSession;
 6 import java.io.IOException;
 7 public class AdminFilter implements Filter {
 8  9     @Override
10     public void init(FilterConfig filterConfig) throws ServletException {
11         Filter.super.init(filterConfig);
12     }
13 14     /**
15     * Description: 专门用于拦截请求 过滤响应(可以做权限检查)  相当servlet中的server方法
16     */
17     @Override
18     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
19         HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
20         HttpSession session = httpServletRequest.getSession();
21         Object user = session.getAttribute("user");
22         // 如果等于 null,说明还没有登录
23         if (user == null) {
24             servletRequest.getRequestDispatcher("/index.jsp").forward(servletRequest,servletResponse);
25         } else {
26             // 让程序继续往下访问用户的目标资源  不执行这行代码就拦截
27             filterChain.doFilter(servletRequest,servletResponse);
28         }
29     }
30 31     @Override
32     public void destroy() {
33         Filter.super.destroy();
34     }
35 }

web.xml 中的配置:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
 5          version="4.0">
 6  7     <!--filter 标签用于配置一个 Filter 过滤器-->
 8     <filter>
 9         <!--给 filter 起一个别名-->
10         <filter-name>AdminFilter</filter-name>
11         <!--配置 filter 的全类名-->
12         <filter-class>com.xing.filter.AdminFilter</filter-class>
13     </filter>
14     <!--filter-mapping 配置 Filter 过滤器的拦截路径-->
15     <filter-mapping>
16         <!--filter-name 表示当前的拦截路径给哪个 filter 使用-->
17         <filter-name>AdminFilter</filter-name>
18         <!--url-pattern 配置拦截路径
19         / 表示请求地址为:http://ip:port/工程路径/ 映射到 IDEA 的 web 目录
20         /admin/* 表示请求地址为:http://ip:port/工程路径/admin/*
21         意思就是拦截http://ip:port/工程路径/admin 这个地址下的请求,进入doFilter方法
22         -->
23         <url-pattern>/admin/*</url-pattern>
24     </filter-mapping>
25 </web-app>

上面代码的意思就是如果没有登陆就拦截掉web/admin目录下的所有的资源,filterChain.doFilter(servletRequest,servletResponse);这行代码就是将程序继续执行下去,不进行拦截,不执行这行代码就拦截

访问 http://localhost:8080/filter/admin/a.html 就会进入拦截器执行

Filter 过滤器的使用步骤:

  • 编写一个类去实现 Filter 接口

  • 实现过滤方法 doFilter()

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

Filter 的生命周期

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

  • 1、构造器方法

  • 2、init 初始化方法 第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建)

  • 3、doFilter 过滤方法 第 3 步,每次拦截到请求就会执行

  • 4、destroy 销毁 第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import java.io.IOException;
 5 public class AdminFilter implements Filter {
 6  7  8     public AdminFilter() {
 9         System.out.println("构造器方法");
10     }
11 12     @Override
13     public void init(FilterConfig filterConfig) throws ServletException {
14         System.out.println("init方法");
15     }
16 17     /**
18     * Description: 专门用于拦截请求 过滤响应(可以做权限检查)  相当servlet中的server方法
19     */
20     @Override
21     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
22 23         System.out.println("doFilter方法");
24     }
25 26     @Override
27     public void destroy() {
28         System.out.println("destroy方法");
29         Filter.super.destroy();
30     }
31 }

FilterConfig 类

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

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

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

  • 获取 Filter 的名称 filter-name 的内容

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

  • 获取 ServletContext 对象

java 代码:

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import java.io.IOException;
 5 public class AdminFilter implements Filter {
 6  7     @Override
 8     public void init(FilterConfig filterConfig) throws ServletException {
 9 10         // 1、获取 Filter 的名称 filter-name 的内容
11         System.out.println("filter-name 的值是:" + filterConfig.getFilterName());
12         // 2、获取在 web.xml 中配置的 init-param 初始化参数
13         System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username"));
14         System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url"));
15         // 3、获取 ServletContext 对象
16         System.out.println(filterConfig.getServletContext());
17     }
18 19 20     /**
21     * Description: 专门用于拦截请求 过滤响应(可以做权限检查)  相当servlet中的server方法
22     */
23     @Override
24     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
25 26     }
27 28     @Override
29     public void destroy() {
30         System.out.println("destroy方法");
31         Filter.super.destroy();
32     }
33 }

web.xml 配置:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
 5          version="4.0">
 6  7     <!--filter 标签用于配置一个 Filter 过滤器-->
 8     <filter>
 9         <!--给 filter 起一个别名-->
10         <filter-name>AdminFilter</filter-name>
11         <!--配置 filter 的全类名-->
12         <filter-class>com.xing.filter.AdminFilter</filter-class>
13 14         <init-param>
15             <param-name>username</param-name>
16             <param-value>root</param-value>
17         </init-param>
18         <init-param>
19             <param-name>url</param-name>
20             <param-value>jdbc:mysql://localhost:3306</param-value>
21         </init-param>
22     </filter>
23 24 25     <!--filter-mapping 配置 Filter 过滤器的拦截路径-->
26     <filter-mapping>
27         <!--filter-name 表示当前的拦截路径给哪个 filter 使用-->
28         <filter-name>AdminFilter</filter-name>
29         <!--url-pattern 配置拦截路径
30         / 表示请求地址为:http://ip:port/工程路径/ 映射到 IDEA 的 web 目录
31         /admin/* 表示请求地址为:http://ip:port/工程路径/admin/*
32         意思就是拦截http://ip:port/工程路径/admin 这个地址下的请求,进入doFilter方法
33         -->
34         <url-pattern>/admin/*</url-pattern>
35     </filter-mapping>
36 </web-app>

启动tomcat

FilterChain 过滤器链

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

情形1

Filter1

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import java.io.IOException;
 5  6 public class Filter1 implements Filter {
 7     @Override
 8     public void init(FilterConfig filterConfig) throws ServletException {
 9         Filter.super.init(filterConfig);
10     }
11 12     @Override
13     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
14         System.out.println("filter1 前置代码");
15         filterChain.doFilter(servletRequest,servletResponse);
16         System.out.println("filter1 后置代码");
17 18     }
19 20     @Override
21     public void destroy() {
22         Filter.super.destroy();
23     }
24 }

Filter2

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import java.io.IOException;
 5  6 public class Filter2 implements Filter {
 7     @Override
 8     public void init(FilterConfig filterConfig) throws ServletException {
 9         Filter.super.init(filterConfig);
10     }
11 12     @Override
13     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
14         System.out.println("filter2 前置代码");
15         filterChain.doFilter(servletRequest,servletResponse);
16         System.out.println("filter2 后置代码");
17     }
18 19     @Override
20     public void destroy() {
21         Filter.super.destroy();
22     }
23 }

web.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
 5          version="4.0">
 6  7     <filter>
 8         <filter-name>Filter1</filter-name>
 9         <filter-class>com.xing.filter.Filter1</filter-class>
10     </filter>
11     <filter-mapping>
12         <filter-name>Filter1</filter-name>
13         <url-pattern>/target.jsp</url-pattern>
14     </filter-mapping>
15 16 17     <filter>
18         <filter-name>Filter2</filter-name>
19         <filter-class>com.xing.filter.Filter2</filter-class>
20     </filter>
21     <filter-mapping>
22         <filter-name>Filter2</filter-name>
23         <url-pattern>/target.jsp</url-pattern>
24     </filter-mapping>
25 26 </web-app>

target.jsp

 1 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 2 <html>
 3 <head>
 4     <title>Title</title>
 5 </head>
 6 <body>
 7     <%
 8         System.out.println("target.jsp执行了");
 9 10     %>
11 </body>
12 </html>

访问http://localhost:8080/filter/target.jsp

情形2

Filter1

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import java.io.IOException;
 5  6 public class Filter1 implements Filter {
 7     @Override
 8     public void init(FilterConfig filterConfig) throws ServletException {
 9         Filter.super.init(filterConfig);
10     }
11 12     @Override
13     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
14         System.out.println("filter1 前置代码");
15         filterChain.doFilter(servletRequest,servletResponse);
16         System.out.println("filter1 后置代码");
17 18     }
19 20     @Override
21     public void destroy() {
22         Filter.super.destroy();
23     }
24 }

Filter2

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import java.io.IOException;
 5  6 public class Filter2 implements Filter {
 7     @Override
 8     public void init(FilterConfig filterConfig) throws ServletException {
 9         Filter.super.init(filterConfig);
10     }
11 12     @Override
13     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
14         System.out.println("filter2 前置代码");
15         // filterChain.doFilter(servletRequest,servletResponse);
16         // System.out.println("filter2 后置代码");
17     }
18 19     @Override
20     public void destroy() {
21         Filter.super.destroy();
22     }
23 }

web.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
 5          version="4.0">
 6  7     <filter>
 8         <filter-name>Filter1</filter-name>
 9         <filter-class>com.xing.filter.Filter1</filter-class>
10     </filter>
11     <filter-mapping>
12         <filter-name>Filter1</filter-name>
13         <url-pattern>/target.jsp</url-pattern>
14     </filter-mapping>
15 16 17     <filter>
18         <filter-name>Filter2</filter-name>
19         <filter-class>com.xing.filter.Filter2</filter-class>
20     </filter>
21     <filter-mapping>
22         <filter-name>Filter2</filter-name>
23         <url-pattern>/target.jsp</url-pattern>
24     </filter-mapping>
25 26 </web-app>

target.jsp

 1 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 2 <html>
 3 <head>
 4     <title>Title</title>
 5 </head>
 6 <body>
 7     <%
 8         System.out.println("target.jsp执行了");
 9 10     %>
11 </body>
12 </html>

访问http://localhost:8080/filter/target.jsp

特点

Filter1

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import java.io.IOException;
 5  6 public class Filter1 implements Filter {
 7     @Override
 8     public void init(FilterConfig filterConfig) throws ServletException {
 9         Filter.super.init(filterConfig);
10     }
11 12     @Override
13     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
14         System.out.println("filter1 前置代码");
15         System.out.println("filter1 线程"+Thread.currentThread().getName());
16         System.out.println("filter1 "+servletRequest.getParameter("username"));
17         filterChain.doFilter(servletRequest,servletResponse);
18         System.out.println("filter1 线程"+Thread.currentThread().getName());
19         System.out.println("filter1 后置代码");
20 21     }
22 23     @Override
24     public void destroy() {
25         Filter.super.destroy();
26     }
27 }

Filter2

 1 package com.xing.filter;
 2  3 import javax.servlet.*;
 4 import java.io.IOException;
 5  6 public class Filter2 implements Filter {
 7     @Override
 8     public void init(FilterConfig filterConfig) throws ServletException {
 9         Filter.super.init(filterConfig);
10     }
11 12     @Override
13     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
14         System.out.println("filter2 前置代码");
15         System.out.println("filter2 线程"+Thread.currentThread().getName());
16         System.out.println("filter2 "+servletRequest.getParameter("username"));
17         filterChain.doFilter(servletRequest,servletResponse);
18         System.out.println("filter2 线程"+Thread.currentThread().getName());
19         System.out.println("filter2 后置代码");
20     }
21 22     @Override
23     public void destroy() {
24         Filter.super.destroy();
25     }
26 }

web.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
 5          version="4.0">
 6  7     <filter>
 8         <filter-name>Filter1</filter-name>
 9         <filter-class>com.xing.filter.Filter1</filter-class>
10     </filter>
11     <filter-mapping>
12         <filter-name>Filter1</filter-name>
13         <url-pattern>/target.jsp</url-pattern>
14     </filter-mapping>
15 16 17     <filter>
18         <filter-name>Filter2</filter-name>
19         <filter-class>com.xing.filter.Filter2</filter-class>
20     </filter>
21     <filter-mapping>
22         <filter-name>Filter2</filter-name>
23         <url-pattern>/target.jsp</url-pattern>
24     </filter-mapping>
25 26 </web-app>

target.jsp

 1 <%--
 2   Created by IntelliJ IDEA.
 3   User: LXingTou
 4   Date: 2023/6/12
 5   Time: 22:50
 6   To change this template use File | Settings | File Templates.
 7 --%>
 8 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 9 <html>
10 <head>
11     <title>Title</title>
12 </head>
13 <body>
14     <%
15         System.out.println("target.jsp执行了");
16         System.out.println("target.jsp 线程"+Thread.currentThread().getName());
17         System.out.println("target.jsp "+request.getParameter("username"));
18 19 20     %>
21 </body>
22 </html>

访问http://localhost:8080/filter/target.jsp?username=xiaoming

线程相同,request域相同

Filter 的拦截路径

  • 精确匹配

1 <filter>
2     <filter-name>Filter2</filter-name>
3     <filter-class>com.xing.filter.Filter2</filter-class>
4 </filter>
5 <filter-mapping>
6     <filter-name>Filter2</filter-name>
7     <url-pattern>/target.jsp</url-pattern>
8 </filter-mapping>
/target.jsp 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp 
  • 目录匹配

1 <filter>
2     <filter-name>AdminFilter</filter-name>
3     <filter-class>com.xing.filter.AdminFilter</filter-class>
4 </filter>
5 6 <filter-mapping>
7     <filter-name>AdminFilter</filter-name>
8     <url-pattern>/admin/*</url-pattern>
9 </filter-mapping>
/admin/* 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/* 
  • 后缀名匹配

1 <filter>
2     <filter-name>Filter2</filter-name>
3     <filter-class>com.xing.filter.Filter2</filter-class>
4 </filter>
5 <filter-mapping>
6     <filter-name>Filter2</filter-name>
7     <url-pattern>*.html</url-pattern>
8 </filter-mapping>
不要斜杠
*.html 以上配置的路径,表示请求地址必须以.html 结尾才会拦截到

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

posted @ 2022-05-23 09:09  暴躁C语言  阅读(5)  评论(0编辑  收藏  举报