阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

过滤器详解

418次阅读
没有评论

共计 6197 个字符,预计需要花费 16 分钟才能阅读完成。

1、过滤器的生命周期

我们已经学习过 Servlet 的生命周期,那么 Filter 的生命周期也就没有什么难度了!

init(FilterConfig)

在服务器启动时会创建 Filter 实例,并且每个类型的 Filter 只创建一个实例,从此不再创建!在创建完 Filter 实例后,会马上调用 init()方法完成初始化工作,这个方法只会被执行一次;

doFilter(ServletRequest req,ServletResponse res,FilterChain chain)

这个方法会在用户每次访问“目标资源(pattern>index.jsp)”时执行,如果需要“放行”,那么需要调用 FilterChain 的 doFilter(ServletRequest,ServletResponse)方法,如果不调用 FilterChain 的 doFilter()方法,那么目标资源将无法执行;

destroy()

服务器会在创建 Filter 对象之后,把 Filter 放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁 Filter 对象,在销毁 Filter 对象之前,服务器会调用 Filter 对象的 destory()方法。

2、FilterConfig

你已经看到了吧,Filter 接口中的 init()方法的参数类型为 FilterConfig 类型。它的功能与 ServletConfig 相似,与 web.xml 文件中的配置信息对应。下面是 FilterConfig 的功能介绍:

  • ServletContext getServletContext():获取 ServletContext 的方法;
  • String getFilterName():获取 Filter 的配置名称;与 元素对应;
  • String getInitParameter(String name):获取 Filter 的初始化配置,与 元素对应;
  • Enumeration getInitParameterNames():获取所有初始化参数的名称。

过滤器详解

3、FilterChain

doFilter()方法的参数中有一个类型为 FilterChain 的参数,它只有一个方法:doFilter(ServletRequest,ServletResponse)。

前面我们说 doFilter()方法的放行,让请求流访问目标资源!但这么说不严密,其实调用该方法的意思是,“我(当前 Filter)”放行了,但不代表其他人(其他过滤器)也放行。

也就是说,一个目标资源上,可能部署了多个过滤器,就好比在你去北京的路上有多个打劫的匪人(过滤器),而其中第一伙匪人放行了,但不代表第二伙匪人也放行了,所以 调用 FilterChain 类的 doFilter()方法表示的是执行下一个过滤器的 doFilter()方法,或者是执行目标资源!

如果当前过滤器是最后一个过滤器,那么调用 chain.doFilter()方法表示执行目标资源,而不是最后一个过滤器,那么 chain.doFilter()表示执行下一个过滤器的 doFilter()方法。

4、多个过滤器执行顺序

一个目标资源可以指定多个过滤器,过滤器的执行顺序是在 web.xml 文件中的部署顺序:

<filter> <filter-name>myFilter1 </filter-name> <filter-class>com.tyschool.filter.MyFilter1</filter-class> </filter> <filter-mapping> <filter-name>myFilter1</filter-name> <url-pattern>/index.jsp</url-pattern> </filter-mapping> <filter> <filter-name>myFilter2</filter-name> <filter-class>com.tyschool.filter.MyFilter2</filter-class> </filter> <filter-mapping> <filter-name>myFilter2</filter-name> <url-pattern>/index.jsp</url-pattern> </filter-mapping>
public class MyFilter1 extends HttpFilter {public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("filter1 start..."); chain.doFilter(request, response);// 放行,执行 MyFilter2 的 doFilter()方法 System.out.println("filter1 end..."); } }
public class MyFilter2 extends HttpFilter {public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("filter2 start..."); chain.doFilter(request, response);// 放行,执行目标资源 System.out.println("filter2 end..."); } }
<body> This is my JSP page. <br> <h1>index.jsp</h1> <%System.out.println("index.jsp"); %> </body>

当有用户访问 index.jsp 页面时,输出结果如下:

filter1 start...
filter2 start...
index.jsp
filter2 end...
filter1 end...

5、四种拦截方式

我们来做个测试,写一个过滤器,指定过滤的资源为 b.jsp,然后我们在浏览器中直接访问 b.jsp,你会发现过滤器执行了!

但是,当我们在 a.jsp 中 request.getRequestDispathcer(“/b.jsp”).forward(request,response)时,就不会再执行过滤器了!也就是说,默认情况下,只能直接访问目标资源才会执行过滤器,而 forward 执行目标资源,不会执行过滤器!

public class MyFilter extends HttpFilter {public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("myfilter..."); chain.doFilter(request, response); } }
<filter> <filter-name>myfilter</filter-name> <filter-class>com.tyschool.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>myfilter</filter-name> <url-pattern>/b.jsp</url-pattern> </filter-mapping>
<body> <h1>b.jsp</h1> </body>
<h1>a.jsp</h1> <% request.getRequestDispatcher("/b.jsp").forward(request, response); %> </body>

http://localhost:8080/filtertest/b.jsp –> 直接访问 b.jsp 时,会执行过滤器内容;

http://localhost:8080/filtertest/a.jsp –> 访问 a.jsp,但 a.jsp 会 forward 到 b.jsp,这时就不会执行过滤器!

其实过滤器有四种拦截方式!分别是:REQUEST、FORWARD、INCLUDE、ERROR。

