[JavaWeb]模拟一个简易的Tomcat服务(Servlet注解)

发布于:2025-09-10 ⋅ 阅读:(18) ⋅ 点赞:(0)

大家天天开心!

文章目录

  • 前言
  • 一、对我的这个Tomcat简介:
  • 、完整详细代码:
    • 下面是代码的详细解释:
  • 总结


前言

      我们在最开始学JavaWeb的时候,是需要配置web.xml文件,来找到Servlet相应的服务,然后还有以注解的方式,这里要清楚注解的方式是@interface.然后我想带着大家了解一下Tomcat到底替我们干了多少事,我们就知道Tomcat有多牛逼了。


提示:以下是本篇文章正文内容,下面案例可供参考

一、对我的这个Tomcat简介:

         该Tomcat(或其他Servlet容器)是通过反射获取@WebServlet注解信息并实例化Servlet的。

         对于这个写的Tomcat服务所完成的:

  1.  

    ​​反射运用正确​​:你使用 Class.forName()加载类,并用 getAnnotation(WebServlet.class)获取注解对象,这是标准做法。

  2.  

    ​​成功提取注解信息​​:你通过 annotation.urlPatterns()拿到了配置的URL模式,这正是Servlet容器建立映射关系的关键。

  3.  

    ​​实例化Servlet​​:使用 aClass.newInstance()(注:较新JDK版本推荐使用 getDeclaredConstructor().newInstance())创建了Servlet实例,模拟了容器初始化Servlet的过程。

二、完整详细代码:

     

package com.hspedu.servlet.annotation;

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsServer;

import javax.servlet.annotation.WebServlet;
import java.util.HashMap;

/**
 * @author 韩顺平
 * @version 1.0
 * 模拟一把Tomcat是如果通过 @WebServlet(urlPatterns = {"/ok1", "/ok2"})
 * 来装载一个Servlet的
 *
 * 说明:这代码主要的目的,就是打破 注解的神秘感
 */
public class TestAnnotationServlet {

    private static final HashMap<String, Object> hm = new HashMap<>();

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        //1. 首先要得到扫描的包 路径 io, 进而得到类的全路径
        String classAllPath = "com.hspedu.servlet.annotation.OkServlet";
        //2. 得到 OkServlet的Class对象
        Class<?> aClass = Class.forName(classAllPath);
        //3. 通过class对象,得到Annotation
        WebServlet annotation = aClass.getAnnotation(WebServlet.class);
        System.out.println(annotation);
        String[] strings = annotation.urlPatterns();
        for (String url : strings) {
            System.out.println("url= " + url);
        }

        //如果匹配url,如果是第一次,tomcat就会创建一个OkServlet实例,放入到hashmap
        Object instance = aClass.newInstance();
        System.out.println("instance= " + instance);//OkServlet

        //简单的模拟,没有深入.
        hm.put("OkServlet", instance);

        System.out.println(hm);

    }
}

你的代码

完整的 Tomcat

手动指定 OkServlet的全类名进行加载。

​自动扫描​​整个 classpath 或指定包下的所有类,寻找带有 @WebServlet等注解的类。

使用 HashMap<String, Object>存储实例。

使用复杂的​​上下文和生命周期管理​​。HashMap的 value 通常是 Servlet 实例,key 则是其配置名或 URL 模式。

没有 HTTP 服务器功能,无法接收和处理实际请求。

包含一个 ​​HTTP 服务器​​(基于 Socket),监听端口,解析 HTTP 协议,并将请求路由到对应的 Servlet。

实例化后直接放入 Map,没有初始化过程。

在 Servlet 实例化后,会​​回调其 init(ServletConfig)方法​​,完成初始化。

没有请求处理和分发逻辑。

接收到 HTTP 请求后,根据 URL ​​查找映射到哪个 Servlet​​,然后调用该 Servlet 的 ​service方法​​,进而分发到 doGet或 doPost等方法。

