Spring Boot Tomcat 连接池

本页将介绍 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-jdbcspring-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-jdbcpom.xmlbuild.gradle我们自己,因为默认spring-boot-starter-jdbcspring-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. initialSize
initialSize是池启动时创建的初始连接数。它配置如下。

spring.datasource.tomcat.initial-size=15 

2. maxWait
maxWait是池在抛出异常之前等待返回连接的最大毫秒数。它配置如下。

spring.datasource.tomcat.max-wait=20000 

3. maxActive
maxActive是池可以同时分配的最大活动连接数。它配置如下。

spring.datasource.tomcat.max-active=50 

4. maxIdle
maxIdle是池中应始终保持的最大连接数。它配置如下。

spring.datasource.tomcat.max-idle=15 

5. minIdle
minIdle是池中应始终保持的最小连接数。它配置如下。

spring.datasource.tomcat.min-idle=8 

6. defaultAutoCommit
defaultAutoCommit属性配置此池创建的连接的默认自动提交状态。它是布尔值,默认值为true

spring.datasource.tomcat.default-auto-commit=true 

7. testOnBorrow
testOnBorrow是一个布尔值,指示对象在从池中借用之前是否会被验证。默认为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 服务客户端,请转到RestClientUtileclipse 中的类并单击Run as -> Java Application

参考

Spring Boot 参考指南
Tomcat JDBC 连接池

下载源代码

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值