本系列帖子是假定读者已经可以初步使用tomcat的基础之上写的。如果你还不会使用tomcat,那么推荐学习韩顺平老师的《细说servlet》视频教程。
参考书籍:深入剖析tomcat
本帖主要是搭建一个简单的web服务器
程序结构如下图所示:
HttpServer类的代码:
package com.tomcat.http;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer {
/**
* System.getProperty("user.dir")的结果是:D:\develop\tomcat 获取项目所在路径
* System.out.println(File.separator);的结果是 \
*/
public static final String WEB_ROOT =
System.getProperty("user.dir")+File.separator+"webroot";
public static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
//the shutdown command received
private boolean shutdown = false; //关闭服务器的状态标志
public static void main(String[] args) {
HttpServer server = new HttpServer();//创建对象
server.await();//调用方法
}
public void await() {
ServerSocket serverSocket = null;
int port = 8080;
try {
//创建serverSocket对象
serverSocket对象 = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
//loop waiting for a request
while(!shutdown) {
Socket socket = null;
InputStream input = null;
OutputStream output = null;
try {
socket = serverSocket.accept();
input = socket.getInputStream();
output = socket.getOutputStream();
//创建Request对象,并解析请求头
Request request = new Request(input);
request.parse();
//创建Response对象
Response response = new Response(output);
response.setRequest(request);
response.setStaticResource();
//close the socket
socket.close();
//check if the previous URI is a shutdown command
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
} catch (Exception e) {
e.printStackTrace();
continue;
}
}
}
}
Request类的代码如下:
package com.tomcat.http;
import java.io.InputStream;
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input) {
this.input = input;
}
/**
* 用于解析HTTP请求中的原始数据
*
* 如何工作:需要知道请求头和请求体的结构
*/
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 (Exception e) {
e.printStackTrace();
i = -1;
}
for (int j = 0; j < i; j++) {
request.append((char)buffer[j]);
}
System.out.println(request.toString());
uri = psrseUri(request.toString());
}
/**
* 解析HTTP请求的URI
* @param requestString
* @return
*/
private String psrseUri(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;
}
public String getUri() {
return uri;
}
}
Response类的代码:
package com.tomcat.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 output;
public Response(OutputStream output) {
this.output = output;
}
public void setRequest(Request request) {
this.request = request;
}
public void setStaticResource() {
byte[] bytes = new byte[BUFFER_SIZE];
FileInputStream fis = null;
try {
System.out.println(123);
File file = new File(HttpServer.WEB_ROOT,request.getUri());
if(file.exists()) {
fis = new FileInputStream(file);
int ch;
while(((ch = fis.read(bytes, 0, BUFFER_SIZE) )!= -1)) {
output.write(bytes, 0, ch);
}
}else {
//file not found
String errorMessage = "file not found";
output.write(errorMessage.getBytes());
}
} catch (Exception e) {
System.out.println(e.toString());
}finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
index.html的代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
hello world.
</body>
</html>
如何发起请求:在浏览器输入如下地址:http://localhost:8080/index.html
最终结果:
页面返回:hello world.
控制台打印输出结果:
GET /index.html HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: Idea-82847fdb=bc822efc-9482-4d70-af1b-9810633d90f9; Idea-deaf1dd9=75405b31-277a-4999-a725-48667070d583