《深入剖析Tomcat》一1.3 应用程序

简介: 本节书摘来自华章出版社《深入剖析Tomcat》一书中的第1章,第1.3节,作者(美)Budi Kurniawan,更多章节内容可以访问云栖社区“华章计算机”公众号查看

1.3 应用程序

本章的Web服务器应用程序位于ex01.pyrmont包下,包括三个类:
HttpServer
Request
Response
应用程序的入口点(静态main()方法)在HttpServer类中。main()方法创建一个HttpServer实例,然后,调用其await()方法。顾名思义,await()方法会在指定端口上等待HTTP请求,对其进行处理,然后发送响应信息回客户端。在接收到关闭命令前,它会保持等待状态。
该应用程序仅发送位于指定目录的静态资源的请求,如HTML文件和图像文件。它也可以将传入到的HTTP请求字节流显示到控制台上。但是,它并不发送任何头信息到浏览器,如日期或cookies等。
下面几节将分别展示三个类的具体实现。
1.3.1 HttpServer类
HttpServer类表示一个Web服务器,具体实现如代码清单1-1所示。注意,为了节省空间,await方法在代码清单1-2中列出,并没有在代码清单1-1中重复。
image
image

这个Web服务器可以处理对指定目录中的静态资源的请求,该目录包括由公有静态变量final WEB_ROOT指明的目录及其所有子目录。WEB_ROOT的初始值为:
image

该代码清单包含一个名为webroot的目录,用于测试该应用程序的一些静态资源都位于该目录下。在该目录下还可以找到用于测试后续章节中应用程序的几个servlet程序。
若要请求静态资源,可以在浏览器的地址栏或URL框中输入如下的URL:

http://machineName:port/staticResource

若从另一台机器(不是运行应用程序的那台机器)上向该应用程序发出请求,则machineName是应用程序所在计算机的名称或IP地址;若在同一台机器上发出的请求,则可以将machineName替换为localhost,此外,连接请求使用的端口为8080。staticResource是请求的文件的名字,该文件必须位于WEB_ROOT指向的目录下。
例如,如果你正使用同一台机器来测试该应用程序,你想让HttpServer对象发送index.html文件,就可以使用如下的URL:

http://localhost:8080/index.html

若要关闭服务器,可以通过Web浏览器的地址栏或URL框,在URL的host:port部分后面输入预先定义好的字符串,从Web浏览器发送一条关闭命令,这样服务器就会收到关闭命令了。关闭命令定义在HttpServer类的SHUTDOWN静态final变量中:

private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";

因此,若要关闭服务器,需要使用如下的URL:

http://localhost:8080/SHUTDOWN

接下来,看一下代码清单1-2中的await()方法。
image

该方法名之所以称为await(),而不是wait(),是因为wait()方法是java.lang.Object类中与使用线程相关的重要方法。
await()方法会先创建一个ServerSocket实例,然后进入一个while循环:
image

当从8080端口接收到HTTP请求后,ServerSocket类的accept()方法返回,等待结束:

socket = serverSocket.accept();

接收到请求后,await()方法会从accept()方法返回的Socket实例中获取java.io.InputStream对象和java.io.OutputStream对象:

input = socket.getInputStream(); 
output = socket.getOutputStream();

然后,await()方法会创建一个ex01.pyrmont.Request对象,并调用其parse()方法来解析HTTP请求的原始数据:

// create Request object and parse 
Request request = new Request(input); 
request.parse();

然后,await()方法会创建一个Response对象,并分别调用其setRequest()方法和sendStaticResource()方法:

// create Response object
Response response = new Response(output); 
response.setRequest(request); 
response.sendStaticResource();

最后,await()方法关闭套接字,调用Request类的getUri()方法来测试HTTP请求的URI是否是关闭命令。若是,则将变量shutdown设置为true,程序退出while循环。

// Close the socket 
socket.close (); 
 
//check if the previous URI is a shutdown command 
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);

1.3.2 Request类

ex01.pyrmont.Request类表示一个HTTP请求。可以传递InputStream对象(从通过处理与客户端通信的Socket对象中获取的),来创建Request对象。可以调用InputStream对象中的read()方法来读取HTTP请求的原始数据。
Request类在代码清单1-3中给出。Request类有两个公共方法(parse()和getUri())和一个私有方法parseUri(),parse()方法和parseUri()方法分别在代码清单1-4和代码清单1-5中给出。
image

