Tomcat簡單實現-- 5.2 HttpServer
阿新 • • 發佈:2020-08-18
HttpServer
- 現在我們的Connector類比較繁瑣不簡潔,因為它既要接收請求,又要處理請求,現在專門用一個類HttpServer來接管請求處理這一部分功能。
HttpServer類
-
接管處理部分,所以要有
handle200()
,handle404()
,handle500()
函式等等。 -
package jerrymice.catalina; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.log.LogFactory; import jerrymice.http.Request; import jerrymice.http.Response; import jerrymice.util.Constant; import jerrymice.util.WebXmlUtil; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; /** * @author :xsliu * @date :Created in 2020/8/18 17:18 * @description:接管Connector類中對請求的處理部分 * @modified By: */ public class HttpServer { public void execute(Socket socket, Request request, Response response){ // 處理請求和響應 try{ String uri = request.getUri(); if (uri == null) { // 說明此時沒有請求過來 return; } Context context = request.getContext(); if ("/500.html".equals(uri)) { throw new Exception("this is a deliberately created "); } if ("/".equals(uri)){ //如果訪問根目錄 uri = WebXmlUtil.getWelcomeFile(request.getContext()); } String fileName = StrUtil.removePrefix(uri, "/"); // 獲取檔名 File file = FileUtil.file(context.getDocBase(), fileName); // 通過context獲取資料夾,然後通過資料夾和檔名來獲取檔案 if (file.exists()){ // 如果訪問的檔案存在,就根據這個獲取字尾名 String extName = FileUtil.extName(file); // 根據字尾名獲取瀏覽器解析該檔案時使用的mimeType String mimeType = WebXmlUtil.getMimeType(extName); response.setContentType(mimeType); } else{ //檔案不存在,返回404錯誤 handle404(socket, uri); return; } handle200(socket, response); }catch (Exception e) { LogFactory.get().info(e.toString()); handle500(socket, e); }finally { try{ if (!socket.isClosed()){ socket.close(); } }catch (IOException e){ LogFactory.get().info(e.toString()); } } } /** * 處理檔案不存在異常 */ private void handle404(Socket socket, String uri) throws IOException { OutputStream outputStream = socket.getOutputStream(); String responseText = StrUtil.format(Constant.textFormat404, uri, uri); responseText = Constant.responseHead404 + responseText; byte[] responseBytes = responseText.getBytes("utf-8"); outputStream.write(responseBytes); } /** * 處理正常響應 */ private void handle200(Socket socket, Response response) throws IOException{ String contentType = response.getContentType(); String headText = Constant.responseHead200; byte[] head = headText.getBytes(); byte[] body = response.getBody(); byte[] responseBytes = new byte[head.length + body.length]; ArrayUtil.copy(head, 0, responseBytes, 0, head.length); ArrayUtil.copy(body, 0, responseBytes, head.length, body.length); OutputStream outputStream = socket.getOutputStream(); outputStream.write(responseBytes); } /** * 處理訪問時出現的問題 * @param socket: 訪問通訊過程中所使用的socket * @param e: 異常 */ private void handle500(Socket socket, Exception e){ try{ OutputStream outputStream = socket.getOutputStream(); StackTraceElement[] stackTraceElements = e.getStackTrace(); StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(e.toString()); stringBuffer.append("\r\n"); for (StackTraceElement element : stackTraceElements) { stringBuffer.append("\t"); stringBuffer.append(element.toString()); stringBuffer.append("\r\n"); } String msg = e.getMessage(); if (null != msg && msg.length() > 20){ msg = msg.substring(0, 19); } String text = StrUtil.format(Constant.textFormat500, msg, e.toString(), stringBuffer.toString()); text = Constant.responseHead500 + text; byte[] responseBytes = text.getBytes("utf-8"); outputStream.write(responseBytes); }catch(IOException e1){ LogFactory.get().info(e1.toString()); } } }
Connector類
-
Connector類中的處理部分可以去掉了,只負責接收請求。
-
package jerrymice.catalina; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.log.LogFactory; import com.sun.org.apache.bcel.internal.ExceptionConst; import jerrymice.http.Request; import jerrymice.http.Response; import jerrymice.util.Constant; import jerrymice.util.ThreadUtil; import jerrymice.util.WebXmlUtil; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; /** * @author xsl20 */ public class Connector implements Runnable{ int port; private Service service; public Service getService(){ return service; } public void setPort(int port){ this.port = port; } public Connector(Service service){ this.service = service; } public void init(){ LogFactory.get().info("Initializing Protocol [http-bio-{}], port"); } public void start(){ LogFactory.get().info("Starting ProtocolHandler [http-bio-{}],port"); new Thread(this).start(); } @Override public void run() { try{ ServerSocket serverSocket = new ServerSocket(port); while(true) { Socket socket = serverSocket.accept(); Runnable r = () -> { try { Request request = new Request(socket, service); Response response = new Response(); HttpServer httpServer = new HttpServer(); httpServer.execute(socket, request, response); }catch (Exception e){ LogFactory.get().info(e.toString()); }finally { // 將socket的關閉提取到最後 try{ socket.close(); }catch(IOException e){ LogFactory.get().info(e); } } }; ThreadUtil.run(r); } }catch (IOException e) { LogFactory.get().info(e); } } }