0%

Tomcat 深度解析:架构、组件与目录结构详解

Tomcat 是 Apache 基金会开发的开源 Servlet 容器,用于运行 Java Web 应用(如 Servlet、JSP),是 Java EE 生态中最常用的应用服务器之一。本文从核心功能、目录结构、组件架构三个维度,全面解析 Tomcat 的工作原理,帮助理解其设计思想与使用方式。

Tomcat 的核心功能

Tomcat 作为 Servlet 容器,核心任务是管理 Servlet 的生命周期并处理 HTTP 请求,具体包括:

  1. Servlet 生命周期管理
    • 首次请求某 Servlet 时,加载该 Servlet 类并调用init()方法(仅执行一次,用于初始化资源);
    • 每次请求时,创建ServletRequest(封装请求数据)和ServletResponse(封装响应数据);
    • 调用 Servlet 的service()方法处理请求,最终通过ServletResponse返回结果;
    • 服务器关闭时,调用destroy()方法释放资源。
  2. HTTP 请求处理
    通过连接器(Connector)接收客户端 HTTP 请求,转发给容器(Container)处理,最终将响应返回给客户端。

Tomcat 目录结构详解

Tomcat 的安装目录结构清晰,各目录分工明确,以下是核心目录的功能说明:

阅读全文 »

MyBatis ResultSetHandler:结果集映射的核心机制(从映射流程到延迟加载)

在 MyBatis 执行查询操作时,StatementHandler 负责执行 SQL 语句,而 ResultSetHandler 则承担着将数据库返回的 ResultSet(结果集)转换为 Java 对象 的关键职责,同时还处理存储过程的输出参数。这一过程涉及结果集解析、对象映射、嵌套关联处理以及延迟加载等复杂逻辑。从 “接口定义→核心实现→映射流程→延迟加载” 四个维度,全面解析 ResultSetHandler 的工作原理。

ResultSetHandler 接口:结果处理的规范定义

ResultSetHandler 是 MyBatis 结果集处理的顶层接口,定义了三类核心操作,覆盖查询结果映射和存储过程输出参数处理:

1
2
3
4
5
6
7
8
9
10
public interface ResultSetHandler {
// 1. 处理 SELECT 语句的结果集,映射为 Java 对象列表
<E> List<E> handleResultSets(Statement stmt) throws SQLException;

// 2. 处理结果集,返回游标对象(用于流式查询)
<E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;

// 3. 处理存储过程的输出参数
void handleOutputParameters(CallableStatement cs) throws SQLException;
}
  • handleResultSets:最核心的方法,将 Statement 执行后得到的 ResultSet 映射为 List 集合(可能包含一个或多个结果集);
  • handleCursorResultSets:用于大数据量查询的流式处理,返回 Cursor 对象支持逐条读取结果,避免内存溢出;
  • handleOutputParameters:针对存储过程,处理 OUTINOUT 类型的输出参数。

DefaultResultSetHandler:结果映射的唯一实现

MyBatis 仅提供 DefaultResultSetHandler 作为 ResultSetHandler 的实现类,它完整实现了结果集到 Java 对象的映射逻辑,包括简单对象映射嵌套关联映射延迟加载等核心功能。

1. 核心流程:handleResultSets 方法

handleResultSets 是结果集处理的入口方法,负责协调多个结果集的映射(如存储过程可能返回多个结果集),并将最终结果整理为 List。

源码解析
阅读全文 »

MyBatis TypeHandler 深度解析:Java 与 JDBC 类型转换的桥梁(从原理到自定义实践)

在 MyBatis 与数据库交互过程中,Java 类型与 JDBC 类型无法直接兼容(如 Java 的 Date 与 JDBC 的 Timestamp、Java 枚举与 JDBC 的 VARCHAR)。TypeHandler(类型处理器)正是解决这一问题的核心组件,负责参数绑定时的 Java→JDBC 类型转换结果映射时的 JDBC→Java 类型转换,是 MyBatis 数据交互的 “翻译官”。从 “接口定义→核心实现→注册管理→自定义实践” 四个维度,彻底拆解 TypeHandler 的工作机制。

TypeHandler 核心定位与接口规范

TypeHandler 是 MyBatis 中类型转换的标准接口,定义了 “参数绑定” 和 “结果获取” 两类核心操作,覆盖所有数据交互场景。

