Tomcat Request请求处理:Container设计

Tomcat Request请求处理:Container设计 理解思路为什么我们说上面的是Container呢我们看下几个Container之间的关系从上图上我们也可以看出Container顶层也是基于Lifecycle的组件设计的。在设计Container组件层次组件时上述4个组件分别做什么的呢为什么要四种组件呢如下是Container接口类的相关注释html* libEngine/b - Representation of the entire Catalina servlet engine, * most likely containing one or more subcontainers that are either Host * or Context implementations, or other custom groups. * libHost/b - Representation of a virtual host containing a number * of Contexts. * libContext/b - Representation of a single ServletContext, which will * typically contain one or more Wrappers for the supported servlets. * libWrapper/b - Representation of an individual servlet definition * (which may support multiple servlet instances if the servlet itself * implements SingleThreadModel). * /ulEngine- 表示整个catalina的servlet引擎多数情况下包含一个或多个子容器这些子容器要么是Host要么是Context实现或者是其他自定义组。Host- 表示包含多个Context的虚拟主机的。Context— 表示一个ServletContext表示一个webapp它通常包含一个或多个wrapper。Wrapper- 表示一个servlet定义的如果servlet本身实现了SingleThreadModel则可能支持多个servlet实例。结合整体的框架图中上述组件部分我们看下包含了什么很明显除了四个组件的嵌套关系Container中还包含了RealmClusterListeners, Pipleline等支持组件。这一点还可以通过相关注释可以看出html**Loader** - Class loader to use for integrating new Java classes for this Container into the JVM in which Catalina is running. **Logger** - Implementation of the log() method signatures of the ServletContext interface. **Manager** - Manager for the pool of Sessions associated with this Container. **Realm** - Read-only interface to a security domain, for authenticating user identities and their corresponding roles. **Resources** - JNDI directory context enabling access to static resources, enabling custom linkages to existing server components when Catalina is embedded in a larger server.Container的设计这container应该包含哪些接口呢如果你看源代码它包含二十多个接口这里理解的时候一定要分组去理解。Container的层次结构方法查找父容器的方法java/** * Get the parent container. * * return Return the Container for which this Container is a child, if * there is one. If there is no defined parent, return * codenull/code. */ public Container getParent(); /** * Set the parent Container to which this Container is being added as a * child. This Container may refuse to become attached to the specified * Container by throwing an exception. * * param container Container to which this Container is being added * as a child * * exception IllegalArgumentException if this Container refuses to become * attached to the specified Container */ public void setParent(Container container);由于Engine显然上层是Service所以里面加了一个getService的方法java/** * Return the Service to which this container belongs. * param container The container to start from * return the Service, or null if not found */ public static Service getService(Container container) { while (container ! null !(container instanceof Engine)) { container container.getParent(); } if (container null) { return null; } return ((Engine) container).getService(); }类比树接口有Parent方法那肯定也child方法java/** * Add a new child Container to those associated with this Container, * if supported. Prior to adding this Container to the set of children, * the childs codesetParent()/code method must be called, with this * Container as an argument. This method may thrown an * codeIllegalArgumentException/code if this Container chooses not * to be attached to the specified Container, in which case it is not added * * param child New child Container to be added * * exception IllegalArgumentException if this exception is thrown by * the codesetParent()/code method of the child Container * exception IllegalArgumentException if the new child does not have * a name unique from that of existing children of this Container * exception IllegalStateException if this Container does not support * child Containers */ public void addChild(Container child); /** * Obtain the child Containers associated with this Container. * * return An array containing all children of this container. If this * Container has no children, a zero-length array is returned. */ public Container[] findChildren(); /** * Remove an existing child Container from association with this parent * Container. * * param child Existing child Container to be removed */ public void removeChild(Container child);Container事件监听相关方法前文我们也分析过Tomcat的事件监听机制Container也是一样 比如如下的ContainerListenerjava/** * Add a container event listener to this component. * * param listener The listener to add */ public void addContainerListener(ContainerListener listener); /** * Obtain the container listeners associated with this Container. * * return An array containing the container listeners associated with this * Container. If this Container has no registered container * listeners, a zero-length array is returned. */ public ContainerListener[] findContainerListeners(); /** * Remove a container event listener from this component. * * param listener The listener to remove */ public void removeContainerListener(ContainerListener listener);除了Container级别的和前文我们理解的一样还有属性相关的Listener, 显然就增删属性的监听方法java/** * Remove a property change listener from this component. * * param listener The listener to remove */ public void removePropertyChangeListener(PropertyChangeListener listener); /** * Add a property change listener to this component. * * param listener The listener to add */ public void addPropertyChangeListener(PropertyChangeListener listener);最后显然还有事件的触发方法java/** * Notify all container event listeners that a particular event has * occurred for this Container. The default implementation performs * this notification synchronously using the calling thread. * * param type Event type * param data Event data */ public void fireContainerEvent(String type, Object data);Container功能支撑方法前面我们知道Loader, Logger, Manager, Realm, Resources等支撑功能。这里简单看下接口定义相关基本实现看下节ContainerBase的实现。Loaderjava/** * Get the parent class loader. * * return the parent class loader for this component. If not set, return * {link #getParent()}.{link #getParentClassLoader()}. If no * parent has been set, return the system class loader. */ public ClassLoader getParentClassLoader(); /** * Set the parent class loader for this component. For {link Context}s * this call is meaningful only strongbefore/strong a Loader has * been configured, and the specified value (if non-null) should be * passed as an argument to the class loader constructor. * * param parent The new parent class loader */ public void setParentClassLoader(ClassLoader parent);Loggerjava/** * Obtain the log to which events for this container should be logged. * * return The Logger with which this Container is associated. If there is * no associated Logger, return the Logger associated with the * parent Container (if any); otherwise return codenull/code. */ public Log getLogger(); /** * Return the logger name that the container will use. * return the abbreviated name of this container for logging messages */ public String getLogName();Manager体现在我们之前分析的JMX管理java/** * Obtain the JMX name for this container. * * return the JMX name associated with this container. */ public ObjectName getObjectName(); /** * Obtain the JMX domain under which this container will be / has been * registered. * * return The JMX domain name */ public String getDomain();