手寫簡易Tomcat
- 一、tomcat啟動類
- 二、Servlet、Request、Response
- 1. `BaseServlet`
- 2. `Request`
- 3. `Response`
- 三、自定義Servlet
- 1. `web.properties`
- 2. `FirstServlet、SecondeServelt`
- 四、運行結果
在java中涉及網路通信的,底層都是Socket通信,可以用ServerSocket(也可使用ServerSocketChannel即NIO,或使用Netty)監聽本地埠,在瀏覽器進行訪問,其本質也是Socket通信,不過是基于HTTP協議,所以需要對接受的訊息需要進行解碼,發送訊息時需要編碼,添加訊息頭,
一、tomcat啟動類
package com.zte;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class TomcatBootStrap {
private int port = 8080;
private ServerSocket server;
private Map<String, BaseServlet> servletMapping = new HashMap<String, BaseServlet>();
private Properties webxml = new Properties();
private void init() {
//加載web.xml檔案,同時初始化 ServletMapping物件
try {
String WEB_INF = this.getClass().getResource("/").getPath();
FileInputStream fis = new FileInputStream(WEB_INF + "web.properties");
webxml.load(fis);
for (Object k : webxml.keySet()) {
String key = k.toString();
if (key.endsWith(".url")) {
String servletName = key.replaceAll("\\.url$", "");
String url = webxml.getProperty(key);
String className = webxml.getProperty(servletName + ".className");
//單實體,多執行緒
BaseServlet obj = (BaseServlet) Class.forName(className).newInstance();
servletMapping.put(url, obj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void start() {
//加載組態檔,初始化url和servlet的映射關系
init();
try {
server = new ServerSocket(this.port);
System.out.println("GP TomcatBootStrap 已啟動,監聽的埠是:" + this.port);
//接受用戶請求
while (true) {
Socket client = server.accept();
//HTTP請求,發送的資料就是字串,有規律的字串(HTTP協議)
process(client);
client.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void process(Socket client) throws Exception {
try (
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream()
) {
//Request(InputStrean)/Response(OutputStrean)
Request request = new Request(is);
Response response = new Response(os);
//從協議內容中拿到URL,把相應的Servlet用反射進行實體化
String url = request.getUrl();
if (servletMapping.containsKey(url)) {
//呼叫實體化物件的service()方法,執行具體的邏輯doGet/doPost方法
servletMapping.get(url).service(request, response);
} else {
response.write("404 - Not Found");
}
os.flush();
}
}
public static void main(String[] args) {
new TomcatBootStrap().start();
}
}
二、Servlet、Request、Response
1. BaseServlet
package com.zte;
import java.io.IOException;
public abstract class BaseServlet {
public void service(Request request, Response response) throws IOException {
if ("GET".equals(request.getMethod())) {
doGet(request, response);
}
}
protected abstract void doGet(Request request, Response response) throws IOException;
protected abstract void doPost(Request request, Response response) throws IOException;
}
2. Request
對請求的輸入流進行決議
package com.zte;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Request {
private String method;
private String url;
public Request(InputStream req) {
try {
BufferedReader reqReader = new BufferedReader(new InputStreamReader(req));
String line = reqReader.readLine();
String[] strings = line.split("\\s");
this.method = strings[0];
//去除引數
this.url = strings[1].split("\\?")[0];
} catch (Exception e
) {
e.printStackTrace();
}
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
3. Response
對輸出添加訊息頭,使得瀏覽器可以決議
package com.zte;
import java.io.IOException;
import java.io.OutputStream;
public class Response {
private OutputStream resp;
public Response(OutputStream resp) {
this.resp = resp;
}
public OutputStream getResp() {
return resp;
}
public void setResp(OutputStream resp) {
this.resp = resp;
}
public void write(String content) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 OK\n")
.append("Content-Type: text/html;\n")
.append("\r\n")
.append(content);
resp.write(sb.toString().getBytes());
}
}
三、自定義Servlet
1. web.properties
servlet.one.url=/first
servlet.one.className=com.zte.FirstServlet
servlet.two.url=/second
servlet.two.className=com.zte.SecondServlet
2. FirstServlet、SecondeServelt
package com.zte;
import java.io.IOException;
public class FirstServlet extends BaseServlet{
@Override
protected void doGet(Request request, Response response) throws IOException {
doPost(request,response);
}
@Override
protected void doPost(Request request, Response response) throws IOException {
response.write("first servlet!");
}
}
package com.zte;
import java.io.IOException;
public class SecondServlet extends BaseServlet{
@Override
protected void doGet(Request request, Response response) throws IOException {
doPost(request,response);
}
@Override
protected void doPost(Request request, Response response) throws IOException {
response.write("second servlet!");
}
}
四、運行結果

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/241497.html
標籤:java
上一篇:Python3 - Seaborn: clustermap(), heatmap(), pivot_table(), corr() 有料~~~
