Servlet 2.4 规范之第七篇:过滤器

过滤器是一套java组件,用于在请求—>资源—>应答的这一过程中即时转换处理负载和头信息。

本章讲述了Servlet 2.4 API中一些类和方法,这些类和方法提供了一套轻量级框架用于过滤动态和静态内容。它讲述了web应用下如何配置过滤器、指定过滤器的实现类。

servlet过滤器的API会在SRV.14的“javax.servlet”章节提供,而其配置语法会在SRV.13章“部署描述符”的语法中讲解。读者阅读本章的同时也应该参考下对应的章节内容。

SRV.6.1    什么是过滤器

过滤器是一段用于转换HTTP请求、响应和头信息的可重用代码段。它不能创建响应对象,一般只用于修改或适配请求和响应过程中的资源处理。

过滤器可以处理动态或静态内容,在本章里,动态或静态内容主要涉及web资源。

开发人员主要在以下场景下使用过滤器:

1. 请求之前访问资源

2. 访问资源之前对请求做处理

3. 通过修改请求的头信息和信息体来封装一个自定义版本的请求对象

4. 通过修改响应的头信息和信息体来提供一个自定义版本的响应对象

5. 在过滤器调用时插入对指定资源的访问请求

6. 通过零到多个指定顺序的过滤器来操作servlet和静态内容

SRV.6.1.1    常见过滤器示例

• 授权过滤器

• 日志和审计过滤器

• 图像转换过滤器

• 数据压缩过滤器

• 加密过滤器

• 令牌过滤器

• 触发资源访问事件的过滤器

• XML内容转换过滤器

• MIME-type 内容链过滤器

• 缓存过滤器

SRV.6.2    主要概念

过滤器模式的主要概念在本章描述。

开发人员通过实现javax.servlet.Filter接口然后提供一个公共无参构造方法来创建过滤器。它会被打包进Web压缩包,正如构成web应用的静态内容和servlet一样。过滤器通过部署描述符中的<filter>元素进行声明。一个或一组过滤器然后通过定义<filter-mapping>元素来配置如何被调用。这个配置通过把过滤器映射到特定的servlet上来完成,或者把一组serlvet和静态内容映射到一个URL模式的过滤器上。

SRV.6.2.1    过滤器的生命周期

在部署应用系统之后容器访问web资源之前,容器必须定位用于访问web资源的所有过滤器。容器必须确保每一个过滤器在调用init(FilterConfig config)方法之后被正确的初始化。过滤器可以抛出异常表示它无法正常工作,如果异常是UnavailableException类型,容器必须检查它的isPermanect属性并可能在一段时间后重试这个过滤器。

一个过滤器实例只会被同一个容器的同一个JVM初始化一次容器负责提供过滤器的config对象,正如在部署描述中声明的那样,另外提供对ServletContext的引用和一系列初始化参数。

当容器收到传入的请求时,它通过doFilter方法调用过滤器列表中的第一个过滤器实例,并传入ServletRequest和ServletResponse,以及容器使用的FilterChain对象的引用。

过滤器的doFilter方法通常实现于以下模式里:

步骤1:检查请求头信息

步骤2:用自定义实现的ServletRequest或HttpServletRequest来封装请求对象,用于修改请求头或信息体。

步骤3:用自定义实现的ServletResponse或HttpServletResponse来封装响应对象,用于修改响应头或信息体。

步骤4:过滤器可能会调用过滤器链上的下一个实体对象,它可以是另一个过滤器,若本身已是最后一个过滤器节点,那下一个实体就是目标web资源。这个调用过程由FilterChain对象的doFilter方法完成,同时也会传递被调用的请求和响应对象。

容器提供的doFilter方法的过滤器链实现,必须定位下一个实体并调用对应的doFilter方法,并随之传递合适的请求和响应对象。

换句话说,过滤器链可以通过不调用下一个实体对象来阻塞请求的处理流程,留下的过滤器负责填充输出响应对象。

步骤5:下一个责任链实体调用之后,过滤器可以检查响应头信息。

步骤6:必要情况下过滤器可以抛出异常以示发生错误。如果过滤器在doFilter执行期间抛出UnavailableException,容器就不必再尝试继续处理剩下的流程。如果异常未标记为永久性的话,那可以等一段时间后再重试整个过滤器链。

