最近在看《深入剖析TOMCAT》这本书,跟着书边看边学,试着搭搭tomcat,主要是试着了解思想~
首先,单纯的只是访问静态资源————比如Html,只需要三个类就可以:
HttpServer、Reuest、
Response
其实单看架构跟一些互联网项目是有类似的地方的。
1.HttpServer
package com.draz.ex01;
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;
/**
* Created by Drazen on 2017/2/24.
*/
public class HttpServer {
public static final String WEB_ROOT =
System.getProperty(
"user.dir") + File.separator +
"web";
private static final String SHUTDOWN_COMMAND =
"/SHUTDOWN";
private boolean shutdown =
false;
public static void main(String[] args) {
HttpServer server =
new HttpServer();
server.await();
}
public void await() {
ServerSocket serverSocket =
null;
int port =
8001;
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 input =
null;
OutputStream output =
null;
try {
socket = serverSocket.accept();
input = socket.getInputStream();
output = socket.getOutputStream();
Request request =
new Request(input);
request.parse();
Response response =
new Response(output);
response.setRequest(request);
response.sendStaticResource();
socket.close();
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
}
catch (Exception e) {
e.printStackTrace();
continue;
}
}
}
}
这个类主要是通过一个main()方法启动一个关于本地的监听,有一个公有方法await(),主要作用是启动监听,设置端口号(后期可以修改成配置文件的形式),加工请求并相应。
WEB_ROOT的值是我存放html的目录,也就是web。
调用的ServerSocket对象的accept()方法,这个方法的执行将使
Server端的程序处于等待状态,程序将一直阻塞直到捕捉到一个来自Client端的请求,并返回一个用于与该Client通信的Socket对象Link-Socket。此后
Server程序只要向这个Socket对象读写数据,就可以实现向远端的Client读写数据。结束监听时,关闭ServerSocket对象:
Socket类的构造函数有两个参数,第一个参数是欲连接到的
Server计算机的主机地址,第二个参数是该
Server机上提供服务的端口号。
Socket对象建立成功之后,就可以在Client和
Server之间建立一个连接,并通过这个连接在两个端点之间传递数据。利用Socket类的方法getOutputStream()和getInputStream()分别获得向Socket读写数据的输入/输出流,最后将从
Server端读取的数据重新返还到
Server端。
当
Server和Client端的通信结束时,可以调用Socket类的close()方法关闭Socket,拆除连接。
这样,在
Request类中处理的访问请求会传给
Response并指向要访问的资源
2.Request
package com.draz.ex01;
import java.io.InputStream;
import java.io.IOException;
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input) {
this.input = input;
}
public void parse() {
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<i; j++) {
request.append((
char) buffer[j]);
}
System.out.print(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;
}
public String
getUri() {
return uri;
}
}
一个公有的parse方法 Request 类里干的最主要的活就是加工!加工!加工 InputStream实例被拆分成字节数组的形式, 打印出来的request是这样的:
GET /index.html HTTP/1.1
Host:
localhost:8001
Connection:
keep-alive
Cache-Control:
max-age=0
Upgrade-Insecure-Requests:
1
User-Agent:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:
gzip, deflate, sdch, br
Accept-Language:
zh-CN,zh;q=0.8
Cookie:
logName=23700013181
最后
3.Response
package com.draz.ex01;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.File;
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 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 {
String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 23\r\n" +
"\r\n" +
"<h1>File Not Found</h1>";
output.write(errorMessage.getBytes());
}
}
catch (Exception e) {
System.out.println(e.toString() );
}
finally {
if (fis!=null)
fis.close();
}
}
}
转载请注明原文地址: https://ju.6miu.com/read-16746.html