zoukankan      html  css  js  c++  java
  • 《Head First Servlets & JSP》-13-过滤器和包装器

    过滤器是什么

    与servlet非常类似,过滤器就是java组件,请求发送到servlet之前,可以用过滤器截获和处理清求,另外 servlet结束工作之后,在响应发回给客户之前,可以用过滤器处理响应。
    容器根据DD中的声明来确定何时调用过滤器。在DD中,部署人员要建映射。明确对于哪个请求URL模式要调用哪些过滤器。所以,要由部署人员(而不是程序员)来确定哪些请求或响应应当由哪些过滤器处理。

    过滤器要做的事情

    只有一个过滤器接口:Filter,根据使用方式,可完成诸如以下工作:

    请求过滤器可以完成:

    • 完成安全检查
    • 重新格式化请求首部或体
    • 建立请求审计或日志

    响应过滤器可以完成:

    • 压缩响应流
    • 追加或修改响应流
    • 创建一个完全不同的响应

    注意,没有RequestFilter或ResponseFilter之类的接口,只有一个Filter接口。

    过滤器是模块化的,可以在DD中配置

    • 容器知道过滤器API
      一个类实现了Filter接口,会从一个普通Java 类变为J2EE过滤器,过滤器API或其他成员允许过滤器访问ServletContext,而且可以与其他过滤器链接。
    • 容器管理过滤器的生命周期
      类似servlet,过滤器有init()和destroy()方法,还有doFilter()方法。
    • 在DD中声明
      DD可以声明请求要运行哪些过滤器,以及运行的顺序。

    实例:建立请求跟踪过滤器

    过滤器的生命周期

    • init()
      完成调用过滤器之前的所有初始化任务,如上述代码显示的保存FilterConfig对象的一个引用,以备过滤器以后使用。
    • doFilter()
      真正的工作在此完成,如把用户名记录到文件中、压缩响应输出。
      它包含三个参数:
      ServletRequest(不是HttpServletRequest)
      ServletResponse(不是HttpServletResponse)
      FilterChain
    • destroy()
      撤销实例之前完成的清理工作。

    注意FilterChain接口的doFilter和Filter接口的doFilter()不同。
    前者负责明确接下来调用谁的doFilter()方法(若没有Filter则调用servlet的service()方法)。
    后者是过滤器的真正方法。

    过滤器可看成“可入栈”

    这个栈是概念性的,可能并不存在。

    DD中声明和确定过滤器

    在DD中配置过滤器,会做3件事:

    • 声明过滤器
    • 将过滤器映射到想要过滤的Web资源
    • 组织这些映射,创建过滤器调用序列


    两个规则:

    • filter元素规则
      必须有filter-name
      必须有filter-class
      init-param可选,可以多个

    • filter-mapping元素规则
      必须有filter-name
      url-patter或servlet-name必须有一个
      url-pattern元素定义了哪些Web应用资源使用这个过滤器
      servlet-name元素定义了哪个servlet使用这个过滤器

    过滤器可以应用于请求分派器

    2.4版本,允许为通过分派请求的Web资源声明一个过滤器映射,如下:

    • 声明规则
      必须要有filter-name。
      必须要有url-pattern或servlet-name元素其中之一。
      可以有0~4个dispatcher元元素。
      REQUEST值表示对客户请求启用过滤器。如果没有指定dispatcher元素.则默认为REQUEST 。
      INCLUDE值表示对由一个include()调用分派来的请求启用过滤器。
      FORWARD位表示对由一个forward()调用分派来的请求启用过滤器。
      ERROR直表示对错误处理器调用的资源启用过滤器。

    用一个响应端过滤器压缩输出

    容器已经实现了HttpServletResponse接口;doFilter()和service()方法就是以这样一个响应作为参数。但是要让这个压缩过滤器正常工作,必须建立我们自己的HttpServletResponse接口定制实现,并把它通过chain.doFilter()调用传递到servlet。而且这个定制实现还必须包含一个定制输出流,因为这正是我们的目标,在servlet写输出之后并且在输出返回给客户之前,过滤器就能拿到这个输出。

    • 缺点难点:需要实现复杂的HttpServletResponse接口,不过通常不这么做。

    实现自己的HttpServletResponse太负责,怎么办?——servlet包装器

    创建一个特定版本的请求或响应,这在创建过滤器里实在太常用了,所以Sun创建了4个“便利’类,以便更容易地完成这个任务,我们只需要继承某个包装器类就可以了:

    • ServletRequestWrapper
    • HttpServletRequestWrapper
    • ServletResponseWrapper
    • HttpServletResponseWrapper

    伪代码

    • 看看下面继承包装器类的伪代码:
    • 增加第2个包装器

    看看具体的实现代码

    • 压缩过滤器代码

    • 调用的压缩包装器代码
      (这个是servlet世界中最复杂的问题之一)

    • 压缩包装器,辅助类:

  • 相关阅读:
    20170417成员运算符、身份运算符、布尔运算符
    20170417学习find、replace、abs三个函数
    shell 双中括号 双小括号
    man 命令
    awk 命令-对文本和数据进行处理
    shell-1-day
    shell---0-day
    /etc
    Selenium IDE使用
    python 自动化测试框架 pytest 和unittest 的区别
  • 原文地址:https://www.cnblogs.com/myitroad/p/6192537.html
Copyright © 2011-2022 走看看