parse()方法用于解析HTTP请求中的原始数据。parse()方法会调用私有方法parseUri()来解析HTTP请求的URI,除此之外,并没有做太多的工作。parseUri()方法将URI存储在变量uri中。调用公共方法getUri()会返回HTTP请求的URI。
注意 处理HTTP请求原始数据的方法会在第3章和随后章节的应用程序中给出。
为了理解parse()和parseUri()方法是如何工作的,需要了解HTTP请求的结构,这在1.1节已经介绍过。在本章中,我们仅仅对HTTP请求的第一部分—请求行—感兴趣。请求行以请求方法开始,接着是请求的URI和请求所使用的协议及其版本,并以CRLF符结束。请求行中的元素以空格分开。例如,使用GET方法请求index.html文件的请求行如下所示:

GET /index.html HTTP/1.1

parse()方法从传入到Request对象中的套接字的InputStream对象中读取整个字节流,并将字节数组存储在缓冲区中。然后,它使用缓冲区字节数组中的数组填充StringBuffer对象request,并将StringBuffer的String表示传递给parseUri()方法。
parse()方法已经在代码清单1-4中给出。
image
image

parseUri()方法从请求行中获取URI。代码清单1-5展示了parseUri()方法的具体实现。parseUri()方法在请求中搜索第一个和第二个空格,从中找出URI。
image

1.3.3 Response类

ex01.pyrmont.Response类表示HTTP响应,其定义如代码清单1-6所示。
image

image

首先要注意的是Response类的构造函数会接收一个java.io.OutputStream对象,如下所示:
image

Response对象在HttpServer类的await()方法中通过传入从套接字中获取的OutputStream来创建。
Response类有两个公共方法:setRequest()和sendStaticResource()。setRequest()方法会接收一个Reuqest对象为参数。
sendStaticResource()方法用于发送一个静态资源到浏览器,如HTML文件。它首先会通过传入父路径和子路径到File类的构造函数中来实例化java.io.File类:
File file = new File(HttpServer.WEB_ROOT, request.getUri());
然后,它检查该文件是否存在。若存在,sendStaticResource()方法会使用File对象创建一个java.io.FileInputStream对象。然后它调用FileInputStream类的read()方法,并将字节数组写入到OutputStream输出中。注意,这种情况下,静态资源的内容是作为原始数据发送到浏览器的:
image

若文件不存在,sendStaticResource()会发送错误消息到浏览器:
image

1.3.4 运行应用程序

若要运行应用程序,需要在工作目录中执行下面的命令:

java ex01.pyrmont.HttpServer

若要测试应用程序,可以打开浏览器,在地址栏或URL框中输入如下URL:
http://localhost:8080/index.html
然后,就可以在浏览器中看到如下的index.html页面,如图1-1所示:
image

在控制台中,可以看到类似于如下的HTTP请求信息:
image
image

相关文章
|
1月前
|
Java 应用服务中间件
解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
132 1
|
3月前
|
存储 安全 Java
从HTTP到Tomcat:揭秘Web应用的底层协议与高性能容器
从HTTP到Tomcat:揭秘Web应用的底层协议与高性能容器
|
8月前
|
开发框架 JavaScript 前端开发
tomcat配置jpress应用
tomcat配置jpress应用
|
10月前
|
设计模式 Java 应用服务中间件
设计模式之责任链模式 Java实例代码 + Tomcat责任链模式应用+安卓责任链模式应用
设计模式之责任链模式 Java实例代码 + Tomcat责任链模式应用+安卓责任链模式应用
67 0
|
10月前
|
XML 安全 前端开发
关于Tomcat服务器在web项目中的应用
关于Tomcat服务器在web项目中的应用
57 0
|
11月前
|
前端开发 安全 Java
Tomcat - 模拟Tomcat的webappClassLoader加载自己war包应用内不同版本类实现相互共存与隔离
Tomcat - 模拟Tomcat的webappClassLoader加载自己war包应用内不同版本类实现相互共存与隔离
150 0
|
11月前
|
SQL Java 应用服务中间件
【JavaWeb】手把手教你Eclipse、IDEA集成Tomcat构建Web应用(三)
【JavaWeb】手把手教你Eclipse、IDEA集成Tomcat构建Web应用(三)
|
11月前
|
应用服务中间件 Android开发
【JavaWeb】手把手教你Eclipse、IDEA集成Tomcat构建Web应用(二)
【JavaWeb】手把手教你Eclipse、IDEA集成Tomcat构建Web应用(二)
|
11月前
|
XML IDE Java
【JavaWeb】手把手教你Eclipse、IDEA集成Tomcat构建Web应用(一)
【JavaWeb】手把手教你Eclipse、IDEA集成Tomcat构建Web应用(一)
|
Java 应用服务中间件 Shell
Tomcat_记一次tomcatwar包应用简单部署过程
Tomcat_记一次tomcatwar包应用简单部署过程
108 0