《how tomcat work》 搬运工 Chapter 13: Host and Engine

Host和Engine是container的其中一种。

如果想要tomcat能够包含多个网站,则需要Host来包含多个context。

1.Host

The Host 接口

public interface Host extends Container {   
  public static final String ADD_ALIAS_EVENT = "addAlias";
  
  public static final String REMOVE_ALIAS_EVENT = "removeAlias";
  
  /**    * Return the application root for this Host.    * This can be an absolute    * pathname, a relative pathname, or a URL.    */
  public String getAppBase();

  /**    * Set the application root for this Host.  This can be an absolute    * pathname, a relative pathname, or a URL.    *    * @param appBase The new application root    */
  public void setAppBase(String appBase);

  /**    * Return the value of the auto deploy flag.    * If true, it indicates that    * this host's child webapps should be discovred and automatically    * deployed.    */
  public boolean getAutoDeploy();

  /**    * Set the auto deploy flag value for this host.    *    * @param autoDeploy The new auto deploy flag    */
  public void setAutoDeploy(boolean autoDeploy);

  /**    * Set the DefaultContext    * for new web applications.    *    * @param defaultContext The new DefaultContext    */
  public void addDefaultContext(DefaultContext defaultContext);

  /**    * Retrieve the DefaultContext for new web applications.    */
  public DefaultContext getDefaultContext();

   /**    * Return the canonical, fully qualified, name of the virtual host    * this Container represents.    */
  public String getName();

  /**    * Set the canonical, fully qualified, name of the virtual host    * this Container represents.    *    * @param name Virtual host name    *    * @exception IllegalArgumentException if name is null    */
  public void setName(String name);

  /**    * Import the DefaultContext config into a web application context.    *    * @param context web application context to import default context    */
  public void importDefaultContext(Context context);

  /**    * Add an alias name that should be mapped to this same Host.    *    * @param alias The alias to be added    */
  public void addAlias(String alias);

  /**    * Return the set of alias names for this Host.  If none are defined,    * a zero length array is returned.    */
  public String[] findAliases();

  /**    * Return the Context that would be used to process the specified    * host-relative request URI, if any;
   otherwise return    * <code>null</code>.    *    * @param uri Request URI to be mapped    */
  public Context map(String uri);

  /**    * Remove the specified alias name from the aliases for this Host.    * @param alias Alias name to be removed    */
  public void removeAlias(String alias);
}

StandardHost

像 StandardContext 和the StandardWrapper classes一样,standardHost在构造函数中添加StandardHostValve到pipeline中。每接受一个请求,standardHost都会触发它的基类baseContainer的invoke方法,而当pipeline触发到standardHostValue的invoke方法时,会通过host的map方法来查找正确的context。

public Context map(String uri) {   
  if (debug > 0)     
    log("Mapping request URI '" + uri + "'");
  if (uri == null) 
    return (null);

  // Match on the longest possible context path prefix
  if (debug > 1)     
    log("  Trying the longest context path prefix");
    Context context = null;
    String mapuri = uri;
    while (true) {     
      context = (Context) findChild(mapuri);
      if (context != null)       break;
      int slash = mapuri.lastIndexOf('/');
      if (slash < 0)       break;
      mapuri = mapuri.substring(0, slash);
    }  
  // If no Context matches, select the default Context   
  if (context == null) {     
    if (debug > 1)       
      log("  Trying the default context");
    context = (Context) findChild("");
  }  
  // Complain if no Context has been selected  
  if (context == null) {     
    log(sm.getString("standardHost.mappingError", uri));
    return (null);
  }  
  // Return the mapped Context (if any)   
  if (debug > 0)     
    log(" Mapped to context '" + context.getPath() + "'");
    return (context);
  }

StandardHostMapper 

在ContaninerBase类中,会在start()方法调用addDefaultMapper()方法来新建一个defaulet mapper,而在standardHost中会添加一个StandardHostMapper,而StandardHostMapper也是继承ContainerBase的,所以StandardHostMapper里的map方法是调用Host的map方法。

