赞
踩
本页将介绍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
。
在使用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
的依赖关系。
对于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
文件中使用。
我们将在这里讨论一些经常使用的配置。
connectionTimeout是客户端从连接池等待连接的最大毫秒数。我们需要对它进行如下配置。
spring.datasource.hikari.connection-timeout=20000
minimumIdle
是HikariCP
在连接池中维护的最小空闲连接数。它被配置为如下。
spring.datasource.hikari.minimum-idle=5
maximumPoolSize配置最大连接池数大小。它的配置方法如下。
spring.datasource.hikari.maximum-pool-size=12
idleTimeout
是允许一个连接在连接池中闲置的最大时间,以毫秒为单位。它的配置方法如下。
spring.datasource.hikari.idle-timeout=300000
maxLifetime
是池中连接关闭后的最长生存时间(以毫秒为单位)。其配置如下所示。
spring.datasource.hikari.max-lifetime=1200000
正在使用的连接将永远不会失效,只有当它关闭时,它才会在最长生存期后被删除。
autoCommit
配置从池中返回的连接的默认自动提交行为。默认值为true
。
spring.datasource.hikari.auto-commit=true
我们将用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
网络服务。
下载项目的源代码。使用命令提示符进入项目的根文件夹并运行命令。
mvn spring-boot:run
Tomcat
服务器将被启动。
使用文章末尾的下载链接下载项目的源代码。将该项目导入eclipse
。使用命令提示符,进入项目的根文件夹并运行。
mvn clean eclipse:eclipse
然后在eclipse
中刷新该项目。点击Run as
-> Java Application
来运行主类SpringBootAppStarter
。Tomcat
服务器将被启动。
使用命令提示符,进入项目的根文件夹并运行该命令。
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。