文章目录
  1. 1. HttpServer.java
  2. 2. Request.java
  3. 3. Response.java

这篇博文来自于《how tomcat works》一书的第一章

我们的服务器程序由下列三个类组成:

HttpServer.java

Request.java

Response.java

HttpServer.java是程序的入口。它的main方法创建了一个HttpServer的实例,然后调用它的await方法,此方法等待客户端的

HTTP请求,处理请求,把响应传回客户端。此服务器程序只能处理静态的资源,如HTML文件和图片文件。

HttpServer.java

我们来看看HttpServer.java的源代码

import java.io.File;  
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class HttpServer {
/**
* WEB_ROOT是存放HTML文件的目录
*/

public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";

//关闭命令
private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";

//收到关闭命令
private boolean shutdown = false;

/**
* @param args
*/

public static void main(String[] args) {
HttpServer server = new HttpServer();
server.await();

}

public void await() {
ServerSocket serverSocket = null;
int port = 8080;
try{
serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
}catch(IOException e){
e.printStackTrace();
System.exit(1);
}
//等待请求
while(!shutdown){
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try{

socket = serverSocket.accept();
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();

//创建请求对象并解析
Request request = new Request(inputStream);
request.parse();

//创建响应对象
Response response = new Response(outputStream);
response.setRequest(request);
response.sendStaticResource();

//关闭socket
if(socket != null){
socket.close();
}

//检查URI是否是一个关闭命令
shutdown = SHUTDOWN_COMMAND.equals(request.getUri());

}catch(Exception e){
e.printStackTrace();
continue;
}
}
}

}

Request.java

Request.java类代表一个HTTP请求,它的构造方法传入一个InputStream输入流,该输入流来自于与客户端交流的那个socket,即ServerSocket的accept方法返回的那个socket对象。下面是Request.java类的源代码:

import java.io.IOException;  
import java.io.InputStream;

public class Request {
private InputStream inputStream;
private String uri;
public Request(InputStream inputStream) {
this.inputStream = inputStream;
}

public void parse(){
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try{
i = inputStream.read(buffer);
}catch(IOException e){
e.printStackTrace();
i = -1;
}
for(int j=0;j<i;j++){
request.append((char)buffer[j]);
}
System.out.println(request.toString());
uri = parseUri(request.toString());
}

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;
}else{
return null;
}
}

public String getUri() {
return uri;
}

public void setUri(String uri) {
this.uri = uri;
}




}

方法parse()用来解析HTTP请求的数据。方法parseUri()根据传入的请求数据(一个字符串)解析出HTTP请求的URI,如GET /index.html HTTP/1.1中的 /index.html

就是一个HTTP请求的URI,方法parseUri()是通过搜索请求的第一个空格和第二个空格间的字符串来得到URI的。

Response.java

Response.java类代表一个HTTP响应,源代码如下:

import java.io.File;  
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Response {
private static final int BUFFER_SIZE = 1024;
Request request;
OutputStream outputStream;

public Response(OutputStream outputStream) {
this.outputStream =outputStream;
}

public void setRequest(Request request) {
this.request = request;
}

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){
outputStream.write(bytes, 0, ch);
ch = fis.read(bytes,0,BUFFER_SIZE);
}
}else{
String errorMessage = "<h1>File not found</h1>";
outputStream.write(errorMessage.getBytes());
}
}catch(Exception e){
System.out.println(e.toString());
}finally{
if(fis != null)
fis.close();
}


}



}

Response类的构造方法传入一个OutputStream输出流,此输出流来自于socket的getOutputStream()方法,而此socket又来自于ServerSocket的accept方法返回的对象

Response类的sendStaticResource()方法先找到HTTP请求头的URI所代表的文件,将此文件读入到一个字节数组,再用OutputStream输出流将字节数组写入到客户端

的浏览器。如果URI所代表的文件不存在,就向浏览器写入一个错误信息。

启动HttpServer类,在浏览器中输入http://localhost:8080/index.html,(可以自己在此web工程的WebRoot根目录下新建一个index.html文件),你将看到index.html在浏览器中显示出来。


控制台输出


文章目录
  1. 1. HttpServer.java
  2. 2. Request.java
  3. 3. Response.java