servlet的体系原理+tomcat原理

1.servlet的执行流程

1.1 Servlet接口定义者servlet生命周期

java 复制代码
init()//初始化方法,目的是创建出servlet对象
getServletConfig()//获取servlet配置信息
service(ServletRequest var1,ServletResponse var2)//进行服务
getServletInfo()//获取servlet运行信息
destroy()//销毁servlet对象

1.1.1 init() 方法

init() 方法是 Servlet 生命周期的初始化阶段,当 Servlet 容器(如 Tomcat)第一次加载 Servlet 时会调用此方法。该方法通常用于执行一次性初始化工作:

  • 创建数据库连接池
  • 加载配置文件
  • 初始化缓存数据
  • 建立网络连接

1.1.2 getServletConfig() 方法

getServletConfig() 方法用于获取 Servlet 的配置信息:

  • 返回 ServletConfig 对象
  • 包含 Servlet 初始化参数
  • 可以访问 Servlet 上下文
  • 通常在 init() 方法执行后调用应用场景:

1.1.3 service() 方法

service() 方法是 Servlet 的核心处理方法,负责处理客户端请求:

  • 参数:ServletRequest 请求对象和 ServletResponse 响应对象
  • 根据请求类型(GET/POST)调用相应的处理方法
  • 线程安全考虑:通常不定义实例变

1.1.4 getServletInfo() 方法

getServletInfo() 提供关于 Servlet 的元信息:

  • 返回字符串形式的描述信息
  • 可包含版本号、作者信息等
  • 主要用于管理目的

1.1.5 destroy() 方法

destroy() 方法在 Servlet 生命周期结束时调用:

  • 释放占用的资源
  • 关闭数据库连接
  • 保存持久化数据
  • 执行清理操作

1.2 GenericServlet实现了处理servlet接口当中的除了service方法 以外的所有方法

GenericServlet类是Java Servlet API中的一个通用实现类,它作为Servlet接口的抽象实现,提供了以下功能实现:

  1. 生命周期方法实现:

    • 实现了init(ServletConfig config)方法,用于初始化Servlet配置
    • 实现了destroy()方法,用于Servlet销毁时的资源释放
    • 提供了无参数的init()方法作为扩展点
  2. 配置信息获取:

    • 实现了getServletConfig()方法,返回Servlet配置对象
    • 实现了getServletInfo()方法,返回Servlet描述信息
  3. 实用方法:

    • 实现了getInitParameter()方法,方便获取初始化参数
    • 实现了getInitParameterNames()方法,枚举所有初始化参数名
    • 提供了log()方法用于记录日志信息

唯一未实现的是service(ServletRequest req, ServletResponse res)方法,这保留了以下特性:

  • 强制子类必须实现具体的服务逻辑
  • 允许开发者根据请求类型(GET/POST等)实现不同的处理方式
  • 保持了对HTTP协议和其他协议实现的灵活性

1.3 HttpServlet 实现了Servlet接口当中的service方法,为了匹配Http的请求 方式,所以我们根据http的请求方式将service方法的内容用不同方法进行 实现

在实现原理上,HttpServlet 重写了 Servlet 接口的 service 方法,并将其拆分为多个针对不同 HTTP 请求方法的专用处理方法。具体实现如下:

  1. service 方法首先将 ServletRequest 和 ServletResponse 转换为 HttpServletRequest 和 HttpServletResponse
  2. 然后根据 HTTP 请求方法调用对应的处理方法:
    • doGet():处理 GET 请求
    • doPost():处理 POST 请求
    • doPut():处理 PUT 请求
    • doDelete():处理 DELETE 请求
    • doHead():处理 HEAD 请求
    • doOptions():处理 OPTIONS 请求
    • doTrace():处理 TRACE 请求

这种设计模式的优点包括:

  • 提高代码可读性和可维护性
  • 使开发者能够专注于特定请求方法的业务逻辑
  • 遵循了单一职责原则

示例代码结构:

java 复制代码
protected void service(HttpServletRequest req, HttpServletResponse resp) {
    String method = req.getMethod();
    if (method.equals("GET")) {
        doGet(req, resp);
    } else if (method.equals("POST")) {
        doPost(req, resp);
    }
    // 其他方法处理...
}

1.4 继承HttpServlet,并且重写doGet(),doPost()...等等方法,进行具体的实现

在Java Web开发中,Servlet是处理HTTP请求的核心组件。要创建一个自定义的Servlet,通常需要按照以下步骤实现:

  1. 继承HttpServlet类
  • 自定义Servlet类必须继承javax.servlet.http.HttpServlet
  • 例如:
java 复制代码
public class MyServlet extends HttpServlet {
    // Servlet实现代码
}
  1. 重写请求处理方法 HttpServlet提供了多个处理不同HTTP请求的方法,开发者可以根据需要重写:
  • doGet()方法:处理HTTP GET请求
java 复制代码
protected void doGet(HttpServletRequest request, 
                    HttpServletResponse response) 
                    throws ServletException, IOException {
    // 处理GET请求的业务逻辑
}
  • doPost()方法:处理HTTP POST请求
