责任链模式及Filter的工作原理是什么

今天就跟大家聊聊有关 责任链模式及Filter的工作原理是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

成都创新互联公司-专业网站定制、快速模板网站建设、高性价比安溪网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式安溪网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖安溪地区。费用合理售后完善,10多年实体公司更值得信赖。

每个软件工程师的词典中,各种高大上的词不少,也可能因为使用开发语言与环境的差异有所不同,但也有不少是超越语言的。

像音乐家常说

音乐是没有国界的。

而对于软件工程师,则无论是JAVA工程师,C#工程师,都会了解设计模式。

设计模式是没有开发语言界限的,是面向对象的经验提炼出来,解决重复问题的设计方法。

关于设计模式,有许多经典的著作,像Gof的设计模式,像Robert.C.Martin的

P.P.P。而分析开源项目中对于设计模式的书籍则不多。我接下来打算写一系列分析Tomcat内设计模式使用的文章,本文是第一篇,先介绍责任链模式在Tomcat中的使用。

介绍 

Chain of Refponsibility(责任链),是一种对象行为模式。

在Gof的设计模式一书中,对于该模式的意图描述如下:

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

对于该模式的理解,最主要的是了解其一直在向下传递一个对象,阎宏曾在书中以击鼓传花来描述此模式。在Web应用中,这个传的花就是请求。

了解了模式之后,我们看Tomcat中对于此模式是如何实现的。

在Filter的使用中,我们会注意到其接口中包含这样一个方法

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

我们看到,这个方法中,除了向下传递请递request和response之外,还传了另一个FilterChain对象。每次当前Filter的逻辑处理完成后,我们一般会调用FilterChain的doFilter方法,以执行下一个Filter的逻辑。这里需要注意的是,可能这个FilterChain的接口方法也叫doFilter容易引起误解,其实这个方法的声明如下:

/**
* Causes the next filter in the chain to be invoked, or if the calling
* filter is the last filter in the chain, causes the resource at the end of
* the chain to be invoked.
*/
public void doFilter(ServletRequest request, ServletResponse response);

如果这里称之为invokeFilter或者executeFilter也许更好理解些。

那么,每一次,一个Filter执行完毕后,FilterChain的doFilter是如何确认下一个Filter该谁去执行了呢?

奥秘就在这里,即FilterChain接口的实现。

/**
* Invoke the next filter in this chain, passing the specified request
* and response.  If there are no more filters in this chain, invoke
* the service() method of the servlet itself.
*
*/
public void doFilter(ServletRequest request, ServletResponse response){

   if( Globals.IS_SECURITY_ENABLED ) {//注意这里是启用了SecurityManager,了解详情可以后台回复关键字003查看。
       final ServletRequest req = request;
       final ServletResponse res = response;
       try {
           java.security.AccessController.doPrivileged(
               new java.security.PrivilegedExceptionAction() {
                   @Override
                   public Void run()
                       throws ServletException, IOException {
                       internalDoFilter(req,res);
                       return null;
                 } });
       } catch( PrivilegedActionException pe) { }
   } else {
    internalDoFilter(request,response);//默认每次调用的处理方法在这里
   }}

private void internalDoFilter(ServletRequest request,
                             ServletResponse response){
   // Call the next filter if there is one
   if (pos < n) {
       ApplicationFilterConfig filterConfig = filters[pos++];
       Filter filter = null;
           filter = filterConfig.getFilter();
               filter.doFilter(request, response, this);
     return;
   }

   // We fell off the end of the chain -- call the servlet instance
       if ((request instanceof HttpServletRequest) &&
           (response instanceof HttpServletResponse)) {
               servlet.service(request, response);
       } else {
           servlet.service(request, response);
       }}

我们看到,在真正处理FilterChain的控制中,是通过pos和n这两个参数来判断的。两者的声明如下:

/**
* The int which is used to maintain the current position
* in the filter chain.
*/
private int pos = 0;

/**
* The int which gives the current number of filters in the chain.
*/
private int n = 0;

我们看到,一个标识当前处理的Filter,一个标识chain中的总filter数。

在chain中的Filter都执行完成后,pos < n 的逻辑不再执行,跳到执行后面真正的Servlet的请求处理。

而每个Filter,可以在filterChain执行前后分别进行预处理后处理。是因为每个filter调用,最后类似于递归调用,在filter的doFilter执行完毕后逻辑中会有return操作,保证不向下执行到Servlet的逻辑中。

了解了Filter的执行原理以及责任链模式的基本概念,我们自己要使用这个模式,只需要保证各个链实现相同的接口,接口方法中每次将Chain传递下去,即可很好的实现。控制Chain执行的逻辑中,可以通过数组或者List来存储整个链的元素,像Tomcat这样:

/**
* Filters.
*/
private ApplicationFilterConfig[] filters =
   new ApplicationFilterConfig[0];

在控制中,每次取出下一个元素执行,就可以实现责任链了。

看完上述内容,你们对 责任链模式及Filter的工作原理是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。


网站名称:责任链模式及Filter的工作原理是什么
网站URL:http://pwwzsj.com/article/pipdig.html