手写简单的tomcat

首先,Tomcat是一个软件,所有的项目都能在Tomcat上加载运行,Tomcat最核心的就是Servlet集合,本身就是HashMap。Tomcat需要支持Servlet,所以有servlet底层的资源:HttpServlet抽象类、HttpRequest和HttpResponse,否则我们无法新建Servlet。

http协议:客户端和用户端进行请求和响应的过程:

这样我们就可以在webapps写项目了,一个项目有两大资源:servlet资源和静态资源,servlet本身是java类,我们让它调用doGet和doPost方法,必须继承HttpServlet,同时也需要@WebServlet注解,那么在Tomcat中就必须要有@WebServlet注解的实现,如果没有@WebServlet,我们就无法拿到相应的注解。这样我们就能成功搭建起Servlet资源。

当Http请求打过来之后,先打到socket上,处理Http请求,其本身就是连接器,从请求上能获取到请求路径和请求方法。先获取到请求路径,判断servlet容器中是否含有相同路径,如果有,再获取请求方法,判断是doGet还是doPost。


简易版tomcat的核心原理

真正的Tomcat很复杂,但它的最核心功能可以简化为:

  1. 监听HTTP请求(Socket 绑定 8080 端口)
  2. 解析HTTP请求(读取请求头、请求体)
  3. 找到对应的Servlet处理请求 (反射调用 service() 方法)
  4. 返回HTTP响应(写回响应头和HTML)

手写tomcat

首先,定义Servlet接口

java 复制代码
public interface servlet {
    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException;
}

其次,定义request和response

java 复制代码
public class HttpServletRequest {
    private String method;
    private String 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;
    }
}


public class HttpServletResponse {

    //输出流
    private OutputStream outputStream;
    public HttpServletResponse(OutputStream outputStream){
        this.outputStream = outputStream;
    }

    /**
     * 返回动态资源
     * @param context
     */
    public void write(String context) throws IOException {
        //System.out.println(context);
        outputStream.write(context.getBytes());
    }

    /**
     * 返回静态资源
     */
    public void writeHtml(String path) throws Exception {
        String resourcesPath = FileUtil.getResoucePath(path);
        File file = new File(resourcesPath);
        if(file.exists()){
            //静态文件存在
            System.out.println("静态文件存在");
            FileUtil.writeFile(file,outputStream);
        }else {
            System.out.println("静态文件不存在");
            write(ResponseUtil.getResponseHeader404());
        }
    }

}

然后,实现一个Httpserver

java 复制代码
public class MyTomcat {

    static HashMap<String, HttpServlet> routes = TomcatRoute.routes; //tomcat路由\


    /**
     * 分发器
     */
    public  void dispatch(HttpServletRequest request ,HttpServletResponse response) throws IOException {
        System.out.println("URL: " + request.getUrl());
        HttpServlet servlet = routes.get(request.getUrl());  //
        if(servlet!=null){ //说明请求的就是我们的servlet
            System.out.println("找到匹配的Servlet: " + servlet.getClass().getName());
            servlet.service(request,response);
        }
    }

    /**
     * socket 启动
     * @throws IOException
     */
    public  void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);  //1.指定监听的端口号
        //2.对端口进行监听
        while (true){
            Socket socket = serverSocket.accept();//阻塞监听
            //3.打开输入流,解析客户端发来的内容
            InputStream inputStream = socket.getInputStream(); //输入流
            HttpServletRequest request = new HttpServletRequest();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));  //将字节流转换成字符流
            String str = reader.readLine();
            //分割
            request.setMethod(str.split("\\s")[0]);
            request.setUrl(str.split("\\s")[1]);

            //4.打开输出流
            OutputStream outputStream = socket.getOutputStream();
            HttpServletResponse response = new HttpServletResponse(outputStream);
            //分发器
            dispatch(request,response);
            socket.close();//socket在这里关闭
        }

    }

    //socket
    public static void main(String[] args) throws IOException {
        MyTomcat myTomcat = new MyTomcat();
        myTomcat.start();
    }
}

然后,自定义一个Servlet

java 复制代码
@CYServlet(url = "/myServlet")
public class MyFirstServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) {
        super.doPost(request, response);
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("Hello World!");
        System.out.println("Servlet实例: " + this);
        response.write(ResponseUtil.getResponseHeader200("hello world  hhhhh"));
    }
}

最后,启动服务并测试

java 复制代码
public static void main(String[] args) throws IOException {
        MyTomcat myTomcat = new MyTomcat();
        myTomcat.start();
    }

访问浏览器localhost:8080会得到:

相关推荐
AC赳赳老秦7 分钟前
农产品公开数据应用:OpenClaw 抓取农产品价格、产销公开数据,实现农产品行情动态监测
java·c语言·javascript·python·php·deepseek·openclaw
1001101_QIA13 分钟前
从 CPU 到 GPU:高速缓存、指令并行与 CUDA 执行原理入门
java·后端·spring
API快乐传递者18 分钟前
淘宝海外商品详情接口实战指南:从全球开放平台到跨境铺货的全链路方案
java·前端·数据库
邪修king21 分钟前
Re: Linux系统篇(十八):进程篇(七): 进程深度解析:从 fork 创建到退出的完整旅程(附写时拷贝原理 + 代码实战)
java·linux·运维
m0_5873830021 分钟前
24小时自助健身系统源码实战:从架构设计到部署落地
java·架构·系统架构·需求分析
卓怡学长28 分钟前
w156一周穿搭App的设计与实现
java·spring boot·spring·maven·intellij-idea
万年咸鱼35 分钟前
Java PrintStream 详解:从基础用法到实战技巧
java·开发语言·python
吴声子夜歌44 分钟前
ApacheCommons——commons-compress(解压缩工具)
java·apache
程序员清风44 分钟前
聊聊怎么缓解找工作的焦虑感?
java·后端·面试