手写tomcat:基本功能实现(4)

逻辑架构

HTTP 请求与 Socket:

  • 左侧的 "HTTP 请求" 箭头指向 "socket",表示客户端发送的 HTTP 请求通过 socket 传输到服务器。Socket 负责接收请求,并提取出其中的 请求路径 (如 /first)和 请求方法(如 GET、POST),为后续处理做准备。

Servlet 容器的路由机制:

  • 图中粉色表格代表 Servlet 容器内的路由映射表,每一行记录了一个 URL 路径与对应 Servlet 对象的映射关系。例如,路径 /first 对应 firstServlet 对象,/second 对应 secondServlet 对象。容器根据 socket 提取的请求路径,从映射表中找到匹配的 Servlet 来处理请求。

Web 应用结构(webapps):

  • webapps 是存放 Web 应用的目录,图中 myweb 是其中一个应用,包含两类资源:
    • Servlet 资源:动态处理请求的 Servlet 程序。
    • 静态资源:如 HTML、CSS、图片等无需动态处理的文件。

核心类与注解支持:

  • 右侧蓝色区域包含 HttpServlet 类、HttpRequest 和 HttpResponse,它们是处理请求和响应的核心类。HttpServlet 是 Servlet 的基类,HttpRequest 用于封装请求信息,HttpResponse 用于构造响应数据。
  • 紫色区域表示对 @WebServlet 注解的支持。该注解用于配置 Servlet 对应的 URL 路径等信息,简化 Servlet 的注册过程,与图中路由映射表的功能相呼应。

TomcatRoute类

java 复制代码
package com.qcby.config;

import com.qcby.Util.SearchClassUtil;
import com.qcby.servlet.Httpservlet;
import com.qcby.zj.YbyServlet;

import java.util.HashMap;
import java.util.List;

import java.util.List;
import java.util.Map;

public class TomcatRoute {
    public static HashMap<String, Httpservlet> Route = new HashMap<>();


        static {
            List<String> classesPath = SearchClassUtil.searchClass();
            for (String path : classesPath) {
                try {
                    //加载类
                    Class clazz = Class.forName(path);
                    //获取注解
                    YbyServlet webServlet = (YbyServlet) clazz.getDeclaredAnnotation(YbyServlet.class);
//                对象
                    Object servlet = clazz.getDeclaredConstructor().newInstance();
                    Route.put(webServlet.url(), (Httpservlet) servlet);
//                Httpservlet servlet = (Httpservlet) clazz.newInstance();
//                servletMap.put(webServlet.url(),servlet);
                    System.out.println(Route);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }


}

主要功能是自动扫描带有特定注解的 Servlet 类并注册到路由表中。使用静态 HashMap 存储路径到 Servlet 的映射关系。加载类:Class.forName("com.qcby.servlet.HomeServlet")。

一、核心功能与设计思想

java 复制代码
public class TomcatRoute {
    public static HashMap<String, Httpservlet> Route = new HashMap<>();
    static { ... }
}

功能 :自动扫描并注册所有带有YbyServlet注解的 Servlet 类

设计思想:

  • 基于 "约定优于配置" 原则,通过注解简化 Servlet 注册
  • 使用静态代码块确保在类加载时完成初始化
  • 采用单例模式管理 Servlet 实例(每个 Servlet 只有一个实例)

二、核心组件详解

1. 路由注册表

java 复制代码
public static HashMap<String, Httpservlet> Route = new HashMap<>();
  • 数据结构:静态 HashMap 存储路径到 Servlet 的映射
  • 键 :URL 路径(如/user),来自YbyServlet注解的url()属性
  • 值 :实现了Httpservlet接口的 Servlet 实例

2. 类扫描机制

java 复制代码
List<String> classesPath = SearchClassUtil.searchClass();
  • SearchClassUtil功能 :
    • 扫描指定包下的所有类
    • 返回类的全限定名列表(如["com.qcby.servlet.UserServlet", "com.qcby.servlet.OrderServlet"])
  • 实现方式 :
    • 使用类加载器获取资源路径
    • 递归遍历所有.class文件
    • 将文件路径转换为类的全限定名

HttpServletResponse类

java 复制代码
package com.qcby.Response;

import com.qcby.Request.HttpServletRequest;

import java.io.IOException;
import java.io.OutputStream;

public class HttpServletResponse {
    private OutputStream outputStream;
    public HttpServletResponse(OutputStream outputStream){
        this.outputStream = outputStream;
    }
    public  void writeServlet(String context) throws IOException {
        outputStream.write(context.getBytes());
    }
}

这段代码实现了 HTTP 响应的基础功能,负责将服务器处理结果返回给客户端

Tomcat

java 复制代码
package com.qcby;
//tomcat主启动类
import com.qcby.config.TomcatRoute;
import com.qcby.servlet.Httpservlet;
import com.qcby.Request.HttpServletRequest;
import com.qcby.Response.HttpServletResponse;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

public class Mytomcat {


    static HashMap<String,Httpservlet> routes= TomcatRoute.Route;

    public  static void dispatch(HttpServletRequest request,HttpServletResponse response) throws IOException {
        Httpservlet servlet=routes.get(request.getPath());
        if(servlet!=null){
            servlet.service(request,response);
        }
    }

    public static void main(String[] args) {
        try {

            System.out.append("服务器启动......");
//				1.定义ServerSocket对象进行服务器的端口注册
            ServerSocket serverSocket = new ServerSocket(8080);
            while (true) {
//				2.监听客户端的socket链接程序
                Socket socket = serverSocket.accept();//阻塞监听
//				3.从socket对象当中获得一个字节流对象
                InputStream iStream = socket.getInputStream();
                 HttpServletRequest request=new HttpServletRequest();
                BufferedReader reader=new BufferedReader(new InputStreamReader(iStream));
                String str=reader.readLine();
                request.setMethod(str.split("\\s")[0]);
                request.setPath(str.split("\\s")[1]);
                System.out.println(request.getMethod() + " " + request.getPath());
                OutputStream outputStream=socket.getOutputStream();
                HttpServletResponse response=new HttpServletResponse(outputStream);
                dispatch(request,response);
            }
            } catch(Exception e){
                e.printStackTrace();
            }
        }


}

相关推荐
猿究院_夏燊4 小时前
Spring Bean 生命周期
java·后端·spring
Wang's Blog4 小时前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
信誓旦旦的程序猿5 小时前
【Python量化实战宝典 #08】可转债与债券接口手册:转股价·溢价率·纯债价值(Python 可跑)
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
砚底藏山河5 小时前
python量化:行情数据回溯
java·开发语言·python·金融·maven
Jlzn88885 小时前
华东电芯分选通道数怎么配才不堵线
java·人工智能·架构·自动化·制造
香吧香5 小时前
GRPC连接机制---长连接分析
java·网络与传输协议
我是人✓6 小时前
SpringBoot项目的五种创建方式
java·spring boot·后端
Wang's Blog6 小时前
Java 项目实战: 交友项目 - 阿里云 OSS 入门案例:从创建 Bucket 到上传拿到可访问 URL
java·阿里云·交友
裕晟资质规划7 小时前
三类涉密资质延续时限差异分析:军工60日与集成印制3个月的边界
java·服务器·前端·网络·安全
念念清晰7 小时前
000-OpenJDK17 源码构建:MacOS环境(M芯片)
java·后端