Host

Host是Context的父容器。如果想在一个tomcat上部署多个context就需要使用Host了。上下文容器的父容器是主机,但是可能有一些其它实现,没有必要的时候也可以忽略。不过在实践中,即使是一个Context,我们也使用了Host,为什么?后面我们再说。

Host是个接口,里面有个map方法比较重要

    /**
     * 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);

根据url来返回一个Context。

Host的标准实现是StandardHost

构造函数,不解释

    public StandardHost() {
        super();
        pipeline.setBasic(new StandardHostValve());
    }

StandardHost并没有invoke方法,它需要调用ContainerBase的invoke方法。

    //ContainerBase.java
    public void invoke(Request request, Response response)throws IOException, ServletException {
        pipeline.invoke(request, response);
    }

另外StandardHostValve这个基础阀会调用StandardHost的map方法获得一个context容器。

    public void invoke(Request request, Response response,
                       ValveContext valveContext)
        throws IOException, ServletException {
    ....
        StandardHost host = (StandardHost) getContainer();
    //这里调用的是ContainerBase的map方法 最终会调用StandardHost的map方法(两个map方法没有关系 没有//复写 参数都不一样)
        Context context = (Context) host.map(request, true);
    ....
    }

StandHostMapper

在ContainerBase的start中有如下的代码

   addDefaultMapper(this.mapperClass);

看ConntainerBase

    ContainerBase.java
    protected void addDefaultMapper(String mapperClass) {
    ......
        // Instantiate and add a default Mapper
            Class<?> clazz = Class.forName(mapperClass);
            Mapper mapper = (Mapper) clazz.newInstance();
            mapper.setProtocol("http");
            addMapper(mapper);
    ......
    }

这里我又一个小问题,为什么ContainerBase的start中的

addDefaultMapper(this.mapperClass);

调用的是子类中的addDefaultMapper呢?

StandardHost.java
    protected void addDefaultMapper(String mapperClass) {
       // 参数默认为 "org.apache.catalina.core.StandardHostMapper";
        super.addDefaultMapper(this.mapperClass);
    }

StandardHost的start方法在结尾的时候会调用父类的start方法。



注意:Tomcat4 中的 standardContext 使用了不同的方法来创建一个默认映射器。它的 start 方法中并没有调用 super.start()。相反 Standardcontext 的start 方法调用 addDefaultMapper 来传递 mapperClass 变量。



StandardHostMapper的map方法就是调用StandardHost的map方法。

 public Container map(Request request, boolean update) {
...
    String uri = ((HttpRequest) request).getDecodedRequestURI();
        Context context = host.map(uri);
...
        return (context);
    }

在得到上下对象的时候需要一个往返过程,map 方法介绍两个参数,该方法是在 ContainerBase 中的。然后 ContainerBase 类又在它的子对象中查找合适的映射器并调用它的 map 方法。

StandardHostValve

这是Host的基础阀,什么时候注入的?大家自己想。



StandardHostValve这个基础阀会调用StandardHost的map方法获得一个context容器。

    public void invoke(Request request, Response response,
                       ValveContext valveContext)
        throws IOException, ServletException {
    ....
        StandardHost host = (StandardHost) getContainer();
    //这里调用的是ContainerBase的map方法 最终会调用StandardHost的map方法(两个map方法没有关系 没有//复写 参数都不一样)
        Context context = (Context) host.map(request, true);
    ....
    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();                 //修改session的最后访问时间
            }
        }
      context.invoke(request, response);          //最后调用context的invoke
    }

为什么必须要有一个Host容器

想想我们之前的SimpleConextConfig,它的作用是将context的configured设置为true,为什么不在context里直接设置?参见观察者模式。

在ConextConfig的标准实现的applicationConfig中

    private void applicationConfig() {
    ...
   synchronized (webDigester) {
            try {
                URL url =
                    servletContext.getResource(Constants.ApplicationWebXml);
    .....
    }

servletContext为ApplicationContext的实例

    public URL getResource(String path)
        throws MalformedURLException {

        DirContext resources = context.getResources();
        if (resources != null) {
            String fullPath = context.getName() + path;

            // this is the problem. Host must not be null
            String hostName = context.getParent().getName();
       ....
    }

看到最后一行的getParent大家都明白了吧。

当然如果使用的是之前的SimpleContextConfig,就不需要Host了。

Engine

在tomcat中,Engine的标准实现是:org.apache.catalina.core.StandardEngine。

同样的Engine也有一个基础阀:StandardEngineValve

同是Engine不能再有父容器了,子容器也只能是Host。

StandardEngineValve

StandardEngineValve的invoke如下:

 public void invoke(Request request, Response response,
                       ValveContext valveContext)
        throws IOException, ServletException {
        ..........

        // Select the Host to be used for this Request
        StandardEngine engine = (StandardEngine) getContainer();
        Host host = (Host) engine.map(request, true);        //同样调用的是Containerbase的map
                                 //addDefaultMapper 怎么来的就不用说//了吧
        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);
    }

验证了request与response后,就调用Containerbase的map获得一个Host,然后调用host的invoke。

How tomcat works 读书笔记十三 Host和Engine的更多相关文章

  1. how tomcat works 读书笔记(二)----------一个简单的servlet容器

    app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...

  2. how tomcat works 读书笔记四 tomcat的默认连接器

    事实上在第三章,就已经有了连接器的样子了,只是那仅仅是一个学习工具,在这一章我们会開始分析tomcat4里面的默认连接器. 连接器 Tomcat连接器必须满足下面几个要求 1 实现org.apache ...

  3. how tomcat works读书笔记 七 日志记录器

    大家可以松一口气了,这个组件比较简单,这一节和前面几节想比,也简单的多. Logger接口 Tomcat中的日志记录器都必须实现org.apache.catalina.Logger接口. packag ...

  4. how tomcat works 读书笔记(一)----------一个简单的webserver

    http协议 若是两个人能正常的说话交流,那么他们间必然有一套统一的语言规则<在网络上server与client能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertex ...

  5. how tomcat works 读书笔记(一)----------一个简单的web服务器

    http协议 若是两个人能正常的说话交流,那么他们间必定有一套统一的语言规则<在网络上服务器与客户端能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertext tran ...

  6. How Tomcat Works读书笔记三-------连接器

    几个概念 HttpServlet,Servlet Servlet是一个接口,定义了一种网络服务,我们所有的servlet都要实现它(或它的子类) HttpServlet是一个抽象类,它针对的就是htt ...

  7. How Tomcat Works 读书笔记 八 载入器 上

    Java的类载入器 详细资料见 http://blog.csdn.net/dlf123321/article/details/39957175 http://blog.csdn.net/dlf1233 ...

  8. How tomcat works 读书笔记十七 启动tomcat 下

    在上一节中,我们程序的起始位置还是Bootstrap,现在我们通过bat文件来启动这个类. 在分析catalina.bat之前,我们先看看几个简单的我们能用到的dos命令. 基础知识 1 rem 注释 ...

  9. How tomcat works 读书笔记十七 启动tomcat 上

    一路跋山涉水,这是最后一章了. 关于tomcat的启动,有两个类,一个是Catalina类,一个是Bootstrap类. 理论上,两个类可以和到一起,但是为了支持多种运行模式,又把他们分开了. 为了让 ...

随机推荐

  1. Mybatis源码分析之存储过程调用

    这一篇博客我们学习一下Mybatis调用存储过程的使用和运行流程.首先我们先创建一个简单的存储过程 DELIMITER $ CREATE PROCEDURE mybatis.ges_user_coun ...

  2. ios zxing扫码问题

    在ios 中 扫瞄二维码,条形码基本有 2中第三方的库,一个是zbar 一个是zxing,zxing 在android中表现的比较出色,但是在ios 中不是很好用,扫瞄效率低,我们一般都用zbar,但 ...

  3. web中间件切换(was切tomcat)

    一.数据源迁移: ①数据源配置在web容器还是在项目本身? 根据开发与生产分离原则选择配置到web容器,以免开发泄露数据库密码. ②数据库密码加密 原先was的数据源直接在console控制,密码是密 ...

  4. Android初级教程理论知识(第三章测试&数据存储&界面展现)

    首先介绍单元测试,我在javaweb部分有详细介绍单元测试框架的一篇文章. 可以先看在javaweb中的单元测试详解篇http://blog.csdn.net/qq_32059827/article/ ...

  5. 打Patch实践

    一.找到相应PATCH 确认系统已安装模块版本. SELECTapp.application_short_name, app.application_name, pi.patch_level   FR ...

  6. ffmpeg.c函数结构简单分析(画图)

    前一阵子研究转码的时候看了FFmpeg的源代码.由于ffmpeg.c的代码相对比较长,而且其中有相当一部分是AVFilter有关的代码(这一部分一直不太熟),因此之前学习FFmpeg的时候一直也没有好 ...

  7. 使用批处理文件(*.bat)同时打多个cmd窗口

    使用批处理文件(*.bat)同时打多个cmd窗口 最近在研究zookeeper,在本地建了几个目录,发现频繁的去各个目录启动zkServer.cmd十分繁琐,于是乎google,才有了下文: 使用批处 ...

  8. 利用HTP工具包开发报表

    利用这种方式的优点是不需要跑请求就可以打印报表 工具包中常用程序说明 htp.print 语法   htp.print (cbuf | dbuf | nbuf); 作用   generates a l ...

  9. (NO.00001)iOS游戏SpeedBoy Lite成形记(十二)

    如果选手能在加速的时候屁股产生推进器效果就跟好了,仿佛选手腾云驾雾的感觉.我们可以用Cocos2D中的CCMotionStreak类来轻松实现.下面在Player.h接口文件添加以下代码: @prop ...

  10. 学习pthreads,使用条件变量进行多线程之间的同步

    条件变量提供另一种多线程同步的方法.互斥量通过控制对共享数据的访问来同步任务.条件变量可以根据数据的值来同步任务.条件变量是当一个事件发生时发送信号的信号量.一旦事件发生,可能会有多个线程在等待信号, ...