自己写一个TomCat

概述


在 Java Web 开发中,Tomcat 是一个广为人知的开源 Servlet 容器,它能够处理客户端的请求并返回响应。本文将深入分析一系列自定义的 Java 代码,这些代码实现了一个简易的 Tomcat 服务器,包括请求处理、路由分发、静态资源响应等核心功能。


整体架构概述

 Tomcat 服务器主要由以下几个核心部分组成:

  1. 主启动类:负责启动服务器并监听客户端请求。
  2. 请求和响应处理类:用于解析客户端请求和生成服务器响应。
  3. Servlet 类:处理具体的业务逻辑。
  4. 路由配置类:管理请求路径和对应的 Servlet 映射关系。
  5. 工具类:提供文件操作、响应头设置等辅助功能。

详细代码

启动类MyTomcat

package com.qcby;

import com.qcby.config.TomcatRoute;
import com.qcby.request.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import com.qcby.servlet.HttpServlet;
import com.qcby.util.ResponseUtil;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;

public class MyTomcat {
    static HashMap<String, HttpServlet> routes = TomcatRoute.routes;

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

    public void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(4700);
        while (true) {
            Socket socket = serverSocket.accept();
            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]);

            OutputStream outputStream = socket.getOutputStream();
            HttpServletResponse response = new HttpServletResponse(outputStream);
            dispatch(request, response);
        }
    }

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

MyTomcat 类是整个服务器的入口点。start 方法通过 ServerSocket 监听 4700 端口,当有客户端连接时,获取输入流解析请求信息,同时创建 HttpServletRequest 和 HttpServletResponse 对象。dispatch 方法根据请求的 URL 从路由表中查找对应的 Servlet 并调用其 service 方法处理请求。


2.请求和响应处理类

package com.qcby.request;

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;
    }
}



package com.qcby.response;

import com.qcby.util.FileUtil;
import com.qcby.util.ResponseUtil;

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

public class HttpServletResponse {
    private OutputStream outputStream;

    public HttpServletResponse(OutputStream outputStream) {
        this.outputStream = outputStream;
    }

    public void write(String context) throws IOException {
        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());
        }
    }
}

HttpServletRequest 类用于封装客户端请求的信息,包括请求方法和请求 URL。

HttpServletResponse 类用于封装服务器的响应信息,提供了 write 方法用于返回动态资源,writeHtml 方法用于返回静态资源。如果静态文件存在,则使用 FileUtil 类将文件内容写入输出流。 


3.Servlet类

package com.qcby.servlet;

import com.qcby.request.HttpServletRequest;
import com.qcby.response.HttpServletResponse;

import java.io.IOException;

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);
        }
    }
}

 HttpServlet 是一个抽象类,实现了 servlet 接口。service 方法根据请求方法调用相应的 doGet 或 doPost 方法。具体的业务逻辑可以在子类中重写 doGet 和 doPost 方法来实现。


 

4.路由配置类

package com.qcby.config;

import com.qcby.servlet.HttpServlet;
import com.qcby.util.SearchClassUtil;
import com.qcby.zj.DjyServlet;

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

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);
                DjyServlet webServlet = (DjyServlet) clazz.getDeclaredAnnotation(DjyServlet.class);
                routes.put(webServlet.url(), (HttpServlet) clazz.getDeclaredConstructor().newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

TomcatRoute 类负责管理请求路径和对应的 Servlet 映射关系。在静态代码块中,使用 SearchClassUtil 类查找所有带有 DjyServlet 注解的类,并将注解中的 URL 与对应的 Servlet 实例添加到路由表中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值