首先,Tomcat是一個軟件,所有的項目都能在Tomcat上加載運行,Tomcat最核心的就是Servlet集合,本身就是HashMap。Tomcat需要支持Servlet,所以有servlet底層的資源:HttpServlet抽象類、HttpRequest和HttpResponse,否則我們無法新建Servlet。
http協議:客戶端和用戶端進行請求和響應的過程:
這樣我們就可以在webapps寫項目了,一個項目有兩大資源:servlet資源和靜態資源,servlet本身是java類,我們讓它調用doGet和doPost方法,必須繼承HttpServlet,同時也需要@WebServlet注解,那么在Tomcat中就必須要有@WebServlet注解的實現,如果沒有@WebServlet,我們就無法拿到相應的注解。這樣我們就能成功搭建起Servlet資源。
當Http請求打過來之后,先打到socket上,處理Http請求,其本身就是連接器,從請求上能獲取到請求路徑和請求方法。先獲取到請求路徑,判斷servlet容器中是否含有相同路徑,如果有,再獲取請求方法,判斷是doGet還是doPost。
簡易版tomcat的核心原理
真正的Tomcat很復雜,但它的最核心功能可以簡化為:
- 監聽HTTP請求(Socket 綁定 8080 端口)
- 解析HTTP請求(讀取請求頭、請求體)
- 找到對應的Servlet處理請求(反射調用?
service()
?方法) - 返回HTTP響應(寫回響應頭和HTML)
手寫tomcat
首先,定義Servlet接口
public interface servlet {public void service(HttpServletRequest request, HttpServletResponse response) throws IOException;
}
其次,定義request和response
public class HttpServletRequest {private String method;private String url;//............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;}
}public class HttpServletResponse {//輸出流private OutputStream outputStream;public HttpServletResponse(OutputStream outputStream){this.outputStream = outputStream;}/*** 返回動態資源* @param context*/public void write(String context) throws IOException {//System.out.println(context);outputStream.write(context.getBytes());}/*** 返回靜態資源*/public void writeHtml(String path) throws Exception {String resourcesPath = FileUtil.getResoucePath(path);File file = new File(resourcesPath);if(file.exists()){//靜態文件存在System.out.println("靜態文件存在");FileUtil.writeFile(file,outputStream);}else {System.out.println("靜態文件不存在");write(ResponseUtil.getResponseHeader404());}}}
然后,實現一個Httpserver
public class MyTomcat {static HashMap<String, HttpServlet> routes = TomcatRoute.routes; //tomcat路由\/*** 分發器*/public void dispatch(HttpServletRequest request ,HttpServletResponse response) throws IOException {System.out.println("URL: " + request.getUrl());HttpServlet servlet = routes.get(request.getUrl()); //if(servlet!=null){ //說明請求的就是我們的servletSystem.out.println("找到匹配的Servlet: " + servlet.getClass().getName());servlet.service(request,response);}}/*** socket 啟動* @throws IOException*/public void start() throws IOException {ServerSocket serverSocket = new ServerSocket(8080); //1.指定監聽的端口號//2.對端口進行監聽while (true){Socket socket = serverSocket.accept();//阻塞監聽//3.打開輸入流,解析客戶端發來的內容InputStream inputStream = socket.getInputStream(); //輸入流HttpServletRequest request = new HttpServletRequest();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); //將字節流轉換成字符流String str = reader.readLine();//分割request.setMethod(str.split("\\s")[0]);request.setUrl(str.split("\\s")[1]);//4.打開輸出流OutputStream outputStream = socket.getOutputStream();HttpServletResponse response = new HttpServletResponse(outputStream);//分發器dispatch(request,response);socket.close();//socket在這里關閉}}//socketpublic static void main(String[] args) throws IOException {MyTomcat myTomcat = new MyTomcat();myTomcat.start();}
}
然后,自定義一個Servlet
@CYServlet(url = "/myServlet")
public class MyFirstServlet extends HttpServlet {@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) {super.doPost(request, response);}@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {System.out.println("Hello World!");System.out.println("Servlet實例: " + this);response.write(ResponseUtil.getResponseHeader200("hello world hhhhh"));}
}
最后,啟動服務并測試
public static void main(String[] args) throws IOException {MyTomcat myTomcat = new MyTomcat();myTomcat.start();}
訪問瀏覽器localhost:8080會得到: