Tomcat一直在用却不知道他的底层是如何实现的,今天就学习了一下Tomcat的一些底层实现原理
其实Tomcat底层是基于TCP的Socket通信的,简单的来将,就是生成一个服务器类然后使他处于监听状态,当有客户端访问是,会生成一个socket通信套接字,可以从中获取输入流从而获得HTTP请求的信息,然后也可以从中获取一个输出流,将响应的内容返回给客户端基本的代码如下:
public class TestTomcat {
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(8888);
while (true) {
socket = serverSocket.accept();
ServerThread serverThread = new ServerThread(socket);
serverThread.start();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class ServerThread extends Thread {
Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
InputStream is = null;
try {
is = socket.getInputStream();
Url url = new Url(is);
String uri = url.getUrl();
OutputStream os = socket.getOutputStream();
HttpResponse httpResponse = new HttpResponse(os);
//需要判断是否是静态资源
if(isStatic(uri)) {
httpResponse.wirteFile(uri.substring(1));
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean isStatic(String url) {
boolean isStatic =false;
String[] suffs = {"html","css","js"};
for(String suff:suffs) {
if(url.endsWith("."+suff)) {
isStatic=true;
break;
}
}
return isStatic;
}
}
我这里是给服务器端添加了多线程.
这是大概的,其实在我们平时的使用中经常会用到HttpRequest和HttpResponse就是输入流和输出流在做的事,
HttpRequest做的就是获取到HTTP请求然后将其中的信息进行解析
HttpRequest代码如下
在这里插入代码片public class HttpRequest {
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
private String url;
public HttpRequest(InputStream inputStream) throws IOException {
byte[] buff = new byte[1024];
int len = inputStream.read(buff);
if (len > 0) {
String msg = new String(buff, 0, len);
System.out.println(msg);
url = msg.substring(msg.indexOf("/"),msg.indexOf("HTTP/1.1")-1);
System.out.println("url:"+url);
} else {
System.out.println("no request");
}
}
}
HttpResponse做的就是通过获取到的url和其他参数信息选择正常的页面返回给客户端
HttpResponse代码如下
public class HttpResponse {
private OutputStream os = null;
public HttpResponse(OutputStream os) {
this.os = os;
}
/**
* 响应静态文件
*/
public void wirteFile(String path) throws IOException {
FileInputStream fis = new FileInputStream(path);
byte[] a = new byte[1024];
int len = 0;
while ((len=fis.read(a))!=-1) {
os.write(a,0,len);
}
fis.close();
os.flush();
os.close();
}
}
然后让我们再细分HttpRequest中对Http请求的解析,Http方法有GET和POST两种,可以通过一些简单的方法获取到是哪一种方法,然后在不同的地方获取到参数,GET方法是在url中获取,POST方法则是在HTTP请求的最后获取到.获取到了参数之后可以将这些参数如userName=wt;这样的数据通过spilt("=")的方法将其分割为数组,然后在定义一个hashmap对象将值存入其中,然后再定义一个我们很熟悉的getParment方法,通过key值返回对应的value值
让我们再细分HttpResponse中返回资源的细分,返回的资源有静态资源和动态资源之分,这个只需要更加url最后的结尾是什么后缀就可以分辨,如".html",".css"都是静态资源,如".action"就是动态资源访问,如果是静态资源的话就比较简单代码中已经写好,如果是动态资源就比较麻烦,需要找到对应的处理类来处理,所以我定义了一个HttpServlet类,他是一个抽象类,有一个抽象方法为HttpServlet(HttpRequest request,HttpResponse response);然后让那些处理类实现它来实现这个抽象方法,这就和我们在用的控制层的类很像了,所以在HttpResponse识别他为动态资源是就可以调用这些控制层类的方法.但是如果这样的类很多,经常要添加修改那就很麻烦,所以就需要写一个web.xml配置文件,这是使用了springIOC的方法,在web.xml配置文件中登记控制层类会被dom4j的一个工具类解析,将其生成一个handlerMap,有了这个handlerMap,就可以HttpResponse在通过url在handlerMap中通过反射找到对应的类,来实现对应的类的方法;