摘要: 摘自《深入体验JAVA WEB开发内幕——高级特性》,如有版权问题,请联系我。

一、Filter的基本工作原理

1、Filter程序是一个实现了特殊接口的Java类,与Servlet类似,也是由Servlet容器进行调用和执行的。

2、当在web.xml注册了一个Filter来对某个Servlet程序进行拦截处理时,它可以决定是否将请求继续传递给Servlet程序,以及对请求和响应消息是否进行修改。

3、当Servlet容器开始调用某个Servlet程序时,如果发现已经注册了一个Filter程序来对该Servlet进行拦截,那么容器不再直接调用Servlet的service方法,而是调用Filter的doFilter方法,再由doFilter方法决定是否去激活service方法。

4、但在Filter.doFilter方法中不能直接调用Servlet的service方法,而是调用FilterChain.doFilter方法来激活目标Servlet的service方法,FilterChain对象时通过Filter.doFilter方法的参数传递进来的。

5、只要在Filter.doFilter方法中调用FilterChain.doFilter方法的语句前后增加某些程序代码,这样就可以在Servlet进行响应前后实现某些特殊功能。

6、如果在Filter.doFilter方法中没有调用FilterChain.doFilter方法,则目标Servlet的service方法不会被执行,这样通过Filter就可以阻止某些非法的访问请求。

二、Filter链

1、在一个Web应用程序中可以注册多个Filter程序,每个Filter程序都可以对一个或一组Servlet程序进行拦截。如果有多个Filter程序都可以对某个Servlet程序的访问过程进行拦截,当针对该Servlet的访问请求到达时,Web容器将把这多个Filter程序组合成一个Filter链(也叫过滤器链)。

2、Filter链中的各个Filter的拦截顺序与它们在web.xml文件中的映射顺序一致,上一个Filter.doFilter方法中调用FilterChain.doFilter方法将激活下一个Filter的doFilter方法,最后一个Filter.doFilter方法中调用的FilterChain.doFilter方法将激活目标Servlet的service方法。

3、只要Filter链中任意一个Filter没有调用FilterChain.doFilter方法,则目标Servlet的service方法都不会被执行。

三、Filter接口

一个Filter程序就是一个Java类,这个类必须实现Filter接口。javax.servlet.Filter接口中定义了三个方法:init、doFilter、destory。

1、init方法

(1)、在Web应用程序启动时,Web服务器(Web容器)将根据其web.xml文件的配置信息来创建每个注册的Filter的实例对象,并将其保存在内存中。

(2)、Web容器创建Filter的实例对象后,将立即调用该Filter对象的init方法。init方法在Filter生命周期中仅被执行一次,Web容器在调用init方法时,会传递一个包含Filter的配置和运行环境信息的FilterConfig对象。

public voic init(FilterConfig filterConfig) throws ServletException

(3)开发人员可以在init方法中完成与构造方法类似的初始化功能,要注意的是:如果初始化代码要使用到FilterConfig对象,这些代码只能在init方法中编写,而不能在构造方法中编写(尚未调用init方法,即并没有创建FilterConfig对象,要使用它则必然出错)。

2、doFilter方法

当一个Filter对象能够拦截访问请求时,Servlet容器将调用Filter对象的doFilter方法。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException.ServletException

其中,参数request和response为Web容器或Filter链中上一个Filter传递过来的请求和响应对象;参数chain为代表当前Filter链的对象

3、destroy方法

该方法在Web容器卸载Filter对象之前被调用,也仅执行一次。可以完成与init方法相反的功能,释放被该Filter对象打开的资源,例如:关闭数据库连接和IO流。

四、FilterChain接口

该接口用于定义一个Filter链的对象应该对外提供的方法,这个接口只定义了一个doFilter方法。

public void doFilter(ServletRequest request, ServletResponse response) throws java.io.IOException.ServletException

FilterChain接口的doFilter方法用于通知Web容器把请求交给Filter链中的下一个Filter去处理,如果当前调用此方法的Filter对象是Filter链中的最后一个Filter,那么将把请求交给目标Servlet程序去处理。

五、FilterConfig接口

1、与普通的Servlet程序一样,Filter程序也很可能需要访问Servlet容器。Servlet规范将代表ServletContext对象和Filter的配置参数信息都封装到一个称为FilterConfig的对象中。

2、FilterConfig接口则用于定义FilterConfig对象应该对外提供的方法,以便在Filter程序中可以调用这些方法来获取ServletContext对象,以及获取在web.xml文件中为Filter设置的友好名称和初始化参数。

3、FilterConfig接口定义的各个方法:

  • getFilterName方法,返回<filter-name>元素的设置值。

  • getServletContext方法,返回FilterConfig对象中所包装的ServletContext对象的引用。

  • getInitParameter方法,用于返回在web.xml文件中为Filter所设置的某个名称的初始化的参数值。

  • getInitParameterNames方法,返回一个Enumeration集合对象。

