How tomcat works 读书笔记十三 Host和Engine
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的更多相关文章
- how tomcat works 读书笔记(二)----------一个简单的servlet容器
app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...
- how tomcat works 读书笔记四 tomcat的默认连接器
事实上在第三章,就已经有了连接器的样子了,只是那仅仅是一个学习工具,在这一章我们会開始分析tomcat4里面的默认连接器. 连接器 Tomcat连接器必须满足下面几个要求 1 实现org.apache ...
- how tomcat works读书笔记 七 日志记录器
大家可以松一口气了,这个组件比较简单,这一节和前面几节想比,也简单的多. Logger接口 Tomcat中的日志记录器都必须实现org.apache.catalina.Logger接口. packag ...
- how tomcat works 读书笔记(一)----------一个简单的webserver
http协议 若是两个人能正常的说话交流,那么他们间必然有一套统一的语言规则<在网络上server与client能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertex ...
- how tomcat works 读书笔记(一)----------一个简单的web服务器
http协议 若是两个人能正常的说话交流,那么他们间必定有一套统一的语言规则<在网络上服务器与客户端能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertext tran ...
- How Tomcat Works读书笔记三-------连接器
几个概念 HttpServlet,Servlet Servlet是一个接口,定义了一种网络服务,我们所有的servlet都要实现它(或它的子类) HttpServlet是一个抽象类,它针对的就是htt ...
- How Tomcat Works 读书笔记 八 载入器 上
Java的类载入器 详细资料见 http://blog.csdn.net/dlf123321/article/details/39957175 http://blog.csdn.net/dlf1233 ...
- How tomcat works 读书笔记十七 启动tomcat 下
在上一节中,我们程序的起始位置还是Bootstrap,现在我们通过bat文件来启动这个类. 在分析catalina.bat之前,我们先看看几个简单的我们能用到的dos命令. 基础知识 1 rem 注释 ...
- How tomcat works 读书笔记十七 启动tomcat 上
一路跋山涉水,这是最后一章了. 关于tomcat的启动,有两个类,一个是Catalina类,一个是Bootstrap类. 理论上,两个类可以和到一起,但是为了支持多种运行模式,又把他们分开了. 为了让 ...
随机推荐
- 设置TextView显示的文字可以复制
设置TextView显示的文字可以复制 效果图 在xml中设置 <TextView android:layout_width="wrap_content" android:l ...
- 【java多线程系列】java内存模型与指令重排序
在多线程编程中,需要处理两个最核心的问题,线程之间如何通信及线程之间如何同步,线程之间通信指的是线程之间通过何种机制交换信息,同步指的是如何控制不同线程之间操作发生的相对顺序.很多读者可能会说这还不简 ...
- c语言求最大公约数
求差判定法. 如果两个数相差不大,可以用大数减去小数,所得的差与小数的最大公约数就是原来两个数的最大公约数.例如:求78和60的最大公约数.78-60=18,18和60的最大公约数是6,所以78和60 ...
- 剑指Offer——网易笔试之解救小易——曼哈顿距离的典型应用
剑指Offer--网易笔试之解救小易--曼哈顿距离的典型应用 前言 首先介绍一下曼哈顿,曼哈顿是一个极为繁华的街区,高楼林立,街道纵横,从A地点到达B地点没有直线路径,必须绕道,而且至少要经C地点,走 ...
- Ext JS 6开发实例(三) :主界面设计
在上文中,已经将CMD创建的应用程序导入到项目里了,而且也看到默认的主界面了,今天的主要工作就是修改这个主界面,以符合项目的需要.除了设计主界面,还有一些其他的东西需要配置一下. 添加本地化包 打开a ...
- unix os下du df简单用法
转自:http://dadoneo.iteye.com/blog/984963 du命令参数详解见:http://baike.baidu.com/view/43913.htm 下面我们只对其做简单介绍 ...
- OpenCV特征点检测匹配图像-----添加包围盒
最终效果: 其实这个小功能非常有用,甚至加上只有给人感觉好像人脸检测,目标检测直接成了demo了,主要代码如下: // localize the object std::vector<Point ...
- Android初级教程图片信息
对图片常规信息要了解其性质.图片大小.像素.位图等等概念总结如下: 图片在计算机中的大小 图片的总大小 = 图片的总像素 * 每个像素占用的大小(图片的总像素=像素尺寸也就是分辨率,例如设定800*4 ...
- Objc运行时读取和写入plist文件遇到的问题
下面是本猫保持游戏NPC和物件交互的plist文件: 随着游戏和玩家逐步发生互动,玩家会修改人物和物件的交互的状态.这也是RPG游戏最基本的功能. 在切换每个地图时需要将上一个地图发生的改变存储到pl ...
- Android的oom详解
Android的oom原因 1.资源对象没关闭造成的内存泄露,try catch finally中将资源回收放到finally语句可以有效避免OOM.资源性对象比如: 1-1,Cursor 1-2,调 ...