手写tomcat+servlet

  • 2019 年 10 月 8 日
  • 筆記

写程序一定要有思路,思路很重要!

一、我们分两步第一步先实现手写tomcat,第二部写servlet

所用技术:

1、soket通信 IO流

2、http请求与相应

3、解析xml

4、java反射技术

导入所需要的jar:

<dependencies>    	 	<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->  		<dependency>  		    <groupId>dom4j</groupId>  		    <artifactId>dom4j</artifactId>  		    <version>1.6.1</version>  		</dependency>    </dependencies>

项目目录结构:

现在开始我们的第一步,手写tomcat

新建 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 rn"              + "Content-Type: text/htmlrn"              + "rn";        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>

运行效果: