cundeng 发表于 2017-2-7 06:47:33

How tomcat work连载一:简易的静态WEB容器

  以下代码是我在学习《HOW Tomcat work》第一章:如何构建一个简单的静态文件容器后,写下的,注释很详细,不懂的可以站内短信我.
  首先建立一个监听Server类,如下所示:
  package ex01.pyrmont;

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;
import java.util.Date;
import org.apache.log4j.Logger;
/**
* 类HttpServer.java的实现描述:
*/
public class HttpServer {
public static final Logger log       = Logger.getLogger("actionLog");
/** 获取当前的文件系统路径 **/
public static final String WEB_ROOT= System.getProperty("user.dir") + File.separator + "webRoot";
/** 关闭的命令 **/
public static final String SHUT_DOWN = "/shutdown";
private ServerSocket       server;
/**
* 构造监听server
*
* @param port 监听的端口
* @param backlog 监听队列的最大长度
* @param serverName 主机名(可以是域名或者是IP)
*/
public HttpServer(int port, int backlog, String serverName){
try {
server = new ServerSocket(port, backlog, InetAddress.getByName(serverName));
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
public static void main(String[] args) {
HttpServer server = new HttpServer(8773, 1, "127.0.0.1");
try {
server.listen();
/** 当监听终止的时候,释放相关资源 **/
server.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
/**
* 启动server的监听程序<br/>
* 当在等待连接的时候,该方法可能会抛出<code>IOException</code><br/>
* 例如server意外关闭等等
*
* @throws IOException
*/
public void listen() throws IOException {
if (log.isInfoEnabled()) {
log.info("server begin to listen on :" + new Date());
}
boolean isShutdown = false;
Socket client = null;
InputStream is = null;
OutputStream os = null;
Request request;
Response response;
while (!isShutdown) {
client = server.accept();
if (log.isInfoEnabled()) {
log.info("get Client:" + client);
}
is = client.getInputStream();
os = client.getOutputStream();
/** 构造请求 **/
request = new Request(is);
/** 提取请求中的参数 **/
request.parse();
response = new Response(request);
response.setOutput(os);
/** 发送静态资源 **/
response.sendStaticMessage();
/** 关闭当前客户端 **/
client.close();
/** 判断是否是关闭命令 **/
isShutdown = request.getUri().equalsIgnoreCase(SHUT_DOWN);
}
}
/**
* 关闭server
*/
public void close() {
if (server != null && !server.isClosed()) {
try {
if (log.isInfoEnabled()) {
log.info("server end to listen on :" + new Date());
}
server.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
}

  建立一个对应静态文件的请求类:
  package ex01.pyrmont;

import java.io.IOException;
import java.io.InputStream;
import org.apache.log4j.Logger;
/**
* 类Request.java的实现描述:
*/
public class Request {
private static final Logger log = Logger.getLogger("actionLog");
private InputStream         is;
private String            uri;
public Request(InputStream is){
this.is = is;
}
/**
* 读取request的内容,并提炼出uri
*/
public void parse() {
StringBuffer sb = new StringBuffer(2048);
byte[] buffers = new byte;
int i;
try {
i = is.read(buffers);
} catch (IOException e) {
log.error(e.getMessage(), e);
i = -1;
}
for (int j = 0; j < i; j++) {
sb.append((char) buffers);
}
if (log.isInfoEnabled()) {
log.info("request:" + sb.toString());
}
this.uri = parseUri(sb.toString());
}
private String parseUri(String request) {
/** 解析HTTP请求的头部,像GET/POST /index.html HTTP1.1 **/
int index1, index2;
/** 获取第一个空格的位置 **/
index1 = request.indexOf(' ');
if (index1 > -1) {
/** 从第一个空格之后,获取第二个空格的位置 **/
index2 = request.indexOf(' ', index1 + 1);
if (index2 > index1) {
return request.substring(index1 + 1, index2);
}
}
return null;
}
/**
* 返回request的uri路径
*
* @return uri
*/
public String getUri() {
return uri;
}
@Override
public String toString() {
return String.format("Request", this.uri);
}
}

  建立响应输出类:
  package ex01.pyrmont;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.log4j.Logger;
/**
* 类Response.java的实现描述:
*/
public class Response {
private static final Logger log         = Logger.getLogger("actionLog");
/** 缓冲区的大小 **/
private static final int    BUFFER_SIZE = 1024;
private Request             request;
private OutputStream      output;
public Response(Request request){
this.request = request;
}
/**
* 初始化一个输出的缓冲流
*
* @param os
*/
public void setOutput(OutputStream os) {
output = os;
}
/**
* 发送静态消息
*/
public void sendStaticMessage() {
InputStream is = null;
String uri = request.getUri();
/** 如果uri为null或者等同与关闭命令时候,直接返回 **/
if (uri == null || uri.equalsIgnoreCase(HttpServer.SHUT_DOWN)) {
return;
}
try {
File file = new File(HttpServer.WEB_ROOT, uri);
/** 如果静态资源文件找不到,则输出一个错误提示页面 **/
if (!file.exists()) {
log.warn("can't find uri:" + uri);
String outputHtml = "<html>" + "<body>" + "<div><h1>can't find your response:" + uri + "</h1></div>"
+ "</body>" + "</html>";
output.write(outputHtml.getBytes());
} else {
is = new FileInputStream(file);
byte[] buffers = new byte;
/** 读入缓冲区的总字节数 **/
int ch = is.read(buffers, 0, BUFFER_SIZE);
while (ch != -1) {
output.write(buffers, 0, ch);
ch = is.read(buffers, 0, BUFFER_SIZE);
}
}
} catch (IOException e) {
log.error(e.getMessage(), e);
}
closeResponse(is);
}
/**
* 逆序的关闭响应的输出流,并输出响应文件
*
* @param is
* @param isr
* @param br
*/
private void closeResponse(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}

  最后我们测试下:
  建立一个简单的HTML文件,如下所示:
  <html>

<body>
<h1>welcome to Sweet's home</h1>
</body>
</html>
   试着在浏览器里输入http://127.0.0.1:8773/index.html,是不是可以看到这个欢迎页面
  如果输入http://127.0.0.1:8773/other.html(一个不存在的页面),是不是可以看到我们的错误页面提示
  如果输入http://127.0.0.1:8773/shutdown,可以看到我们的简易服务器正常关闭。
页: [1]
查看完整版本: How tomcat work连载一:简易的静态WEB容器