自动动手写Tomcat

来源:互联网 发布:mac os版本是什么意思 编辑:程序博客网 时间:2024/05/02 02:00

最近研究一方socket编程,由于想动手写关于socket方面的东西。然而我们知道通过URL去访问某网址,其实其底层用的就是socket,于是我就写了一个很简单的tomcat服务器,主要目地在于学习,在此分享给大家。同时提供下载源工程。

 

我写的工程用Maven管理的,但是我没有引入其它的JAR包,为此我就不列出pom.xml文件了。

在此简要地说明每个类的作用:

 

Server.java

该类的作用就是将服务提起来的,并且利用线程池。

 

Java代码  收藏代码
  1. package com.cloud.tomcat.server;  
  2.   
  3. import java.io.OutputStreamWriter;  
  4. import java.io.PrintWriter;  
  5. import java.net.ServerSocket;  
  6. import java.net.Socket;  
  7. import java.util.concurrent.ExecutorService;  
  8. import java.util.concurrent.Executors;  
  9.   
  10. public class Server {  
  11.     private static ServerSocket serverSocket;  
  12.     private static ExecutorService executorService;  
  13.     private final static int POOL_SIZE = 15;  
  14.   
  15.     public static void main(String[] args) throws Exception {  
  16.         serverSocket = new ServerSocket(8080);  
  17.         Socket socket = null;  
  18.         executorService = Executors.newFixedThreadPool(POOL_SIZE);  
  19.   
  20.         while (true) {  
  21.             socket = serverSocket.accept();  
  22.             PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));  
  23.             writer.println("HTTP/1.1 200 OK");  
  24.             writer.println("Content-Type: text/html;charset=UTF-8");  
  25.             writer.println();  
  26.   
  27.             executorService.execute(new Handler(socket, writer));  
  28.         }  
  29.     }  
  30. }  

 

 

Handler.java

该类的作用是根据浏览器传过来信息做出相应的处理,同时实现Runnable接口。

 

Java代码  收藏代码
  1. package com.cloud.tomcat.server;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.io.PrintWriter;  
  8. import java.net.Socket;  
  9.   
  10. import com.cloud.tomcat.servlet.HttpServlet;  
  11.   
  12. public class Handler implements Runnable {  
  13.     private Socket socket;  
  14.     private PrintWriter writer;  
  15.   
  16.     public Handler(Socket socket, PrintWriter writer) {  
  17.         this.socket = socket;  
  18.         this.writer = writer;  
  19.     }  
  20.   
  21.     @Override  
  22.     public void run() {  
  23.         try {  
  24.             InputStream inputStream = socket.getInputStream();  
  25.             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));  
  26.             String path = "";  
  27.             String method = "";  
  28.   
  29.             while (true) {  
  30.                 String msg = reader.readLine();  
  31.                 if (null == msg || "".equals(msg.trim())) {  
  32.                     break;  
  33.                 }  
  34.   
  35.                 String[] msgs = msg.split(" ");  
  36.                 if (3 == msgs.length && "HTTP/1.1".equalsIgnoreCase(msgs[2])) {  
  37.                     method = msgs[0];  
  38.                     path = msgs[1];  
  39.                     break;  
  40.                 }  
  41.             }  
  42.   
  43.             if (path.endsWith("ico")) {  
  44.                 return;  
  45.             }  
  46.   
  47.             HttpServlet httpServlet = ServletContainer.getHttpServlet(path);  
  48.             String html = "";  
  49.             if ("GET".equals(method)) {  
  50.                 html = httpServlet.doGet();  
  51.             } else if ("POST".equals(method)) {  
  52.                 html = httpServlet.doGet();  
  53.             }  
  54.             writer.write(html);  
  55.             writer.flush();  
  56.         } catch (IOException e) {  
  57.             e.printStackTrace();  
  58.         } finally {  
  59.             try {  
  60.                 writer.close();  
  61.                 socket.close();  
  62.             } catch (Exception e) {  
  63.                 e.printStackTrace();  
  64.             }  
  65.         }  
  66.           
  67.     }  
  68.   
  69. }  

 

 

ServletContainer.java

该类首先会解析web.xml文件,然后根据url的信息,拿到相应的servlet。

 

