2019独角兽企业重金招聘Python工程师标准>>>

1、Servlet Filter概述

  凡是开发过J2EE的web application的人员都知道,经常需要处理以下几种情况:

   访问特定资源(Web 页、JSP 页、servlet)时的身份认证

   应用程序级的访问资源的审核和记录

   应用程序范围内对资源的加密访问,它建立在定制的加密方案基础上

   对被访问资源的及时转换, 包括从 servlet 和 JSP 的动态输出

  

  在servlet2.3之前这些功能处理是很难实现的,但是Java Servlet 2.3 规范新增了不少激动人心的功能,其中之一便是过滤器(Filter),其实这就是我们所说的管道和过滤器体系架构在J2EE中的应用实践. 通过使用该模式使得Web Application开发者能够在请求到达Web资源之前截取请求,在处理请求之后修改应答。其结构图如下:

500){this.resized=true;this.style.width=500;}" align=center vspace=1 border=1>

  一个执行过滤器的Java 类必须实现javax.servlet.Filter 接口。这一接口含有三个方法:

  init(FilterConfig):这是容器所调用的初始化方法。它保证了在第一次 doFilter() 调用前由容器调用。它能获取在 web.xml 文件中指定的filter初始化参数。

  doFilter(ServletRequest, ServletResponse, FilterChain):这是一个完成过滤行为的方法。它同样是上一个过滤器调用的方法。引入的 FilterChain 对象提供了后续过滤器所要调用的信息。

  destroy():容器在销毁过滤器实例前,doFilter()中的所有活动都被该实例终止后,调用该方法。

500){this.resized=true;this.style.width=500;}" align=center vspace=1 border=1>

  2、Filter链介绍

  所有过滤器都服从调用的过滤器链,并通过定义明确的接口得到执行。WebApplication可以指定许多过滤器来完成相关的工作.那么它们就组成一个过滤器链来完成相应的工作.其结构如下图:

500){this.resized=true;this.style.width=500;}" align=center vspace=1 border=1>

  3、例子

  3.1 简单filter

  在PetStore1.3.1中的就存在两个Filter过滤器.其中一个过滤器,完成字符集的编码的转化,如大家经常遇到的汉字编码问题,你只需配置为GBK即可.它从Web.xml之中读取这些参数的配置信息,然后进行编码的转化.另一个是安全校验Fliter,它负责进行安全检查哪些页面可以进行,哪些不可。它们组成一个Filter链,结构图和实现代码如下:

500){this.resized=true;this.style.width=500;}" align=center vspace=1 border=1>

public class EncodingFilter implements Filter {

 private FilterConfig config = null;

 // default to ASCII

 private String targetEncoding = "ASCII";

 public void init(FilterConfig config) throws ServletException {

  this.targetEncoding = config.getInitParameter("encoding");

 }

 //在过滤器中实现字符集编码转化

 public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain chain)

 throws IOException, ServletException {

 

  HttpServletRequest request = (HttpServletRequest)srequest;

  request.setCharacterEncoding(targetEncoding);

  // move on to the next

  chain.doFilter(srequest,sresponse);

 }

 public void destroy() {

  .................

 }

}

public class SignOnFilter implements Filter {

 public void init(FilterConfig config) throws ServletException {

  this.config = config;

  URL protectedResourcesURL = null;

  try {

   protectedResourcesURL = config.getServletContext().getResource("/WEB-INF/signon-config.xml");

   ...............

  } catch (java.net.MalformedURLException ex) {

   System.out.println("SignonFilter: malformed URL exception: " + ex);

  }

 }

 public void destroy() {

  config = null;

 }

 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

 throws IOException, ServletException {

  ........

 }

}

  容器通过 Web 应用程序中的配置描述符 web.xml 文件解析过滤器配置信息。有两个新的标记与过滤器相关:<filter> 和 <filter-mapping>。<filter> 标记是一个过滤器定义,它必定有一个 <filter- name> 和 <filter-class> 子元素。<filter-name> 子元素给出了一个与过滤器实例相关的名字。<filter-class> 指定了由容器载入的实现类。您能随意地包含一个 <init-param> 子元素为过滤器实例提供初始化参数。<filter-mapping> 标记代表了一个过滤器的映射,指定了过滤器会对其产生作用的 URL 的子集。

<!-- Encoding Filter Declaration Start -->

<filter>

 <filter-name>EncodingFilter</filter-name>

 <display-name>Encoding Filter</display-name>

 <description>no description</description>

 <filter-class>com.sun.j2ee.blueprints.encodingfilter.web.EncodingFilter</filter-class>

 <init-param>

  <param-name>encoding</param-name>

  <param-value>UTF-8</param-value>

 </init-param>

