手写简单的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会得到:

相关推荐
const_qiu4 小时前
第四章 05:4.5 Multi-Agent —— 五个专职智能体协作
java·人工智能
A小码哥4 小时前
大模型成本怎么降,5 个动作先做前两个
java·前端·spring
鬼手点金4 小时前
构建有效 Agent 的核心原则
java·人工智能·git·学习·自动化
神魔皆以血嗜4 小时前
Java 实现简单状态机(订单状态流转)
java·后端
随性而行3605 小时前
企业微信 API 如何实现业务消息自动通知?接口应用场景解析
java·人工智能·后端·微信·机器人·企业微信
姜九笙5615 小时前
python学习---归来仍是新人
java·python·学习
HEJOO95 小时前
Java 并发运行中的安全问题详解
java·开发语言
2601_962106645 小时前
【无标题】
java·idea
汉吉龙测控技术5 小时前
激光对中仪作用介绍(AS 激光对中仪)
java
Wang's Blog5 小时前
Java 项目实战: 交友项目 - 完善用户信息章节复盘:套路清单与自检清单
java·dubbo·交友