1. 概述
Spring Boot 是一个基于普通 Spring 平台的、带有一定“主观倾向”但功能强大的抽象层,它极大地简化了独立应用和 Web 应用的开发流程。Spring Boot 提供了一些非常实用的 “starter” 依赖项,可以让我们以最小的配置运行和测试 Java 应用。
其中一个重要组件是 **spring-boot-starter-data-jpa**,它使我们可以使用 JPA 来操作生产数据库,并支持多种流行的 JDBC 连接池实现,比如 HikariCP 和 Tomcat JDBC Connection Pool。
在本教程中,我们将学习如何在 Spring Boot 中配置并使用 Tomcat JDBC 连接池。
2. Maven 依赖配置
默认情况下,Spring Boot 使用 HikariCP 作为连接池,因为它的性能表现优异且具备企业级特性。
✅ Spring Boot 自动配置连接池数据源的逻辑如下:
- 如果 classpath 中存在 HikariCP,则优先使用它;
- 如果没有 HikariCP,但有 Tomcat JDBC 连接池,则会自动选用;
- 如果两者都没有,则尝试使用 Apache Commons DBCP2(如果可用);
如果我们想使用 Tomcat JDBC 连接池而不是默认的 HikariCP,可以通过以下方式操作:
- 在
spring-boot-starter-data-jpa
中排除 HikariCP; - 添加
[tomcat-jdbc](https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jdbc/9.0.11/jar)
依赖;
示例 pom.xml
配置如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>10.1.7</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
<scope>runtime</scope>
</dependency>
⚠️ 注意:我们这里使用的是 H2 内存数据库,Spring Boot 会自动帮我们配置好,无需手动指定 URL、用户名或密码。
✅ 另一种方式:显式指定连接池类型
你也可以跳过 Spring Boot 的自动扫描机制,在 application.properties
文件中通过 spring.datasource.type
显式指定连接池类型:
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
// 其他 datasource 配置...
3. 使用 application.properties 调整连接池参数
一旦成功配置了 Tomcat 连接池,通常还需要根据实际业务场景进行一些性能调优和参数设置。
在 application.properties
中添加如下配置即可:
spring.datasource.tomcat.initial-size=15
spring.datasource.tomcat.max-wait=20000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.max-idle=15
spring.datasource.tomcat.min-idle=8
spring.datasource.tomcat.default-auto-commit=true
上面这些配置项包括:
- 初始连接数;
- 获取连接的最大等待时间;
- 最大活跃连接数;
- 最大空闲连接数;
- 最小空闲连接数;
- 是否开启自动提交;
此外,还可以配置一些 Hibernate 特定的属性:
# Hibernate specific properties
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.id.new_generator_mappings=false
4. 测试连接池是否生效
我们可以编写一个简单的集成测试来验证 Spring Boot 是否正确加载了 Tomcat 连接池:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootTomcatConnectionPoolIntegrationTest {
@Autowired
private DataSource dataSource;
@Test
public void givenTomcatConnectionPoolInstance_whenCheckedPoolClassName_thenCorrect() {
assertThat(dataSource.getClass().getName())
.isEqualTo("org.apache.tomcat.jdbc.pool.DataSource");
}
}
这个测试确保我们使用的确实是 Tomcat 的连接池实现。
5. 示例命令行应用
现在我们已经完成了连接池的基础配置,接下来构建一个简单的命令行应用来演示如何结合 Spring Data JPA 和 Tomcat 连接池对 H2 数据库执行 CRUD 操作。
5.1. Customer 实体类
首先定义一个简单的实体类:
@Entity
@Table(name = "customers")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "first_name")
private String firstName;
// 标准构造函数 / getter / setter / toString
}
5.2. CustomerRepository 接口
我们只需要继承 Spring Data JPA 的 CrudRepository
接口,并自定义一个按姓氏查找的方法:
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
这样就能轻松实现按姓氏查询客户的功能。
5.3. CommandLineRunner 实现
最后创建一个 CommandLineRunner
实现类,在应用启动时执行一些数据库操作:
public class CommandLineCrudRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(CommandLineCrudRunner.class);
@Autowired
private final CustomerRepository repository;
public void run(String... args) throws Exception {
repository.save(new Customer("John", "Doe"));
repository.save(new Customer("Jennifer", "Wilson"));
logger.info("Customers found with findAll():");
repository.findAll().forEach(c -> logger.info(c.toString()));
logger.info("Customer found with findById(1L):");
Customer customer = repository.findById(1L)
.orElseGet(() -> new Customer("Non-existing customer", ""));
logger.info(customer.toString());
logger.info("Customer found with findByLastName('Wilson'):");
repository.findByLastName("Wilson").forEach(c -> {
logger.info(c.toString());
});
}
}
这段代码主要做了以下几件事:
- 插入两条客户记录;
- 查询所有客户;
- 根据 ID 查询单个客户;
- 根据姓氏查询客户;
5.4. 启动 Spring Boot 应用
最后,我们只需要一个标准的 Spring Boot 主类来启动整个程序:
@SpringBootApplication
public class SpringBootConsoleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootConsoleApplication.class);
}
}
运行后你会看到 Tomcat 连接池配合 Spring Boot 正常工作的日志输出。
6. 总结
在本教程中,我们详细介绍了如何在 Spring Boot 中配置并使用 Tomcat JDBC 连接池,并通过一个简单的命令行应用展示了其与 H2 数据库配合使用的便捷性。
一如既往,本文中的所有代码都可以在 GitHub 仓库 中找到。