本页将介绍 Spring Boot Tomcat JDBC 连接池示例。Tomcat 连接池支持高性能的高并发环境。Tomcat 连接池非常简单,因为它的实现非常简单。Tomcat 连接池具有配置自定义拦截器、更好的空闲连接处理和执行异步连接检索的能力。在 Spring Boot 1.x 中,Tomcat 连接池是默认连接池,但在 Spring Boot 2.x 中 HikariCP 是默认连接池。在此页面上,我们将提供带有 Spring Boot Data 和 MySQL 的 Tomcat JDBC 连接池的完整示例。我们将创建一个演示应用程序,在其中我们将在数据库中执行创建和读取操作。我们将配置 Tomcat 连接池属性,例如 initialSize、maxWait、maxActive、application.properties
文件。
使用的技术
找出我们示例中使用的技术。
1. Java 8
2. Spring 5.0.7.RELEASE
3. Spring Boot 2.0.3.RELEASE
4. Maven 3.5.2
5. MySQL 5.5
6. Eclipse Oxygen
Tomcat JDBC 依赖
在使用 Tomcat 连接池之前,我们需要确保我们已经解决了 Tomcat JDBC 依赖。如果我们使用 Maven,我们可以使用以下依赖项。
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>9.0.8</version>
</dependency>
tomcat-jdbc
与spring-boot-starter-data-jpa
或一起使用spring-boot-starter-jdbc
。为了解决这个问题spring-boot-starter-data-jpa
,我们可以使用下面给出的 Maven 依赖项。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
要解决spring-boot-starter-jdbc
,请使用 Maven 依赖项,如下所示。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
在 Spring Boot 2.0 发布之前的旧版本 Spring Boot 1.x 中,我们不需要包含tomcat-jdbc
在pom.xml
或build.gradle
我们自己,因为默认spring-boot-starter-jdbc
会spring-boot-starter-data-jpa
解析它。
Tomcat 连接池配置
对于 Tomcat 连接池配置,我们通过使用spring.datasource.type
并在文件中为其分配 Tomcat 连接池实现的完全限定名称来启用它,application.properties
如下所示。
spring.datasource.type = org.apache.tomcat.jdbc.pool.DataSource
如果我们使用的是 Spring Boot 1.x 版本,Spring Boot 默认选择 Tomcat 数据源,我们不需要配置上述行。
现在要配置 Tomcat 特定的连接池设置,Spring Boot 提供spring.datasource.tomcat.*
了要在application.properties
文件中使用的前缀。我们将在这里讨论一些常用的配置。
1. initialSizeinitialSize
是池启动时创建的初始连接数。它配置如下。
spring.datasource.tomcat.initial-size=15
2. maxWaitmaxWait
是池在抛出异常之前等待返回连接的最大毫秒数。它配置如下。
spring.datasource.tomcat.max-wait=20000
3. maxActivemaxActive
是池可以同时分配的最大活动连接数。它配置如下。
spring.datasource.tomcat.max-active=50
4. maxIdlemaxIdle
是池中应始终保持的最大连接数。它配置如下。
spring.datasource.tomcat.max-idle=15
5. minIdleminIdle
是池中应始终保持的最小连接数。它配置如下。
spring.datasource.tomcat.min-idle=8
6. defaultAutoCommitdefaultAutoCommit
属性配置此池创建的连接的默认自动提交状态。它是布尔值,默认值为true。
spring.datasource.tomcat.default-auto-commit=true
7. testOnBorrowtestOnBorrow
是一个布尔值,指示对象在从池中借用之前是否会被验证。默认为false。
spring.datasource.tomcat.test-on-borrow=false
Spring Boot Data + Tomcat JDBC 连接池 + MySQL 示例
我们将使用 Spring Boot 数据、Tomcat JDBC 连接池和 MySQL 创建一个 Spring Boot REST Web 服务。我们将用于CrudRepository
查询数据库。我们还将创建一个 REST 客户端,RestTemplate
用于测试我们的应用程序。首先找到演示应用程序的项目结构。
找到我们示例中使用的 MySQL 表结构。
MySQL 表:articles
CREATE TABLE `articles` (
`article_id` INT(5) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(200) NOT NULL,
`category` VARCHAR(100) NOT NULL,
PRIMARY KEY (`article_id`)
)
找到 Maven 文件以解决依赖关系。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.concretepage</groupId>
<artifactId>spring-boot-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-app</name>
<description>Spring Boot Application</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>9</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>9.0.8</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/concretepage
spring.datasource.username=root
spring.datasource.password=cp
spring.datasource.type = org.apache.tomcat.jdbc.pool.DataSource
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
spring.datasource.tomcat.test-on-borrow=false
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.id.new_generator_mappings=false
spring.jpa.properties.hibernate.format_sql=true
ArticleRepository.java
package com.concretepage.repository;
import org.springframework.data.repository.CrudRepository;
import com.concretepage.entity.Article;
public interface ArticleRepository extends CrudRepository<Article, Long> {
}
Article.java
package com.concretepage.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="articles")
public class Article implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="article_id")
private long articleId;
@Column(name="title")
private String title;
@Column(name="category")
private String category;
public long getArticleId() {
return articleId;
}
public void setArticleId(long articleId) {
this.articleId = articleId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
IArticleService.java
package com.concretepage.service;
import java.util.List;
import com.concretepage.entity.Article;
public interface IArticleService {
List<Article> getAllArticles();
void addArticle(Article article);
}
ArticleService.java
package com.concretepage.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.concretepage.entity.Article;
import com.concretepage.repository.ArticleRepository;
@Service
public class ArticleService implements IArticleService {
@Autowired
private ArticleRepository articleRepository;
@Override
public List<Article> getAllArticles(){
List<Article> list = new ArrayList<>();
articleRepository.findAll().forEach(e -> list.add(e));
return list;
}
@Override
public void addArticle(Article article){
articleRepository.save(article);
}
}
ArticleInfo.java
package com.concretepage.controller;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
public class ArticleInfo {
@JsonInclude(Include.NON_NULL)
private long articleId;
@JsonInclude(Include.NON_NULL)
private String title;
@JsonInclude(Include.NON_NULL)
private String category;
public long getArticleId() {
return articleId;
}
public void setArticleId(long articleId) {
this.articleId = articleId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
ArticleController.java
package com.concretepage.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import com.concretepage.entity.Article;
import com.concretepage.service.IArticleService;
@RestController
@RequestMapping("user")
public class ArticleController {
@Autowired
private IArticleService articleService;
//Fetches all articles
@GetMapping(value= "articles")
public ResponseEntity<List<ArticleInfo>> getAllArticles() {
List<ArticleInfo> responseArticleList = new ArrayList<>();
List<Article> articleList = articleService.getAllArticles();
for (int i = 0; i < articleList.size(); i++) {
ArticleInfo ob = new ArticleInfo();
BeanUtils.copyProperties(articleList.get(i), ob);
responseArticleList.add(ob);
}
return new ResponseEntity<List<ArticleInfo>>(responseArticleList, HttpStatus.OK);
}
//Creates a new article
@PostMapping(value= "article")
public ResponseEntity<Void> addArticle(@RequestBody ArticleInfo articleInfo, UriComponentsBuilder builder) {
Article article = new Article();
BeanUtils.copyProperties(articleInfo, article);
articleService.addArticle(article);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(builder.path("/article/{id}").buildAndExpand(article.getArticleId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
}
现在找到 Main Java 类来运行应用程序。为了确保我们使用的是 Tomcat JDBC 连接池,我们正在打印数据源名称。
SpringBootAppStarter.java
package com.concretepage;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootAppStarter implements CommandLineRunner {
@Autowired
DataSource dataSource;
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringBootAppStarter.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("DataSource = " + dataSource);
}
}
当我们启动我们的应用程序时,我们可以在服务器日志末尾的控制台中看到以下消息。
输出
DataSource = org.apache.tomcat.jdbc.pool.DataSource@5437ca1b{ConnectionPool[defaultAutoCommit=true;
defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null;
driverClassName=com.mysql.jdbc.Driver; maxActive=50; maxIdle=15; minIdle=8;
initialSize=15; maxWait=20000; testOnBorrow=false; testOnReturn=false;
timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000;
testWhileIdle=false; testOnConnect=false; password=********; url=jdbc:mysql://localhost:3306/concretepage;
username=root; validationQuery=/* ping */ SELECT 1; validationQueryTimeout=-1;
validatorClassName=null; validationInterval=3000; accessToUnderlyingConnectionAllowed=true;
removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null;
initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true;
abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null;
suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false;
useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false;
ignoreExceptionOnPreLoad=false; useStatementFacade=true; }
现在找到 REST 客户端来测试应用程序。
RestClientUtil.java
package com.concretepage.client;
import java.net.URI;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import com.concretepage.entity.Article;
public class RestClientUtil {
public void getAllArticlesDemo() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/user/articles";
HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
ResponseEntity<Article[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article[].class);
Article[] articles = responseEntity.getBody();
for(Article article : articles) {
System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle()
+", Category: "+article.getCategory());
}
}
public void addArticleDemo() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/user/article";
Article objArticle = new Article();
objArticle.setTitle("Spring REST Security using Hibernate");
objArticle.setCategory("Spring");
HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers);
URI uri = restTemplate.postForLocation(url, requestEntity);
System.out.println(uri.getPath());
}
public static void main(String args[]) {
RestClientUtil util = new RestClientUtil();
util.addArticleDemo();
util.getAllArticlesDemo();
}
}
当我们运行客户端时,我们将得到以下输出。
输出
Id:1, Title:Spring REST Security using Hibernate, Category: Spring
测试申请
要测试应用程序,首先按照文章中的说明在 MySQL 中创建表,并在application.properties
文件中配置您的数据库凭据。然后我们可以通过以下方式运行 REST Web 服务。
1. 使用 Maven 命令:下载项目源代码。使用命令提示符转到项目的根文件夹并运行命令。
mvn spring-boot:run
Tomcat 服务器将被启动。
2. 使用 Eclipse:使用文章末尾给出的下载链接下载项目源代码。将项目导入eclipse。使用命令提示符,转到项目的根文件夹并运行。
mvn clean eclipse:eclipse
然后在eclipse中刷新项目。SpringBootAppStarter
通过单击Run as -> Java Application来运行 Main 类。Tomcat 服务器将被启动。
3. 使用 Executable JAR:使用命令提示符,转到项目的根文件夹并运行命令。
mvn clean package
我们将在目标文件夹中获得可执行的 JAR spring-boot-app-0.0.1-SNAPSHOT.jar 。将此 JAR 运行为
java -jar target/spring-boot-app-0.0.1-SNAPSHOT.jar
Tomcat 服务器将被启动。
现在我们准备好测试应用程序了。要运行 Web 服务客户端,请转到RestClientUtil
eclipse 中的类并单击Run as -> Java Application。
参考
Spring Boot 参考指南
Tomcat JDBC 连接池
下载源代码