JavaWeb——Filter过滤器
1、Filter的目的
Filter用于在Servlet之前检测和修改请求和响应,它可以拒绝、重定向或转发请求。常见的有这几种:
- 日志过滤器
使用过滤器记录请求,提供请求日志记录,还可以添加追踪信息用于特定的请求。
- 验证过滤器
用于验证用户已经“登陆”,很多Servlet的操作都需要验证用户的身份权限,验证过滤器就是把这一功能提取出来,将验证和授权操作集中带一个位置,方便开发和维护
- 压缩和加密过滤器
其实根本上的目的和上一个验证过滤器一样,不过这里的功能是压缩和加密
- 错误处理过滤器
对于客户端来说,有时候出现错误错误通常会返回一个Http响应代码500,一般还伴随这一些诊断信息,通常这些信息对于开发者而言是有用的,但是对于黑客来说,这些诊断信息可能暴露一些敏感的系统信息,而且错误几乎是不可避免的,所以我们需要防止这些信息泄露,使用错误处理过滤器为用户显示一个特殊的页面,比如这个,url是我随便填的一个:
2、创建Filter
其实Filter只是一个接口,源代码如下:
public interface Filter {
void init(FilterConfig var1) throws ServletException; void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; void destroy();
}
- init()方法用于初始化过滤器,这里可以看到一个FilterConfig类,Filter就是使用这个类来进行初始化配置
- doFilter()方法就是用来实现具体功能,检测和修改请求和响应,因为一个项目可能不止需要一个Filter,就比如某个Servlet需要先验证再加密压缩,可能就需要使用两个Filter,这样就形成了一个过滤器链,验证的Filter成功后再将请求传递给加密压缩的Filter,FilterChain将用于传递请求和响应。
- destroy()方法将用于销毁Filter
3、Filter链
通常只有一个Servlet可以处理请求,但可以使用许多过滤拦截请求。一个请求将被很多过滤器处理后传递最终传递给Servlet。如图所示这样:
这样的工作方式被称为过滤器链,这种工作方式相当于一个工作栈,当请求进入时,第一个过滤器将被添第一个过滤器将被添加到栈中,然后再把第二个过滤器添加到栈中,直到最终的Servlet,这是栈的最后一个元素,当Servlet的请求完成的时候,Servlet将从栈中去除,然后控制权将返回最后一个过滤器,然后再移除最后一个过滤器,一直到第一个过滤器中,当栈空的时候,请求处理也就完成了。
4、Filter的部署方式
Filter除了可以映射到某个URL上,某个Servlet上,还可以映射到不同的请求派发器类型,在Servlet容器中有这么几种派发请求方式:
- 普通请求:通常来自客户端,,并包含了容器中特定的Web应用程序的目标URL
- 转发请求:当代码调用RequestDispatcher的forward方法或者使用<jsp:forward>标签是将触发这些请求。
- 包含请求:使用<jsp:include>标签或者调用RequestDispatcher的include方法的时候,将会产生一个不同的、与原始请求相关的内部请求
- 错误资源请求:访问HTTP错误的错误页面的请求
- 异步请求
部署Filter有两种方式,第一种是使用部署描述符
<filter>
<filter-name>filterA</filter-name>
<filter-class>filter.FilterA</filter-class>
</filter>
<filter-mapping>
<filter-name>filterA</filter-name>
<url-pattern>/filterA</url-pattern>
<servlet-name>someServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
- <filter-name>将指定filter的名字
- <filter-class>将指定filter的类名
- <url-pattern>将指定映射的URL
- <servlet-name>将指定映射的Servlet的名字
- <dispatcher>将响应的请求的派发方式,有效的<dispatcher>类型有REQUEST、FORWARD、INCLUDE、ERROR、ASYNC
使用注解:
@WebFilter(
filterName = "filterA",
urlPatterns = {"/filterA","/filterB"},
servletNames = {"someServlet"},
dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.ASYNC}
)
5、过滤器排序
- 匹配请求的过滤器将按照它们出现在部署描述符的顺序添加到过滤器链中
- URL映射的过滤器优先级比Servlet名称映射的过滤器优先级高
定义三个Filter,分别为FilterA、FilterB、FilterC,三个Filter在启动的时候都会输出类名+start,然后将请求和响应传递给下一个Filter,到出栈之前都会输出类名+end
public class FilterA implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterA start");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("FilterA end");
} @Override
public void destroy() { }
}
然后定义一个Servlet,这里就是启动的时候输出“ServletOne.doget() start”,结束的时候输出“ServletOne.doget() start”
@WebServlet(
name = "servletOne",
urlPatterns = "/servletOne"
)
public class ServletOne extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletOne.doget() start");
resp.getWriter().write("ServletOne");
System.out.println("ServletOne.doget() end");
}
}
然后这样配置Filter:
<filter>
<filter-name>filterA</filter-name>
<filter-class>filter.FilterA</filter-class>
</filter>
<filter-mapping>
<filter-name>filterA</filter-name>
<servlet-name>servletOne</servlet-name>
</filter-mapping> <filter>
<filter-name>filterB</filter-name>
<filter-class>filter.FilterB</filter-class>
</filter>
<filter-mapping>
<filter-name>filterB</filter-name>
<url-pattern>/servletOne</url-pattern>
</filter-mapping> <filter>
<filter-name>filterC</filter-name>
<filter-class>filter.FilterC</filter-class>
</filter>
<filter-mapping>
<filter-name>filterC</filter-name>
<url-pattern>/servletOne</url-pattern>
</filter-mapping>
FilterA将映射到名称为servletOne的Servlet,FilterB、FilterC都将映射的URL是/servletOne。运行成功之后在浏览器中输入http://localhost:8080/hello-world/servletOne,我们将在IDEA的输出中看到这样的结果
filter.FilterB@17f58a6f start
filter.FilterC@193266e1 start
filter.FilterA@1d0de11fstart
ServletOne.doget() start
ServletOne.doget() end
filter.FilterA@1d0de11f end
filter.FilterC@193266e1 end
filter.FilterB@17f58a6f end
可以看到最先启动的是FilterB,其次是FilterC,最后是FilterA。因为FilterA是映射的Servlet的名称而FilterB、FilterC都是映射的URL所以FilterA将在最后启动,同时也在Servlet结束后结束。因为FilterB在部署时在FilterC之前所以FilterB是最先被启动的,最后结束的。
JavaWeb——Filter过滤器的更多相关文章
- JavaWeb基础—过滤器Filter
一.概念 JavaWeb三大组件之一(组件都有一个特性,需要在web.xml中配置) 过滤器:会在一组资源(jsp servlet等)的前面执行,可以让请求得到目标资源,也可以终止请求,不再继续 也就 ...
- 【JavaWeb】Filter 过滤器
Filter 过滤器 简介 Filter 过滤器是 JavaWeb 三大组件之一 Filter 过滤器是 JavaEE 的规范,也就是接口 Filter 过滤器的作用是 拦截请求,过滤响应 拦截请求的 ...
- javaweb学习总结(四十二)——Filter(过滤器)学习
一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态 ...
- javaWeb学习总结(10)- Filter(过滤器)学习
一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有 web资源:例如Jsp, Servlet, 静 ...
- JavaWeb(五)Filter过滤器
Filter过滤器 Fileter介绍 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Serv ...
- javaweb之Filter过滤器详解
快速入门 1.新建一个类,实现Filter接口 2.实现doFilter()方法,打印一句话,来证明能够进行拦截 3.在web.xml中进行配置(参照Servlet配置) 4.访问一个页面,看看能不能 ...
- JavaWeb学习篇--Filter过滤器
Filter过滤器简介 ServletAPI中提供了一个Filter接口,开发web应用时,如果编写的 java 类实现了这个接口,则把这个java类称之为过滤器Filter. WEB服务器每次在调用 ...
- Filter(过滤器)常见应用
孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(四十六)——Filter(过滤器)常见应用 一.统一全站字符编码 通过配置参数charset指明使用何种字符编码,以处理Html F ...
- Filter(过滤器)
一.Filter过滤器(重要) Javaweb中的过滤器可以拦截所有访问web资源的请求或响应操作. 1.Filter快速入门 1.1.步骤: 1. 创建一个类实现Filter接口 2. 重写接口中方 ...
随机推荐
- curl推送示例:熊掌号,百度站长的链接推送(系统环境变量配置)
curl推送示例:熊掌号,百度站长的链接推送(需要用户系统环境变量配置)这篇文章主要讲解curl推送,熊掌号,百度站长的链接推送,我们很多seo朋友都搞不定curl的推送链接,而且还要配置系统的环境变 ...
- os.path.join用法
os.path.join()函数:连接两个或更多的路径名组件 1.如果各组件名首字母不包含’/’,则函数会自动加上 2.如果有一个组件是一个绝对路径,则在它之前的所有组件均会被舍弃 3.如果最后一个组 ...
- JPA自定义实体的id
背景:继上一篇文章,已经实现客户端数据库数据,存入服务器,但是,两张表的id不一样,应该是id设置自增了,所以虽然从客户端查出的实体带id,但是存入服务器时id被抹掉,按照服务端表的id序号向上自增, ...
- 利用Jmeter模拟Github登录
最近学习了Jmeter的简单操作,很想找点东西来实战一下,因为我之前写过一篇通过Python模拟登录的文章,于是便想尝试下学习通过Jmeter来模拟登录. 本人环境:Jmeter5.1.1 关于Git ...
- scala刷LeetCode--21 合并两个有序链表
一.题目描述 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 二.示例 输入:1->2->4, 1->3->4输出:1->1 ...
- python 3.7 新特性 - popitem
百度上大多文章说 popitem 随机删除字典的一个键值对 python 3.7 官方文档已经说了,popitem 删除字典最后一个添加进去的键值对
- STM32F0_HAL库驱动描述——LL驱动程序概述
LL驱动概述 低层(LL)驱动器旨在提供快速轻量级的专家导向层,它比硬件更接近硬件: 与HAL相反,LLAPI不适用于优化访问不是关键功能的外设设备,或者需要大量软件配置和/或复杂的高级堆栈(如USB ...
- 【模拟】CF409C 【Magnum Opus】-C++
题目背景 愚人节题目,题面似乎是一位名叫Nicolas Flamel的炼金术士用拉丁文写的某种物质的配方,结合谷歌尝试翻译了一下: 吾友: 哲人石所言不虚,人不可貌相,海不可斗量,唯努力得胜万象,亦无 ...
- Preface Numbering序言页码
题面 (preface.pas/c/cpp) 一类书的序言是以罗马数字标页码的.传统罗马数字用单个字母表示特定的数值,以下是标准数字表: I 1 V 5 X 10 L 50 C 100 D 500 M ...
- Java中的I/O输入输出流概述
流是一组有序的数据序列,根据操作类型,可以分为输入流和输出流两种,Java语言中定义的负责各种输入输出的类都被放在java.io包中.其中所有的输入流类都是抽象类InputStream(字节输入流)或 ...