Tomcat源码分析 (四)----- Pipeline和Valve
2019-08-16 12:33:46来源:博客园 阅读 ()
Tomcat源码分析 (四)----- Pipeline和Valve
在 Tomcat源码分析 (二)----- Tomcat整体架构及组件 中我们简单分析了一下Pipeline和Valve,并给出了整体的结构图。而这一节,我们将详细分析Tomcat里面的源码。
Valve
Valve
作为一个个基础的阀门,扮演着业务实际执行者的角色。我们看看Valve
这个接口有哪些方法。
public interface Valve { // 获取下一个阀门 public Valve getNext(); // 设置下一个阀门 public void setNext(Valve valve); // 后台执行逻辑,主要在类加载上下文中使用到 public void backgroundProcess(); // 执行业务逻辑 public void invoke(Request request, Response response) throws IOException, ServletException; // 是否异步执行 public boolean isAsyncSupported(); }
Contained
ValveBase
、Pipeline
及其他相关组件都实现了Contained
接口,我们看看这个接口有哪些方法。很简单,就是get/set容器操作。
public interface Contained { /** * Get the {@link Container} with which this instance is associated. * * @return The Container with which this instance is associated or * <code>null</code> if not associated with a Container */ Container getContainer(); /** * Set the <code>Container</code> with which this instance is associated. * * @param container The Container instance with which this instance is to * be associated, or <code>null</code> to disassociate this instance * from any Container */ void setContainer(Container container); }
ValveBase
从Valve的类层次结构,我们发现几乎所有Valve都继承了ValveBase
这个抽象类,所以这儿我们需要分析一下它。
public abstract class ValveBase extends LifecycleMBeanBase implements Contained, Valve { // 国际化管理器,可以支持多国语言 protected static final StringManager sm = StringManager.getManager(ValveBase.class); //------------------------------------------------------ Instance Variables // 无参构造方法,默认不支持异步 public ValveBase() { this(false); } // 有参构造方法,可传入异步支持标记 public ValveBase(boolean asyncSupported) { this.asyncSupported = asyncSupported; } //------------------------------------------------------ Instance Variables // 异步标记 protected boolean asyncSupported; // 所属容器 protected Container container = null; // 容器日志组件对象 protected Log containerLog = null; // 下一个阀门 protected Valve next = null; //-------------------------------------------------------------- Properties // 获取所属容器 @Override public Container getContainer() { return container; } // 设置所属容器 @Override public void setContainer(Container container) { this.container = container; } // 是否异步执行 @Override public boolean isAsyncSupported() { return asyncSupported; } // 设置是否异步执行 public void setAsyncSupported(boolean asyncSupported) { this.asyncSupported = asyncSupported; } // 获取下一个待执行的阀门 @Override public Valve getNext() { return next; } // 设置下一个待执行的阀门 @Override public void setNext(Valve valve) { this.next = valve; } //---------------------------------------------------------- Public Methods // 后台执行,子类实现 @Override public void backgroundProcess() { // NOOP by default } // 初始化逻辑 @Override protected void initInternal() throws LifecycleException { super.initInternal(); // 设置容器日志组件对象到当前阀门的containerLog属性 containerLog = getContainer().getLogger(); } // 启动逻辑 @Override protected synchronized void startInternal() throws LifecycleException { setState(LifecycleState.STARTING); } // 停止逻辑 @Override protected synchronized void stopInternal() throws LifecycleException { setState(LifecycleState.STOPPING); } // 重写toString,格式为[${containerName}] @Override public String toString() { StringBuilder sb = new StringBuilder(this.getClass().getName()); sb.append('['); if (container == null) { sb.append("Container is null"); } else { sb.append(container.getName()); } sb.append(']'); return sb.toString(); } // -------------------- JMX and Registration -------------------- // 设置获取MBean对象的keyProperties,格式如:a=b,c=d,e=f... @Override public String getObjectNameKeyProperties() { StringBuilder name = new StringBuilder("type=Valve"); Container container = getContainer(); name.append(container.getMBeanKeyProperties()); int seq = 0; // Pipeline may not be present in unit testing Pipeline p = container.getPipeline(); if (p != null) { for (Valve valve : p.getValves()) { // Skip null valves if (valve == null) { continue; } // Only compare valves in pipeline until we find this valve if (valve == this) { break; } if (valve.getClass() == this.getClass()) { // Duplicate valve earlier in pipeline // increment sequence number seq ++; } } } if (seq > 0) { name.append(",seq="); name.append(seq); } String className = this.getClass().getName(); int period = className.lastIndexOf('.'); if (period >= 0) { className = className.substring(period + 1); } name.append(",name="); name.append(className); return name.toString(); } // 获取所属域,从container获取 @Override public String getDomainInternal() { Container c = getContainer(); if (c == null) { return null; } else { return c.getDomain(); } } }
Pipeline
Pipeline
作为一个管道,我们可以简单认为是一个Valve的集合,内部会对这个集合进行遍历,调用每个元素的业务逻辑方法invoke()
。
是不是这样呢?我们还是分析一下源码,先看看接口定义。
public interface Pipeline { // ------------------------------------------------------------- Properties // 获取基本阀门 public Valve getBasic(); // 设置基本阀门 public void setBasic(Valve valve); // --------------------------------------------------------- Public Methods // 添加阀门 public void addValve(Valve valve); // 获取阀门数组 public Valve[] getValves(); // 删除阀门 public void removeValve(Valve valve); // 获取首个阀门 public Valve getFirst(); // 管道内所有阀门是否异步执行 public boolean isAsyncSupported(); // 获取管道所属的容器 public Container getContainer(); // 设置管道所属的容器 public void setContainer(Container container); // 查找非异步执行的所有阀门,并放置到result参数中,所以result不允许为null public void findNonAsyncValves(Set<String> result); }
StandardPipeline
接着我们分析一下Pipeline
唯一的实现StandardPipeline
。代码很长,但是都很简单。
public class StandardPipeline extends LifecycleBase implements Pipeline, Contained { private static final Log log = LogFactory.getLog(StandardPipeline.class); // ----------------------------------------------------------- Constructors // 构造一个没有所属容器的管道 public StandardPipeline() { this(null); } // 构造一个有所属容器的管道 public StandardPipeline(Container container) { super(); setContainer(container); } // ----------------------------------------------------- Instance Variables /** * 基本阀门,最后执行的阀门 */ protected Valve basic = null; /** * 管道所属的容器 */ protected Container container = null; /** * 管道里面的首个执行的阀门 */ protected Valve first = null; // --------------------------------------------------------- Public Methods // 是否异步执行,如果一个阀门都没有,或者所有阀门都是异步执行的,才返回true @Override public boolean isAsyncSupported() { Valve valve = (first!=null)?first:basic; boolean supported = true; while (supported && valve!=null) { supported = supported & valve.isAsyncSupported(); valve = valve.getNext(); } return supported; } // 查找所有未异步执行的阀门 @Override public void findNonAsyncValves(Set<String> result) { Valve valve = (first!=null) ? first : basic; while (valve != null) { if (!valve.isAsyncSupported()) { result.add(valve.getClass().getName()); } valve = valve.getNext(); } } // ------------------------------------------------------ Contained Methods // 获取所属容器 @Override public Container getContainer() { return (this.container); } // 设置所属容器 @Override public void setContainer(Container container) { this.container = container; } // 初始化逻辑,默认没有任何逻辑 @Override protected void initInternal() { // NOOP } // 开始逻辑,调用所有阀门的start方法 @Override protected synchronized void startInternal() throws LifecycleException { // Start the Valves in our pipeline (including the basic), if any Valve current = first; if (current == null) { current = basic; } while (current != null) { if (current instanceof Lifecycle) ((Lifecycle) current).start(); current = current.getNext(); } setState(LifecycleState.STARTING); } // 停止逻辑,调用所有阀门的stop方法 @Override protected synchronized void stopInternal() throws LifecycleException { setState(LifecycleState.STOPPING); // Stop the Valves in our pipeline (including the basic), if any Valve current = first; if (current == null) { current = basic; } while (current != null) { if (current instanceof Lifecycle) ((Lifecycle) current).stop(); current = current.getNext(); } } // 销毁逻辑,移掉所有阀门,调用removeValve方法 @Override protected void destroyInternal() { Valve[] valves = getValves(); for (Valve valve : valves) { removeValve(valve); } } /** * 重新toString方法 */ @Override public String toString() { StringBuilder sb = new StringBuilder("Pipeline["); sb.append(container); sb.append(']'); return sb.toString(); } // ------------------------------------------------------- Pipeline Methods // 获取基础阀门 @Override public Valve getBasic() { return (this.basic); } // 设置基础阀门 @Override public void setBasic(Valve valve) { // Change components if necessary Valve oldBasic = this.basic; if (oldBasic == valve) return; // Stop the old component if necessary // 老的基础阀门会被调用stop方法且所属容器置为null if (oldBasic != null) { if (getState().isAvailable() && (oldBasic instanceof Lifecycle)) { try { ((Lifecycle) oldBasic).stop(); } catch (LifecycleException e) { log.error("StandardPipeline.setBasic: stop", e); } } if (oldBasic instanceof Contained) { try { ((Contained) oldBasic).setContainer(null); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); } } } // Start the new component if necessary // 新的阀门会设置所属容器,并调用start方法 if (valve == null) return; if (valve instanceof Contained) { ((Contained) valve).setContainer(this.container); } if (getState().isAvailable() && valve instanceof Lifecycle) { try { ((Lifecycle) valve).start(); } catch (LifecycleException e) { log.error("StandardPipeline.setBasic: start", e); return; } } // Update the pipeline // 替换pipeline中的基础阀门,就是讲基础阀门的前一个阀门的next指向当前阀门 Valve current = first; while (current != null) { if (current.getNext() == oldBasic) { current.setNext(valve); break; } current = current.getNext(); } this.basic = valve; } // 添加阀门 @Override public void addValve(Valve valve) { // Validate that we can add this Valve // 设置所属容器 if (valve instanceof Contained) ((Contained) valve).setContainer(this.container); // Start the new component if necessary // 调用阀门的start方法 if (getState().isAvailable()) { if (valve instanceof Lifecycle) { try { ((Lifecycle) valve).start(); } catch (LifecycleException e) { log.error("StandardPipeline.addValve: start: ", e); } } } // Add this Valve to the set associated with this Pipeline // 设置阀门,将阀门添加到基础阀门的前一个 if (first == null) { first = valve; valve.setNext(basic); } else { Valve current = first; while (current != null) { if (current.getNext() == basic) { current.setNext(valve); valve.setNext(basic); break; } current = current.getNext(); } } container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve); } // 获取阀门数组 @Override public Valve[] getValves() { ArrayList<Valve> valveList = new ArrayList<>(); Valve current = first; if (current == null) { current = basic; } while (current != null) { valveList.add(current); current = current.getNext(); } return valveList.toArray(new Valve[0]); } // JMX方法,在此忽略 public ObjectName[] getValveObjectNames() { ArrayList<ObjectName> valveList = new ArrayList<>(); Valve current = first; if (current == null) { current = basic; } while (current != null) { if (current instanceof JmxEnabled) { valveList.add(((JmxEnabled) current).getObjectName()); } current = current.getNext(); } return valveList.toArray(new ObjectName[0]); } // 移除阀门 @Override public void removeValve(Valve valve) { Valve current; if(first == valve) { // 如果待移出的阀门是首个阀门,则首个阀门的下一个阀门变成首个阀门 first = first.getNext(); current = null; } else { current = first; } // 遍历阀门集合,并进行移除 while (current != null) { if (current.getNext() == valve) { current.setNext(valve.getNext()); break; } current = current.getNext(); } if (first == basic) first = null; // 设置阀门所属容器为null if (valve instanceof Contained) ((Contained) valve).setContainer(null); // 调用待移除阀门的stop方法和destroy方法,并触发移除阀门事件 if (valve instanceof Lifecycle) { // Stop this valve if necessary if (getState().isAvailable()) { try { ((Lifecycle) valve).stop(); } catch (LifecycleException e) { log.error("StandardPipeline.removeValve: stop: ", e); } } try { ((Lifecycle) valve).destroy(); } catch (LifecycleException e) { log.error("StandardPipeline.removeValve: destroy: ", e); } } container.fireContainerEvent(Container.REMOVE_VALVE_EVENT, valve); } // 获取首个阀门,如果阀门列表为null,返回基础阀门 @Override public Valve getFirst() { if (first != null) { return first; } return basic; } }
总结
通过上面的代码分析,我们发现了几个关键的设计模式:
- 模板方法模式,父类定义框架,子类实现
- 责任链模式,就是这儿的管道/阀门的实现方式,每个阀门维护一个next属性指向下一个阀门
原文链接:https://www.cnblogs.com/java-chen-hao/p/11341478.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- java环境教程:Tomcat下载,安装,设置为Windows服务,启动 2020-06-09
- 你说研究过Spring里面的源码,循环依赖你会么? 2020-06-09
- 通俗理解spring源码(六)—— 默认标签(import、alias、be 2020-06-07
- 数据结构:用实例分析ArrayList与LinkedList的读写性能 2020-06-04
- Idea实现SpringBoot外置Tomcat的Web项目热部署(包含静态文 2020-06-04
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash