有比较宏观的问题,如下(持续更新中):
1.能否用一句话说明tomcat或者一个java web服务器做的事情?
2.http请求是怎么进入tomcat服务器的,即内部的调用序列是怎么样的?
3.tomcat或者jboss如何和我们的web框架整合?
……
也有微观的问题,如下(持续更新中):
1.http1.1的新特性是什么?你又是否知道为什么会新添加这些新特性?
2. servlet实现了的singleTreadModel接口,就是线程安全的吗?
3.你也许知道filter是干嘛的,但是你知道filter是在哪里、何时、被哪个模块调用执行的吗?
……
深入剖析tomcat读书笔记1涉及1-3章,本身并不涉及tomcat的任何源码。
介绍了简单的实现web服务器的方法(对于静态资源的处理,不涉及动态内容)。解析http报文得到请求的对象,处理请求对象得到结果,封装结果返回相应对象。其实都是在用Java来实现一些字符串操作,通过字节流来承载内容。
Http协议
主要简单介绍了http协议,更详细地介绍在
http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html
http请求组成:请求行、请求头、实体。
请求行:请求方法----URI----协议/版本
请求头:Accept、Accept-Charset、Host、User-Agent、Content-Length、Content-Type
实体:各个请求参数
http响应组成:状态行、响应报头、响应正文
状态行:协议—状态码—描述
响应报头:Location、Server、Content-Length、Content-Type、Last-Modified
Socket类
Socket就是网络连接的端点,有Socket和serverSocket两种,前者为客户端建立,后者为服务端建立。客户端和服务端建立了socket链接,就可以进行通信。
socket通信是什么?
我认为本质上就是一边输入数据,一边输出数据。在java里面,就是用封装的字节流来处理。
如何通信?
发送数据方调用socket的getOutPutStream()方法,获取OutputStream对象,用该OutputStream对象创建一个PrintWriter对象,调用PrintWriter的print()方法即可。接受数据方调用socket的getInputStream()方法,获取InputStream对象,用该InputStream创建一个BufferReader,调用BufferReader的read()方法即可。
serverSocket
serverSocket是服务端创建的,要等待来自客户端的请求。当serverSocket接收到了连接请求后,它会创建一个socket处理与客户端的通信。就是调用serverSocket.accept()方法。
serverSocket构造函数中有一个backlog属性,表示连接的队列的长度(而不是连接的数量)。“输入连接指示(对连接的请求)的最大队列长度被设置为 backlog 参数。如果队列满时收到连接指示,则拒绝该连接。”
第二章-----一个简单的servlet容器
servlet容器主要可以处理动态内容。和Servlet技术并行的技术是cgi。和一个在腾讯工作的同学交流,腾讯web系统采用得就是cgi技术,后台用C来实现。
Servlet是一套规范,要熟悉他,要参考在javax.servlet和java.servlet.http两个包下的接口和类。最重要的接口就是servlet接口,有5个方法。
public void init(ServletConfig config)throws ServletException;
//当某个servlet被实例化后,servlet容器调用其init()方法进行初始化,比如设置数据库链接、初始化默认值等等
public ServletConfig getServletConfig();
//取得的是web.xml文件中,配置的参数
public void service(ServletRequestreq, ServletResponse res) throws ServletException,
IOException;
//当servlet的一个客户端请求到达后,servlet容器就调用相应servlet的service()方法。参数类型分别为ServletRequest和ServletResponse。前者包含http请求的信息,后者封装servlet的响应信息。
public String getServletInfo();
//用Servlet类的getServletInfo方法获取网页的说明信息,GetServletInfo()方法是一个可选的方法,它提供有关servlet的信息,如作者、版本、版权。
public void destroy();
//在将servlet实例从服务中移出前,servlet容器会调用servlet实例的destory()方法。调用该方法,一般用来清理自身持有的资源,如内存、文件句柄和线程等等。
如何实现一个简单的servlet容器?
作者给出了一个实例。思路如下:
1:等待HTTP请求。
2:构造一个ServletRequest对象和一个ServletResponse对象。
3:假如该请求需要一个静态资源的话,调用StaticResourceProcessor实例的process方法,同时传递ServletRequest和ServletResponse对象。
4:假如该请求需要一个servlet的话,加载servlet类并调用servlet的service方法,同时传递ServletRequest和ServletResponse对象
5: 处理后结果,把封装为ServletResponse,返回。
第三章—连接器
tomcat使用的servlet容器的名字是catalina,主要包含2个模块:连接器(connector)和容器(container)。
连接器
连接器作用:解析http请求头(其实不只是可以接受http协议,还可以接受AJP协议,用于纯web服务器比如apache和应用服务器比如tomcat的连接。关于web服务器和应用服务器的区别,可以自行谷歌之),使得servlet实例能够获取到请求头、cookie等信息。
一个简单的连接器实现
一个简单的连接器由2个部分组成:httpConnector、httpProcessor。
httpConnector作用:
1. 等待http请求
2. 为每个请求创建一个httpProcessor实例
3. 调用httpProcessor的process()方法
核心的代码如下:
while (!stopped) {
// Acceptthe next incoming connection from the server socket
Socket socket = null;
try {
socket = serverSocket.accept();
}
catch (Exception e) {
continue;
}
// Handthis socket off to an HttpProcessor
HttpProcessor processor = new HttpProcessor(this);
processor.process(socket);
}
httpProcessor作用:创建请求对象和响应对象。显然,为了servlet能够处理,请求对象必须实现httpRequest接口,响应对象必须实现httpResponse接口。
对于每一个传入的http请求,完成4个操作:
1. 创建一个HttpRequest对象;
2. 创建一个HttpResponse对象;
3. 解析Http的请求行和请求头,填充HttpRequest对象;
4. 将HttpRequest和HttpResponse传递给servlet的service()方法。
解析http请求步骤如下:
1. 读取套接字的输入流;
2. 解析请求行;
3. 解析请求头;
4. 解析cookie;
5. 获取参数
读取套接字的输入流仅需要调用servlet的getInputStream();解析请求行、请求头、cookie
的parse方法都是按照http协议,比如如何从
“GET /my/app/servlet?username=mohe&password=123 HTTP /1.1”字符串中得到请求方法、URI、版本version。这些都是纯字符串操作,大量运用了indexof()、subString()等方法。