步骤7:链条上的最后一个过滤器被调用之后,下一个被访问对象会是目标servlet或者链条末端的资源。

步骤8:容器删除一个过滤器的实例之前,必须先调用过滤器的destroy方法,用以释放所有的占用资源并执行清理操作。

SRV.6.2.2    封装请求和响应

过滤器的本质就是对请求或响应的封装,以便于能重写对应的行为方式去执行些过滤任务。在此模式下,开发人员不但负责重写请求和响应对象已存在的方法,而且还要提供新的API集给链条上接下来的其他过滤器和web资源。例如,开发人员可能想增强响应对象的输出能力,像允许DOM对象输出到客户端的API之类的情形。

为了支持这些过滤器,容器必须满足以下需求。当过滤器调用doFilter方法时,容器必须确保请求和响应对象在整个责任链条上始终一致。

这些需求也同样适用于RequestDispatcher.forward或RequestDispathcer.include,当他们想封装请求和响应对象时。

SRV.6.2.3    过滤器环境

一组初始化参数可以通过部署描述符中的<init-params>元素与过滤器关联起来。过滤器在运行时可以通过getInitParameter和getInitParameterNames方法来访问这些名值对。另外,FilterConfig提供了一条访问web应用系统的ServletConfig的途径。

SRV.6.2.4    Web应用中的过滤器配置

一个过滤器对应于部署描述符下的一个<filter>元素,在此元素中,开发人员可以声明以下内容:

• filter-name:  用于映射过滤器到一个servlet或URL下
• filter-class: 由容器用于标识唯一的过滤器类
• init-params: 过滤器的初始化参数

必要情况下,开发人员还能指定图标、文本描述和工具封装时使用的显示名。容器必须精确地对每一个过滤器的声明对应初始化一个Java类实例。如果两个过滤器声明指定了同一个Java类,那么容器就会对应的为这两个过滤器分别初始化一份Java类。

示例:

<filter>
    <filter-name>Image Filter</filter-name>
    <filter-class>com.acme.ImageServlet</filter-class>
</filter>

部署描述符一旦声明一个过滤器,对应的就会使用<filter-mapping>元素定义配套的servlet或静态资源。过滤器通过<servlet-name>元素和某个servlet关联起来。例如,以下代码把Image Filter映射到了ImageServlet这个servlet上:

<filter-mapping>
    <filter-name>Image Filter</filter-name>
    <servlet-name>ImageServlet</servlet-name>
</filter-mapping>

过滤器还可以通过<url-pattern>元素和一组serlvet或静态内容建立对应的关联关系:

<filter-mapping>
    <filter-name>Logging Filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

