如何用JAVA手写一个Tomcat

一、初步理解Tomcat

Tomcat是什么?

Tomcat 是一个开源的 轻量级 Java Web 应用服务器 ,核心功能是 运行 Servlet/JSP

Tomcat的核心功能?

**Servlet 容器:**负责加载、实例化、调用和销毁 Servlet。

**HTTP 服务器:**监听端口(默认 8080),解析 HTTP 请求,封装 HTTP 响应。

**JSP 支持:**将 JSP 文件编译为 Servlet 执行。

**线程池管理:**并发处理多个请求,提高性能。

二、Servlet的原理

Servlet框架

三、什么是socket

Socket(套接字)是计算机网络中用于进程间通信的核心技术,它允许不同主机或同一主机上的不同程序通过网络交换数据

Socket 是什么?

  • 定义 :Socket 是操作系统提供的抽象接口 ,本质上是通信的端点(Endpoint)。它封装了底层网络协议(如TCP/IP或UDP)的复杂性,提供了一组简单的API【API(Application Programming Interface,应用程序编程接口) 是软件系统之间交互的桥梁,定义了如何请求服务、传递数据以及返回结果的规则。】供应用程序使用。

  • 关键要素

    • IP地址:标识网络中的主机。

    • 端口号:标识主机上的具体服务(如HTTP默认80端口)。

    • 协议:如TCP(可靠连接)或UDP(无连接)。


端口是逻辑抽象概念,并非物理硬件。

端口是操作系统用来区分不同网络服务的数字标识(范围0~65535)。

网卡(硬件)负责收发数据,而端口由操作系统通过协议栈(如TCP/IP)管理。

Socket 是软件技术,不是物理硬件。


Socket的作用

  • 跨网络通信:使不同设备上的进程能够交换数据(例如浏览器与服务器交互)。

  • 支持多种协议:可通过TCP、UDP等协议传输数据。

  • 双向通信:建立连接后,双方可同时发送和接收数据。

  • 灵活性:可用于构建各种网络应用(如Web服务器、聊天软件、文件传输等)。

为什么 Tomcat 需要 Socket?

Tomcat 是一个基于Java的Web服务器Servlet容器,其核心功能依赖Socket实现:

  1. HTTP请求处理

    • 当用户访问网站时,浏览器通过Socket(TCP连接)向Tomcat发送HTTP请求。

    • Tomcat监听8080端口(默认),通过Socket接收请求数据,解析后交给Servlet处理。

    • 处理完成后,再通过Socket将HTTP响应返回给浏览器。

  2. 连接管理

    • Tomcat使用ServerSocket监听端口,等待客户端连接。

    • 每收到一个请求,Tomcat会创建一个新的Socket连接(或复用线程池中的连接)处理该请求,实现高并发。

  3. 协议支持

    • 除了HTTP/1.1(基于TCP Socket),Tomcat还支持HTTP/2、WebSocket等,这些协议最终都依赖Socket实现数据传输。

Tomcat 中的 Socket 工作流程

四、Tomcat框架及代码

网卡上需要注册端口号。

通过searchClassUtil类能获取类的全路径------>>根据全路径名生成类对象(反射)------>>获取类信息


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;
    }
}
java 复制代码
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());
        }
    }

}
java 复制代码
/**
 * tomcat路由
 */
public class TomcatRoute {
    public static HashMap<String, HttpServlet> routes = new HashMap<>();
    static {
        List<String> paths  = SearchClassUtil.searchClass();  //获取全路径名
        //根据全路径名称生成类对象
        for (String path: paths) {
            try {
                Class clazz = Class.forName(path);  //生成类对象
                WDServlet webServlet = (WDServlet) clazz.getDeclaredAnnotation(WDServlet.class);
                routes.put(webServlet.url(), (HttpServlet) clazz.getDeclaredConstructor().newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
java 复制代码
public interface servlet {
    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException;
}
java 复制代码
public abstract class HttpServlet implements servlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {}
    public void doPost(HttpServletRequest request,HttpServletResponse response){}

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
         if(request.getMethod().equals("GET")){
             doGet(request,response);
         }else if(request.getMethod().equals("POST")){
             doPost(request,response);
         }
    }
}
java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface WDServlet {
    String url() default "";
}
java 复制代码
@WDServlet(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");
        response.write(ResponseUtil.getResponseHeader200("hello world  hhhhh"));
    }
}
java 复制代码
@WDServlet(url = "/insert")
public class InsertServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)  throws IOException {
        System.out.println("我是insert......");
    }

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

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        super.doGet(request, response);
    }
}
java 复制代码
/**
 * tomcat主启动类
 */
public class MyTomcat {

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


    /**
     * 分发器
     */
    public  void dispatch(HttpServletRequest request ,HttpServletResponse response) throws IOException {
        HttpServlet servlet = routes.get(request.getUrl());  //
        if(servlet!=null){ //说明请求的就是我们的servlet
            servlet.service(request,response);
        }
    }

    /**
     * socket 启动
     * @throws IOException
     */
    public  void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(4700);  //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
    public static void main(String[] args) throws IOException {
        MyTomcat myTomcat = new MyTomcat();
        myTomcat.start();
    }
}

五、字节流、字符流

字节流:二进制;

字符流:各种字符

相关推荐
吾零鬼泣37 分钟前
day09-新热文章-实时计算
java·kafka·maven·mybatis
白日依山尽yy2 小时前
SpringBoot Day_03|数据校验|异常处理|日志级别|定时器
java·spring boot·spring
Java&Develop2 小时前
springboot 集成kerberos 用户认证 获取域账号
java·spring boot·后端
..过云雨3 小时前
01. Qt介绍及Qt开发环境搭建(2025.05最新官网下载方式)
开发语言·qt
努力也学不会java4 小时前
【RabbitMQ】 RabbitMQ高级特性(二)
java·分布式·后端·中间件·rabbitmq
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ4 小时前
crud方法命名示例
java·开发语言
多则惑少则明5 小时前
java 代码查重(三)常见的距离算法和相似度(相关系数)计算方法
java·算法·常见的距离算法和相似度
瓦力wow5 小时前
python 绘制3D平面图
开发语言·python·3d·matplotlib
Yu_Mao_Cat6 小时前
数独求解器3.0 增加latex格式读取
开发语言·python·算法
头发那是一根不剩了6 小时前
Spring Boot 注解 @ConditionalOnMissingBean是什么
java·spring boot·后端