https://mp.weixin.qq.com/s?__biz=MzA5MzcxNjY4Ng==&mid=2648107477&idx=1&sn=237afdcd8dc67f3a36aac8a38fcaada9&chksm=887be074bf0c69627659d3f076420ba7d477bc08405437eafe4d99ed22e6d2f9a53c80a73d87&mpshare=1&scene=1&srcid=0606qoAMsGtii5eGzil3h35x&key=abc5240e014eede13ee3b36db10a8651176fd1ff480250a3b2660676db6e3a4f4c0857207a64f65dbafc7c5276b2d8e8375d9a65c25572ed6df33fa45995f85c0fc5588801f2def497593ae43d6347d5&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=mxEo2xKCtH9iR2PLbxrAcJSXJ7pfbLGSU5PqNtNoXLtIgAf3or95FesHIZkUX27e
tomcat简介
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
2手动实现
项目结构如下图所示
接下来我们就开始一步步实现,有servlet开发经验的对于Request和Response一定不陌生,所以就先实现自己的Request和Response。首先实现Response如下所示。
package com.duomeng.tomcat;import java.io.IOException;import java.io.InputStream;/** * */public class MyRequest { private String url; private String method; public MyRequest(InputStream inputStream) throws IOException { StringBuilder httpRequest = new StringBuilder(); byte[] httpRequestByte = new byte[1014]; int length = 0; if ((length = inputStream.read(httpRequestByte)) > 0) { httpRequest.append(new String(httpRequestByte,0,length)); } System.out.println("httpRequest = [" + httpRequest + "]"); /** GET /student HTTP/1.1 Host: localhost:8080 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng, */ String httpHead = httpRequest.toString().split("\n")[0]; url = httpHead.split("\\s")[1]; method = httpHead.split("\\s")[0]; System.out.println("MyRequests = [" + this + "]"); } 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; }}
接着来实现自己的Reponse,如下图所示。
package com.duomeng.tomcat;import java.io.IOException;import java.io.OutputStream;public class MyResponse { private OutputStream outputStream; public MyResponse(OutputStream outputStream) { this.outputStream = outputStream; } public void write(String content) throws IOException { /** * HTTP/1.1 200 OK Content-type:text/html */ StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("HTTP/1.1 200 OK\n") .append("Content-type:text/html\n") .append("\r\n") .append("<html><head><title>Hello World</title></head><body>") .append(content) .append("</body><html>"); outputStream.write(stringBuffer .toString().getBytes()); outputStream.close(); }}
有了自己的请求信息和响应信息,那接下来就要写servlet了。通常写自己的Servlet的时候要继承一个Servlet的父类HttpServlet,所以首先要写一个Servlet的父类,代码如下。
package com.duomeng.tomcat;public abstract class MyServlet { protected abstract void doGet(MyRequest request,MyResponse response); protected abstract void doPost(MyRequest request,MyResponse response); public void service(MyRequest request,MyResponse response) throws NoSuchMethodException { if (request.getMethod().equalsIgnoreCase("POST")) { doPost(request,response); }else if(request.getMethod().equalsIgnoreCase("GET")){ doGet(request,response); }else { throw new NoSuchMethodException("not support"); } }}
那么接下来就要写自己业务相关的Servlet,这里写一个和学生相关的Servlet,叫StudentServlet,还有一个和老师相关的Servlet,叫TeacherServlet。具体的代码分别如下。
package com.duomeng.tomcat;import java.io.IOException;public class StudentServlet extends MyServlet{ @Override protected void doGet(MyRequest request, MyResponse response) { try { response.write("I am a student."); } catch (IOException e) { e.printStackTrace(); } } @Override protected void doPost(MyRequest request, MyResponse response) { try { response.write("I am a student."); } catch (IOException e) { e.printStackTrace(); } }}
和老师相关的Servlet如下:
package com.duomeng.tomcat;import java.io.IOException;public class TeacherServlet extends MyServlet{ @Override protected void doGet(MyRequest request, MyResponse response) { try { response.write("I am a treacher."); } catch (IOException e) { e.printStackTrace(); } } @Override protected void doPost(MyRequest request, MyResponse response) { try { response.write("I am a treacher."); } catch (IOException e) { e.printStackTrace(); } }}
因为浏览器在请求的时候还会请求浏览器上面显示的favicon.ico,所以要编写一个相关的servlet来处理请求,代码如下。
package com.duomeng.tomcat;import java.io.IOException;public class FaviconServlet extends MyServlet{ @Override protected void doGet(MyRequest request, MyResponse response) { try { response.write("Favicon"); } catch (IOException e) { e.printStackTrace(); } } @Override protected void doPost(MyRequest request, MyResponse response) { try { response.write("Favicon"); } catch (IOException e) { e.printStackTrace(); } }}
以上就是写的跟具体实际当中业务相关的代码,还记得在Servlet的时候要在项目web.xml中配置请求地址和具体的servlet的映射关系,所以此处要手动来实现一个映射的关系。具体代码如下。
package com.duomeng.tomcat;public class ServletMapping { private String servletName; private String url; private String clazz; public ServletMapping(String servletName, String url, String clazz) { this.servletName = servletName; this.url = url; this.clazz = clazz; } public String getServletName() { return servletName; } public void setServletName(String servletName) { this.servletName = servletName; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getClazz() { return clazz; } public void setClazz(String clazz) { this.clazz = clazz; }}
以上是每个具体的Servlet的信息,接下来要写一个存储有映射关系的类,代码如下。
package com.duomeng.tomcat;import java.util.ArrayList;import java.util.List;public class ServletMappingConfig { public static List<ServletMapping> servletMappings = new ArrayList<ServletMapping>(16); static { servletMappings.add(new ServletMapping("student","/student","com.duomeng.tomcat.StudentServlet")); servletMappings.add(new ServletMapping("teacher","/teacher","com.duomeng.tomcat.TeacherServlet")); servletMappings.add(new ServletMapping("favicon","/favicon.ico","com.duomeng.tomcat.FaviconServlet")); }}
接下来就是真正的主角登场了,那就是对于请求做分发处理的相关逻辑了,具体代码如下所示。
package com.duomeng.tomcat;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Map;public class MyTomcat { private int port = 8080; private Map<String,String> urlServletMap = new HashMap<String, String>(16); public MyTomcat(int port) { this.port = port; } public void start(){ //初始化请求映射关系 initServletMapping(); ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); System.out.println("My tomcat begin start"); while (true){ Socket socket = serverSocket.accept(); InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); MyRequest request = new MyRequest(inputStream); MyResponse response = new MyResponse(outputStream); //分发请求 dispatch(request,response); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } private void initServletMapping(){ for (ServletMapping servletMapping:ServletMappingConfig.servletMappings) { urlServletMap.put(servletMapping.getUrl(),servletMapping.getClazz()); } } private void dispatch(MyRequest request,MyResponse response){ String clazz = urlServletMap.get(request.getUrl()); try { Class servletClass = Class.forName(clazz); MyServlet myServlet = (MyServlet)servletClass.newInstance(); myServlet.service(request,response); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public static void main(String[] args) { new MyTomcat(8080).start(); }}
如果没有问题的话,启动main函数之后,在浏览器发起具体的请求会看到如下显示内容。
原文地址:https://www.cnblogs.com/silyvin/p/9164072.html