下面是代码的详细解释:
String classAllPath = "com.hspedu.servlet.annotation.OkServlet";
Class<?> aClass = Class.forName(classAllPath);
    • 这行代码手动指定了要加载的 Servlet 类的全限定名。​​在实际的 Tomcat 中,这个过程是自动的​​。Tomcat 会扫描整个 Web 应用(如 WAR 包的 WEB-INF/classes和 WEB-INF/lib中的 JAR 包),找到所有带有 @WebServlet注解的类。

    • Class.forName()方法利用 ​​Java 的反射机制​​,根据类名动态地加载这个类到 JVM 中,并返回它的 Class对象。这是所有后续操作的基础。

WebServlet annotation = aClass.getAnnotation(WebServlet.class);
System.out.println(annotation);
  • 通过 Class对象的 getAnnotation()方法,并传入注解的类型(WebServlet.class),可以​​获取到该类上的特定注解对象​​。

  •  

    如果这个类上确实标注了 @WebServlet,那么这里返回的就是一个包含了所有注解属性值的 WebServlet注解实例。如果不存在,则返回 null

  •  

    打印 annotation可以看到注解的具体信息,如 @javax.servlet.annotation.WebServlet(urlPatterns={"/ok1", "/ok2"}, ...)

String[] strings = annotation.urlPatterns();
for (String url : strings) {
    System.out.println("url= " + url);
}
  • 这是整个模拟的​​关键目的​​。从注解对象中,你可以调用其方法(如 urlPatterns())来获取配置的属性值。

  •  

    ​Tomcat 在启动时就是这样做的​​:它读取所有 Servlet 类上的 @WebServlet注解,​​建立了一个 URL 路径到 Servlet 类的映射表​​。

Object instance = aClass.newInstance(); // 注意:较新JDK推荐getDeclaredConstructor().newInstance()
System.out.println("instance= " + instance);

  

  • 通过 Class对象的 newInstance()方法(​​注:较新版本的 JDK 已弃用此方法,推荐使用 getDeclaredConstructor().newInstance()​),可以​​创建该 Servlet 类的一个新实例​​。

  •  

    ​Tomcat 正是在这个时候创建 Servlet 实例的​​(通常在容器启动或首次请求时,取决于配置)。

  •  

    打印出的 instance应该是类似 com.hspedu.servlet.annotation.OkServlet@xxx的形式,证明实例化成功了。

hm.put("OkServlet", instance);
System.out.println(hm);
  • 这里用一个 HashMap来模拟 Tomcat 内部用于​​管理 Servlet 实例的容器​​。

  •  

    在真实的 Tomcat 中,维护了一个更为复杂但功能类似的结构,用来根据 URL 查找并获取对应的 Servlet 实例来处理请求。


总结

​最核心的“发现”和“装载”机制​​:

  1.  

    ​发现 (Discovery)​​:通过扫描或配置,找到所有需要管理的 Servlet 类。

  2.  

    ​解析 (Parsing)​​:读取类上的元信息(这里是 @WebServlet注解),特别是 URL 映射。

  3.  

    ​装载 (Loading & Instantiation)​​:使用​​反射​​机制动态地创建这些 Servlet 的实例。

  4.  

    ​管理 (Management)​​:将实例存储起来,建立 URL 到实例的映射关系,以备请求时调用。

​如果要让这个模拟更接近真实的 Tomcat,接下来可以考虑:​

  •  

    ​实现一个简单的 HTTP 服务器​​:使用 ServerSocket监听端口(如 8080)。

  •  

    ​解析 HTTP 请求​​:从 Socket 连接中读取数据,解析出请求的 ​​URL 路径​​。

  •  

    ​实现请求分发​​:根据解析出的路径,从你的 HashMap里找到对应的 Servlet 实例,然后​​通过反射调用其 service方法​​。


网站公告

今日签到

点亮在社区的每一天
去签到