使用socket编写一个简单版本Tomcat

    技术2022-07-10  112

    1.项目工程结构

    1.1 大致模拟官方Tomcat源码包结构

    1.2 web.xml文件用properties文件代替

    2.具体源码分析

    2.1 HttpServlet

    public abstract class HttpServlet {//所有Servlet的抽象 public abstract void doGet(Request request, Response response) throws Exception; public abstract void doPost(Request request, Response response) throws Exception; //service不为abstract,但doGet和doPost是的 public void service(Request request, Response response) throws Exception { String method = request.getMethod(); if ("GET".equals(method)) { //调用抽象方法,具体实现在子类 doGet(request, response); } else { doPost(request, response); } } }

    2.2 Request

    public class Request { //主要是这两个参数 private String url; private String method; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public Request(InputStream in) throws Exception { byte[] buff = new byte[1024]; if (in.read(buff) > 0) { String msg = new String(buff, 0, 1024); String[] arr = msg.split(" "); method = arr[0]; url = arr[1]; } } }

    2.3 Response

    public class Response { private OutputStream out; public Response(OutputStream out) { this.out = out; } public void out(String retmsg) throws Exception { //用的是HTTP协议,输出也要遵循HTTP协议 StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("HTTP/1.1 200 OK\n") .append("Content-Type: text/html;\n") .append("\r\n") .append(retmsg); retmsg = stringBuilder.toString(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out)); writer.write(retmsg); writer.flush(); writer.close(); } }

    2.4 FirstServlet

    public class FirstServlet extends HttpServlet { public void doGet(Request request, Response response) throws Exception { doPost(request, response); } public void doPost(Request request, Response response) throws Exception { response.out("this is FirstServlet!"); } }

    2.5 SecondServlet

    public class SecondServlet extends HttpServlet { @Override public void doGet(Request request, Response response) throws Exception { } @Override public void doPost(Request request, Response response) throws Exception { } }

    2.6 webxml.properties

    #模拟web.xml FirstServlet.urlPattern=/firstServlet.action FirstServlet.servletClass=com.test.servlet.FirstServlet SecondServlet.urlPattern=/secondServlet.action SecondServlet.servletClass=com.test.servlet.SecondServlet

    2.7 Tomcat

    public class Tomcat { private static Properties webxml; //url servlet映射对应Map private static Map<String, Object> urlToServletMap = new HashMap<>(); public static void main(String[] args) { try { initConfig(); startTomcatServer(8080); } catch (Exception e) { e.printStackTrace(); } } private static void initConfig() throws Exception { loadWebxml(); initUrlToServletMap(); } private static void startTomcatServer(int port) throws Exception { ServerSocket serverSocket = new ServerSocket(port); while (true) { Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); Request request = new Request(in); Response response = new Response(out); prcessRequestData(request, response); in.close(); out.close(); socket.close(); } } private static void prcessRequestData(Request request, Response response) throws Exception { HttpServlet servlet = (HttpServlet) urlToServletMap.get(request.getUrl()); servlet.service(request, response); } private static void initUrlToServletMap() throws Exception { //遍历webxml Set<Object> set = webxml.keySet(); for (Object o : set) { String key = o.toString(); if (key.contains("urlPattern")) { String servletName = key.substring(0, key.indexOf(".")); String serletClass = webxml.getProperty(servletName + ".servletClass"); Class clazz = Class.forName(serletClass); //Servlet单实例,多线程 urlToServletMap.put(webxml.getProperty(key), clazz.newInstance()); } } } private static void loadWebxml() throws Exception { webxml = new Properties(); String path = Tomcat.class.getResource("/").getPath(); InputStream in = new FileInputStream(path + "webxml.properties"); webxml.load(in); in.close(); } }
    Processed: 0.016, SQL: 9