中的陈设描述符形式给出,使用过滤器创新应用程序

选择过滤器创新应用程序

Filtering

过滤器(Filter)是 Java 组件,
允许运维进度中退换步入能源的伏乞和能源再次回到的响应中的有效载荷和 header
信息。

本章描述了 Java Servlet v3.0 API
类和章程,它提供了一种轻量级的框架用于过滤动态和静态内容。还描
述了如何在 Web 应用配置 Filter和它们贯彻的预约和语义。

网络提供servlet过滤器的API文书档案在。过滤器的布置语法由第14章“陈设描述符”中的布置描述符情势给出。阅读本章时,读者应运用这几个来作为参谋。

一、过滤器的目标

1. 怎样是过滤器

过滤器是一段可采纳的代码,它能够调换HTTP乞请、响应和头新闻的源委。过滤器平日不会像servlet那样创设响应或响应须要,而是修改或调解能源的乞求,并修改或调度能源的响应。

过滤器能够成效于动态或静态内容。为了本章的指标,动态和静态内容被叫作Web能源。

对此急需运用过滤器的开辟职员可用的效果与利益体系如下:

  • 能源的拜候央浼此前调用它。
  • 叁个能源需要的处理在此之前调用。
  • 由此包装定制版本的乞求对象对央求头和数码的修改
  • 由此提供定制版本的响应对象对响应头和响应数据的修改。
  • 财富的调用的后拦截。
  • 以钦命的一一通过零,一个或多少个过滤器操作servlet、servlet、组或静态内容。

过滤器是足以阻挡访问能源的伏乞、能源的响应或然相同的时候阻止两个的运用组件。过滤器能够检查评定和退换诉求和响应,同期也能够拒绝、重定向或转向呼吁。javax.servlet.Filter接口达成了过滤器本领,使用HttpServletRequest和HttpServletResponse。过滤器能够在布置描述符中以以编制程序的章程宣示,它们得以有初步化参数况且能够访问ServletContext。

1.1 过滤器组件例子
  • Authentication filters
  • Logging and auditing filters
  • Image conversion filters
  • Data compression filters
  • Encryption filters
  • Tokenizing filters
  • Filters that trigger resource access events
  • XSL/T filters that transform XML content
  • MIME-type chain filters
  • Caching filters

日志过滤器

2.关键概念

本章描述了过滤器模型的重大约念。
应用程序开采职员通过兑现javax.servlet.Filter接口创制一个过滤器,并提供二个不带参数的共用构造函数。该类及创设Web
应用的静态财富和 Servlet 打包在 Web
应用归档文件中。在布局描述符中使用要素证明过滤器。通过在安插描述符中定义<filter-mapping>要素,可认为过滤器或过滤器集合配置调用。能够动用
servlet 的
逻辑名把过滤器映射到三个特定的 servlet,也许选取 ULacrosseL
情势把过滤器映射到一组 Servlet 和静态内容财富。

在应用程序开辟中,须求记录全体应用程序的伸手和种种伏乞的结果(状态码,长度等其余音信)。经常Web容器提供了乞请日志的编写制定,但假诺急需在呼吁日志中显得出一些蓄意的音讯,能够运用过滤记录央求。

2.1 过滤器生命周期

The doFilter method of a filter will typically be implemented following
this or some subset of the following pattern:
在配备Web应用程序之后,在伸手导致容器访谈Web财富在此之前,容器必须牢固必须运用于Web财富的过滤器列表,如下所述。容器必须确定保证它曾经为列表中的每一种过滤器实例化了一个适当类的过滤器,并调用它的init(FilterConfig
config)方法。那几个过滤器大概会抛出一个不胜来表示它无法平常干活。借使不行类型为UnavailableException,则容器能够检查相当的isPermanent属性,并在稍后的日子选取重试过滤器。

