【Spring Boot 】Spring Boot + HikariCP 连接池使用示例
文章目录示例工具版本HikariCP 依赖HikariCP 配置1. connectionTimeout2. minimumIdle3. maximumPoolSize4. idleTimeout5. maxLifetime6. autoCommitSpring Boot Data + HikariCP + MySQL示例测试应用程序1. 使用 Maven 命令2. 使用 Eclipse3. 使用
文章目录
本页将介绍Spring Boot
和HikariCP
的例子。
HikariCP
是快速、简单、可靠且可用于生产的JDBC
连接池。
在Spring Boot 2.0
版本中,默认的数据库连接池技术已经从Tomcat
池切换到HikariCP
。
这是因为HikariCP
提供了卓越的性能。
现在,自Spring Boot 2.0
发布以来,spring-boot-starter-jdbc
和spring-boot-starter-data-jpa
默认解决HikariCP
的依赖关系,spring.datasource.type
属性的默认值是HikariDataSource
。
Spring boot
首先选择HikariCP
,然后是Tomcat
池,最后是Commons DBCP2
(基于可用性)。
在这一页,我们将提供HikariCP
与Spring Boot
数据和MySQL
的完整例子。
我们将创建一个演示应用程序,其中我们将在数据库中执行创建和读取操作。
我们将在application.properties
文件中配置HikariCP
属性,例如connectionTimeout
、minimumIdle
、maxPoolSize
、idleTimeout
、maxLifetime
和autoCommit
。
示例工具版本
- Java 9
- Spring 5.0.7.RELEASE
- Spring Boot 2.0.3.RELEASE
- Maven 3.5.2
- MySQL 5.5
- Eclipse Oxygen
HikariCP 依赖
在使用HikariCP
之前,我们需要确保我们已经解决了HikariCP
的依赖。
如果我们使用的是Maven
,我们可以使用以下依赖关系。
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.1.0</version>
</dependency>
如果我们使用的是Spring Boot 2.0
及以后的版本,我们不需要在pom.xml
或build.gradle
中加入HikariCP
依赖,因为spring-boot-starter-jdbc
和spring-boot-starter-data-jpa
默认会解决它。
这意味着,如果我们使用的依赖项是
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
或者
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
那么我们就不需要在pom.xml
或build.gradle
中包含HikariCP
的依赖关系。
HikariCP 配置
对于Hikari
连接池的配置,我们通过使用spring.datasource.type
并在application.properties
文件中指定连接池实现的完全限定名称来启用它,如下所示。
spring.datasource.type = com.zaxxer.hikari.HikariDataSource
如果我们使用的是Spring Boot 2.0
及以后的版本,Spring Boot
会默认选择HikariDataSource
,我们不需要配置上述行。
现在要配置Hikari
特定的连接池设置,Spring Boot
提供了spring.datasource.hikari.*
前缀,可以在application.properties
文件中使用。
我们将在这里讨论一些经常使用的配置。
1. connectionTimeout
connectionTimeout是客户端从连接池等待连接的最大毫秒数。我们需要对它进行如下配置。
spring.datasource.hikari.connection-timeout=20000
2. minimumIdle
minimumIdle
是HikariCP
在连接池中维护的最小空闲连接数。它被配置为如下。
spring.datasource.hikari.minimum-idle=5
3. maximumPoolSize
maximumPoolSize配置最大连接池数大小。它的配置方法如下。
spring.datasource.hikari.maximum-pool-size=12
4. idleTimeout
idleTimeout
是允许一个连接在连接池中闲置的最大时间,以毫秒为单位。它的配置方法如下。
spring.datasource.hikari.idle-timeout=300000
5. maxLifetime
maxLifetime
是池中连接关闭后的最长生存时间(以毫秒为单位)。其配置如下所示。
spring.datasource.hikari.max-lifetime=1200000
正在使用的连接将永远不会失效,只有当它关闭时,它才会在最长生存期后被删除。
6. autoCommit
autoCommit
配置从池中返回的连接的默认自动提交行为。默认值为true
。
spring.datasource.hikari.auto-commit=true
Spring Boot Data + HikariCP + MySQL 示例
我们将用Spring Boot Data
、HikariCP
和MySQL
创建一个Spring Boot REST
网络服务。
我们将使用CrudRepository
来查询数据库。
我们还将使用RestTemplate
创建一个REST
客户端来测试我们的应用程序。
首先找到演示应用程序的项目结构。
找到我们例子中使用的MySQL
表结构。
MySQL Table: 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`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB;
找到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>
<!-- Spring Boot Data 2.0 includes HikariCP by default -->
<!-- dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.1.0</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>
如果我们使用的Spring Boot
版本低于Spring Boot 2.0
,那么我们需要引入HikariCP
的依赖,如下所示。
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.1.0</version>
</dependency>
HikariCP 3.1.0
适用于Java 8
和Java 9
。
现在找到属性文件来配置数据源和其他属性。
连接池将使用HikariCP
进行配置。
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/concretepage
spring.datasource.username=root
spring.datasource.password=cp
#Spring Boot 2.0 includes HikariDataSource by default
#spring.datasource.type = com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=12
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=1200000
spring.datasource.hikari.auto-commit=true
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
如果我们使用的Spring Boot
版本低于Spring Boot 2.0
,那么我们需要为HikariCP
添加spring.datasource.type
属性,如下所示。
spring.datasource.type = com.zaxxer.hikari.HikariDataSource
现在找到演示程序中使用的其他文件。
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);
}
}
现在找到Java
类的Main
方法来运行该应用程序。为了确保我们使用的是HikariCP
,我们打印数据源名称。
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 = HikariDataSource (HikariPool-1)
现在找到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
网络服务。
1. 使用 Maven 命令
下载项目的源代码。使用命令提示符进入项目的根文件夹并运行命令。
mvn spring-boot:run
Tomcat
服务器将被启动。
2. 使用 Eclipse
使用文章末尾的下载链接下载项目的源代码。将该项目导入eclipse
。使用命令提示符,进入项目的根文件夹并运行。
mvn clean eclipse:eclipse
然后在eclipse
中刷新该项目。点击Run as
-> Java Application
来运行主类SpringBootAppStarter
。Tomcat
服务器将被启动。
3. 使用可执行 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
服务客户端,在eclipse
中进入RestClientUtil
类,点击Run as
-> Java Application
。
参考文献
【1】Spring Boot Reference Guide
【2】HikariCP
【3】Spring Boot 2.0 Release Notes
【4】Spring Boot + HikariCP
源码下载
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)