TypeHandler 接口定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface TypeHandler<T> {
// ------------------------------ 1. 参数绑定:Java类型 → JDBC类型 ------------------------------
// 为 PreparedStatement 绑定参数时调用,将 Java 对象转为 JDBC 支持的类型
// 参数:ps=PreparedStatement 对象;i=参数索引(从1开始);parameter=Java 参数值;jdbcType=目标 JDBC 类型
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

// ------------------------------ 2. 结果获取:JDBC类型 → Java类型 ------------------------------
// 从 ResultSet 按列名获取值,转为 Java 类型
T getResult(ResultSet rs, String columnName) throws SQLException;

// 从 ResultSet 按列索引获取值,转为 Java 类型
T getResult(ResultSet rs, int columnIndex) throws SQLException;

// 从 CallableStatement(存储过程)按列索引获取值,转为 Java 类型
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
接口设计思路:
  • 泛型 <T>:指定该 TypeHandler 处理的 Java 类型(如 DateTypeHandler 的泛型是 Date);
  • 两类操作:
    • setParameter:参数绑定时的 “正向转换”(Java→JDBC),由 ParameterHandler 调用;
    • getResult:结果映射时的 “反向转换”(JDBC→Java),由 ResultSetHandler 调用。

BaseTypeHandler:简化自定义实现的抽象基类

MyBatis 提供 BaseTypeHandler<T> 抽象类,它实现了 TypeHandler<T> 接口,并抽离了 null 值的统一处理逻辑,让自定义 TypeHandler 只需关注 “非 null 类型转换”,大幅降低开发成本。

核心源码解析
阅读全文 »

MyBatis Mapper 接口与 SQL 绑定机制全解析:从动态代理到 SQL 执行

MyBatis 的核心特性之一是 “接口无实现类却能执行 SQL”—— 开发者只需定义 Mapper 接口(如 UserMapper),并在 XML / 注解中编写对应 SQL,调用接口方法即可触发 SQL 执行。这一 “魔法” 的本质是 JDK 动态代理 + 注册中心 + 方法与 SQL 绑定 的协同机制。从 “注册→代理→绑定→执行” 四个阶段,彻底拆解 Mapper 接口与 SQL 的绑定原理。

核心问题:为什么接口能执行 SQL?

Mapper 接口本身没有实现类,MyBatis 通过以下机制实现 “接口调用→SQL 执行” 的闭环:

  1. 注册中心(MapperRegistry):初始化时扫描 Mapper 接口,将 “接口” 与 “代理工厂(MapperProxyFactory)” 绑定并注册;
  2. 动态代理(MapperProxy):调用接口方法时,通过代理工厂生成接口的动态代理对象,拦截方法调用;
  3. 方法与 SQL 绑定(MapperMethod):代理对象将接口方法解析为 “SQL 标识(namespace+methodName)” 和 “参数信息”,找到对应的 SQL;
  4. 委托执行(SqlSession):通过 SqlSession 调用底层执行器(Executor),最终执行 SQL 并返回结果。

阶段 1:初始化注册 ——MapperRegistry 管理绑定关系

MapperRegistry 是 MyBatis 的 Mapper 接口注册中心,负责在 MyBatis 初始化时,将 Mapper 接口与对应的 “代理工厂(MapperProxyFactory)” 关联并存储,为后续生成代理对象做准备。

1. 核心属性:存储接口与代理工厂的映射

阅读全文 »

MyBatis ParameterHandler:参数绑定的核心桥梁(从源码到实践)

ParameterHandler 是 MyBatis 中连接 Java 参数与 JDBC 预编译 SQL 的关键组件,负责将 Java 中的参数值正确绑定到 SQL 语句的占位符(?)上。它通过协调 TypeHandler 完成 Java 类型到 JDBC 类型的转换,是 SQL 预编译后执行前的最后一步关键操作。本文结合源码,深入解析 ParameterHandler 的工作机制、参数绑定流程及核心设计。

ParameterHandler 接口:参数处理的规范定义

ParameterHandler 接口仅定义了两个核心方法,清晰界定了参数处理的职责边界:

1
2
3
4
5
6
7
public interface ParameterHandler {
// 1. 获取原始参数对象(如 JavaBean、Map、基本类型等)
Object getParameterObject();

// 2. 核心方法:将参数绑定到 PreparedStatement 的占位符上
void setParameters(PreparedStatement ps) throws SQLException;
}
  • getParameterObject():提供对原始参数的访问,方便其他组件(如插件)获取参数信息;
  • setParameters(PreparedStatement):负责将 Java 参数值通过 JDBC API(如 ps.setInt(1, value))绑定到 SQL 占位符,是参数处理的核心逻辑。

DefaultParameterHandler:唯一实现类的核心逻辑

MyBatis 仅提供了一个 ParameterHandler 实现类 ——DefaultParameterHandler,它完整实现了从 Java 参数到 JDBC 占位符的绑定流程。其核心依赖包括:

阅读全文 »