重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
今天就跟大家聊聊有关 责任链模式及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
* theservice()
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的工作原理是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。