java request 原理_服务器_基于Java的Web服务器工作原理(三),Request 类   Request 类对应 HTT - phpStudy...

基于Java的Web服务器工作原理(三)

Request 类

Request 类对应 HTTP 请求。创建这个类的实例,并传给它从 Socket 获得的 InputStream 对象,从而捕获与客户端的通信。呼叫 InputStream 对象的 read 方法中的一个就可以得到 HTTP 请求的原始数据。

Request 类有二个 public 方法 parse 与 getUri。parse 方法解析 HTTP 请求的原始数据。它做的事情不多--唯一它使之有效的信息是 HTTP 请求的 URI ,这个通过呼叫私有方法 parseUri 来获得。parseUri 方法把 URI 作为一个变量。调用 getUri 方法可以得到 HTTP 请求的 URI 。

要明白 parse 与 parseUri 的工作原理,你需要知道 HTTP 请求的结构,由 RFC2616 定义。

一个 HTTP 请求包括三个部分:

Request line

Headers

Message body

现在,我们只需要关注 HTTP 请求的第一部分--请求行。请求行以方法记号开始,接着是请求的 URI 与协议版本,以回车换行符结束。请求行的元素之间以空格分开。例如,一个用 GET 方法的 index.html 文件的请求行如下:

GET /index.html HTTP/1.1

parse 方法从 socket 的 InputStream 传递给 Request 对象中读取字节流,把这个字节数组存在缓冲里。然后,它把 buffer 字节数组里的字节放入叫做 request 的 StringBuffer 对象中,再把 StringBuffer 替换成 String 传递给 parseUri 方法。

parse 方法的代码如列表 1.2

Listing 1.2. The Request class' parse method

public void parse() {

// Read a set of characters from the socket

StringBuffer request = new StringBuffer(2048);

int i;

byte[] buffer = new byte[2048];

try {

i = input.read(buffer);

}

catch (IOException e) {

e.printStackTrace();

i = -1;

}

for (int j=0; j

request.append((char) buffer[j]);

}

System.out.print(request.toString());

uri   = parseUri(request.toString());

}

parseUri 方法查找请求行的第一个与第二个空格,从而从请求行获得了 URI 。列表 1.3 展示了 parseUri 方法的代码。

Listing 1.3. The Request class' parseUri method

private String parseUri(String requestString) {

int index1, index2;

index1 = requestString.indexOf(' ');

if (index1 != -1) {

index2 = requestString.indexOf(' ', index1 + 1);

if (index2 > index1)

return requestString.substring(index1 + 1, index2);

}

return null;

}

response 类

Response 类描述 HTTP 响应。它的构建方法接受 OutputStream 对象,如下:

public Response(OutputStream output) {

this.output = output;

}

Response 对象通过传递从 socket 获得的 OutputStream 对象到 HttpServer 类的 await 方法而创建。

Response 类有二个公共方法 setRequest 与 setStaticResource 。setRequest 用来传递 Request 对象到 Response 对象。它比较简单,代码如列表 1.4 所示:

Listing 1.4. The Response class' setRequest method

public void setRequest(Request request) {

this.request = request;

}

sendStaticResource 方法用来发送静态的资源,例如 HTML 文件。它的实现如列表 1.5 所示:

Listing 1.5. The Response class' sendStaticResource method

public void sendStaticResource() throws IOException {

byte[] bytes        = new byte[BUFFER_SIZE];

FileInputStream fis = null;

try {

File file  = new File(HttpServer.WEB_ROOT, request.getUri());

if (file.exists()) {

fis    = new FileInputStream(file);

int ch = fis.read(bytes, 0, BUFFER_SIZE);

while (ch != -1) {

output.write(bytes, 0, ch);

ch = fis.read(bytes, 0, BUFFER_SIZE);

}

}

else {

// file not found

String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +

"Content-Type: text/html\r\n" +

"Content-Length: 23\r\n" +

"\r\n" +

"

File Not Found

";

output.write(errorMessage.getBytes());

}

}

catch (Exception e) {

// thrown if cannot instantiate a File object

System.out.println(e.toString() );

}

finally {

if (fis != null)

fis.close();

}

}

SendStaticResource 方法非常简单。它首先通过传递父与子目录到 File 类的构建方法从而实例化 java.io.File 类。

File file = new File(HttpServer.WEB_ROOT, request.getUri());

然后检查这个文件是否存在。如果存在,则 sendStaticResource 方法传递 File 对象创建 java.io.FileInputStream 对象。然后调用 FileInputStream 的 read 方法,并把字节数组写到 OutputStream 对象 output 。就这样,静态资源的内容作为原始数据被发送到浏览器。

if (file.exists()) {

fis    = new FileInputStream(file);

int ch = fis.read(bytes, 0, BUFFER_SIZE);

while (ch != -1) {

output.write(bytes, 0, ch);

ch = fis.read(bytes, 0, BUFFER_SIZE);

}

}

如果文件不存在,sendStaticResource 发送一个错误信息到浏览器。

String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +

"Content-Type: text/html\r\n" +

"Content-Length: 23\r\n" +

"\r\n" +

"

File Not Found

";

output.write(errorMessage.getBytes());

编译与运行应用程序

要编辑与运行本文的应用,首先你需要解压源码 zip 文件。直接解压出来的目录被称为工作目录,它有三个子目录:src/,classes/,lib/。要编译应用,从工作目录输入如下命令:

javac -d . src/ex01/pyrmont/*.java

-d 选项把结果写到当前目录,而不是 src/ 目录。

要运行应用,在当前工作目录输入如下命令:

java ex01.pyrmont.HttpServer

测试这个应用,打开你的浏览器,在地址栏输入如下地址:

http://localhost:8080/index.html

你将在你的浏览器看到 index.html 显示出来。

在控制台,你看到如下的内容:

GET /index.html HTTP/1.1

Accept: */*

Accept-Language: en-us

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)

Host: localhost:8080

Connection: Keep-Alive

GET /images/logo.gif HTTP/1.1

Accept: */*

Referer: http://localhost:8080/index.html

Accept-Language: en-us

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)

Host: localhost:8080

Connection: Keep-Alive

总结

在这篇文章中(分为三个部分),你看到了一个简单的 web 服务器的工作原理。本文相关的应用只包括了三个类,功能是不全面的。然而,它仍不失为一个好的学习工具。

matrix开源技术经Onjava授权翻译并发布.

如果你对此文章有任何看法或建议,请到Matrix论坛发表您的意见.

注明: 如果对matrix的翻译文章系列感兴趣,请点击oreilly和javaworld文章翻译计划查看详细情况

您也可以点击-fajaven查看翻译作者的详细信息.

本文作者:相关阅读:

bat延时执行命令的另一种方法

HTML文档中小meta标签的大作用

linux查看系统时间命令

php 仿Comsenz安装效果代码打包提供下载

php 5.3.5安装memcache注意事项小结

JS读取cookies信息(记录用户名)

Webjx分享非常棒的国外的jQuery教程

在Framework4.0中实现延迟加载的实现方法

oracle关于加锁的讨论

ubuntu 9.10 更换登录界面的方法

实现窄屏/宽屏的切换——给宽屏用户超值享受

纯css完美解决图片在div内垂直水平居中

用vbs列出机器上所有能调用的组件

设置DropDownList的当前选项

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值