news 2026/6/23 11:31:00

手写Tomcat代码整理(自用)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手写Tomcat代码整理(自用)

一、配置Maven环境

新建项目需要加载,等右下方的进度条满就行。

在D盘根目录上解压apache-maven-3.6.2-zip

同时在D盘根目录新建文件夹Maven

二、手写Tomcat

1、ServletConfigMapping

package com.qcby.config; import com.qcby.lib.HttpServlet; import com.qcby.lib.WebServlet; import com.qcby.utils.SearchClassUtil; import java.util.HashMap; import java.util.List; import java.util.Map; /** * servlet容器配置类 */ public class ServletConfigMapping { /** * <String, HttpServlet> * String:路径作为key值 * HttpServlet:servlet对象作为value值 (多态:向上转型----->父类引用指向子类对象) * */ public static Map<String, HttpServlet> classMapping = new HashMap<>(); //servlet容器 //特点:在main方法执行之前执行,以修饰main方法 static { List<String> paths = SearchClassUtil.searchClass( "com.qcby.webapps.myweb"); for (String path: paths) { // 获取类的注解信息,并将path作为key值,将对象作为value值 存放如classMapping当中 try{ Class clazz =Class.forName(path); //获取类对象 //获取类的注解信息 WebServlet webServlet =(WebServlet) clazz.getDeclaredAnnotation(WebServlet.class); //System.out.println(webServlet.value()); HttpServlet servlet = (HttpServlet) clazz.getDeclaredConstructor().newInstance(); classMapping.put(webServlet.value(),servlet); }catch (Exception e){ e.printStackTrace(); } } } public static void main(String[] args) { } }

2、GenericServlet

package com.qcby.lib; import java.io.IOException; public abstract class GenericServlet implements Servlet{ @Override public void init() { } public abstract void service(ServletRequest request, ServletResponse response) throws IOException; @Override public void destroy() { } }

3、HttpServlet

package com.qcby.lib; import java.io.IOException; public abstract class HttpServlet extends GenericServlet{ public abstract void doGet(ServletRequest request, ServletResponse response) throws IOException; public abstract void doPost(ServletRequest request, ServletResponse response); @Override public void service(ServletRequest request, ServletResponse response) throws IOException { if(request.getMethod().equals("GET")){ doGet(request,response); }else if(request.getMethod().equals("POST")){ doPost(request,response); } } }

4、HttpServletRequest

package com.qcby.lib; public class HttpServletRequest implements ServletRequest{ private String method; private String path; @Override public String getMethod() { return method; } @Override public String getPath() { return path; } @Override public String setMethod(String method) { return this.method = method ; } @Override public String setPath(String path) { return this.path = path; } }

5、HttpServletResponse

package com.qcby.lib; import com.qcby.utils.FileUtil; import java.io.File; import java.io.IOException; import java.io.OutputStream; public class HttpServletResponse implements ServletResponse{ //获取输出流 private OutputStream outputStream; public OutputStream getOutputStream() { return outputStream; } public void setOutputStream(OutputStream outputStream) { this.outputStream = outputStream; } /** * 动态资源数据写回 * @param context * @throws IOException */ public void append(String context) throws IOException { outputStream.write(context.getBytes()); } /** * 返回静态资源 * @param path 静态资源文件的相对路径 * @throws Exception */ public void returnStatic(String path) throws Exception { String resource = FileUtil.getResourcePath(path); // 获取静态资源真实路径 File file = new File(resource); // 静态文件 if(file.exists()){ //静态文件存在 FileUtil.writeFile(file,outputStream); }else { System.out.println("404静态资源文本不存在......"); } } }

6、Servlet

package com.qcby.lib; import java.io.IOException; public interface Servlet { public void init(); public void service(ServletRequest request,ServletResponse response) throws IOException; public void destroy(); }

7、ServletRequest

package com.qcby.lib; public interface ServletRequest { String getMethod(); String getPath(); String setMethod(String method); String setPath(String path); }

8、ServletResponse

package com.qcby.lib; import java.io.IOException; public interface ServletResponse { public void append(String context)throws IOException; }

9、WebServlet

package com.qcby.lib; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) //生命周期 @Target(ElementType.TYPE) //作用范围 public @interface WebServlet { String value(); }

10、MyFirstServlet

package com.qcby.webapps.myweb; import com.qcby.lib.HttpServlet; import com.qcby.lib.ServletRequest; import com.qcby.lib.ServletResponse; import com.qcby.lib.WebServlet; import com.qcby.utils.ResponseUtil; import java.io.IOException; @WebServlet("/first") public class MyFirstServlet extends HttpServlet { @Override public void doGet(ServletRequest request, ServletResponse response) throws IOException { System.out.println("MyFirstServlet doGet 这里的地址"); response.append(ResponseUtil.getResponseHeader200("<h1>这是第一个Servlet</h1>")); } @Override public void doPost(ServletRequest request,ServletResponse response){ } }

11、MySecondServlet

package com.qcby.webapps.myweb; import com.qcby.lib.HttpServlet; import com.qcby.lib.ServletRequest; import com.qcby.lib.ServletResponse; import com.qcby.lib.WebServlet; import com.qcby.utils.ResponseUtil; import java.io.IOException; /** * 1.继承HttpServlet * 2.重写doGet()和doPost()方法 省略 * 3.@WebServlet("/MySecondServlet") 配置访问路径 */ @WebServlet("/second") public class MySecondServlet extends HttpServlet { @Override public void doGet(ServletRequest request, ServletResponse response) throws IOException { System.out.println("MySecondServlet doGet 这里的地址"); response.append(ResponseUtil.getResponseHeader200( "<h1>SecondServlet</h1>")); } @Override public void doPost(ServletRequest request, ServletResponse response) { } }

12、MyTomcat

package com.qcby; import com.qcby.config.ServletConfigMapping; import com.qcby.lib.*; import com.qcby.utils.ResponseUtil; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class MyTomcat { private static HttpServletRequest httpServletRequest = new HttpServletRequest(); private static HttpServletResponse httpServletResponse = new HttpServletResponse(); private static final Integer PORT = 7788; //监听的端口号 public static void start() throws Exception { ServerSocket serverSocket = new ServerSocket(PORT); while (true) { Socket socket = serverSocket.accept(); //阻塞监听 InputStream stream = socket.getInputStream();//打开输出流 httpServletResponse.setOutputStream(socket.getOutputStream()); //获取输入流 handler(stream); } } /** * 处理客户端的请求数据,并进行保持 * * @param stream * @throws IOException */ public static void handler(InputStream stream) throws Exception { int count = 0; while (count == 0) { count = stream.available(); } byte[] bytes = new byte[count]; int read = stream.read(bytes); String request = new String(bytes, 0, read); if (request.equals("")) { System.out.println("请求为null"); } else { String firstLine = request.split("\n")[0]; String method = firstLine.split("\\s")[0]; // 请求方式(原代码存在变量名大小写错误:firstline → firstLine) String path = firstLine.split("\\s")[1]; // 请求路径(同变量名错误) System.out.println("请求方式:" + method + " " + "请求路径:" + path); httpServletRequest.setMethod(method); httpServletRequest.setPath(path); if (path.equals("")) { System.out.println("请求路径为空"); httpServletResponse.append(ResponseUtil.responseHeader404); } else if (ServletConfigMapping.classMapping.get(path) != null) { // 虽然是用HttpServlet对象进行接受,但是实际上我们返回的是MyFirstServlet/MySecondServlet/...... // HttpServlet 实际上是向上转型的产物 HttpServlet servlet = ServletConfigMapping.classMapping.get(path); servlet.service(httpServletRequest, httpServletResponse); } else { httpServletResponse.returnStatic(path); } } } //tomcat启动器 public static void main(String[] args) throws Exception { start(); } }

13、index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>hello world</h1> <h1>中文测试</h1> </body> </html>
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/23 10:43:12

雷科电力-REKE920S涂层测厚仪

一、概述&#xff1a;雷科电力-REKE920S涂层测厚仪是磁性、涡流一体的便携式涂层测厚仪&#xff0c;它能快速、无损伤、精密地进行涂、镀层厚度的测量。既可用于实验室&#xff0c;也可用于工程现场。本仪器能广泛地应用在制造业、金属加工业、化工业、商检等检测领域&#xff…

作者头像 李华
网站建设 2026/6/22 22:40:50

相机选型学习

根据一些学习资料总结了一个相机选型的大概步骤&#xff1a; 1.确定像素精度&#xff0c;就是一个像素对应多少距离。根据工艺上的最小误差确定&#xff0c;比如客户要求最小为误差是10个μ&#xff0c;那考虑工件的过度像素&#xff0c;要把单个像素表示的距离控制在10/3 3.3…

作者头像 李华
网站建设 2026/6/22 21:37:41

华为-AI智算网络学习-4 运维与监控实例

AI智算网络的场景下&#xff0c;运维设备量大、排查故障困难、摸排耗时长。1、运算、存储设备硬件故障2、网络设备故障3、fabriclnsight 监控平台页面4、案例举例-15、案例举例-26、案例举例-37、案例举例-4

作者头像 李华
网站建设 2026/6/23 9:42:51

ABAP Console Reloaded:ADT 控制台与 CL_DEMO_OUTPUT 的合体进化

在 ADT 里写 ABAP 的人,大概率都用过控制台:在实现了 IF_OO_ADT_CLASSRUN 的类里,把数据对象丢给 out->write( ... ),就能在一个文本视图里看到输出,拿它做快速验证、临时调试、跑通流程,特别省心。(SAP ABAP Central) 也有不少同学更偏爱 CL_DEMO_OUTPUT:它实现了 …

作者头像 李华