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 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在!!!
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
· 全程使用 AI 从 0 到 1 写了个小工具