在安排描述符中,每种<filter>注明独有一个实例被实例化到容器的每种JVM中。容器提供过滤器陈设描述符中声明的过滤器配置,用于Web应用程序的ServletContext的援用,以及起头化参数集。

当容器接收到二个传诵央求时,它就要列表中获取第三个过滤器实例,并调用它的doFilter方法,传入ServletRequest和ServletResponse,并援引它将动用的FilterChain对象。

过滤器的doFilter方法日常会根据以下方式的有些子集实现:

  1. 该措施行检查查乞求的header。

  2. 该办法能够用定制的ServletRequest或HttpServletRequest达成来包装诉求对象,以修改诉求头或数额。

  3. 该措施能够将响应对象封装到其doFilter方法中,并定制达成ServletResponse或HttpServletResponse来修改响应头或数额。

  4. 过滤器可以调用过滤器链中的下一个实体。下三个实体或然是另贰个过滤器,大概只要调用的过滤器是这几个链的安排描述符中配置的终极一个过滤器,那么下一个实体正是目的Web能源。下一个实体的调用是通过调用FilterChain对象上的doFilter方法来促成的,并在央求和响应中传递它大概早就创办的卷入版本。过滤器链的doFilter方法的落到实处,由容器提供,必须在过滤器链中稳固下多个实体,并调用它的doFilter方法,传入适当的呼吁和响应对象。也许,过滤器链可以阻碍必要,并不是调用调用下二个实体,让过滤器担当填充响应对象。service方法需求在与应用于servlet的富有过滤器一样的线程中运作。

  5. 在调用链中的下一个过滤器之后,过滤器能够检查响应头。

  6. 依旧,过滤器只怕会抛出二个要命来提醒管理中的错误。如果过滤器在其doFilter管理进程中抛出三个不能够利用的不胜,容器就不能尝尝继续本着过滤器链进行拍卖。假设那些不是永远性的,它能够选取在事后重新尝试任何链。

  7. 当调用链中的最终三个过滤器时,将访问的下一个实体是链末端的目的servlet或财富。

  8. 在过滤器实例能够被容器从服务中剔除在此之前,容器必须首先调用过滤器上的destroy方法,以使过滤器能够自由其余资源并施行其他清理操作。

注明过滤器

2.2装进央求和响应

过滤概念的主干是包装央求或响应的定义,以便它能够覆盖作为来实行过滤职务。在那几个模型中,开荒人士不止有技艺覆盖央浼和响应对象上的现成措施,並且还是能够提供符合于特定筛选职责的新API,进而使过滤器或目的web财富沿着链向下。举例,开荒职员也许希望将响应对象扩张到输出流或写入器的越来越高档其余出口对象,例如允许将DOM对象写回客户机的API。

为了扶助那类别型的过滤器,容器必须帮衬以下供给。当一个过滤器调用容器的过滤器链上的doFilter方法达成中,容器必须保障它经过过滤器链中的下贰个实体,或到指标web财富要是过滤器链中的最终叁个的乞请和响应对象,是经过调用过滤器传递到doFilter方法的同一的靶子。

包装器对象标志的同等需要适用于从servlet或过滤器到RequestDispatcher的调用。或RequestDispatcher向前发展。包蕴,当调用者包装诉求或响应对象时。在这种情形下,被调用的servlet所看到的呼吁和响应对象必须是通过调用servlet或过滤器传入的同样的包装器对象。

要是急需确认保证独有授权用户才足以访谈应用程序,日常能够检查种种必要的新闻,保障用户已登入,过滤器能够通过将注明和授权操作聚焦到八个地点的方法使办事变得简单。

2.3 过滤器情形

在安排描述符中使用<initparams>成分,能够将一组初阶化参数关联到三个过滤器。这几个参数的名目和值能够通过getInitParameter和getInitParameterNames方法在运作时通过过滤器的FilterConfig对象开始展览筛选。其余,FilterConfig提供了对Web应用程序的ServletContext的拜会,用于加载能源、记录功用,以及在ServletContext的本性列表中存款和储蓄状态。过滤器和过滤器链末端的对象servlet或能源必须在一样的调用线程中施行。