这个例子里Loggin Filter会被用于所有的servlet和静态页面,因为每一个请求URL都和’/* ’相匹配。

当使用<url-pattern>方式处理<filter-mapping>元素时,容器必须检测<url-pattern>是否匹配请求的URL。

容器按照以下先后顺序编译过滤器链,用以处理对应的请求URI:

1. 首先,按照部署描述符中出现的先后顺序,<url-pattern>依次匹配过滤器映射。

2. 下一步,按照部署描述符中出现的先后顺序,<servlet-name>依次匹配过滤器映射。

这个需求意味着当容器收到请求时按照以下说明依次处理:

按照“映射规范”标识出目标Web资源。

若通过servlet名和web资源匹配到的过滤器有<servlet-name>,容器会按照部署描述符中出现的先后顺序依次编译创建对应的过滤器责任链。最后一个过滤器对应于最后一个<servlet-name>,并且它会用于调用最终的web资源。

若使用<url-pattern>模式的过滤器匹配到了请求的URI,容器按照过滤器在部署描述符中出现的先后顺序依次编译创建对应的过滤器责任链。过滤器链条最后一个过滤器是部署描述符中这个请求最后一个<url-pattern>匹配的过滤器。链条中的最后一个过滤器调用<servlet-name>匹配链条中的第一个过滤器,如果没有,就调用目标web资源。

专业一点来说高性能web容器都应该缓存过滤器责任链,这样一来就不用每次请求时都进行对应的计算了。

SRV.6.2.5    过滤器和请求分发器

个人理解上尚有不完善,待译。。。

文档信息

Servlet 2.4 规范之第七篇:过滤器

时间: 2024-10-27 06:57:20

Servlet 2.4 规范之第七篇:过滤器的相关文章

Servlet 2.4 规范之第四篇:Servlet上下文

SRV.3.1    ServletContext接口说明 ServletContext接口定义了运行servlet的web应用中和servlet相关的视图信息.容器提供者负责提供ServletContext的一套具体实现.通过ServletContext对象,servlet能记录事件.获得资源引用,以及设置和保存当前context上其他servlet的一些属性信息. ServletContext以web应用的某一路径为根节点,例如,servlet上下文能写成http://www.mycorp.

Servlet 2.4 规范之第六篇:响应

响应对象封装了服务端返回给客户端的所有信息.在HTTP协议中,这些信息通过HTTP头和消息体传送. SRV.5.1    缓冲 出于效率考量,servlet容器可以缓冲输出数据,但这并非强制要求.常见的WEB服务都会默认使用缓冲,但也允许servlet自行指定缓冲参数. ServletResponse接口的以下几个方法用于servlet访问和设置缓冲信息: ? getBufferSize    ? setBufferSize    ? isCommitted    ? reset    ? re

Servlet 2.4 规范之第四篇:Servlet上下文最注坐卒揍琢

http://www.ebay.com/cln/1vz_jbnv/2015-01-30/166653198017 http://www.ebay.com/cln/ntx_ntnd/2015-01-30/166918113011 http://www.ebay.com/cln/pt3_hzzh/2015-01-30/166764520010 http://www.ebay.com/cln/r5d_thbr/2015-01-30/166738785014 http://www.ebay.com/cl

Servlet 2.4 规范之第一篇:概览

      写在前面的话: 本系列是对<Java Servlet Specification Version 2.4>的完全翻译,力争但不保证完美表达出英文原文的思想内涵.如有疏漏之处,还请各位海涵并留言纠正.       SRV.1.1    Servlet是什么? Servlet是一种用于生成动态内容的Java Web组件技术,由容器(Container)负责管理其生命周期.和Java领域的其他技术一样,Servlet被编译为平台中立的class文件,然后动态的载入并运行在Web serv

Servlet 2.4 规范之第二篇:Servlet接口

Servlet接口是Servlet API的最核心抽象类.所有的servlets都直接实现了这个接口,或者以更通用的方式继承了这个接口的实现类.Servlet API自带了两个实现了Servlet接口的类:GenericServlet和HttpServlet.绝大多数情况下,开发人员都会继承HttpServlet来开发servlets. SRV.2.1    处理请求的方法 Servlet接口定义了一个service方法来处理客户端请求.servlet容器把每一个请求都路由到对应的Servlet

javaWeb核心技术第七篇之HTTP、Tomcat、Servlet、Request和Response

- Web服务器 - 概念: - web资源: "英文直译"网"的意思 资源:一切数据文件 web资源:通过网络可以访问到的资源,通常指的是一切放在服务器上的文件" - web资源的分类: - 静态的web资源: " 内容是一成不变的" - 动态的web资源: " 内容有可能在不同的时间或者不同的人访问的时候会发生改变的" - web技术分类 - 静态的web技术 " 例如: html css js .....&qu

SaltStack 入门到精通 - 第七篇: Targeting

什么是Targeting? Targeting minions 是指那些minion会作为运行命令或是执行状态的目标.这些目标可以是一个主机名,系统信息,定义的分组,甚至是自定义的绑定的对象. 例如命令  salt web1 apache.signal restart 可以重启ID 为web1的minion的apache.当然也可以在top文件中使用web1来作为目标匹配的内容: base:   'web1':     - webserver Targing 有哪些匹配方式? Minion Id

Python之路【第七篇】:线程、进程和协程

Python之路[第七篇]:线程.进程和协程 Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env python # -*- coding:utf-8 -*- import threading import time   def show(arg):     time.sleep(1)     print 'thread'+str(arg)   for i in

用仿ActionScript的语法来编写html5——第七篇,自定义按钮

第七篇,自定义按钮 这次弄个简单点的,自定义按钮.其实,有了前面所定义的LSprite,LBitmap等类,定义按钮就很方便了.下面是添加按钮的代码, function gameInit(event){ backLayer = new LSprite(); addChild(backLayer); btn01 = new LButton(new LBitmap(new LBitmapData(imglist["replay_button_up"])),new LBitmap(new L