  • REQUEST:直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是 REQUEST;
  • FORWARD:转发访问执行过滤器。包括 RequestDispatcher#forward()方法、jsp:forward标签都是转发访问;
  • INCLUDE:包含访问执行过滤器。包括 RequestDispatcher#include()方法、jsp:include标签都是包含访问;
  • ERROR:当目标资源在 web.xml 中配置为 中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。

可以在 中添加 0~n 个 子元素,来说明当前访问的拦截方式。

<filter-mapping> <filter-name>myfilter</filter-name> <url-pattern>/b.jsp</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
<filter-mapping> <filter-name>myfilter</filter-name> <url-pattern>/b.jsp</url-pattern> </filter-mapping>
<filter-mapping> <filter-name>myfilter</filter-name> <url-pattern>/b.jsp</url-pattern> <dispatcher>FORWARD</dispatcher> </filter-mapping>

其实最为常用的就是 REQUEST 和 FORWARD 两种拦截方式,而 INCLUDE 和 ERROR 都比较少用!其中 INCLUDE 比较好理解,我们这里不再给出代码,学员可以通过 FORWARD 方式修改,来自己测试。而 ERROR 方式不易理解,下面给出 ERROR 拦截方式的例子:

<filter-mapping> <filter-name>myfilter</filter-name> <url-pattern>/b.jsp</url-pattern> <dispatcher>ERROR</dispatcher> </filter-mapping> <error-page> <error-code>500</error-code> <location>/b.jsp</location> </error-page>
<body> <h1>a.jsp</h1> <% if(true) throw new RuntimeException("嘻嘻~"); %> </body>

6、过滤器的应用场景

过滤器的应用场景:

  • 执行目标资源之前做 预处理 工作,例如设置编码,这种试 通常都会放行,只是在目标资源执行之前做一些准备工作;
  • 通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户 IP 是否已经被禁用;
  • 在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理;

7、设置目标资源

在 web.xml 文件中部署 Filter 时,可以通过“*”来执行目标资源:

	<filter-mapping>
		<filter-name>myfilter</filter-name>
		<url-pattern>/*</url-pattern> 
	</filter-mapping>

这一特性与 Servlet 完全相同!通过这一特性,我们可以在用户访问敏感资源时,执行过滤器,例如:/admin/*,可以把所有管理员才能访问的资源放到 /admin 路径下,这时可以通过过滤器来校验用户身份。

还可以为 指定目标资源为某个 Servlet,例如:

<servlet>
		<servlet-name>myservlet</servlet-name>
		<servlet-class>cn.itcast.servlet.MyServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>myservlet</servlet-name>
		<url-pattern>/abc</url-pattern>
	</servlet-mapping>
	<filter>
		<filter-name>myfilter</filter-name>
		<filter-class>cn.itcast.filter.MyFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>myfilter</filter-name>
		<servlet-name>myservlet</servlet-name> 
	</filter-mapping>

当用户访问 http://localhost:8080/filtertest/abc 时,会执行名字为 myservlet 的 Servlet,这时会执行过滤器。

8、Filter 小结

Filter 的三个方法:

  • void init(FilterConfig):在 Tomcat 启动时被调用;
  • void destroy():在 Tomcat 关闭时被调用;
  • void doFilter(ServletRequest,ServletResponse,FilterChain):每次有请求时都调用该方法;

FilterConfig 类:与 ServletConfig 相似,用来获取 Filter 的初始化参数

  • ServletContext getServletContext():获取 ServletContext 的方法;
  • String getFilterName():获取 Filter 的配置名称;
  • String getInitParameter(String name):获取 Filter 的初始化配置,与 元素对应;
  • Enumeration getInitParameterNames():获取所有初始化参数的名称。

FilterChain 类:

void doFilter(ServletRequest,ServletResponse):放行!表示执行下一个过滤器,或者执行目标资源。可以在调用 FilterChain 的 doFilter()方法的前后添加语句,在 FilterChain 的 doFilter()方法之前的语句会在目标资源执行之前执行,在 FilterChain 的 doFilter()方法之后的语句会在目标资源执行之后执行。

四各拦截方式:REQUEST、FORWARD、INCLUDE、ERROR,默认是 REQUEST 方式。

  • REQUEST:拦截直接请求方式;
  • FORWARD:拦截请求转发方式;
  • INCLUDE:拦截请求包含方式;
  • ERROR:拦截错误转发方式。

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-06-06发表,共计6197字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7982380
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
在Windows系统中通过VMware安装苹果macOS15

在Windows系统中通过VMware安装苹果macOS15

在 Windows 系统中通过 VMware 安装苹果 macOS15 许多开发者和爱好者希望在 Window...
12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换...
星哥带你玩飞牛NAS-14:解锁公网自由!Lucky功能工具安装使用保姆级教程

星哥带你玩飞牛NAS-14:解锁公网自由!Lucky功能工具安装使用保姆级教程

星哥带你玩飞牛 NAS-14:解锁公网自由!Lucky 功能工具安装使用保姆级教程 作为 NAS 玩家,咱们最...
开源MoneyPrinterTurbo 利用AI大模型,一键生成高清短视频!

开源MoneyPrinterTurbo 利用AI大模型,一键生成高清短视频!

  开源 MoneyPrinterTurbo 利用 AI 大模型,一键生成高清短视频! 在短视频内容...
亚马逊云崩完,微软云崩!当全球第二大云“摔了一跤”:Azure 宕机背后的配置风险与警示

亚马逊云崩完,微软云崩!当全球第二大云“摔了一跤”:Azure 宕机背后的配置风险与警示

亚马逊云崩完,微软云崩!当全球第二大云“摔了一跤”:Azure 宕机背后的配置风险与警示 首先来回顾一下 10...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face 免费服务器 +Docker 快速部署 HertzBeat 监控平台 ...
告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

  告别 Notion 焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁” 引言 在数字笔记工...
浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍 前言 在 AI 自动化快速发展的当下,浏览器早已不再只是...
多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞定

多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞定

多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞...
你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你 为什么要用宝塔跑分? 宝塔跑分其实就是对 CPU、内存、磁盘、IO 做...