Java代码  收藏代码
  1. package com.cloud.tomcat.server;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5.   
  6. import com.cloud.tomcat.model.Servlet;  
  7. import com.cloud.tomcat.model.ServletMapping;  
  8. import com.cloud.tomcat.servlet.HttpServlet;  
  9. import com.cloud.tomcat.util.XMLUtil;  
  10.   
  11. public class ServletContainer {  
  12.     private static Map<String, Object> servletMaps = new HashMap<String, Object>();  
  13.     private static Map<String, Object> servletMappingMaps = new HashMap<String, Object>();  
  14.     private static Map<String, HttpServlet> servletContainer = new HashMap<String, HttpServlet>();  
  15.   
  16.     static {  
  17.         try {  
  18.             Map<Integer, Map<String, Object>> maps = XMLUtil.parseWebXML();  
  19.             if (null != maps && 2 == maps.size()) {  
  20.                 servletMaps = maps.get(0);  
  21.                 servletMappingMaps = maps.get(1);  
  22.             }  
  23.         } catch (Exception e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.     }  
  27.   
  28.     public static HttpServlet getHttpServlet(String path) {  
  29.   
  30.         if (null == path || "".equals(path.trim()) || "/".equals(path)) {  
  31.             path = "/index";  
  32.         }  
  33.       
  34.         if (servletContainer.containsKey(path)) {  
  35.             return servletContainer.get(path);  
  36.         }  
  37.   
  38.         if (!servletMappingMaps.containsKey(path)) {  
  39.             return null;  
  40.         }  
  41.         ServletMapping servletMapping = (ServletMapping) servletMappingMaps.get(path);  
  42.         String name = servletMapping.getName();  
  43.   
  44.         if (!servletMaps.containsKey(name)) {  
  45.             return null;  
  46.         }  
  47.         Servlet servlet = (Servlet) servletMaps.get(name);  
  48.         String clazz = servlet.getClazz();  
  49.   
  50.         if (null == clazz || "".equals(clazz.trim())) {  
  51.             return null;  
  52.         }  
  53.   
  54.         HttpServlet httpServlet = null;  
  55.         try {  
  56.             httpServlet = (HttpServlet) Class.forName(clazz).newInstance();  
  57.             servletContainer.put(path, httpServlet);  
  58.         } catch (Exception e) {  
  59.             e.printStackTrace();  
  60.         }  
  61.         return httpServlet;  
  62.     }  
  63. }  

 

 

HttpServlet.java

为了实现起来简单方便,我自己定义了一个HttpServlet。

 

Java代码  收藏代码
  1. package com.cloud.tomcat.servlet;  
  2.   
  3. public interface HttpServlet {  
  4.     public String doGet();  
  5.     public String doPost();  
  6. }  

 

 

CloudServlet.java

HttpServlet的具体实现类。

 

Java代码  收藏代码
  1. package com.cloud.tomcat.servlet;  
  2.   
  3. public class CloudServlet implements HttpServlet {  
  4.   
  5.     @Override  
  6.     public String doGet() {  
  7.         return this.doPost();  
  8.     }  
  9.   
  10.     @Override  
  11.     public String doPost() {  
  12.         return "<h1>Chicago at Cloud!!!</h1>";  
  13.     }  
  14.   
  15. }  

 

 

下面一一列出解析web.xml用到的类,由于我没有引入第三JAR包,可能这部分有点麻烦。

Servlet.java

 

Java代码  收藏代码
  1. package com.cloud.tomcat.model;  
  2.   
  3. public class Servlet {  
  4.     private String name;  
  5.     private String clazz;  
  6.   
  7.     public String getName() {  
  8.         return name;  
  9.     }  
  10.   
  11.     public void setName(String name) {  
  12.         this.name = name;  
  13.     }  
  14.   
  15.     public String getClazz() {  
  16.         return clazz;  
  17.     }  
  18.   
  19.     public void setClazz(String clazz) {  
  20.         this.clazz = clazz;  
  21.     }  
  22. }  

 

ServletMapping.java

 

Java代码  收藏代码
  1. package com.cloud.tomcat.model;  
  2.   
  3. public class ServletMapping {  
  4.     private String name;  
  5.     private String url;  
  6.   
  7.     public String getName() {  
  8.         return name;  
  9.     }  
  10.   
  11.     public void setName(String name) {  
  12.         this.name = name;  
  13.     }  
  14.   
  15.     public String getUrl() {  
  16.         return url;  
  17.     }  
  18.   
  19.     public void setUrl(String url) {  
  20.         this.url = url;  
  21.     }  
  22. }  

 

XMLUtil.java

Java代码  收藏代码
  1. package com.cloud.tomcat.util;  
  2.   
  3. import java.io.InputStream;  
  4. import java.util.HashMap;  
  5. import java.util.Map;  
  6.   
  7. import javax.xml.parsers.DocumentBuilder;  
  8. import javax.xml.parsers.DocumentBuilderFactory;  
  9.   
  10. import org.w3c.dom.Document;  
  11. import org.w3c.dom.Element;  
  12. import org.w3c.dom.Node;  
  13. import org.w3c.dom.NodeList;  
  14.   
  15. import com.cloud.tomcat.model.Servlet;  
  16. import com.cloud.tomcat.model.ServletMapping;  
  17.   
  18. public class XMLUtil {  
  19.   
  20.     public static Map<Integer, Map<String, Object>> parseWebXML() throws Exception {  
  21.         Map<Integer, Map<String, Object>> result = new HashMap<Integer, Map<String,Object>>();  
  22.         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();  
  23.         DocumentBuilder db = dbf.newDocumentBuilder();  
  24.   
  25.         InputStream in = XMLUtil.class.getClassLoader().getResourceAsStream("web.xml");  
  26.         Document document = db.parse(in);  
  27.         Element root = document.getDocumentElement();  
  28.         NodeList xmlNodes = root.getChildNodes();  
  29.         for (int i = 0; i < xmlNodes.getLength(); i++) {  
  30.             Node config = xmlNodes.item(i);  
  31.             if (null != config && config.getNodeType() == Node.ELEMENT_NODE) {  
  32.                 String nodeName1 = config.getNodeName();  
  33.                 if ("servlet".equals(nodeName1)) {  
  34.                     Map<String, Object> servletMaps = null;  
  35.                     if (result.containsKey(0)) {  
  36.                         servletMaps = result.get(0);  
  37.                     } else {  
  38.                         servletMaps = new HashMap<String, Object>();  
  39.                     }  
  40.   
  41.                     NodeList childNodes = config.getChildNodes();  
  42.                     Servlet servlet = new Servlet();  
  43.                     for (int j = 0; j < childNodes.getLength(); j++) {  
  44.                         Node node = childNodes.item(j);  
  45.                         if (null != node && node.getNodeType() == Node.ELEMENT_NODE) {  
  46.                             String nodeName2 = node.getNodeName();  
  47.                             String textContent = node.getTextContent();  
  48.                             if ("servlet-name".equals(nodeName2)) {  
  49.                                 servlet.setName(textContent);  
  50.                             } else if ("servlet-class".equals(nodeName2)) {  
  51.                                 servlet.setClazz(textContent);  
  52.                             }  
  53.                         }  
  54.                     }  
  55.                     servletMaps.put(servlet.getName(), servlet);  
  56.   
  57.                     result.put(0, servletMaps);  
  58.                 } else if ("servlet-mapping".equals(nodeName1)) {  
  59.                     Map<String, Object> servletMappingMaps = null;  
  60.                     if (result.containsKey(1)) {  
  61.                         servletMappingMaps = result.get(1);  
  62.                     } else {  
  63.                         servletMappingMaps = new HashMap<String, Object>();  
  64.                     }  
  65.   
  66.                     NodeList childNodes = config.getChildNodes();  
  67.                     ServletMapping servletMapping = new ServletMapping();  
  68.                     for (int j = 0; j < childNodes.getLength(); j++) {  
  69.                         Node node = childNodes.item(j);  
  70.                         if (null != node && node.getNodeType() == Node.ELEMENT_NODE) {  
  71.                             String nodeName2 = node.getNodeName();  
  72.                             String textContent = node.getTextContent();  
  73.                             if ("servlet-name".equals(nodeName2)) {  
  74.                                 servletMapping.setName(textContent);  
  75.                             } else if ("url-pattern".equals(nodeName2)) {  
  76.                                 servletMapping.setUrl(textContent);  
  77.                             }  
  78.                         }  
  79.                     }  
  80.                     servletMappingMaps.put(servletMapping.getUrl(), servletMapping);  
  81.   
  82.                     result.put(1, servletMappingMaps);  
  83.                 }  
  84.             }  
  85.         }  
  86.         return result;  
  87.     }  
  88.   
  89.     public static void main(String[] args) throws Exception {  
  90.         System.out.println(parseWebXML());  
  91.     }  
  92. }  

 

web.xml

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns="http://java.sun.com/xml/ns/javaee"  
  3.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  5.    version="2.5">   
  6.   
  7.     <servlet>  
  8.         <servlet-name>cloud</servlet-name>  
  9.         <servlet-class>com.cloud.tomcat.servlet.CloudServlet</servlet-class>  
  10.     </servlet>  
  11.   
  12.     <servlet-mapping>  
  13.         <servlet-name>cloud</servlet-name>  
  14.         <url-pattern>/index</url-pattern>  
  15.     </servlet-mapping>  
  16. </web-app>  

 

运行结果:

将Server类运行起来,然后用浏览器输入:

http://localhost:8080/index或http://localhost:8080

得到如下结果:


 



 

 

原创粉丝点击