java 复制代码
protected void doPost(HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {
    // 处理POST请求的业务逻辑
}
  • 其他可重写的方法:
    • doPut():处理PUT请求
    • doDelete():处理DELETE请求
    • doHead():处理HEAD请求
    • doOptions():处理OPTIONS请求
    • doTrace():处理TRACE请求
  1. 实际应用场景示例
  • 用户登录处理(POST请求):
java 复制代码
protected void doPost(HttpServletRequest request,
                     HttpServletResponse response) {
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    // 验证用户凭证...
}
  • 数据查询接口(GET请求):
java 复制代码
protected void doGet(HttpServletRequest request,
                    HttpServletResponse response) {
    String id = request.getParameter("id");
    // 查询数据库...
    response.getWriter().write(jsonData);
}

2.tomcat的执行流程

tomcat执行流程图

  1. 请求发起 客户端通过http://ip:8080/xxx/xxx发送 HTTP 请求,服务器的网卡已注册 8080 等端口,等待请求连接。

  2. BIO 阻塞监听与连接 服务器通过BIO(阻塞式 IO) 监听 Socket 连接:

    • 当请求到达时,建立 Socket 通信 "管道";
    • 打开InputStream输入流,读取请求数据。
  3. 请求数据解析服务器解析输入流中的请求数据,提取关键信息:

    • 来源 IP、端口、编码;
    • Cookie、请求路径(如/my/)、请求类型(如get)等。
  4. 匹配 Servlet 处理器 Tomcat 根据请求路径(如/my/login),在 "Servlet 容器" 中匹配对应的 Servlet 对象:

    • 比如/my/login对应loginServlet对象,/my对应MyServlet对象。
  5. 执行 Servlet 方法 根据请求类型(get/post),调用对应 Servlet 的方法:

    • 若为get请求,调用MyServlet的doGet(),生成response响应信息;
    • 若为post请求,调用对应 Servlet 的doPost()。
  6. 响应返回 打开OutputStream输出流,通过 Socket 管道将response响应数据返回给客户端。

2.1 阻塞方式

2.1.1. BIO (Blocking I/O) 阻塞式I/O

BIO是最传统的I/O模型,其特点是:

  • 采用同步阻塞方式处理I/O操作
  • 每个连接需要一个独立的线程处理
  • 当没有数据可读时,线程会被阻塞,直到数据到达
  • 实现简单直观,但资源消耗大

典型应用场景:

  • 传统的Socket编程
  • 连接数较少的客户端/服务器应用
  • 需要简单实现的场景

示例代码结构:

java 复制代码
ServerSocket server = new ServerSocket(8080);
while(true) {
    Socket socket = server.accept(); // 阻塞等待连接
    new Thread(() -> {
        InputStream in = socket.getInputStream();
        // 处理数据...
    }).start();
}

2.1.2. NIO (Non-blocking I/O) 非阻塞I/O

NIO提供了非阻塞的I/O操作方式:

  • 基于事件驱动模型(Selector)
  • 单线程可以处理多个连接
  • 当没有数据可读时,线程不会被阻塞
  • 需要更复杂的编程模型

核心组件:

  • Channel:数据通道
  • Buffer:数据缓冲区
  • Selector:多路复用器

典型应用场景:

  • 高并发服务器应用
  • 需要处理大量连接的场景
  • 如Netty、Tomcat等框架底层实现

工作流程:

  1. 注册感兴趣的事件到Selector
  2. 调用select()方法检查就绪的通道
  3. 处理就绪的事件
  4. 重复上述过程

2.1.3. AIO (Asynchronous I/O) 异步I/O

AIO是真正的异步非阻塞I/O:

  • 操作系统完成I/O操作后通知应用程序
  • 不需要应用程序主动检查状态
  • 回调机制处理完成事件
  • 编程模型最复杂

实现方式:

  • 基于操作系统提供的异步I/O接口
  • 在Linux上主要通过epoll实现
  • Windows通过IOCP实现

典型应用场景:

  • 超高并发服务器
  • 需要极致性能的场景
  • 如高性能代理服务器、消息队列等

示例代码结构:

java 复制代码
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();
server.bind(new InetSocketAddress(8080));
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
    @Override
    public void completed(AsynchronousSocketChannel client, Void attachment) {
        // 处理连接完成
    }
    
    @Override
    public void failed(Throwable exc, Void attachment) {
        // 处理错误
    }
});

2.1.4. 三种模型对比

特性 BIO NIO AIO
阻塞方式 完全阻塞 非阻塞 完全非阻塞
线程模型 一连接一线程 单线程多连接 回调机制
复杂度 简单 中等 复杂
吞吐量 低 高 最高
适用场景 低并发 高并发 超高并发
资源消耗 高(线程多) 中等 低

3自定义tomcat如何实现原理

tomcat执行流程图

3.1 启动初始化阶段

  1. 扫描与收集 Servlet 信息

    • 扫描项目目录下所有 Servlet 文件,获取其全路径名;
    • 读取 Servlet 类中@WebServlet注解的配置(即 Servlet 的访问路径)。
  2. 构建 Servlet 容器(HashMap)

    • 容器的key是 Servlet 的访问路径;
    • 容器的value是对应的Servlet 对象(通过全路径名实例化生成)。

3.2 请求处理阶段

  1. 接收前端请求利用 Socket 打开输入流,获取请求信息;处理完成后通过输出流返回响应。

  2. 封装请求对象 创建HttpServletRequest对象,将请求信息(路径、参数等)全部封装到该对象中。

  3. 匹配 Servlet 或静态资源

    • 以请求路径为key,判断 Servlet 容器中是否存在对应对象:
      • ✅ 存在 :调用该 Servlet 对象的对应方法(如doGet/doPost);
      • ❌ 不存在 :判断请求是否为静态资源(HTML/CSS/ 图片等):
        • ✅ 是静态资源:返回对应静态文件;
        • ❌ 不是:返回 404 错误。
  4. 封装响应并返回 创建HttpServletResponse对象,封装处理结果,通过 Socket 输出流返回给前端。

相关推荐
小羊没烦恼!3 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里3 天前
java中的继承和多态的区别
java
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕3 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码3 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖3 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时3 天前
01-06-A-JVM排查实战详解
java·jvm
vipxieliang3 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
ba_pi3 天前
mysql 查询所有表名并授权
java
ProcessOn官方账号3 天前
java函数式编程--入门基础
java·编程·函数式编程