生活随笔
收集整理的這篇文章主要介紹了
自己动手写Tomcat
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
今天看到有人寫了個簡單的tomcat,讓我想起多年以前自己也寫了個demo,興奮了好意振。貼出來分享下。有些簡陋... ??自定義服務(wù)器及瀏覽器.rar
轉(zhuǎn):
最近研究一方socket編程,由于想動手寫關(guān)于socket方面的東西。然而我們知道通過URL去訪問某網(wǎng)址,其實其底層用的就是socket,于是我就寫了一個很簡單的tomcat服務(wù)器,主要目地在于學(xué)習(xí),在此分享給大家。同時提供下載源工程。
?
我寫的工程用Maven管理的,但是我沒有引入其它的JAR包,為此我就不列出pom.xml文件了。
在此簡要地說明每個類的作用:
?
Server.java
該類的作用就是將服務(wù)提起來的,并且利用線程池。
view sourceprint? 01.
package?com.cloud.tomcat.server; 02.
? 03.
import?java.io.OutputStreamWriter; 04.
import?java.io.PrintWriter; 05.
import?java.net.ServerSocket; 06.
import?java.net.Socket; 07.
import?java.util.concurrent.ExecutorService; 08.
import?java.util.concurrent.Executors; 09.
? 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(newOutputStreamWriter(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
該類的作用是根據(jù)瀏覽器傳過來信息做出相應(yīng)的處理,同時實現(xiàn)Runnable接口。
view sourceprint? 01.
package?com.cloud.tomcat.server; 02.
? 03.
import?java.io.BufferedReader; 04.
import?java.io.IOException; 05.
import?java.io.InputStream; 06.
import?java.io.InputStreamReader; 07.
import?java.io.PrintWriter; 08.
import?java.net.Socket; 09.
? 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(newInputStreamReader(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文件,然后根據(jù)url的信息,拿到相應(yīng)的servlet。
view sourceprint? 01.
package?com.cloud.tomcat.server; 02.
? 03.
import?java.util.HashMap; 04.
import?java.util.Map; 05.
? 06.
import?com.cloud.tomcat.model.Servlet; 07.
import?com.cloud.tomcat.model.ServletMapping; 08.
import?com.cloud.tomcat.servlet.HttpServlet; 09.
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
為了實現(xiàn)起來簡單方便,我自己定義了一個HttpServlet。
view sourceprint? 1.
package?com.cloud.tomcat.servlet; 2.
? 3.
public?interface?HttpServlet { 4.
public?String doGet(); 5.
public?String doPost(); 6.
}
CloudServlet.java
HttpServlet的具體實現(xiàn)類。
view sourceprint? 01.
package?com.cloud.tomcat.servlet; 02.
? 03.
public?class?CloudServlet?implements?HttpServlet { 04.
? 05.
@Override 06.
public?String doGet() { 07.
return?this.doPost(); 08.
} 09.
? 10.
@Override 11.
public?String doPost() { 12.
return?"<h1>Chicago at Cloud!!!</h1>"; 13.
} 14.
? 15.
}
下面一一列出解析web.xml用到的類,由于我沒有引入第三JAR包,可能這部分有點麻煩。
Servlet.java
view sourceprint? 01.
package?com.cloud.tomcat.model; 02.
? 03.
public?class?Servlet { 04.
private?String name; 05.
private?String clazz; 06.
? 07.
public?String getName() { 08.
return?name; 09.
} 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
view sourceprint? 01.
package?com.cloud.tomcat.model; 02.
? 03.
public?class?ServletMapping { 04.
private?String name; 05.
private?String url; 06.
? 07.
public?String getName() { 08.
return?name; 09.
} 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
view sourceprint? 01.
package?com.cloud.tomcat.util; 02.
? 03.
import?java.io.InputStream; 04.
import?java.util.HashMap; 05.
import?java.util.Map; 06.
? 07.
import?javax.xml.parsers.DocumentBuilder; 08.
import?javax.xml.parsers.DocumentBuilderFactory; 09.
? 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
view sourceprint? 01.
<?xml?version="1.0"?encoding="UTF-8"?> 02.
<web-app?xmlns="http://java.sun.com/xml/ns/javaee" 03.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 04.
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 05.
version="2.5"> 06.
? 07.
<servlet> 08.
<servlet-name>cloud</servlet-name> 09.
<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>
運行結(jié)果:
將Server類運行起來,然后用瀏覽器輸入:
http://localhost:8080/index或http://localhost:8080
得到如下結(jié)果:
?
?
總結(jié)
以上是生活随笔為你收集整理的自己动手写Tomcat的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。