攻城狮在路上(肆)How tomcat works(三) 连接器:Connector
在介绍中提到,Catalina中有两个主要的模块:连接器和容器。本章中你将会写一个可以创建更好的请求和响应对象的连接器,用来改进第2章中的程序。一个符合Servlet 2.3和2.4规范的连接器必须创建javax.servlet.http.HttpServletRequest和javax.servlet.http.HttpServletResponse,并传递给被调用的servlet的service方法。
在本章的应用程序中,连接器解析HTTP请求头部并让servlet可以获得头部, cookies, 参数名/值等等。你将会完善第2章中Response类的getWriter方法,让它能够正确运行。由于这些改进,你将会从 PrimitiveServlet中获取一个完整的响应,并能够运行更加复杂的ModernServlet。
本章你建立的连接器是将在第4章详细讨论的Tomcat4的默认连接器的一个简化版本。Tomcat的默认连接器在Tomcat4中是不推荐使用的,但它仍然可以作为一个非常棒的学习工具。在这章的剩余部分,"connector"指的是内置在我们应用程序的模块。
注意:和上一章的应用程序不同的是,本章的应用程序中,连接器和容器是分离的。
本章的应用程序可以在包ex03.pyrmont和它的子包中找到。组成连接器的这些类是包 ex03.pyrmont.connector 和ex03.pyrmont.connector.http的一部分。在本章的开头,每个附带的程序都有个bootstrap类用来启动应用程序。不过,在这个阶段,尚未有一个机制来停止这个应用程序。一旦运行,你必须通过关闭控制台(Windows)或者杀死进程(UNIX/Linux)的方法来鲁 莽的关闭应用程序。
先来说说包org.apache.catalina.util里边的StringManager类。这个类用来处理这个程序中不同模块和Catalina自身的错误信息的国际化
一、StringManager类:
该类基本功能是实现国际化错误提示,由于在整个tomcat中只用一个配置文件的话会难以维护,所以这里的做法是每个包都会对于一个配置文件,每个属性文件都会被一个 org.apache.catalina.util.StringManager类的实例所处理。所以当tomcat运行的时候,会有多个StringManager实例。为了避免资源浪费,该类被设计为单例模式。
基本用法:
StringManager sm = StringManager.getManager("ex03.pyrmont.connector.http");
public String getString(String key)
二、应用程序说明:
本节共有三个包:connector+startup+core.
startup模块只有一个类,Bootstrap,用来启动应用的。
connector模块的类可以分为五组:
连接器和它的支撑类(HttpConnector和HttpProcessor)。
指代HTTP请求的类(HttpRequest)和它的辅助类。
指代HTTP响应的类(HttpResponse)和它的辅助类。
Facade类(HttpRequestFacade和HttpResponseFacade)。
Constant类
core模块由两个类组成:ServletProcessor和StaticResourceProcessor。
第2章中的HttpServer类被分离为两个类:HttpConnector和HttpProcessor,Request被 HttpRequest所取代,而Response被HttpResponse所取代。同样,本章的应用使用了更多的类。
三、启动应用程序Bootstrap:
该类中的main方法中就是简单的创建了一个HttpConnector对象,然后调用了其connector.start();方法。仅仅是一个入口。
四、 connector模块:
1、HttpConnector:
该类作为一个单独的线程启动,定义了一个ServerSocket,监听8080端口。然后提供了一个阻塞式的循环。
当接受到一个Socket对象时,创建一个HttpProcessor对象,执行其process方法。
总体来说,HttpConnector仅仅是用于监听请求,剩余的事情都完全交给HttpProcessor去处理。
2、HttpProcessor:
该类最重要的方法是:public void process(Socket socket);
A、在该方法中首先获取Socket的输入、输出流,将其封装成一个自定义的流对象。
B、创建HttpRequest对象,该对象实现了HttpServletRequest接口。同样使用了外观对象HttpRequestFacade.
C、创建HttpResponse对象,该对象实现了HttpServletResponse接口。同样使用了外观对象HttpResponseFacade.
D、private void parseRequest(SocketInputStream input, OutputStream output)方法解析请求行。
E、private void parseHeaders(SocketInputStream input)解析头部,生成一个HttpHeader对象。
F、获取参数只会在第一次调用getParameter()等方法时才会对查询字符串或者POST请求内容进行解析,目的是提高效率。
G、根据是否包含“/servlet/”选择ServletProcessor或者StaticResourceProcessor。
3、HttpResponse:该类和第二节最大的区别在于对getWriter()方法进行了改进,返回的是一个自定义的Writer,可以实现自动刷新。