削减和加密过滤器

2.4 在一个Web应用中filter的配置

过滤器是通过@WebFilter注释定义的,如在正式的第8-72页中定义的“@WebFilter”或选取安排描述符中的
<filter>成分 。在那么些因素中,技术员注脚如下:

  • 过滤器名称:用于过滤器映射到叁个servlet或U福特ExplorerL

  • 过滤器类:容器使用来鉴定分别过滤器类型

  • 开端化:叁个过滤器的初叶化参数

可选地,工程师能够钦赐图标、文本描述和工具操作的呈现名称。容器必须实例化定义在布局描述符中每一种过滤器证明的过滤器的Java类的贰个实例。由此,若是开辟职员为同二个过滤器类生成八个过滤器注明,那么容器将实例化同多个过滤器类的四个实例。

下边是三个过滤器注脚的例子:

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

在布置描述符中注明了过滤器之后,汇编器使用filter-mapping>成分来定义Web应用程序中的servlet和静态财富。过滤器能够应用<servlet-name>成分与servlet关联。举例,下边包车型地铁代码示例将图像过滤器过滤器映射到ImageServlet
servlet:

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

Filters can be associated with groups of servlets and static content
using the <urlpattern> style of filter mapping:

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

这里,日志过滤器应用于Web应用程序中的全数servlet和静态内容页,因为种种伏乞UPRADOI都协作“/*”URL模式。

当使用<url-pattern>样式管理<filter-mapping>成分时,容器必须鲜明是不是协作伏乞UPAJEROI,使用第12章中定义的门路映射准则,“将呼吁映射到servlet”。

在塑造用于特定乞求UCRUISERI的筛选器链时,容器使用的相继如下:

  1. 率先,<url-pattern>相配的过滤器映射与这一个要素在安顿描述符中出现的依次同样。
  2. 接下去,<servlet-name>相配的过滤器映射与这几个成分在布置描述符中出现的各样同样。

假如贰个筛选映射包括了<servlet-name>
和<url-pattern>,那么容器必须将筛选映射扩张到多个筛选映射(各类<servletname>
and <url-pattern>),保存<servlet-name> and
<urlpattern>成分的一一。举个例子,下边的筛选器映射:

<filter-mapping>
<filter-name>Multiple Mappings Filter</filter-name>
<url-pattern>/foo/*</url-pattern>
<servlet-name>Servlet1</servlet-name>
<servlet-name>Servlet2</servlet-name>
<url-pattern>/bar/*</url-pattern>
</filter-mapping>

is equivalent to:

<filter-mapping>
<filter-name>Multipe Mappings Filter</filter-name>
<url-pattern>/foo/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Multipe Mappings Filter</filter-name>
<servlet-name>Servlet1</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>Multipe Mappings Filter</filter-name>
<servlet-name>Servlet2</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>Multipe Mappings Filter</filter-name>
<url-pattern>/bar/*</url-pattern>
</filter-mapping>

至于过滤器链顺序的渴求表示容器在收受到传播哀告时按如下格局管理诉求:
■依据第126页上的“映射标准”的平整标识指标Web能源。
■假诺存在通过servlet名称匹配的过滤器並且Web能源有着<servletname>,那么容器会依照陈设描述符中证明的一一营造相配的过滤器链。该链中的最终二个过滤器对应于最后贰个<servlet-name>相配过滤器,况兼是调用目的Web财富的过滤器。
■假如存在使用<url-pattern>相配的过滤器况且<url-pattern>依据第12.2节“映射标准”的法规相称必要U翼虎I,则容器会塑造相称过滤器的<url-pattern>链与布局描述符中注明的次第一样。此链中的最终三个过滤器是此恳请USportageI的陈设描述符中的尾声三个<url-pattern>相称过滤器。该链中的最终贰个过滤器是调用<servlet-name>相配链中的第二个过滤器的过滤器,可能调用目的Web能源(若无)。

展望高质量Web容器将缓存过滤器链,以便它们无需依据种种央浼总计它们。

留存着网络带宽有限而CPU财富充裕的事态,日常在数量传输此前对数据开展削减。过滤器能够在收受必要时,诉求保持不改变,但在响应重临给用户时,使用过滤器能够削减相应对象。

2.5 Filters and the RequestDispatcher

自Java Servlet规范2.4版来讲的新添效果与利益是能够配置被呼吁调整器(request
dispatcher)的forward()和include()调用的过滤器。
经过在配置描述符中使用新的<dispatcher>成分,开垦人士能够提出过滤器映射是或不是期待在偏下情况下将过滤器应用于央浼:
1.伸手直接源于客户端。那由具有值REQUEST的<dispatcher>成分或从不任何<dispatcher>成分提醒。
2.伸手正在被代表相称<url-pattern>或<servlet-name>的Web组件的伸手调治程序下行使forward()调用所拍卖。这由全体值FO奥迪Q3WA悍马H2D的<dispatcher>成分提醒。
3.伸手正在代表相配<url-pattern>或<servlet-name>的Web组件的乞求分派器下使用include()进行拍卖。
呼唤。那由八个值为INCLUDE的<dispatcher>元素表示。
4.该央浼正在选取第112页上的“错误管理”中钦点的不当页机制管理为与<url-pattern>相称的荒唐能源。那由全数值E中华VRO奇骏的<dispatcher>成分提醒。
5.该央求正在使用第10页上的“异步管理”中钦定的异步上下文分派机制,通过调节呼叫管理到Web组件。那由具备值ASYNC的<dispatcher>成分提示。
6.或上述1,2,3,4或5的另外组合。
例如:

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

会导致日志过滤器被客户端运营的/products/..央求调用,但不在必要分派器调用之下调用,在那之中央求分派器材备路线始于/
products/…。LoggingFilter将在呼吁最初的调节和死灰复然的伸手时被调用。
以下代码:

<filter-mapping>
<filter-name>Logging Filter</filter-name>
<servlet-name>ProductServlet</servlet-name>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

将招致日志过滤器不会被客户端央求调用到ProductServlet,也不会在伸手dispatcher
forward()调用下调用ProductServlet,而是会在哀求调节程序include()调用中调用,当中央求分派器的称呼以ProductServlet先河。上边包车型客车代码:

<filter-mapping>
<filter-name>Logging Filter</filter-name>
<url-pattern>/products/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>

将导致Logging
Filter被/products/…开首的乞请和以/products/…起首的哀求分发器forward()调用下调用。
最终,以下代码应用非常的servlet名“*”

<filter-mapping>
<filter-name>All Dispatch Filter</filter-name>
<servlet-name>*</servlet-name>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

在按名字或按路线获取的具有诉求分派器 forward()调用时该代码将导致 All
Dispatch Filter 被调用。

错误管理过滤器

对此Web用用程序来讲,出现错误,是二个HTTP响应代码500,一般还有可能会伴随着叁个常备的HTML页面,写着“Internal
Server
Error”以及部分会诊音讯。对于在地点运维的应用程序对开荒者是一蹴而就的,但是对于远程的应用程序来说是不需求的。须要经过过滤器给用户体现出更为团结的和通用的错误管理页面,并记录必要的错误音讯。

二、创造、申明和照耀过滤器

创造过滤器正是贯彻Filter接口同样,过滤器在开端化的时候将调用init方法,他可以访问过滤器的计划开头化参数和ServletContext。当呼吁进入到过滤器中,doFilter方法将会被调用,它提供了对ServletRequest、ServletResponse和FilterChain对象的探问。在doFilter中,能够拒绝央求或然调用FilterChain对象的doFilter方法,能够打包央求和响应对象。

过滤器链

固然只有三个Servlet能够管理央求,但是足以动用过多的过滤拦截央浼。在过滤器链中每贰个过滤器接受步向的呼吁并将它传递到下一个过滤链中,直到全体相配的过滤器都管理达成,最后再将它传到Servlet中。调用FilterChain.doFilter()将触及过滤器链的无休止推行。即使当前的过滤器没有调用FilterChain.doFilter(),将把调整权重返值Servlet容器中。

映射到URL模式和Servlet名称

同Servlet一样,过滤器能够被映射到UCR-VL方式,这会调控哪些或什么过滤器将截留有些央求。任何相称有些过滤器的U福睿斯L形式的央浼在被匹配的Servlet处理在此之前将首先走入该过滤器,通过动用URAV4L方式,不仅能阻止Servlet央浼,还足以阻碍任何能源。

但是当未来一度有五个UMercedes-迈巴赫L已经映射到Servlet上,何况期望某个过滤器映射到那么些ULacrosseL上。与映射到ULX570L上反而,能够将那几个过滤器映射到二个或五个Servlet名称上。

1.在配备描述符中使用<filter>和<filter-mapping>元素:

    <filter>
        <filter-name>filterA</filter-name>
        <filter-class>com.wrox.AnyRequestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filterA</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

在宣称了过滤器之后,能够将它映射到自由数目标USportageL或Servlet名称。当然过滤器UHavalL映射还可以分包通配符。

2.施用表明注脚和照耀过滤器

@WebFilter{
    filterName = "myFilter",
    urlPatterns = {"/foo","/bar/*"},
    serVletNames = {"myServlet"},
    dispatcherTypes = {DispatcherType.REQUEST,         
    DispatcherType.ASYNC}    
}

可是不得以对对过滤器链上的过滤器举办排序

三、过滤器排序

过滤器的顺序决定了过滤器在过滤器链中出现的任务,这里将会选择安插描述符来进行配备,因为注解不恐怕进展排序配置。

UQashqaiL方式映射和Servlet名称映射,相称央浼的过滤器将如约它们出未来安顿描述符或然编制程序式配置中的顺序增加到过滤器链中,可是须求注意UEvoqueL映射的过滤器优先级比Servlet名称映射到的过滤器高,由U奥迪Q5L格局相称的过滤器总是出现在有Servlet名称相称的过滤器在此以前。

    <filter>
        <filter-name>filterA</filter-name>
        <filter-class>com.wrox.FilterA</filter-class>
    </filter>

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

    <filter>
        <filter-name>filterB</filter-name>
        <filter-class>com.wrox.FilterB</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>filterB</filter-name>
        <url-pattern>/servletTwo</url-pattern>
        <url-pattern>/servletThree</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>filterC</filter-name>
        <filter-class>com.wrox.FilterC</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>filterC</filter-name>
        <url-pattern>/servletTwo</url-pattern>
    </filter-mapping>

这是二个filter的实例:

那是管理中的第二个过滤器,它将记录管理诉求的时光,并记录全体访问应用程序的央求消息——IP地址、时间戳、央浼方法等音信,finally块中是日记的操作。

public class RequestLogFilter implements Filter
{
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException
    {
        Instant time = Instant.now();
        StopWatch timer = new StopWatch();
        try
        {
            timer.start();
            chain.doFilter(request, response);
        }
        finally
        {
            timer.stop();
            HttpServletRequest in = (HttpServletRequest)request;
            HttpServletResponse out = (HttpServletResponse)response;
            String length = out.getHeader("Content-Length");
            if(length == null || length.length() == 0)
                length = "-";
            System.out.println(in.getRemoteAddr() + " - - [" + time + "]" +
                    " \"" + in.getMethod() + " " + in.getRequestURI() + " " +
                    in.getProtocol() + "\" " + out.getStatus() + " " + length +
                    " " + timer);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }

    @Override
    public void destroy() { }
}

 

相关文章