做Java Web开发多多少少都接触过tomcat。tomcat用起来确实简单啊,静态页面网上一丢,war包往上一丢,然后浏览器就直接访问了。用起来简单,但是忽略了tomcat的很多原理。Java程序都是通过main方法启动的,那tomcat是如何启动的?为什么资源往上一丢,就能通过浏览器访问?tomcat是如何与浏览器进行通信的?还有许多许多问题...从这些问题看来,tomcat用起来确实简单,但是他不是一只普通的猫啊!先上我写的Web容器
package com.wy.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author :WangYi
* @date :Created in 2019/5/5 10:04
* @description:
* @modified By:
*/
public class HTTPServer {
public static void service(Socket socket) throws Exception {
/**
* 读取HTTP信息
*/
InputStream socketInputStream = socket.getInputStream();
int size = 0;
while (size == 0) {
size = socketInputStream.available();
}
byte[] buffer = new byte[size];
socketInputStream.read(buffer); //将socketInputStream中的文本读到 buffer
String request = new String(buffer);
System.out.println(request);
/**
* 解析请求
*/
String firstLineOfRequest = request.substring(0, request.indexOf("\r\n"));//获取请求第一行信息
String[] parts = firstLineOfRequest.split(" ");//根据空格分隔成数组
String uri = parts[1];//获取求路径
System.out.println("uri:" + uri);
String contentType;
if (uri.indexOf("html") != -1 || uri.indexOf("htm") != -1) contentType = "text/html";
else if (uri.indexOf("jpg") != -1 || uri.indexOf("jpeg") != -1) contentType = "image/jpeg";
else contentType = "application/octet-stream";//MIME 参考手册:http://www.w3school.com.cn/media/media_mimeref.asp
/**
* 设置响应信息
*/
String responseFirstLine = "HTTP/1.1 200 OK\r\n";
String responseHeader = "Content-Type:" + contentType + "\r\n\r\n";
System.out.println(uri);
InputStream in = HTTPServer.class.getResourceAsStream("/root" + uri);//获取HTTPServer类路径下的资源文件
OutputStream socketOut = socket.getOutputStream();
socketOut.write(responseFirstLine.getBytes());//将响应信息写入输出流
socketOut.write(responseHeader.getBytes());//同上
int len = 0;
buffer = new byte[128];
while ((len = in.read(buffer)) != -1){
socketOut.write(buffer, 0, len);//将文件写入输出流
}
socket.close();
}
public static void main(String[] args) {
int port = 8080;
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(port);
System.out.println("服务器正在监听端口:" + serverSocket.getLocalPort());
while (true) {
try {
Socket socket = serverSocket.accept();//这里会有阻塞
System.out.println("建立了与客户端的一个新的TCP连接,该客户地址为:" + socket.getInetAddress() + ":" + socket.getPort());
service(socket);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上是我写的web容器源码,下面进行测试。
我用的maven构建项目,所以我在resources新建了root文件夹用来存放资源,上面代码也是指定到该文件夹。
index.html里简单写了几行测试代码,现在启动HTTPServer,控制台显示如下。
浏览器输入:http://localhost:8080/index.html
效果如下,页面正常显示
请求过后的控制台如下显示
通过控制台能很清楚的看到有哪些请求,能看到请求的详细信息。
结合代码与演示,可以进行一个简单的总结。Web容器的实现依赖于1.Socket2.输入输出流3.网络协议