</filter>

<!-- Encoding Filter Declaration End -->

<!-- Signon Filter Declaration Start -->

<filter>

 <filter-name>SignOnFilter</filter-name>

 <display-name>SignOn Filter</display-name>

 <description>no description</description>

 <filter-class>com.sun.j2ee.blueprints.signon.web.SignOnFilter</filter-class>

</filter>

<!-- Signon Filter Declaration End -->

<!-- Encoding Filter Mapping Start-->

<filter-mapping>

 <filter-name>EncodingFilter</filter-name>

 <url-pattern>/*</url-pattern>

</filter-mapping>

<!-- Encoding Filter Mapping End -->

<!-- Signon Filter Mapping Start-->

<filter-mapping>

 <filter-name>SignOnFilter</filter-name>

 <url-pattern>/*</url-pattern>

</filter-mapping>

<!-- Signon Filter Mapping End -->

  3.2 复杂的filter

  上面是petstore的例子,演示了通过Fliter修改字符编码和安全认证的功能。下面提供一个示例演示通过修改返回数据(通过过滤器把response的字符串变成大写)。

public class UCaseResponse extends HttpServletResponseWrapper {

 public UCaseResponse(HttpServletResponse response) {

  super(response);

 }

 public PrintWriter getWriter() throws IOException {

  return new UCaseWriter(super.getWriter());

 }

}

public class UCaseWriter extends PrintWriter {

 public UCaseWriter(Writer out) {

  super(out);

 }

 public void write(int c) {

  super.write(Character.toUpperCase( (char) c));

 }

 public void write(char buf[], int off, int len) {

  for (int i = 0;i < len;i++) {

   write(buf[off + i]);

  }

 }

 public void write(String s, int off, int len) {

  for (int i = 0;i < len;i++) {

   write(s.charAt(off + i));

  }

 }

}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {

 try {

  filterChain.doFilter(request, new UCaseResponse((HttpServletResponse)(response)));

 }catch(Exception sx) {

  filterConfig.getServletContext().log(sx.getMessage());

}

  该示例使用HttpServletResponseWrapper技术,它是对HttpServletResponse的包装,其实就是装饰(decorate)设计模式的应用.这个例子能够工作的关键是UCaseResponse和UCaseWriter类,它实现了对每个要输出的字符都转成了大写后再写入实际的输出流的功能。

  4、体系架构的实现

  实现一个管道和过滤器一般要注意以下几个方面:

  把系统任务分成一系列处理阶段。

  根据管道和过滤器的设计方案,必须把系统处理的任务分割成相应独立的任务,如日志,数据转化,安全认证等。这样每个阶段仅依赖其前一阶段的输出。通过数据流将所有阶段相连起来。并且你可以进行替换每个步骤,或者可以调整它们之间的顺序,以产生新的结果.如petstore中的编码转化Filter和安全Filter,分成两个独立的处理阶段。

  定义沿每个管道传输的数据格式。

  我们知道每个过滤器,定义一个统一格式以获得最大的灵活性,因为它使过滤器的重组变得容易。如:每个过滤器的方法是doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)它们的参数是必须相同的。

  决定如何实现每个管道连接

  Filter过滤器的连接是推得方式来实现的.前一个过滤器主动的调用filterChain.doFilter(request, response);来实现转向下一个过滤器。

  设计和实现过滤器

  设计每个Filter具有独立的功能,如编码转化,安全校验,等功能.并且每个Fliter都应该在实现javax.servlet.Filter接口。

  建立处理流水线

  过滤器的部署是在Web.xml中进行配置,描述过滤器的实现类以及它们的map关系,来确定它们的顺序。

  其他应用实例

  1、JBOSS

  如果大家对EJB了解,应该知道客户调用EJB实际上并不是直接引用EJB实例(ejb instance).它通过容器来截获客户端的请求,然后按照EJB描述符做些许多相应的工作如,安全校验,事务的处理,线程并发处理等.这样就可以使开发人员仅关心自己的业务逻辑,而不需对复杂的基础服务进行实现.使开发人员从繁琐的工作中解脱出来.集中精力处理自己的业务逻辑,它的结构图如下:

500){this.resized=true;this.style.width=500;}" align=center vspace=1 border=1>

  笔者有幸阅读了JBOSS的源码,分析了Jboss的EJB容器的实现. EJB的容器通过许多拦截器(Inteceptor)来实现,每个拦截器处理一定的功能,一个处理结束后转发给下一个拦截器,最后一个拦截器才把真正调用EJB的实例.其中它的EntityBean 容器的拦截器的结构如下:

500){this.resized=true;this.style.width=500;}" align=center vspace=1 border=1>

  我们看其中的log拦截器

public class LogInterceptor extends AbstractInterceptor{

public Object invoke(Invocation invocation)

throws Exception

{

 boolean trace = log.isTraceEnabled();

 // Log call details

 if (callLogging)

 {

  ......进行log的处理

 }

 //处理结束,把请求转发给下一个拦截器

 return getNext().invoke(invocation);

}

  这些拦截器配置在standardjboss.xml文件中,如下:

<container-interceptors>

 <interceptor>org.jboss.ejb.plugins.LogInterceptor</interceptor>

 <interceptor>org.jboss.ejb.plugins.SecurityInterceptor</interceptor>

 <interceptor>org.jboss.ejb.plugins.TxInterceptorCMT</interceptor>

 <interceptor metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor>

 <interceptor>org.jboss.ejb.plugins.EntityLockInterceptor</interceptor>

 <interceptor>org.jboss.ejb.plugins.EntityInstanceInterceptor</interceptor>

 <interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptor</interceptor>

 <interceptor>org.jboss.ejb.plugins.EntitySynchronizationInterceptor</interceptor>

 <interceptor>org.jboss.ejb.plugins.cmp.jdbc.JDBCRelationInterceptor</interceptor>

</container-interceptors>

  这就是Jboss容器架构最巧妙的地方,最初这个架构就是由天才少年Rickard Oberg提出的.其实这个架构就应用我们讨论的管道和过滤器模式,其实每个拦截器就是一个过滤器,使用该模式给Jboss带来了如下的好处:

  使系统的架构更容易理解,因为每个过滤器完成单一的功能。

  使系统更加模块化,有利于系统的模块重用和扩展,如果系统想增加某种功能只需增加一个实现Interceptor接口的拦截器,然后配置在standardjboss.xml文件中即可。

  使系统的容易进行错误处理,如果在一个拦截器中发现错误(error)或者异常(exception),只需返回即可.

  2、AXIS

  无独有偶,同样在Axis上也应用了管道和过滤器模式.Aixs是apache开源的webservice实现服务器。简单的说,axis就是处理Message,它首先截获客户端的请求,然后转发到真正的实现业务逻辑上处理客户端的请求,在这之前经过一系列的handler处理.它的结构很像EJB容器.其实就是管道和过滤器模式的应用,Handler就是过滤器.它的处理顺序主要考虑两个方面一个是部署描述符(deployment configuration )另一个就是是客户端还是服务器端。Handler处理的对象是MessageContext它的由3个重要的部分组成,一是一个request Message,一个是response message,还有许多属性。

  我们经研究源码分析,在服务器端,有一个Transport Listener 它监听客户端的请求, 可以通过多种协议,一旦有客户请求,它将按照协议的规范把数据解析生成生成一个Message对象,然后把它设置到MessageContext,然后调用一系列的Handler进行处理。

  其结构图如下:

500){this.resized=true;this.style.width=500;}" align=center vspace=1 border=1>

  相关设计模式

  在使用管道和过滤器模式时,一般会使用以下的GOF设计模式。

  1、职责链模式(Chain Of Responsibility)

  职责链设计模式的意图就是使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。其实管道和过滤器模式就是职责链模式的抽象,把它应用到软件体系架构中。

  2、 命令模式(Command)

  命令模式的意图将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。在管道和过滤器模式中每个过滤器一般使用命令模式,把请求封装成一个命令进行处理。

  3、装饰模式(Decorator)

  装饰模式的意图就是动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

  在管道和过滤器模式中,在每个过滤器中经常需要对请求进行动态的增加功能,或者修改请求的内容,这时一般会使用装饰模式.如Servlet filter的javax.servlet.http.HttpServletRequestWrapper, javax.servlet.http.HttpServletResponseWrapper就是装饰模式的应用.

  总结

  本文讨论了管道和过滤器模式的解决方案,以及它的优缺点.然后以J2EE规范的Servlet Filter为例详细介绍了怎样应用该模式,同时简单的介绍了在Jboss,Axis中的应用。

转载于:https://my.oschina.net/u/660122/blog/71937

Filter使用详解相关推荐

  1. JavaWeb中filter的详解及应用案例

    JavaWeb中filter的详解及应用案例 转载自:http://www.cnblogs.com/vanl/p/5742501.html 一:Filter介绍 Filter可认为是Servlet的一 ...

  2. Photoshop CS 中的“照片滤镜/Photo Filter”命令详解(转)

    Photoshop CS 中的"照片滤镜/Photo Filter"命令详解(转)[@more@] 这是一个跟摄影有关的重要图像调整命令. 有关这一命令的教程,现在网上没一个能说得 ...

  3. 双边滤波(Bilateral Filter)详解

    双边滤波(Bilateral Filter)详解 转自:睁开眼就变帅 原理分析: 双边滤波与高斯滤波器相比,对于图像的边缘信息能过更好的保存.其原理为一个与空间距离相关的高斯函数与一个灰度距离相关的高 ...

  4. Java过滤器Filter使用详解

    <div id="post_detail"> 转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6374212.html 在我的项目 ...

  5. Filter的详解与配置应用

    1.filter概念与用处: filter 直译为过滤器,是servlet中的重点对象,是web应用组件,是个典型的处理链 主用用于: Jsp, Servlet, 静态图片文件或静态 html 文件等 ...

  6. java 日志框架 详解_java日志框架系列(9):logback框架过滤器(filter)详解

    过滤器放在了logback-classic模块中. 1.logback-classic模块中过滤器 分类(2种):常规过滤器.TurboFilter过滤器. 1.常规过滤器 常规过滤器可以通过自定义进 ...

  7. Servlet3.0新特性WebFilter(Annotation Filter)详解

    摘要: Servlet3.0作为J2EE 6规范一部分,并随J2EE6一起发布,WeFilter是过滤器注解,是Servlet3.0的新特性,不需要在web.xml进行配置,简化了配置. Name T ...

  8. 【Servlet】Filter过滤器详解、使用示例

    Filter过滤器讲解 定义 过滤器处于浏览器与servlet之间,是一个实现了 javax.servlet.Filter 接口的 Java 类 客户端发送的请求.服务器发送的资源,需要通过过滤器,才 ...

  9. 【CSS进阶】box-shadow 与 filter:drop-shadow 详解及奇技淫巧

    box-shadow 在前端的 CSS 编写工作想必十分常见.但是 box-shadow 除去它的常规用法,其实还存在许多不为人知的奇技淫巧. 喜欢 markdown 版本的可以戳这里 . box-s ...

  10. Python中过滤序列内置函数filter()的详解(常用)

    目录 一.功能 二.语法 三.举例 3.1代码 3.2运行结果 一.功能   用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换. https: ...

最新文章

  1. seajs学习心得和新产品福利
  2. 网络名称空间 实例研究 veth处于不同网络的路由问题
  3. 河南省第十三届ICPC大学生程序设计竞赛 【部分题题解】
  4. 单片机中如何将BCD码拆开_单片机二进制BCD码转换实验程序流程图
  5. android d-bus,android EventBus的使用
  6. Linux bash卸载软件,Ubuntu卸载软件的4种方法
  7. 易宝典文章——用ISA 2006标准版发布Exchange 2010的OWA系列之生成Exchange证书申请文件...
  8. java蓝桥杯算法训练 奇偶判断
  9. 使用U盘引导安装CentOS操作系统
  10. Android布局基础知识
  11. html5页面访问统计代码,两行代码搞定博客访问量统计
  12. i510200h和i78750h哪个好
  13. 计算过去某天距离今天过去了多少天。
  14. 旅客因航班耽搁殴打工作职员被拘
  15. Hive中使用sort_array函数解决collet_list列表排序混乱问题
  16. 今日头条-快速获取爆文素材的5大途经
  17. Debian安装网易云音乐记录
  18. 黑龙江认识电子计算机ppt,[IT认证]认识计算机配件.ppt
  19. 电快速脉冲群(EFT)设计-EMC系列 硬件设计笔记4
  20. 分享一个最近很火的前端小游戏

热门文章

  1. 手机壁纸自动采集小程序源码
  2. 说说过游戏保护(4)
  3. Linux Shell脚本入门教程系列之(十)Shell for循环
  4. bxslider 纵向滑动 vertical image thumbnail slider
  5. Sublime Text 2插件安装及快捷键介绍
  6. Magento 显示下拉货币 How to add Currency selector to Magento’s header
  7. 时区日期处理及定时 (NSDate,NSCalendar,NSTimer,NSTimeZone) -- IOS(实例)
  8. 如何用Pygame写游戏(二十一)
  9. 接口进阶 java 1614956772
  10. python类属性的应用 子类继承可以节约空间