手写Tomcat代码整理(自用)
2026/5/24 8:11:14 网站建设 项目流程

一、配置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>

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询