一、纯 MyBatis 项目(无 Spring)
纯 MyBatis 有两种方式配置第三方连接池:
方式一:自定义 DataSourceFactory
原理 :MyBatis 内置只支持 POOLED/UNPOOLED/JNDI,没有 HikariCP/Druid 的内置支持。
通过自定义工厂类,让 MyBatis 能创建第三方连接池。
1. 添加 Maven 依赖
XML
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 连接池:三选一 -->
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
<!-- 或 Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>
2. 编写自定义工厂类
HikariCP 版本:
java
package com.example.factory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.datasource.DataSourceFactory;
import javax.sql.DataSource;
import java.util.Properties;
public class HikariDataSourceFactory implements DataSourceFactory {
private Properties props;
// MyBatis 自动调用,传入 xml 里的 <property>
@Override
public void setProperties(Properties props) {
this.props = props;
}
// MyBatis 调用此方法获取 DataSource
@Override
public DataSource getDataSource() {
// 用 Properties 创建 HikariCP 配置
HikariConfig config = new HikariConfig(props);
// 返回连接池实例
return new HikariDataSource(config);
}
}
Druid 版本:
java
package com.example.factory;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.ibatis.datasource.DataSourceFactory;
import javax.sql.DataSource;
import java.util.Properties;
public class DruidDataSourceFactory implements DataSourceFactory {
private Properties props;
@Override
public void setProperties(Properties props) {
this.props = props;
}
@Override
public DataSource getDataSource() {
try {
return DruidDataSourceFactory.createDataSource(props);
} catch (Exception e) {
throw new RuntimeException("创建 DruidDataSource 失败", e);
}
}
}
3. MyBatis 配置文件 mybatis-config.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<!-- type 填自定义工厂类的全限定名 -->
<dataSource type="com.example.factory.HikariDataSourceFactory">
<!-- 这些属性会被收集成 Properties 传给 setProperties() -->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<!-- HikariCP 参数 -->
<property name="maximumPoolSize" value="20"/>
<property name="minimumIdle" value="5"/>
<property name="connectionTimeout" value="30000"/>
<property name="idleTimeout" value="600000"/>
<property name="maxLifetime" value="1800000"/>
</dataSource>
</environment>
</environments>
<!-- Mapper 注册 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
4. Java 代码中使用
java
public class Main {
public static void main(String[] args) throws IOException {
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 构建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取 SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectById(1);
System.out.println(user);
}
}
}
【注意】:
方式一,不需要tomcat容器!
整个过程和 Tomcat 没有任何关系 ,就是一个普通的 Java 程序,用
main()方法就能直接跑。
方式二:JNDI 方式
原理 :连接池不由 MyBatis 创建,而是由 Tomcat 等 Web 容器提前配置好,MyBatis 通过 JNDI 名称去"查找"获取。
适用场景
-
多应用共享同一个连接池
-
数据库密码不写在应用代码里
-
企业级 war 包部署到外部 Tomcat
JNDI 方式的本质
┌─────────────────────────────────────┐
│ Tomcat 服务器 │
│ ┌─────────────────────────────┐ │
│ │ context.xml 里配置: │ │
│ │ - 数据库密码 │ │
│ │ - 连接池参数 │ │
│ │ - 连接池实现(Druid等) │ │
│ │ │ │
│ │ 对外暴露:name="jdbc/MyDB" │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
↑
JNDI 查找(按名字)
↓
┌─────────────────────────────────────┐
│ MyBatis 应用(war包) │
│ │
│ mybatis-config.xml 里只有: │
│ <dataSource type="JNDI"> │
│ <property name="data_source" │
│ value="java:comp/env/ │
│ jdbc/MyDB"/> │
│ </dataSource> │
│ │
│ ❌ 没有数据库密码 │
│ ❌ 没有连接池参数 │
│ ❌ 不知道用的是 Druid 还是 Hikari │
└─────────────────────────────────────┘
为什么企业级部署常用 JNDI?
场景:一个 Tomcat 跑 3 个应用
不用 JNDI(每个应用自己配)
应用A:配了 HikariCP,max=10,密码=123456
应用B:配了 Druid,max=10,密码=123456
应用C:配了 c3p0,max=10,密码=123456
→ 总共 30 个连接,密码改了要改 3 个地方
用 JNDI(统一配置)
Tomcat 配 1 个连接池:max=20,密码=123456
应用A、B、C 都引用 jdbc/MyDB
→ 总共 20 个连接,密码改了只改 1 个地方
一句话总结
JNDI 方式 = 把数据库配置"外包"给 Tomcat
MyBatis 只负责说"给我 jdbc/MyDB",具体怎么连、用什么连、密码是什么,全由 Tomcat 管。
这和 Spring 无关,是 纯 MyBatis 项目在企业部署时的标准做法。
1. 在 Tomcat 中配置连接池
找到 Tomcat/conf/context.xml,添加:
XML
<Context>
<!-- 给连接池起个名字:jdbc/MyDB -->
<Resource
name="jdbc/MyDB"
auth="Container"
type="javax.sql.DataSource"
<!-- 连接池实现:可换 Druid、DBCP、HikariCP 等 -->
factory="com.alibaba.druid.pool.DruidDataSourceFactory"
<!-- 数据库基本信息 -->
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb"
username="root"
password="123456"
<!-- 连接池参数 -->
maxActive="20"
maxIdle="10"
maxWait="10000"
/>
</Context>
不同连接池只需改 factory 和参数名:
| 连接池 | factory 值 | 参数特点 |
|---|---|---|
| Druid | com.alibaba.druid.pool.DruidDataSourceFactory |
maxActive, maxWait |
| DBCP | org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory |
maxTotal, maxWaitMillis |
| HikariCP | com.zaxxer.hikari.HikariJNDIFactory |
maximumPoolSize, connectionTimeout |
2. MyBatis 配置文件 mybatis-config.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<!-- type="JNDI",只需填名字 -->
<dataSource type="JNDI">
<!-- java:comp/env/ 是 JNDI 标准前缀 -->
<property name="data_source" value="java:comp/env/jdbc/MyDB"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
关键点:
-
type="JNDI":告诉 MyBatis,"我不自己创建连接池,去服务器上找" -
java:comp/env/:这是 JNDI 的标准前缀(就像打电话要加区号) -
jdbc/MyDB:就是 Tomcat 里配置的那个名字
3. 项目打包为 war 部署到 Tomcat
XML
<!-- pom.xml -->
<packaging>war</packaging>
<dependencies>
<!-- Servlet API(provided,Tomcat 自带) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
</dependencies>
完整流程图
┌─────────────────┐
│ Tomcat 服务器 │
│ ┌───────────┐ │
│ │ Druid连接池 │ ← 统一管理:20个连接
│ │ name= │ │
│ │ jdbc/MyDB │ │
│ └─────┬─────┘ │
└────────┼────────┘
│
JNDI 查找(按名字要)
│
┌────────┼────────┐
│ MyBatis 应用 │
│ "给我 jdbc/MyDB" │
│ (不知道真实密码) │
└─────────────────┘
注意:
不同的连接池,比如:c3p0、dbcp,就直接修改tomcat配置文件中的factory="com.alibaba.druid.pool.DruidDataSourceFactory",其他的不用变就行了
两种"纯 MyBatis"方式的对比
| 自定义 DataSourceFactory | JNDI 方式 | |
|---|---|---|
| 连接池在哪创建 | MyBatis 应用内部 | Tomcat 服务器里 |
| 谁管理连接池 | MyBatis 自己 | Tomcat 容器 |
| 密码存在哪 | mybatis-config.xml 里 |
Tomcat 的 context.xml 里 |
| 应用是否知道密码 | ✅ 知道 | ❌ 不知道(只知道名字) |
| 多个应用共享 | ❌ 每个应用独立 | ✅ 共享同一个 |
| 适用场景 | 单机部署 | 多应用共享、企业级部署 |
二、MyBatis + Spring 项目(推荐)
Spring 管理连接池,MyBatis 直接引用,最常用、最简洁。
Spring + MyBatis 配置第三方连接池非常灵活,核心思路是:Spring 创建连接池 Bean → MyBatis 引用这个 Bean。
1. 添加 Maven 依赖
XML
<dependencies>
<!-- Spring 核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.29</version>
</dependency>
<!-- Spring JDBC(包含事务管理) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.29</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- MyBatis-Spring 整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.1.1</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 连接池:三选一 -->
<!-- HikariCP(推荐) -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
<!-- 或 Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>
<!-- 或 DBCP(Tomcat 自带,无需额外依赖) -->
<!-- 使用 org.apache.commons:commons-dbcp2 -->
</dependencies>
2. Spring 配置文件 applicationContext.xml
方案 A:HikariCP
XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- ========== 1. 连接池:HikariCP ========== -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<!-- 基本配置 -->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<!-- 连接池参数 -->
<property name="maximumPoolSize" value="20"/> <!-- 最大连接数 -->
<property name="minimumIdle" value="5"/> <!-- 最小空闲连接 -->
<property name="connectionTimeout" value="30000"/> <!-- 连接超时(毫秒) -->
<property name="idleTimeout" value="600000"/> <!-- 空闲超时(毫秒) -->
<property name="maxLifetime" value="1800000"/> <!-- 最大生命周期(毫秒) -->
<property name="poolName" value="HikariPool"/> <!-- 连接池名称 -->
</bean>
<!-- ========== 2. SqlSessionFactory ========== -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 引用 dataSource -->
<!-- 引用上面的 dataSource -->
<property name="dataSource" ref="dataSource"/>
<!-- Mapper XML 文件位置 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<!-- 可选:MyBatis 全局配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 可选:实体类别名包 -->
<property name="typeAliasesPackage" value="com.example.entity"/>
</bean>
<!-- ========== 3. Mapper 接口扫描 ========== -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!-- ========== 4. 事务管理器 ========== -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- ========== 5. 开启注解事务 ========== -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
方案 B:Druid(带监控)
XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- ========== 1. 连接池:Druid ========== -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本配置 -->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<!-- 连接池参数 -->
<property name="maxActive" value="20"/> <!-- 最大连接数 -->
<property name="minIdle" value="5"/> <!-- 最小空闲连接 -->
<property name="maxWait" value="60000"/> <!-- 获取连接最大等待时间(毫秒) -->
<property name="initialSize" value="5"/> <!-- 初始连接数 -->
<!-- Druid 特有:监控和防御 -->
<property name="filters" value="stat,wall,slf4j"/> <!-- 监控+防火墙+日志 -->
<property name="validationQuery" value="SELECT 1"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<!-- 连接池监控页面配置(需要配置 Servlet) -->
<property name="resetEnable" value="false"/>
</bean>
<!-- ========== 2. SqlSessionFactory ========== -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
<!-- ========== 3. Mapper 扫描 ========== -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
</bean>
<!-- ========== 4. 事务管理器 ========== -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
方案 C:DBCP(Tomcat 自带,简单)
XML
<!-- 无需额外 Maven 依赖 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="maxTotal" value="20"/> <!-- 最大连接数 -->
<property name="maxIdle" value="10"/> <!-- 最大空闲连接 -->
<property name="minIdle" value="5"/> <!-- 最小空闲连接 -->
<property name="maxWaitMillis" value="10000"/> <!-- 最大等待时间(毫秒) -->
</bean>
3. 参数名速查表
| 功能 | HikariCP | Druid | DBCP |
|---|---|---|---|
| 驱动类 | driverClassName |
driverClassName |
driverClassName |
| 数据库URL | jdbcUrl |
url |
url |
| 用户名 | username |
username |
username |
| 密码 | password |
password |
password |
| 最大连接数 | maximumPoolSize |
maxActive |
maxTotal |
| 最小空闲连接 | minimumIdle |
minIdle |
minIdle |
| 初始连接数 | --- | initialSize |
initialSize |
| 连接超时/等待 | connectionTimeout |
maxWait |
maxWaitMillis |
| 空闲超时 | idleTimeout |
--- | minEvictableIdleTimeMillis |
| 最大生命周期 | maxLifetime |
--- | --- |
| 连接检测SQL | --- | validationQuery |
validationQuery |
4. Java 代码中使用
java
// 实体类
package com.example.entity;
public class User {
private Integer id;
private String name;
// getter/setter...
}
// Mapper 接口
package com.example.mapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User selectById(Integer id);
}
java
// Service 层
package com.example.service;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUserById(Integer id) {
return userMapper.selectById(id);
}
@Transactional
public void updateUser(User user) {
// 事务自动管理
userMapper.update(user);
}
}
java
// 启动类
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// 加载 Spring 配置
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取 Service
UserService userService = context.getBean(UserService.class);
// 使用
User user = userService.getUserById(1);
System.out.println(user);
}
}
换连接池 = 换 class + 调参数名,MyBatis 端完全无感知。
三、三种方式对比总结
| 对比项 | 纯 MyBatis 自定义 Factory | 纯 MyBatis JNDI | MyBatis + Spring |
|---|---|---|---|
| 复杂度 | 中(需写工厂类) | 高(需配 Tomcat) | 低(Spring 管理) |
| 灵活性 | 一般 | 低(依赖容器) | 高 |
| 连接池管理 | 应用内 | Tomcat 容器 | Spring 容器 |
| 密码位置 | mybatis-config.xml |
context.xml(安全) |
applicationContext.xml |
| 多应用共享 | ❌ | ✅ | ❌(每个 Spring 容器独立) |
| 事务管理 | 手动 | 手动 | 注解自动 |
| 推荐度 | ⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 适用场景 | 简单纯 MyBatis 项目 | 企业 war 部署 | 现代项目首选 |
四、快速选择指南
┌─────────────────────────────────────────┐
│ 项目类型判断 │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────┐
│ 有 Spring 吗? │
└─────────────────────────┘
│ │
是 否
│ │
▼ ▼
┌──────────┐ ┌─────────────────────────┐
│ 直接用 │ │ 需要 war 部署到外部 │
│ Spring │ │ Tomcat 且多应用共享? │
│ 方式 │ └─────────────────────────┘
└──────────┘ │ │
是 否
│ │
▼ ▼
┌──────────┐ ┌─────────────────┐
│ JNDI 方式 │ │ 自定义 DataSource│
│ │ │ Factory 方式 │
└──────────┘ └─────────────────┘
五、生产环境推荐
| 场景 | 推荐方案 |
|---|---|
| 新项目/微服务 | Spring + MyBatis + HikariCP |
| 需要 SQL 监控 | Spring + MyBatis + Druid |
| 传统 war 部署 | JNDI + Tomcat 统一管理 |
| 老项目维护 | 保持原有方案,逐步迁移到 Spring |
六、Spring Boot + Mybatis项目
6-1、Spring boot项目换不同的web容器
一、Spring Boot 怎么换 Web 容器
Spring Boot 默认内嵌 Tomcat,但换起来非常简单,就是排除一个依赖、引入另一个依赖。
1. 换成 Jetty
XML
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除默认的 Tomcat -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入 Jetty -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
2. 换成 Undertow(性能极高)
XML
<!-- 同样排除 Tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入 Undertow -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
就改这几行 Maven 依赖,代码完全不用动,Spring Boot 自动适配。
二、为什么要换?------ 三种容器对比
| 特性 | Tomcat(默认) | Jetty | Undertow |
|---|---|---|---|
| 出身 | Apache 基金会 | Eclipse 基金会 | JBoss(红帽) |
| 体积 | 中等 | 最轻量 | 轻量 |
| 性能 | 中等 | 中等 | 最高(高并发场景优势明显) |
| 内存占用 | 中等 | 较低 | 最低 |
| 启动速度 | 中等 | 最快 | 快 |
| 并发模型 | 线程池(阻塞IO) | 线程池 | 非阻塞IO(XNIO) |
| 热部署 | 支持 | 支持最好 | 支持 |
| 嵌入式友好 | 好 | 最好 | 好 |
| 企业级生态 | 最成熟 | 较少 | 较少 |
| 典型场景 | 通用、企业级 | 微服务、嵌入式设备 | 高并发、云原生、低内存 |
三、什么场景换什么容器?
场景 1:用 Tomcat(默认,不动就行)
XML
企业级应用,求稳
需要丰富的监控和管理工具
团队熟悉,文档多
兼容性好,第三方插件多
场景 2:换成 Jetty
XML
微服务架构,追求启动快
嵌入式设备 / 物联网(内存受限)
需要频繁热部署开发
和 Eclipse 生态集成
场景 3:换成 Undertow(趋势)
XML
高并发、高吞吐(如网关、API服务)
云原生 / K8s 部署(内存省=省钱)
长连接、WebSocket 场景
追求极致性能
四、回到 JNDI ------ 换容器后配置会变吗?
会变一点,但核心逻辑不变。
| 容器 | JNDI 配置位置 | 说明 |
|---|---|---|
| Tomcat | conf/context.xml |
最常用,资料最多 |
| Jetty | WEB-INF/jetty-env.xml |
语法类似 |
| Undertow | 通常用 Spring 配置代替 | 内嵌模式很少用 JNDI |
⚠️ 注意 :Spring Boot 内嵌容器模式下,一般不用 JNDI ,而是直接用
application.yml配置数据源:
XMLspring: datasource: url: jdbc:mysql://localhost:3306/mydb username: root password: 123456 type: com.zaxxer.hikari.HikariDataSourceJNDI 更多用于 传统 war 包部署到外部 Tomcat 的场景。
一句话总结
| 问题 | 答案 |
|---|---|
| 怎么换? | 改 Maven 依赖,排除 Tomcat,引入 Jetty/Undertow |
| 为什么要换? | Tomcat 求稳、Jetty 求轻、Undertow 求快 |
| JNDI 受影响吗? | 内嵌模式一般不用 JNDI,外部部署时各容器配置位置不同 |