StandardHostValve 

作为pipeline的basevalue,standardHostValve的作用就是查找适当的context处理请求,查看是否有session,更新session的时间限制。

public void invoke(Request request, Response response,   ValveContext valveContext)   throws IOException, ServletException {  
  // Validate the request and response object types  
  if (!(request.getRequest() instanceof HttpServletRequest) || !(response.getResponse() instanceof HttpServletResponse)) {     
    return;
    // NOTE - Not much else we can do generically   
  }  
  // Select the Context to be used for this Request 
  StandardHost host = (StandardHost) getContainer();
  Context context = (Context) host.map(request, true);
  if (context == null) {     
    ((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,     
    sm.getstring("StandardHost.noContext"));
    return;
  }  
  // Bind the context CL to the current thread   
  Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());

  // Update the session last access time for our session (if any)   
  HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
  String sessionId = hreq.getRequestedSessionId();
  if (sessionId != null) {     
    Manager manager = context.getManager();
    if (manager != null) {       
      Session session = manager.findSession(sessionId);
      if ((session != null) && session.isValid())         
        session.access();
    }     
  }  
  // Ask this Context to process this request   context.invoke(request, response);
}

 

2.Engine

 Engine就代表了整个 Catalina servlet,你使用Engine就可以用多个host

The Engine 接口 

public interface Engine extends Container {   
  /**    * Return the default hostname for this Engine.    */
  public String getDefaultHost();

  /**    * Set the default hostname for this Engine.    *    * @param defaultHost The new default host    */
  public void setDefaultHost(String defaultHost);

  /**    * Retrieve the JvmRouteId for this engine.    */
  public String getJvmRoute();

  /**    * Set the JvmRouteId for this engine. 
  *    * @param jvmRouteId the (new) JVM Route ID. Each Engine within a    * cluster must have a unique JVM Route ID.    */
  public void setJvmRoute(String jvmRouteId);

  /**    * Return the <code>Service</code> with which we are associated (if    * any).    */
  public Service getService();

  /**    * Set the <code>Service</code> with which we are associated (if    * any).    *    * @param service The service that owns this Engine    */
  public void setService(Service service);

  /**    * Set the DefaultContext    * for new web applications.    *    * @param defaultContext The new DefaultContext    */
  public void addDefaultContext(DefaultContext defaultContext);

  /**    * Retrieve the DefaultContext for new web applications.    */
  public DefaultContext getDefaultContext();
  
  /**    * Import the DefaultContext config into a web application context.    *    * @param context web application context to import default context    */
  public void importDefaultContext(Context context);
}

StandardEngineValve 

这个和standardHostValve差不多,查找正确的Host来处理请求

public void invoke(Request request, Response response,ValveContext valveContext) throws IOException, ServletException {   
  // Validate the request and response object types   
  if (!(request.getRequest() instanceof HttpServletRequest) || !(response.getResponse() instanceof HttpServletResponse)) { 
    return;
    // NOTE - Not much else we can do generically   
  }   
  // Validate that any HTTP/1.1 request included a host header   HttpServletRequest hrequest = (HttpServletRequest) request;
  if ("HTTP/1.1".equals(hrequest.getProtocol()) &&     (hrequest.getServerName() == null)) {     
    ((HttpServletResponse)response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST,sm.getString("standardEngine.noHostHeader", request.getRequest().getServerName()));
    return;
  }   
  // Select the Host to be used for this Request   
  StandardEngine engine = (StandardEngine) getContainer();
  Host host = (Host) engine.map(request, true);
  if (host == null) {     
    ((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST,sm.getString("standardEngine.noHost",request.getRequest().getServerName()));
    return;
  }   
    // Ask this Host to process this request   
    host.invoke(request, response);
}

 

posted @ 2015-10-18 11:06  Xuyung  阅读(174)  评论(0编辑  收藏  举报