Tomcat从零开始(十七)——StandardWrapper
第十七课:StandardWrapper
课前复习:
不知道大家是否还有印象,就是在6、7节课说的4种container,粗略的从大到小来说就是engine,host,context,和wrapper。当时写的时候很纠结,因为后面有详细介绍这4个的计划,所以前面写的可能不是很详尽。
让我们回忆一下,当一个请求到来的时候,发生了什么。比如什么创建Request这里就不说了,之后connector会调用与之关联的容器的invoke方法,之后那就肯定会调用pipeline的invoke,之后一顿invoke valve。好,那让我们回想一下之前写过的context和wrapper,总结一个比较详细的执行过程。
1. Connector创建req和resp
2. 调用StandardContext的invoke,调用xxxPipeline的invoke方法
3. Pipeline调用了wrapper的invoke方法
4. Wrapper调用valve的invoke方法
5. valve调用了servlet的 allocate(这里在以前的课程中讲过)
6. allocate方法调用servlet的load方法(当servlet需要加载的时候)
7. init方法,之后就是servlet处理了。
关于SingleThreadModel
这个SingleThreadModel在servlet2.4以上版本就已经移除了,因为这个东西只能给你的servlet的service保证同一时刻只有一个进程在访问,给人一种假象的安全。而且只是给service方法给予同步,这显然是不能完全解决多线程访问的问题的。其实说这个是为了给下面的StandardWrapper做铺垫。因为我们都知道StrandardWrapper是负责加载它所代表的servlet并allocate一个对象的实例。之后交给valve来调用servlet的service方法。这个allocate在使用和不使用SingleThreadModel的时候是不同的。好的,我们接下来就说这个StandardWrapper。
StandardWrapper
这个之前介绍过了,我们这次主要介绍的是allocate方法,我们看下面这一段源码可以发现,当没有实现SingleThreadModel的时候,allocate总是返回第一次时候产生的servlet实例。而如果实现SingleThreadModel接口,那么就开始控制分配的数量,当分配的大于nInstance时候,就load一个servlet实例,当然这个load实在maxInstance控制之内的。
代码如下。
public Servlet allocate() throws ServletException { if (debug >= 1)
log("Allocating an instance"); // If we are currently unloading this servlet, throw an exception
if (unloading)
throw new ServletException
(sm.getString("standardWrapper.unloading", getName())); // If not SingleThreadedModel, return the same instance every time
if (!singleThreadModel) { // Load and initialize our instance if necessary
if (instance == null) {
synchronized (this) {
if (instance == null) {
try {
instance = loadServlet();
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException
(sm.getString("standardWrapper.allocate"), e);
}
}
}
} if (!singleThreadModel) {
if (debug >= 2)
log(" Returning non-STM instance");
countAllocated++;
return (instance);
} } synchronized (instancePool) { while (countAllocated >= nInstances) {
// Allocate a new instance if possible, or else wait
if (nInstances < maxInstances) {
try {
instancePool.push(loadServlet());
nInstances++;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException
(sm.getString("standardWrapper.allocate"), e);
}
} else {
try {
instancePool.wait();
} catch (InterruptedException e) {
;
}
}
}
if (debug >= 2)
log(" Returning allocated STM instance");
countAllocated++;
return (Servlet) instancePool.pop(); } }
Load
这个没什么多说的,以前说过了,我们知道wrapper接口有一个load方法,其实他和Allocate里的一样,都是调用的LoadServlet方法。我们来看看它的源码。
先看看这一段。
// 这里是说如果不是第一次访问了,并且不是singleThreadModel
//就直接返回 Servlet实例
if (!singleThreadModel && (instance != null))
return instance; if ((actualClass == null) && (jspFile != null)) {
Wrapper jspWrapper = (Wrapper)
((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
if (jspWrapper != null) {
actualClass = jspWrapper.getServletClass();
// Merge init parameters
String paramNames[] = jspWrapper.findInitParameters();
for (int i = 0; i < paramNames.length; i++) {
if (parameters.get(paramNames[i]) == null) {
parameters.put
(paramNames[i],
jspWrapper.findInitParameter(paramNames[i]));
}
}
}
}
这是Tomcat4 的方法,以后的版本就没有了。都是直接loadservletclass。之后就是Loader了,回忆一下我们当时讲的,是自定义的一个classLoader,需要注意的是,container提供一个特殊的servlet,可以访问container的内部内容,名称以org.apache.catalina.起始。之后就是加载servlet,之后就是权限验证,没啥说的。在之后就是在init()的前后fire事件。之后用instanceof来确定是否是实现了singleThreadModel的,如果是就放入pool(如果pool为空就创建一个新的)中。剩下就是Return了。
ServletConfig
接下来就是servletConfig,这个东西我们回忆一下是在哪里看到这个东西的,想想在servlet被load的时候,就会调用一个init方法,而且他的参数是ServletConfig config,那么,我们就需要知道servlet是怎么拿到servletConfig的,我们看源码,会发现StandardWrapper他实现了ServletConfig接口,所以说他把自己传过去就行了。但是想一个事情,如果这样可以,那么servlet的每一个实现就都可以用wrapper之内的方法了,wrapper是container的,所以我们要保证安全,那么就像req,resp那样,用一个façade设计模式就行,这个就是隐藏子系统。
Filter
做过web开发,大家应该知道filter这个东西,那么filter是怎么实现的呢,我们想一下之前学的东西,我们应该能想到ServletWrapperValve做了这件事情,因为filter是跟service方法前后后关系。那么我们就可以知道valve的invoke方法做了什么:
1. 首先要得到一个wrapper的对象,allocate一个servlet
2. 来一系列的Filter,调用他们的doFilter方法,当然还有service方法
3. 销毁,这个应该是在servlet超时的时候才进行。
剩下就是讲解一下filter的chain了,这个东西其实是一个ArrayList,但是注意filterChain是一个对象,其中的filter是一个该对象之中的一个arraylist,所以我们就知道,这个东西其实就是靠iterator来实现一个接一个的调用过滤器。所以,本章就结束了,这章其实没有多少自己写的东西,基本都是对源代码的一种分析,希望大家可以多理解,或者下一个tomcat的sourcecode版本,之后多用断点 跑一跑就能理解是怎么工作的了。
最后还是冒充一下大神说说读代码的事吧,刚才有人问了问为啥我能读懂一些,刚开始的时候我也看不懂,其实就是你最开始看的时候不要纠结于所有的语句,至少你能看懂这个方法主要是干啥功能的,大概哪几个语句能实现就行了,等你慢慢的看完这个,再看完另一个,你就能知道到底那个语句是干什么的了。
Tomcat从零开始(十七)——StandardWrapper的更多相关文章
- Tomcat从零开始(十一)WebappLoader概述
好的,我们先看看这个WebappLoader到底在开始的时候做了什么,先看看他的start()方法. public void start() throws LifecycleException { / ...
- Tomcat从零开始(十)Loader
第十课: 不知不觉就10篇blog了,说实话,我是第一次更这么长时间的Blog. 嗯,今天说说Loader,在以前的课程中,也就是内个能使用最初级的servlet的那一节,我们使用了URLClassL ...
- 详解web容器 - Jetty与Tomcat孰强孰弱
Jetty 基本架构 Jetty目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器.它有一个基本数据模型,这个数据模型就是 Handler(处理器 ...
- 从零开始学 Java - 我放弃了 .NET ?
这不是一篇引起战争的文章 毫无疑问,我之前是一名在微软温暖怀抱下干了近三年的 .NET 开发者,为什么要牛(sha)X一样去搞 Java 呢?因为我喜欢 iOS 阿!哈哈,开个玩笑.其实,开始学 Ja ...
- Jetty 的工作原理以及与 Tomcat 的比较
Jetty 的基本架构 Jetty 目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器,它有一个基本数据模型,这个数据模型就是 Handler,所 ...
- 【Jetty】Jetty 的工作原理以及与 Tomcat 的比较
Jetty 应该是目前最活跃也是很有前景的一个 Servlet 引擎.本文将介绍 Jetty 基本架构与基本的工作原理:您将了解到 Jetty 的基本体系结构:Jetty 的启动过程:Jetty 如何 ...
- Tomcat学习总结(7)——Tomcat与Jetty比较
Jetty 基本架构 Jetty目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器. 它有一个基本数据模型,这个数据模型就是 Handler(处理 ...
- Jetty与Tomcat综合比较
Jetty基本架构 Jetty目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器.它有一个基本数据模型,这个数据模型就是 Handler(处理器) ...
- 摘录:Jetty 的工作原理以及与 Tomcat 的比较
引子:Jetty 应该是目前最活跃也是很有前景的一个 Servlet 引擎.本文将介绍 Jetty 基本架构与基本的工作原理:您将了解到 Jetty 的基本体系结构:Jetty 的启动过程:Jetty ...
随机推荐
- 洛谷P3195 [HNOI2008] 玩具装箱 [DP,斜率优化,单调队列优化]
题目传送门 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N ...
- SCU - 4439 Vertex Cover (图的最小点覆盖集)
Vertex Cover frog has a graph with \(n\) vertices \(v(1), v(2), \dots, v(n)\) and \(m\) edges \((v(a ...
- Java-并发入门
本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ Java中实现多线程的方法 实现Runnable接口 实现Runnable接口里的run()方法 ...
- 【BZOJ 4570】【SCOI 2016】妖怪
http://www.lydsy.com/JudgeOnline/problem.php?id=4570 对于每个妖怪的两个值,看成二位平面上的一个点的横纵坐标(x,y). 因为只关心a/b,所以设经 ...
- [BZOJ2458][BeiJing2011]最小三角形(分治)
求平面上n个点组成的周长最小的三角形. 回忆平面最近点对的做法,找到横坐标的中点mid分治到两边,合并时考虑离mid横坐标不超过当前最小值d的所有点,按y排序后暴力更新答案. 这个题也一样,先分治到两 ...
- [LOJ6191][CodeM]配对游戏(概率期望DP)
n次向一个栈中加入0或1中随机1个,如果一次加入0时栈顶元素为1,则将这两个元素弹栈.问最终栈中元素个数的期望是多少. 首先容易想到用概率算期望,p[i][j][k]表示已加入i个数,1有j个,总长为 ...
- [NOIP2015] D1T2 信息传递
洛谷题目链接:https://www.luogu.org/problemnew/show/2661 一道有很多种解法的题目 通过划归,发现就是求最小环 那么立即能想到的算法:1.Tarjan求强连通分 ...
- BZOJ 4756 [Usaco2017 Jan]Promotion Counting(线段树合并)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4756 [题目大意] 给出一棵树,对于每个节点,求其子树中比父节点大的点个数 [题解] ...
- 【树形dp】hdu6035 Colorful Tree
非常棒的题解,我就不复述了:http://blog.csdn.net/Bahuia/article/details/76141574 O(n) #include<cstdio> #incl ...
- 浅析HashMap和Hashtable的区别
HashMap和Hashtable两个类都实现了Map接口,二者保存键值对(key-value对): HashMap和HashTable区别 第一,继承的父类不同.HashMap继承自Abstract ...