zoukankan      html  css  js  c++  java
  • 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

    ValveBasePipeline及其他相关组件都实现了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;
        }
    }

    总结

    通过上面的代码分析,我们发现了几个关键的设计模式:

    1. 模板方法模式,父类定义框架,子类实现
    2. 责任链模式,就是这儿的管道/阀门的实现方式,每个阀门维护一个next属性指向下一个阀门
  • 相关阅读:
    Web Api系列教程第2季(OData篇)(一)——OData简介和一个小应用
    漫步ASP.NET MVC的处理管线
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【十】——使用CacheCow和ETag缓存资源
    工具分享——将C#文档注释生成.chm帮助文档
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【外传】——Attribute Routing
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【九】——API变了,客户端怎么办?
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【八】——Web Api的安全性
    C#基础——谈谈.NET异步编程的演变史
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【七】——实现资源的分页
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【六】——实现资源间的关联
  • 原文地址:https://www.cnblogs.com/java-chen-hao/p/11341478.html
Copyright © 2011-2022 走看看