寫程序必定要有思路,思路很重要!html
1、咱們分兩步第一步先實現手寫tomcat,第二部寫servlet java
所用技術:web
一、soket通訊 IO流tomcat
二、http請求與相應 app
三、解析xmldom
四、java反射技術socket
導入所須要的jar:ide
<dependencies> <!-- https://mvnrepository.com/artifact/dom4j/dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> </dependencies>
項目目錄結構:post
如今開始咱們的第一步,手寫tomcatthis
新建 Request 類:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class Request { private String method; private String url; public Request(InputStream inputStream) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String[] methodAndUrl = bufferedReader.readLine().split(" "); this.method= methodAndUrl[0]; this.url=methodAndUrl[1]; System.out.println(method); System.out.println(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; } }
Response 類:
import java.io.IOException; import java.io.OutputStream; public class Response { public OutputStream outputStream; public String wirte; public static final String responseHeader="HTTP/1.1 200 \r\n" + "Content-Type: text/html\r\n" + "\r\n"; public Response(OutputStream outputStream) throws IOException { this.outputStream= outputStream; } public String getWirte() { return wirte; } public void setWirte(String wirte) { this.wirte = wirte; } }
SocketProcess 類:
import java.io.OutputStream; import java.net.Socket; import java.util.Map; public class SocketProcess extends Thread{ protected Socket socket; public SocketProcess(Socket socket){ this.socket = socket; } @Override public void run() { try { Request request = new Request(socket.getInputStream()); Response response = new Response(socket.getOutputStream()); // Map<String, Object> map = Mytomcat.servletMapping; // // System.out.println("map大小爲:"+map.size()); // for (Map.Entry<String, Object> entry : map.entrySet()) { // System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); // } //從映射中找 System.out.println(request.getUrl()); String servelName = (String) Mytomcat.servletMapping.get(request.getUrl()); System.out.println(servelName); if(servelName!=null && !servelName.isEmpty()) { //映射有的話找到對應的對象 Servelt servlet = (Servelt) Mytomcat.servlet.get(servelName); if(servlet!=null) { servlet.doGet(request, response); }else { System.out.println("找不到對應的servlet"); } }else { System.out.println("找不到對應的servletMapping"); } String res = Response.responseHeader+response.getWirte(); OutputStream outputStream = socket.getOutputStream(); outputStream.write(res.getBytes("GBK")); outputStream.flush(); outputStream.close(); }catch (Exception ex){ ex.printStackTrace(); }finally { if (socket != null) { try { socket.close(); } catch (Exception e) { e.printStackTrace(); } } } } }
Mytomcat
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.List; import org.dom4j.Element; public class Mytomcat { private static final int port = 8099; public static final HashMap<String, Object> servletMapping = new HashMap<String, Object>(); public static final HashMap<String, Object> servlet = new HashMap<String, Object>(); private void init() { InputStream io = null; String basePath; try { System.out.println("加載配置文件開始"); //讀取web.xml UtilsXml xml = new UtilsXml(UtilsXml.class.getResource("/")+"web.xml"); //講全部的類都存儲到容器中 而且創造對象 List<Element> list = xml.getNodes("servlet"); for (Element element : list) { servlet.put(element.element("servlet-name").getText(), Class.forName(element.element("servlet-class").getText()).newInstance()); } //映射關係建立 List<Element> list2 = xml.getNodes("servlet-mapping"); for (Element element : list2) { servletMapping.put(element.element("url-pattern").getText(), element.element("servlet-name").getText()); } System.out.println("加載配置文件結束"); } catch (Exception ex) { ex.printStackTrace(); } finally { if (io != null) { try { io.close(); } catch (Exception e) { e.printStackTrace(); } } } } private void start() { try { ServerSocket serverSocket = new ServerSocket(port); System.out.println("Tomcat 服務已啓動,地址:localhost ,端口:" + port); this.init(); //持續監聽 do { Socket socket = serverSocket.accept(); System.out.println(socket); //處理任務 Thread thread = new SocketProcess(socket); thread.start(); } while (true); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { Mytomcat tomcat = new Mytomcat(); tomcat.start(); } }
UtilsXml:
import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class UtilsXml { //定義解析器和文檔對象 public SAXReader saxReader; public Document document; public UtilsXml(String path){ //獲取解析器 saxReader = new SAXReader(); try { //獲取文檔對象 document = saxReader.read(path); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 根據節點名稱獲取內容 * @param name 節點名稱 * @return 節點內容 */ public String getElementText(String name){ //定位根節點 Element root = document.getRootElement(); List<Element> mapp = root.elements("servlet-mapping"); List<Element> servlet = root.elements("servlet"); String serveltName = ""; String classpath = ""; for (Element e : mapp) { // System.out.println(e.element("url-pattern").getText()); if(e.element("url-pattern").getText().equals(name)){ serveltName = e.element("servlet-name").getText(); break; } } for (Element e : servlet) { // System.out.println(e.element("servlet-name").getText()); if(e.element("servlet-name").getText().equals(serveltName)){ classpath = e.element("servlet-class").getText(); break; } } return classpath; // //根據名稱定位節點 // Element element = root.element(name); // //返回節點內容 // return element.getText(); } /** * 獲取節點下的全部節點 * @param root * @param name * @return */ public List<Element> getNodes(String name){ Element root = document.getRootElement(); return root.elements(name); } public static void main(String[] args) { UtilsXml xml = new UtilsXml(UtilsXml.class.getResource("/")+"web.xml"); //System.out.println(xml.getElementText("/myhtml.html")); List<Element> list = xml.getNodes("servlet"); for (Element element : list) { System.out.println(element.element("servlet-name").getText() ); System.out.println(element.element("servlet-class").getText() ); } }
Servelt 抽象類:
import com.siyuan.http.Request; import com.siyuan.http.Response; public abstract class Servelt { public void service(Request request, Response response) { //判斷是調用doget 仍是 dopost if ("get".equalsIgnoreCase(request.getMethod())) { this.doGet(request, response); } else { this.doPost(request, response); } } public abstract void doGet(Request request, Response response); public abstract void doPost(Request request, Response response); }
第一個servlet :
import com.siyuan.http.Request; import com.siyuan.http.Response; public class MyfisrtServlet extends Servelt { @Override public void doGet(Request request, Response response) { System.out.println("進入了個人第一個servlet"); response.setWirte("進入了第一個servlet"); } @Override public void doPost(Request request, Response response) { } }
第二個servlet:
import com.siyuan.http.Request; import com.siyuan.http.Response; public class ScoendServlet extends Servelt{ @Override public void doGet(Request request, Response response) { System.out.println("進入了個人第二個servlet"); response.setWirte("進入了第二個servlet"); } @Override public void doPost(Request request, Response response) { // TODO Auto-generated method stub } }
新建web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>myhtml.html</servlet-name> <servlet-class>com.siyuan.servlet.MyfisrtServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>myhtml.html</servlet-name> <url-pattern>/myhtml.html</url-pattern> </servlet-mapping> <servlet> <servlet-name>myhtml2.html</servlet-name> <servlet-class>com.siyuan.servlet.ScoendServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>myhtml2.html</servlet-name> <url-pattern>/myhtml2.html</url-pattern> </servlet-mapping> </web-app>
運行效果:
有問題討論能夠加羣一塊兒討論:
600922504