六、Filter的注册与映射

1、注册Filter

一个<filter>元素用于注册一个Filter。其中,<filter-name>元素是必需的,<filter-class>元素也是必需的,<init-param>元素是可选的,可以有多个<init-param>元素。

<filter><filter-name>FirstFilter</filter-name><filter-class>FirstFilter</filter-class><init-param><param-name>encoding</param-name><param-value>GB2312</param-value></init-param>
</filter>

2、映射Filter

<filter-mapping>元素用于设置一个Filter所负责拦截的资源。一个Filter拦截的资源可以通过两种方式来指定:资源的访问请求路径和Servlet名称。

第一种:指定资源的访问路径

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

<url-pattern>元素中的访问路径的设置方式遵循Servlet的URL映射规范。http://my.oschina.net/u/1171518/blog/220147。eg:

/*:表示拦截所有的访问请求

/filter/*:表示拦截filter目录下的所有访问请求,如:http://localhost:8888/testFilter_001/filter/xxxxxx

/test.html:表示拦截根目录下以test.html为资源名的访问请求,访问链接只会是:http://localhost:8888/test.html

第二种:指定Servlet的名称

<filter-mapping><filter-name>FirstFilter</filter-name><servlet-name>default></servlet-name><dispatcher>INCLUDE</dispatcher><dispatcher>REQUEST</dispatcher>
</filter-mapping>

(1)、<servlet-name>元素与<url-pattern>元素是二选一的关系,其值是某个Servlet在web.xml文件中的注册名称。

(2)、<dispatcher>元素的设置值有4种:REQUEST、INCLUDE、FORWARD、ERROR,分别对应Servlet容器调用资源的4种方式:

  • 通过正常的访问请求调用;

  • 通过RequestDispatcher.include方法调用;

  • 通过RequestDispatcher.forward方法调用;

  • 作为错误响应资源调用。

如果没有设置<dispatcher>子元素,则等效于REQUEST的情况。也可以设置多个<dispatcher>子元素,用于指定Filter对资源的多种调用方式都进行拦截。

七、Filter程序示例

1、

FitstFilter.java

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;public class FirstFilter implements Filter {private FilterConfig filterConfig = null;String paramValue = null;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig;paramValue = filterConfig.getInitParameter("encoding");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {System.out.println("begin headers-------------------");Enumeration<?> headerNames = ((HttpServletRequest)request).getHeaderNames();while(headerNames.hasMoreElements()) {String headerName = (String)headerNames.nextElement();System.out.println(headerName + ": " + ((HttpServletRequest)request).getHeader(headerName));}System.out.println("end headers-------------------");//在调用目标前写入响应内容response.setContentType("text/html; charset=gb2312");PrintWriter out = response.getWriter();out.println("IP地址为:" + request.getRemoteHost() + "<br>");chain.doFilter(request, response);//在目标返回后写入响应内容out.println("<br>名称为encoding的初始化参数的值为:" + paramValue);out.println("<br>当前Web程序的真实路径为:" + filterConfig.getServletContext().getRealPath("/"));//out.println("<br>修改了test.html文件!");}@Overridepublic void destroy() {this.filterConfig = null;}
}

web.xml

<filter><filter-name>FirstFilter</filter-name><filter-class>FirstFilter</filter-class><init-param><param-name>encoding</param-name><param-value>GB2312</param-value></init-param>
</filter><filter-mapping><filter-name>FirstFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

test.html(位于WebContent路径的filter目录中)

<html>
<head>
<meta charset="GB2312">
<title>Insert title here</title>
</head>
<body>
这就是test.html页面的原始内容!
</body>
</html>

访问:http://localhost:8888/testFilter_001/filter/test.html

浏览器显示页面:

Tomcat后台(第一次访问):

2、

把FirstFilter.java中如下语句的注释去掉:(整个过程,并未特意或无意改变了test.html文件的内容)

out.println("<br>修改了test.html文件!");

等Tomcat Reload完成,刷新页面,惊奇地发现浏览器页面并未发生改变,Tomcat后天多了三个请求头:

原因(存在疑问,是否真的是If-Modified-Since标签来决定是否采用缓存):

(1)、缓存里存储的不只是网页文件,还有服务器发过来的该文件的最后服务器修改时间;

(2)、客户端发HTTP请求时,使用If-Modified-Since标签,把上次服务器告诉它的文件最后修改时间返回到服务器端了;

(3)、服务器会把这个时间与服务器上实际文件的最后修改时间进行比较;

(4)、如果时间一致,那么返回HTTP状态码304,尽管FirstFilter程序在拦截处理中向ServletResponse对象中写入的数据也传送给了浏览器。但是浏览器因为收到304则显示原来缓存的内容;

(5)、如果时间不一致,就返回HTTP状态码200,浏览器接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。

解决:

在test.html文件中增加一个空格又删去这个空格,造成text.html文件被修改过的假象,然后在浏览器刷新test.html页面的访问。

© 著作权归作者所有

Filter、FilterChain、FilterConfig相关推荐

  1. Filter、FilterChain、FilterConfig 介绍

    一.Filter 的基本工作原理 1.Filter 程序是一个实现了特殊接口的 Java 类,与 Servlet 类似,也是由 Servlet 容器进行调用和执行的. 2.当在 web.xml 注册了 ...

  2. java servlet filter_Java的Servlet、Filter、Interceptor、Listener

    写在前面: 使用Spring-Boot时,嵌入式Servlet容器可以通过扫描注解(@ServletComponentScan)的方式注册Servlet.Filter和Servlet规范的所有监听器( ...

  3. Java中Filter、Servlet、Listener的学习

    1.Filter的功能filter功能,它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个reques ...

  4. Servlet、Filter、Listener、Interceptor基础

    第一:Servlet Servlet是个接口,全限定名是javax.servlet.Servlet,在javax.servlet包中,在servlet-api.jar(在tomcat自带的lib文件夹 ...

  5. Java的Servlet、Filter、Interceptor、Listener

    写在前面: 使用Spring-Boot时,嵌入式Servlet容器可以通过扫描注解(@ServletComponentScan)的方式注册Servlet.Filter和Servlet规范的所有监听器( ...

  6. java response 输出流_java-springmvc+filter 替换输出流、response、响应内容

    java-springmvc+filter 替换输出流.response.响应内容 一.问题 1.描述:在使用 filter 替换.修改 response 输出内容时常见的错误如下异常提示 getWr ...

  7. java day43【Filter:过滤器 、Listener:监听器】

    第一章  Filter:过滤器 1. 概念: * 生活中的过滤器:净水器,空气净化器,土匪. * web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能. * 过滤器的作 ...

  8. Java Web 项目入门指南(http、Servlet、Request、Response、ServletContext、会话技术[cookie、session]、Filter、Listener)

    概述 web 服务器.项目.资源概述 web 服务器:可以被浏览器访问到的服务器 常见的 web 服务器: tomcat:中小型的服务器软件,免费开源,支持 JSP 和 Servlet apache ...

  9. 整合Mybatis、Servlet、Mysql、Axios、Filter、Session写一个入门级项目:非常适合初接触JavaWeb的小白白来进阶

    文章目录 写在前言 写作收获&目的 目录结构 1 依赖配置 1.1 创建一个Web项目 1.2 Pom.xml 2 配置Mybatis 2.1 Mybatis-config.xml 2.2 U ...

最新文章

  1. pom.xml 引入 net.sf.json-lib 报错
  2. sql 关联使用id还是code_使用sh格式化nginx访问日志并存入mysql
  3. 简介struct cmsghdr结构
  4. html怎样使图片不占位子,复式客厅上阁楼楼梯安装什么位置不占地方 最节约空间的阁楼楼梯设计图片...
  5. 【简单数论】H - A^X mod P_HRBUST - 2049_31行代码AC
  6. oc 实例变量可见度、方法
  7. kali linux u盘自启,如何实现Kali linux系统下的U盘启动(小白指导)
  8. SQL Server系统数据库– msdb数据库
  9. mysql自建云盘_使用nextcloud自建私人云盘
  10. setSystemUiVisibility() 与 getSystemUiVisibility() 显示隐藏状态栏
  11. 计算机班英语试卷考法,计算机专业英语期末考试试卷A
  12. matlab 行 读取文件 跳过_matlab中textscan跳行使用
  13. 即将到来的Xcode8 都更新了什么?
  14. Git初学--创建版本库
  15. [半监督学习] In Defense of Pseudo-Labeling: An Uncertainty-Aware Pseudo-label Selection Framework for SSL
  16. 【第八期送书活动】+ 购书福利
  17. 九麟SDK 接入文档
  18. 《云云众声》第94期:HP网络策略遭质疑 IBM牵手ARM发力物联网
  19. 植物图像识别python_python实现图像识别功能
  20. AI强度相关的研究:MCTS 蒙特卡洛树搜索 Monte Carlo Tree Search

热门文章

  1. ae2018怎么打开2019_AE能直接导出mp4格式视频吗_怎么导出_2019相关教程免费分享
  2. 修改Java的环境变量
  3. 01-初识Node.js
  4. 测试心理素质的软件,心理素质测试
  5. Java面试题(131-135)
  6. 蒙特卡罗MCNP学习汇总(三)----源项基础(数据卡\源卡编写)
  7. Docker怎么样拉取镜像?怎样删除镜像?
  8. MySql数据库记录相差14小时排错,使用Java访问Mysql数据库时出现时区异常的解决方案
  9. Android访问网络资源
  10. 【办公类-11】20220611python 为每个孩子创建统一的照片整理三级文件夹