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请求,调用MyServletdoGet(),生成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 输出流返回给前端。

相关推荐
古城小栈1 小时前
Jenkins 自动构建 搞起来
java·servlet·jenkins
一叶飘零_sweeeet1 小时前
Java 17 异步多线程视频上传实战
java·文件上传
百锦再1 小时前
.NET到Java的终极迁移指南:最快转型路线图
android·java·开发语言·python·rust·go·.net
stella·1 小时前
RabbitMQ是什么?如何使用
java·分布式·中间件·消息队列·rabbitmq·削峰填谷
在坚持一下我可没意见1 小时前
Spring Boot 实战(一):拦截器 + 统一数据返回 + 统一异常处理,一站式搞定接口通用逻辑
java·服务器·spring boot·后端·spring·java-ee·tomcat
廋到被风吹走1 小时前
【JDK版本】JDK1.8相比JDK1.7 语言特性之函数式编程
java·开发语言·python
fire-flyer1 小时前
Reactor Context 详解
java·开发语言
3***89191 小时前
TypeScript 与后端开发Node.js
java
老兵发新帖1 小时前
Spring Boot 的配置文件加载优先级和合并机制分析
java·spring boot·后端