29. 使用 SQL 数据库

Spring Framework 为使用 SQL 数据库提供了广泛的支持,使用 JdbcTemplate 直接 JDBC 访问来完成 “对象关系映射” 技术(如 Hibernate)。Spring Data 提供了额外的功能级别:直接从接口创建存储库实现,并使用约定从方法名称生成查询。

29.1 配置数据源

Java 的 javax.sql.DataSource 接口提供了一种处理数据库连接的标准方法。传统上,数据源使用 URL 和一些凭证来建立数据库连接。

[Tip] Tip

请参阅关于更高级示例的 “How-to” 部分,通常是对数据源的配置进行完全控制。

29.1.1 嵌入式数据库支持

使用内存中的嵌入式数据库开发应用程序通常是方便的。显然,在内存数据库中不提供持久存储。当应用程序启动时,你需要填充数据库,并准备在应用程序结束时丢弃数据。

[Tip] Tip

“How-to” 部分包括 如何初始化数据库部分。

Spring Boot 可以自动配置嵌入式 H2、HSQL 和 Derby 数据库。你不需要提供任何连接URL。只需要对要使用的嵌入式数据库包含构建依赖项。

[Note] Note

如果在测试中使用此特性,你可能会注意到同一个数据库被整个测试套件重用,而不考虑使用的应用程序上下文数量。如果要确保每个上下文都有一个独立的嵌入式数据库,则应将 spring.datasource.generate-unique-name 设置为 true。

例如,典型的 POM 依赖关系如下:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
	<groupId>org.hsqldb</groupId>
	<artifactId>hsqldb</artifactId>
	<scope>runtime</scope>
</dependency>
[Note] Note

你需要对 spring-jdbc 依赖于嵌入式数据库进行自动配置。在这个例子中,它是通过 spring-boot-starter-data-jpa 来传递的。

[Tip] Tip

如果,不论何原因,你确实配置了嵌入式数据库的连接 URL,请注意确保数据库的自动关机被禁用了。如果使用 H2,则应该使用 DB_CLOSE_ON_EXIT=FALSE 这样做。如果使用 HSQLDB,则应确保不使用 shutdown=true。禁用数据库自动关闭,可以让 Spring Boot 控制数据库关闭,从而确保一旦不再需要访问数据库就触发。

29.1.2 连接到生产数据库

生产数据库连接也可以通过使用 DataSource 连接池自动配置。Spring Boot 使用以下算法来选择特定的实现:

  1. 我们更喜欢 HikariCP 的性能和并发性。如果 HikariCP 是可用的,我们总是选择它。
  2. 否则,如果 Tomcat DataSource 连接池可用,我们使用它。
  3. 如果 HikariCP 和 Tomcat 数据源连接池都不可用,并且 Commons DBCP2 可用,我们使用它。

如果使用 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa 启动器,则自动获得对 HikariCP 的依赖项。

[Note] Note

你可以完全绕过该算法,并通过设置 spring.datasource.type 属性指定要使用的连接池。如果你在 Tomcat 容器中运行应用程序,默认会提供 tomcat-jdbc。

[Tip] Tip

额外的连接池总是可以手动配置的。如果你定义了 DataSource bean,则自动配置不会发生。

数据源配置由 spring.datasource.* 中的外部配置属性控制。例如,你可以在 application.properties 中声明以下部分:

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
[Note] Note

你至少应该通过设置 spring.datasource.url 属性来指定 URL。否则,Spring Boot 会尝试自动配置嵌入式数据库。

[Tip] Tip

你通常不需要指定 driver-class-name,因为 Spring Boot 可以从 url 推断大多数数据库。

[Note] Note

对于要创建 DataSource 连接池,我们需要能够验证一个有效的驱动程序类可用,所以在做任何事情之前检查它。换句话说,如果设置 spring.datasource.driver-class-name=com.mysql.jdbc.Driver,则该类必须是可加载的。

更多支持的选项请查阅 DataSourceProperties。这些都是标准的选项,不管实际的执行情况如何。还可以通过使用它们各自的前缀(spring.datasource.hikari.*、spring.datasource.tomcat.* 和 spring.datasource.dbcp2.*)来微调实现特定的设置。有关详细信息请参阅你正在使用的连接池实现的文档。

例如,如果使用 Tomcat 连接池,你可以自定义许多附加设置,如下面的示例所示:

# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.tomcat.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=50

# Validate the connection before borrowing it from the pool.
spring.datasource.tomcat.test-on-borrow=true

29.1.3 连接到 JNDI 数据源

如果将 Spring Boot 应用程序部署到应用服务器,你可能希望通过使用应用服务器的内置特性来配置和管理数据源,并通过使用 JNDI 访问它。

spring.datasource.jndi-name 属性可以用作 spring.datasource.url、spring.datasource.username 和 spring.datasource.password 属性的替代,以从特定 JNDI 位置访问数据源。例如,application.properties 中的下面部分说明了如何访问定义为 DataSource 的 JBoss:

spring.datasource.jndi-name=java:jboss/datasources/customers

29.2 使用 JdbcTemplate

Spring 的 JdbcTemplate 和 NamedParameterJdbcTemplate 类是自动配置的,并且可以直接将它们直接 @Autowire 到你自己的 bean 中,如下面的示例所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final JdbcTemplate jdbcTemplate;

	@Autowired
	public MyBean(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	// ...

}

你可以使用 spring.jdbc.template.* 属性自定义模板的一些属性,如下面的示例所示:

spring.jdbc.template.max-rows=500
[Note] Note

NamedParameterJdbcTemplate 在后台重用相同的 JdbcTemplate 实例。如果定义了多于一个 JdbcTemplate,并且没有主候选存在,则 NamedParameterJdbcTemplate 不会自动配置的。

29.3 JPA 和 “Spring Data”

Java 持久化 API 是一种允许将对象映射到关系数据库的标准技术。spring-boot-starter-data-jpa POM 提供了一种快速启动的方法。它提供以下关键依赖:

  • Hibernate: 最流行的 JPA 实现之一。
  • Spring Data JPA: 使得很容易实现基于 JPA 的存储库。
  • Spring ORM: Spring Framework 提供的核心 ORM 支持
[Tip] Tip

我们这里不涉及 JPA 或 Spring Data 的太多细节。可以从 spring.io 中查阅 “使用 JPA 访问数据”指南,并阅读 Spring Data JPA 和 Hibernate 参考文档。

29.3.1 实体类

传统上,在 persistence.xml 文件中指定 JPA 实体类。使用 Spring Boot,这个文件不是必需的,而是使用实体扫描。默认情况下,搜索所有主要配置类以下的包(使用 @EnableAutoConfiguration 或 @SpringBootApplication 注解)。

考虑使用 @Entity、@Embeddable 或 @MappedSuperclass 注解的任何类。典型的实体类类似于以下示例:

package com.example.myapp.domain;

import java.io.Serializable;
import javax.persistence.*;

@Entity
public class City implements Serializable {

	@Id
	@GeneratedValue
	private Long id;

	@Column(nullable = false)
	private String name;

	@Column(nullable = false)
	private String state;

	// ... additional members, often include @OneToMany mappings

	protected City() {
		// no-args constructor required by JPA spec
		// this one is protected since it shouldn't be used directly
	}

	public City(String name, String state) {
		this.name = name;
		this.country = country;
	}

	public String getName() {
		return this.name;
	}

	public String getState() {
		return this.state;
	}

	// ... etc

}
[Tip] Tip

你可以使用 @EntityScan 注解自定义实体扫描位置。请参阅小节 81.4, “从 Spring 配置分离 @Entity 定义” how-to。

29.3.2 Spring Data JPA 存储库

Spring Data JPA 存储库是可以定义访问数据的接口。JPA 查询是从方法名称自动创建的。例如,CityRepository 接口可以声明 findAllByState(String state) 方法来查找给定状态下的所有城市。

对于更复杂的查询,可以用 Spring Data 的 Query 注解来注解你的方法。

Spring Data 存储库通常从 Repository 或 CrudRepository 接口扩展。如果使用自动配置,则从包含主配置类的包中搜索存储库(用 @EnableAutoConfiguration 或 @SpringBootApplication 注解)。

下面的示例展示了一个典型的 Spring Data 存储库接口定义:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

	Page<City> findAll(Pageable pageable);

	City findByNameAndCountryAllIgnoringCase(String name, String country);

}
[Tip] Tip

我们仅仅接触了 Spring Data JPA 的表面内容。完整的详细信息请参阅 Spring Data JPA参考文档。

29.3.3 创建和删除 JPA 数据库

默认情况下,只有使用嵌入式数据库(H2、HSQL 或 Derby)才能自动创建 JPA 数据库。可以通过使用 spring.jpa.* 属性显式配置 JPA 设置。例如,创建和删除表可以将以下行添加到 application.properties 中:

spring.jpa.hibernate.ddl-auto=create-drop
[Note] Note

Hibernate 的内部属性名称(如果你记得更好)是 hibernate.hbm2ddl.auto。你可以通过使用 spring.jpa.properties.*(在添加到实体管理之前删除前缀)设置它,以及其它 Hibernate 本地特性。下面展示了一个设置 Hibernate JPA 属性的示例:

spring.jpa.properties.hibernate.globally_quoted_identifiers=true

前一个示例中的那行展示了将 hibernate.globally_quoted_identifiers 属性的 true 值传递给 Hibernate 实体管理器。

默认情况下,DDL 执行(或验证)被推迟,直到 ApplicationContext 已启动。还有一个 spring.jpa.generate-ddl 标志,但如果 Hibernate 自动配置是活动的,则不使用它,因为 ddl-auto 设置更细粒度。

29.3.4 在视图中打开 EntityManager

如果你正在运行一个 web 应用,Spring Boot 默认地注册 OpenEntityManagerInViewInterceptor 来应用在视图中打开 EntityManager 模式,以允许在 web 视图中延迟加载。如果你不想使用此行为,则应该在 application.properties 中设置 spring.jpa.open-in-view 为 false。

29.4 使用 H2 的 web 控制台

H2 数据库提供了一个基于浏览器的控制台,Spring Boot 会自动为你配置。当满足以下条件时,控制台自动配置:

  • 你正在开发基于 servlet 的 web 应用程序。
  • com.h2database:h2 在类路径上。
  • 你在使用 Spring Boot 的开发者工具。
[Tip] Tip

如果你不使用 Spring Boot 的开发工具,但仍想使用 H2 的控制台,你可以配置 spring.h2.console.enabled 属性为 true。

[Note] Note

H2 的控制台是用于在开发过程中,所以你要确保在生产中未设置 spring.h2.console.enabled 为 true。

29.4.1 更改 H2 控制台路径

默认情况下,控制台在 /h2-console 上可用。可以通过使用 spring.h2.console.path 属性自定义控制台的路径。

29.5 使用 jOOQ

Java 面向对象查询(jOOQ)是一种流行的产品,它从 Data Geekery 中生成Java代码,并通过它的 fluent API 来构建类型安全的 SQL 查询。商业版本和开源版本都可以与 Spring Boot 使用。

29.5.1 代码生成

为了使用 jOOQ 类型安全查询,需要从数据库 schema 生成 Java 类。你可以按照 jOOQ 用户手册中的说明进行操作。如果你使用 jooq-codegen-maven 插件并且也使用 spring-boot-starter-parent 父 POM,则可以安全地忽略插件版本的 <version> 标签。你也可以使用 Spring Boot 定义版本的变量(如 h2.version)宣布插件的数据依赖。下面的列表显示了一个示例:

<plugin>
	<groupId>org.jooq</groupId>
	<artifactId>jooq-codegen-maven</artifactId>
	<executions>
		...
	</executions>
	<dependencies>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<version>${h2.version}</version>
		</dependency>
	</dependencies>
	<configuration>
		<jdbc>
			<driver>org.h2.Driver</driver>
			<url>jdbc:h2:~/yourdatabase</url>
		</jdbc>
		<generator>
			...
		</generator>
	</configuration>
</plugin>

29.5.2 使用 DSLContext

jOOQ 提供的 fluent API 是通过 org.jooq.DSLContext 接口初始化的。Spring Boot 自动配置了一个为 Spring Bean 的 DSLContext,并连接它到你的应用程序 DataSource。为了使用 DSLContext,你可以 @Autowire 它,如下面的示例所示:

@Component
public class JooqExample implements CommandLineRunner {

	private final DSLContext create;

	@Autowired
	public JooqExample(DSLContext dslContext) {
		this.create = dslContext;
	}

}
[Tip] Tip

jOOQ 手动指定使用一个命名为 create 的变量来保存 DSLContext。

然后你可以使用 DSLContext 来构建你的查询,如下面的示例所示:

public List<GregorianCalendar> authorsBornAfter1980() {
	return this.create.selectFrom(AUTHOR)
		.where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
		.fetch(AUTHOR.DATE_OF_BIRTH);
}

29.5.3 jOOQ SQL 方言

除非 spring.jooq.sql-dialect 属性已经配置,Spring Boot 决定你的数据源使用的 SQL 方言。如果 Spring Boot 无法检测的话,它使用 DEFAULT。

[Note] Note

Spring Boot 只能自动配置 jOOQ 开源版本支持的方言。

29.5.4 定制 jOOQ

更高级的定制可以通过定义自己的 @Bean 定义实现的,当 jOOQ Configuration 创建时使用。你可以使用下面的 jOOQ 类型定义 bean:

  • ConnectionProvider
  • TransactionProvider
  • RecordMapperProvider
  • RecordUnmapperProvider
  • RecordListenerProvider
  • ExecuteListenerProvider
  • VisitListenerProvider
  • TransactionListenerProvider

如果你想完全控制 jOOQ 配置,则可以创建你自己的 org.jooq.Configuration @Bean。

30. 使用 NoSQL 技术

Spring Data 提供了额外的项目来帮你访问各种各样的 NoSQL 技术,包含 MongoDB、Neo4J、Elasticsearch、Solr、Redis、Gemfire、Cassandra、Couchbase 和 LDAP。Spring Boot 为 Redis、MongoDB、Neo4j、Elasticsearch、Solr Cassandra、Couchbase 和 LDAP 提供了自动配置。你可以使用其它的项目,但你必须自己配置它们。在 projects.spring.io/spring-data 可以找到适当的参考文档。

30.1 Redis

Redis 是一个缓存、消息代理和功能丰富的键值存储。Spring Boot 使用 Spring Data Redis 为 Lettuce 和 Jedis 客户端库以及它们之上的抽象提供基础自动配置,

这有一个 spring-boot-starter-data-redis 启动器为收集依赖提供了一个方便的方式。默认情况下,它使用 Lettuce。这个启动器处理传统和响应式应用程序。

[Tip] Tip

我们还提供了一个 spring-boot-starter-data-redis-reactive 启动器,为了和其它存储的响应式支持保持一致性。

30.1.1 连接到 Redis

你可以像你需要的其它任何 Spring bean 一样,注入一个自动配置 RedisConnectionFactory、StringRedisTemplate 或普通的 RedisTemplate 实例。默认情况下,实例试图连接到 localhost:6379 的 Redis 服务器。下面的列展示了这样的一个 bean 例子:

@Component
public class MyBean {

	private StringRedisTemplate template;

	@Autowired
	public MyBean(StringRedisTemplate template) {
		this.template = template;
	}

	// ...

}
[Tip] Tip

你也可以注册随意数量实现 LettuceClientConfigurationBuilderCustomizer 的 bean 来实现更高级的定制。如果你使用 Jedis,JedisClientConfigurationBuilderCustomizer 也是可以的。

如果你添加你自己的任意自动配置类型的 @Bean,它会取代默认的(除了 RedisTemplate,排除是基于 bean 名称,redisTemplate,而不是它的类型)。默认情况下,如果 commons-pool2 在类路径上,你会得到一个混合连接工厂。

30.2 MongoDB

MongoDB 是一个开源的 NoSQL 文档数据库,它使用类似 JSON 的模式,而不是传统的基于表的关系数据。Spring Boot 为使用 MongoDB 提供了许多便利,包括 spring-boot-starter-data-mongodb 和 spring-boot-starter-data-mongodb-reactive 启动器。

30.2.1 连接到 MongoDB 数据库

为了访问 Mongo 数据库,你可以注入一个自动配置的 org.springframework.data.mongodb.MongoDbFactory。默认情况下,实例试图连接到 mongodb://localhost/test 的 MongoDB 服务器。下面的示例展示了如何连接到 MongoDB 数据库。

import org.springframework.data.mongodb.MongoDbFactory;
import com.mongodb.DB;

@Component
public class MyBean {

	private final MongoDbFactory mongo;

	@Autowired
	public MyBean(MongoDbFactory mongo) {
		this.mongo = mongo;
	}

	// ...

	public void example() {
		DB db = mongo.getDb();
		// ...
	}

}

你可以设置 spring.data.mongodb.uri 属性来更改 URL 并配置其它设置,如 replica set,如下面的示例所示:

spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test

或者,当你使用 Mongo 2.x,你可以指定 host/port。例如,你可以在 application.properties 中声明以下设置:

spring.data.mongodb.host=mongoserver
spring.data.mongodb.port=27017
[Note] Note

如果你使用 Mongo 3.0 Java 驱动,则不支持 spring.data.mongodb.host 和 spring.data.mongodb.port。在这种情况下,spring.data.mongodb.uri 应该用它来提供所有的配置。

[Tip] Tip

如果没有指定 spring.data.mongodb.port,默认使用 27017。你可以从前面展示的示例中删除此行。

[Tip] Tip

如果你不使用 Spring Data Mongo 时,则可以注入 com.mongodb.MongoClient bean 代替 MongoDbFactory。如果你想要完全控制建立 MongoDB 的连接,也可以定义你自己的 MongoDbFactory 或 MongoClient bean。

[Note] Note

如果你使用的是响应式驱动,Netty 需要 SSL。如果 Netty 可用并且工厂没有自定义,则自动配置会自动配置工厂。

30.2.2 MongoTemplate

Spring Data MongoDB 提供了一个 MongoTemplate 类,它和 Spring JdbcTemplate 的设计非常相似。和 JdbcTemplate一样,Spring Boot 自动配置一个 bean 来为你注入这个模版,如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final MongoTemplate mongoTemplate;

	@Autowired
	public MyBean(MongoTemplate mongoTemplate) {
		this.mongoTemplate = mongoTemplate;
	}

	// ...

}

更完整的细节请参阅 MongoOperations Javadoc。

30.2.3 Spring Data MongoDB 存储库

Spring Data 包含 MongoDB 支持的库。与前面所讨论的 JPA 库,其基本原理是,查询的自动构建,以及基于名称的方法。

实际上,Spring Data JPA 和 Spring Data MongoDB 共享同样的公共基础内容。你可以拿来前面的 JPA 例子,假设 City 是一个 Mongo 数据类而不是 JPA @Entity,它将以同样的方式工作,如下面的示例所示:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

	Page<City> findAll(Pageable pageable);

	City findByNameAndCountryAllIgnoringCase(String name, String country);

}
[Tip] Tip

你可以使用 @EntityScan 注解自定义文件扫描位置。

[Tip] Tip

为了 Spring Data MongoDB 完整的详细信息,包括其丰富的对象映射技术,请参阅它的参考文档。

30.2.4 嵌入式 Mongo

Spring Boot 为嵌入式 Mongo提供了自动配置。为了在你的 Spring Boot 应用程序中使用它,请添加一个 de.flapdoodle.embed:de.flapdoodle.embed.mongo 依赖。

Mongo 监听的端口可以通过设置 spring.data.mongodb.port 属性来配置。为了使用未使用的随机端口,使用值为 0。MongoClient 使用 MongoAutoConfiguration 创建的是自动配置为随机分配的端口。

[Note] Note

如果你不配置自定义端口,嵌入式支持默认使用随机端口(而不是 27017)。

如果在类路径上有 SLF4J,则由 Mongo 生成的输出自动路由到名为 org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongo 的日志记录。

你可以声明自己的 IMongodConfig 和 IRuntimeConfig bean 以控制 Mongo 实例的配置和日志记录路由。

30.3 Neo4j

Neo4j 是一个开源的 NoSQL 图形数据库,为第一级关系的节点关系使用丰富的数据模型,这是比传统关系型数据库更适合连接大数据。Spring Boot 提供了几个使用 Neo4j 有用的工具,包括 spring-boot-starter-data-neo4j 启动器。

30.3.1 连接到 Neo4j 数据库

你可以像其它你需要的 Spring Bean 那样,注入自动配置的 Neo4jSession、Session 或 Neo4jOperations。默认情况下,实例试图连接到 localhost:7474 的 Neo4j 服务器。下面的示例展示了如何注入一个 Neo4j bean:

@Component
public class MyBean {

	private final Neo4jTemplate neo4jTemplate;

	@Autowired
	public MyBean(Neo4jTemplate neo4jTemplate) {
		this.neo4jTemplate = neo4jTemplate;
	}

	// ...

}

你可以通过添加 org.neo4j.ogm.config.Configuration @Bean 来完全控制配置。同时,添加一个 Neo4jOperations 类型的 @Bean 禁用自动配置。

你可以通过设置 spring.data.neo4j.* 属性配置用户和凭证,如下面的示例所示:

spring.data.neo4j.uri=http://my-server:7474
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret

30.3.2 使用嵌入式模式

如果你在应用程序中添加了 org.neo4j:neo4j-ogm-embedded-driver 到依赖中,Spring Boot 自动配置线程中的嵌入式 Neo4j 实例,当你的应用程序关闭时不会持久化任何数据。你可以显式设置 spring.data.neo4j.embedded.enabled=false 禁用该模式。你也可以提供使嵌入式模式到数据库文件的持久化路径,如下面的示例所示:

	spring.data.neo4j.uri=file://var/tmp/graph.db
[Note] Note

Neo4j OGM 嵌入式驱动程序不提供 Neo4j 内核。用户需要手动提供这种依赖。更多详情请参阅文档。

30.3.3 Neo4jSession

默认情况下,如果你正在运行一个 web 应用程序,会话会绑定到处理整个请求的线程上(即,它使用 "Open Session in View" 模式)。如果你不希望这种行为,添加以下行到你的 application.properties 文件:

spring.data.neo4j.open-in-view=false

30.3.4 Spring Data Neo4j 存储库

Spring Data 包含支持 Neo4j 的库。

事实上,Spring Data JPA 和 Spring Data Neo4j 共享同样的公共基础内容,你可以拿来前面的 JPA 例子,假设 City 是一个 Neo4j OGM @NodeEntity而不是 JPA @Entity,它将以同样的方式工作。

[Tip] Tip

你可以使用 @EntityScan 注解来自定义实体扫描位置。

若要启用库支持(并可选地支持 @Transactional),请在 Spring 配置中添加以下两个注解:

@EnableNeo4jRepositories(basePackages = "com.example.myapp.repository")
@EnableTransactionManagement

30.3.5 存储库示例

下面的示例展示一个 Neo4j 存储库的接口定义:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends GraphRepository<City> {

	Page<City> findAll(Pageable pageable);

	City findByNameAndCountry(String name, String country);

}
[Tip] Tip

有关 Spring Data Neo4j 的完整细节,包括其丰富的对象映射技术,请参阅参考文档。

30.4 Gemfire

Spring Data Gemfire 为访问 Pivotal Gemfire 数据管理平台提供了方便的 Spring 友好工具。这有一个 spring-boot-starter-data-gemfire 启动器以方便的方式收集了依赖关系。目前还没有对 Gemfire 的自动配置支持,但是你可以用一个注解: @EnableGemfireRepositories 启用 Spring Data 库。

30.5 Solr

Apache Solr 是一个搜索引擎。Spring Boot 使用 Spring Data Solr 提供 Solr 5 客户端库和它之上的抽象提供基本自动配置。spring-boot-starter-data-solr “Starter” 提供一个收集依赖的方便的方式。

30.5.1 连接到 Solr

你可以像任何其它 Spring bean 一样注入一个自动配置的 SolrClient 实例。默认情况下,实例试图连接到 localhost:8983/solr 的服务器。下面的示例展示了如何注入 Solr bean:

@Component
public class MyBean {

	private SolrClient solr;

	@Autowired
	public MyBean(SolrClient solr) {
		this.solr = solr;
	}

	// ...

}

如果你添加了你自己的 SolrClient 类型的 @Bean,这将会替换默认的。

30.5.2 Spring Data Solr 存储库

Spring Data 支持 Apache Solr 的存储库。与前面所讨论的 JPA 存储库一样,其基本原理是,基于你的方法名称自动构建查询。

事实上,Spring Data JPA 和 Spring Data Solr 共享同样的公共基础内容,你可以拿来前面的 JPA 例子,假设 City 是一个 @SolrDocument 类而不是 JPA @Entity,它将以同样的方式工作。

[Tip] Tip

有关 Spring Data Solr 的完整细节,请参阅参考文档。

30.6 Elasticsearch

Elasticsearch 是一个开源的,分布式的,RESTful 搜索和分析引擎。Spring Boot 为 Elasticsearch 提供基本自动配置。

Spring Boot 支持多种 HTTP 客户端:

  • 官方 Java "Low Level" 和 "High Level" REST 客户端
  • Jest

传输客户端仍然是由 Spring Data Elasticsearch 使用,你可以使用 spring-boot-starter-data-elasticsearch 启动器来开始。

30.6.1 使用 REST 客户端连接 Elasticsearch

Elasticsearch 可以使用两个不同的 REST 客户端来查询集群:"Low Level" 客户端和 "High Level" 客户端。

如果你类路上有 org.elasticsearch.client:elasticsearch-rest-client 依赖,Spring Boot 会自动配置并注册一个 RestClient bean,它默认指向 localhost:9200。你可以进一步调整 RestClient 配置,如下面的示例所示:

spring.elasticsearch.rest.uris=http://search.example.com:9200
spring.elasticsearch.rest.username=user
spring.elasticsearch.rest.password=secret

你还可以注册任意数量的 bean 来实现 RestClientBuilderCustomizer 以进行更高级的自定义,若要完全控制注册,则定义一个 RestClient bean。

如果你类路径上有 org.elasticsearch.client:elasticsearch-rest-high-level-client 依赖,Spring Boot 会自动配置一个 RestHighLevelClient,它封装任何现有的 RestClient bean,重用其 HTTP 配置。

30.6.2 使用 Jest 连接 Elasticsearch

如果你的类路径上有 Jest,可以注入自动配置的 JestClient,它默认指向 localhost:9200。你可以进一步调整客户端配置的方式,如下面的示例所示:

spring.elasticsearch.jest.uris=http://search.example.com:9200
spring.elasticsearch.jest.read-timeout=10000
spring.elasticsearch.jest.username=user
spring.elasticsearch.jest.password=secret

你还可以注册任意数量的 bean,这些 bean 实现 HttpClientConfigBuilderCustomizer 用于更高级的自定义。下面的示例调整额外的 HTTP 设置:

static class HttpSettingsCustomizer implements HttpClientConfigBuilderCustomizer {

	@Override
	public void customize(HttpClientConfig.Builder builder) {
		builder.maxTotalConnection(100).defaultMaxTotalConnectionPerRoute(5);
	}

}

要完全控制注册,定义一个 JestClient bean。

30.6.3 使用 Spring Data 连接 Elasticsearch

为了连接到 Elasticsearch,你必须提供一个或多个集群节点的地址。可以通过设置 spring.data.elasticsearch.cluster-nodes 属性为逗号分隔的 host:port 列表来指定地址。使用此配置,ElasticsearchTemplate 或 TransportClient 可以像其它任何 Spring bean 一样注入,如下面的示例所示:

spring.data.elasticsearch.cluster-nodes=localhost:9300
@Component
public class MyBean {

	private final ElasticsearchTemplate template;

	public MyBean(ElasticsearchTemplate template) {
		this.template = template;
	}

	// ...

}

如果你添加了自己的 ElasticsearchTemplate 或 TransportClient @Bean,它将替换默认值。

30.6.4 Spring Data Elasticsearch 存储库

Spring Data 包括支持 Elasticsearch 的存储库。与前面所讨论的 JPA 存储库一样,其基本原理是,基于你的方法名称自动构建查询。

实际上,Spring Data JPA 和 Spring Data Elasticsearch 共享同样的公共基础内容,你可以拿来前面的 JPA 例子,假设 City 是一个 Elasticsearch @Document 类而不是 JPA @Entity,它将以同样的方式工作。

[Tip] Tip

有关 Spring Data Elasticsearch 的完整细节,请参阅参考文档。

30.7 Cassandra

Cassandra 是一个开源的分布式数据库管理系统,用于处理大量商业服务器上的大数据。Spring Boot 使用 Spring Data Cassandra 为 Cassandra 以及之上的抽象提供了自动配置。有一个 spring-boot-starter-data-cassandra 启动器为收集依赖提供了方便的方式。

30.7.1 连接 Cassandra

你可以像其它 Spring bean 一样,注入一个自动配置的 CassandraTemplate 或 Cassandra Session 实例。spring.data.cassandra.* 属性可以用于自定义连接。通常,你提供 keyspace-name 和 contact-points 属性,如下面的示例所示:

spring.data.cassandra.keyspace-name=mykeyspace
spring.data.cassandra.contact-points=cassandrahost1,cassandrahost2

下面的代码列表展示了如何注入一个 Cassandra bean:

@Component
public class MyBean {

	private CassandraTemplate template;

	@Autowired
	public MyBean(CassandraTemplate template) {
		this.template = template;
	}

	// ...

}

如果你添加了自己的 CassandraTemplate 类型的 @Bean,它将替换默认值。

30.7.2 Spring Data Cassandra 库

Spring Data 包含支持 Cassandra 的存储库。目前来说,这比前面讨论的 JPA 存储库更有限,需要用 @Query 来注解查询方法。

[Tip] Tip

有关 Spring Data Cassandra 的完整细节,请参阅参考文档。

30.8 Couchbase

Couchbase 是一个开源的、分布式的、多模型 NoSql 面向文档数据库,它是交互应用的最优方案。Spring Boot 使用 Spring Data Couchbase 为 Couchbase 和之上的抽象提供了自动配置。spring-boot-starter-data-couchbase 和 spring-boot-starter-data-couchbase-reactive 启动器为收集依赖提供了方便的方式。

30.8.1 连接 Couchbase

你可以通过添加 Couchbase SDK 和一些配置来获得一个 Bucket 和 Cluster。spring.couchbase.* 属性可用于自定义连接。通常,你提供 bootstrap hosts、bucket name 和 password,如下面的示例所示:

spring.couchbase.bootstrap-hosts=my-host-1,192.168.1.123
spring.couchbase.bucket.name=my-bucket
spring.couchbase.bucket.password=secret
[Tip] Tip

你至少需要提供 bootstrap host(s),在这种情况下,bucket name 是默认的,password 是空字符串。或者,你可以自定义 org.springframework.data.couchbase.config.CouchbaseConfigurer @Bean 来控制整个配置。

还可以自定义一些 CouchbaseEnvironment 设置。例如,以下配置更改打开新 Bucket 的超时时间和启用 SSL 支持:

spring.couchbase.env.timeouts.connect=3000
spring.couchbase.env.ssl.key-store=/location/of/keystore.jks
spring.couchbase.env.ssl.key-store-password=secret

查看 spring.couchbase.env.* 属性来获得更多细节。

30.8.2 Spring Data Couchbase 库

Spring Data 包含支持 Couchbase 的库。有关 Spring Data Couchbase 的完整细节,请参阅参考文档。

你可以像其它任何 Spring bean 一样,注入一个自动配置的 CouchbaseTemplate 实例,只要默认的 CouchbaseConfigurer 可用(当你启用 Couchbase 支持时,正如前面所描述的)。

下面的示例展示了如何注入一个 Couchbase bean:

@Component
public class MyBean {

	private final CouchbaseTemplate template;

	@Autowired
	public MyBean(CouchbaseTemplate template) {
		this.template = template;
	}

	// ...

}

你可以在自己的配置中定义一些 bean 来覆盖自动配置所提供的那些 bean:

  • 一个命名为 couchbaseTemplate 的 CouchbaseTemplate @Bean。
  • 一个命名为 couchbaseIndexManager 的 IndexManager @Bean。
  • 一个命名为 couchbaseCustomConversions 的 CustomConversions @Bean。

为了避免在自己的配置中对这些名称进行硬编码,可以重用 Spring Data Couchbase 提供的 BeanNames。例如,你可以自定义使用的转换器,如下:

@Configuration
public class SomeConfiguration {

	@Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
	public CustomConversions myCustomConversions() {
		return new CustomConversions(...);
	}

	// ...

}
[Tip] Tip

如果你想完全绕过 Spring Data Couchbase 的自动配置,请提供你自己的 org.springframework.data.couchbase.config.AbstractCouchbaseDataConfiguration 实现。

30.9 LDAP

LDAP (Lightweight Directory Access Protocol)是一种开放的,供应商中立的,行业标准的应用协议,用于访问和维护 IP 网络上的分布式目录信息服务。Spring Boot 为任何兼容的 LDAP 服务器提供了自动配置,并从 UnboundID 支持嵌入式内存 LDAP 服务器。

LDAP 抽象由 Spring Data LDAP 提供。spring-boot-starter-data-ldap 启动器以方便的方式提供收集依赖。

30.9.1 连接 LDAP 服务器

若要连接到 LDAP 服务器,请确保在 spring-boot-starter-data-ldap 启动器或 spring-ldap-core 上声明一个依赖,然后在 application.properties 中声明服务器的 URL,如下面的示例所示:

spring.ldap.urls=ldap://myserver:1235
spring.ldap.username=admin
spring.ldap.password=secret

如果需要自定义连接设置,你可以使用 spring.ldap.base 和 spring.ldap.base-environment 属性。

基于这些设置自动配置一个 LdapContextSource。如果你需要自定义它,例如使用 PooledContextSource,你仍然可以注入自动配置的 LdapContextSource。请确保标记你自定义的 ContextSource 为 @Primary,以便自动配置的 LdapTemplate 使用它。

30.9.2 Spring Data LDAP 存储库

Spring Data 包含支持 LDAP 的存储库。有关 Spring Data LDAP 的完整细节,请参阅参考文档。

你也可以像其它任何 Spring bean 一样注入一个自动配置的 LdapTemplate 实例,如下面的示例所示:

@Component
public class MyBean {

	private final LdapTemplate template;

	@Autowired
	public MyBean(LdapTemplate template) {
		this.template = template;
	}

	// ...

}

30.9.3 嵌入式内存 LDAP 服务器

为了测试的目的,Spring Boot 支持 UnboundID 的内存 LDAP 服务器的自动配置。若要配置服务器,请添加依赖到 com.unboundid:unboundid-ldapsdk,并声明一个 base-dn 属性,如下:

spring.ldap.embedded.base-dn=dc=spring,dc=io
[Note] Note

定义多个 base-dn 值是可能的,因为区分的名称通常包含逗号,它们必须使用正确的符号来定义。

在 yaml 文件中,可以使用 yaml 列表表示法:

spring.ldap.embedded.base-dn:
  - dc=spring,dc=io
  - dc=pivotal,dc=io

在 properties 文件中,必须将索引包含为属性名称的一部分:

spring.ldap.embedded.base-dn[0]=dc=spring,dc=io
spring.ldap.embedded.base-dn[1]=dc=pivotal,dc=io

默认情况下,服务器在随机端口启动,并触发常规 LDAP 支持。不需要指定 spring.ldap.urls 属性。

如果类路径上有一个 schema.ldif 文件,它用于初始化服务器。如果你要从不同的资源加载初始化脚本,还可以使用 spring.ldap.embedded.ldif 属性。

默认情况下,一个标准 scheam 用于验证 LDIF 文件。你可以通过设置 spring.ldap.embedded.validation.enabled 属性来完全关闭验证。如果你有自定义属性,可以使用 spring.ldap.embedded.validation.schema 来定义自定义属性类型或对象类。

30.10 InfluxDB

InfluxDB 是一个开源的时间序列数据库,用于在操作控制、应用度量、物联网传感器数据和实时分析等领域中对时间序列数据的快速、高可用性存储和检索进行优化。

30.10.1 连接 InfluxDB

Spring Boot 会自动配置一个 InfluxDB 实例,只要 influxdb-java 客户端在类路径上并且数据库的 URL 被设置了,如下面的示例所示:

spring.influx.url=http://172.0.0.1:8086

如果连接到 InfluxDB 需要一个用户和密码,则可以相应的设置 spring.influx.user 和 spring.influx.password 属性。

InfluxDB 依赖于 OkHttp。如果需要调整 http 客户端 InfluxDB 在后台使用,则可以注册 OkHttpClient.Builder bean。

31. 缓存

Spring Framework 为透明地向应用程序添加缓存提供了支持。在其核心上,抽象的将缓存应用于方法,从而基于缓存中可用的信息来减少执行次数。缓存逻辑被透明地应用,对调用者没有任何干扰。Spring Boot 自动配置缓存基础结构,只要通过 @EnableCaching 注解启用缓存支持。

[Note] Note

查看 Spring Framework 参考的相关部分来获取更多细节。

简而言之,向服务的操作中添加缓存与向其方法添加相关注解一样简单,如下面的示例所示:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class MathService {

	@Cacheable("piDecimals")
	public int computePiDecimal(int i) {
		// ...
	}

}

这个示例展示了在潜在的高代价操作上使用缓存。在调用 computePiDecimal 之前,抽象查找与 i 参数匹配的 piDecimals 缓存中的条目。如果找到一个条目,则缓存中的内容立即返回给调用方,并且不会调用该方法。否则,调用该方法,并在返回值之前更新缓存。

[Caution] 警告

你还可以透明地使用标准 JSR-107 (JCache) 注解(例如@CacheResult )。但是,我们强烈建议你不要混合和匹配 Spring Cache 和 JCache 注解。

如果你不添加任何特定的缓存库,Spring Boot 将自动配置在内存中使用并发映射的简单提供者。当需要缓存时(例如前面示例中的 piDecimals),此提供者为你创建缓存。简单的提供者不推荐真正用于生成使用,但它是很好的开始,并确保你了解功能。当你决定要使用缓存提供者时,请务必阅读其文档,以了解如何配置应用程序使用的缓存。几乎所有的提供者都要求你显式配置应用程序中使用的每个缓存。有些提供了一种使用 spring.cache.cache-names 属性自定义默认缓存的定义。

[Tip] Tip

还可以从缓存中透明地 update 或 evict 数据。

31.1 支持的缓存提供者

缓存抽象不提供实际的存储,依赖于由 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口实现的抽象。

如果尚未定义 CacheManager 类型的 bean 或名为 cacheResolver 的 CacheResolver(参见 CachingConfigurer),Spring Boot 尝试检测以下提供者(按指示的顺序):

  1. Generic
  2. JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, 和其它)
  3. EhCache 2.x
  4. Hazelcast
  5. Infinispan
  6. Couchbase
  7. Redis
  8. Caffeine
  9. Simple
[Tip] Tip

还可以通过设置 spring.cache.type 属性来强制指定缓存提供者。如果需要在某些环境中禁用缓存(例如测试),请使用此属性。

[Tip] Tip

使用 spring-boot-starter-cache 启动器快速添加基本的缓存依赖关系。启动器带来了 spring-context-support。如果手动添加依赖项,则必须使用 spring-context-support,以便使用 JCache、EhCache 2.x 或 Guava 支持。

如果 CacheManager 是由 Spring Boot 自动配置的,则可以通过暴露实现 CacheManagerCustomizer 接口的 bean 来进一步调整它的配置。下面的示例设置一个标志,表示应该将空值传递到底层映射:

@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
	return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
		@Override
		public void customize(ConcurrentMapCacheManager cacheManager) {
			cacheManager.setAllowNullValues(false);
		}
	};
}
[Note] Note

在前面的示例中,期望自动配置的 ConcurrentMapCacheManager。如果不是这样(无论你提供了自己的配置还是自动配置了不同的缓存提供者),都不会调用自定义程序。你可以有多个定制器,也可以使用 @Order 或 Ordered。

31.1.1 Generic

如果上下文至少定义了一个 org.springframework.cache.Cache bean,则使用 Generic 缓存。一种包含这种类型的 bean 的 CacheManager 被创建。

31.1.2 JCache (JSR-107)

JCache 通过在类路上存在 javax.cache.spi.CachingProvider(即在类路径上存在一个 JSR-107 兼容的缓存库)而被引导,而且 JCacheCacheManager 由 spring-boot-starter-cache 启动器提供。可以使用各种兼容库,Spring Boot 为 Ehcache 3、Hazelcast 和 Infinispan 提供依赖管理。也可以添加其它任何兼容的库。

可能出现不止一个提供者,在这种情况下,必须显式指定提供者。即使 JSR-107 标准不强制定义配置文件的位置的标准化方式,Spring Boot 尽其所能适应设置具有实现细节的缓存,如下面的示例所示:

   # Only necessary if more than one provider is present
spring.cache.jcache.provider=com.acme.MyCachingProvider
spring.cache.jcache.config=classpath:acme.xml
[Note] Note

当缓存库提供本地实现和 JSR-107 支持时,Spring Boot 更喜欢 JSR-107 支持,因此如果你切换到不同的 JSR-107 实现,则可以使用相同的特性。

[Tip] Tip

Spring Boot 对 Hazelcast 有广泛的支持。如果一个 HazelcastInstance 可用,则它也将自动重用到 CacheManager,除非指定了 spring.cache.jcache.config 属性。

有两种方法来定制底层的 javax.cache.cacheManager:

  • 可以通过设置 spring.cache.cache-names 属性来在启动时创建缓存。如果定义了自定义的 javax.cache.configuration.Configuration bean,则用于自定义它们。
  • org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer bean 与 CacheManager 的引用一起调用以进行完全定制。
[Tip] Tip

如果定义了一个标准的 javax.cache.CacheManager bean,它将自动封装在抽象期望的 org.springframework.cache.CacheManager 实现中。没有进一步的定制应用到它。

31.1.3 EhCache 2.x

如果在类路径的根中找到一个名为 ehcache.xml 的文件,则使用 EhCache 2.x。 如果找到了 EhCache 2.x,则由 spring-boot-starter-cache 启动器提供的 EhCacheCacheManager 用于引导缓存管理器。也可以提供备用配置文件,如下面的示例所示:

spring.cache.ehcache.config=classpath:config/another-config.xml

31.1.4 Hazelcast

Spring Boot 对 Hazelcast 广泛的支持。如果 HazelcastInstance 已经被自动配置,它将自动包装在 CacheManager 中。

31.1.5 Infinispan

Infinispan 没有默认的配置文件位置,因此必须显式指定。否则,使用默认引导程序。

spring.cache.infinispan.config=infinispan.xml

可以通过设置 spring.cache.cache-names 属性来在启动时创建缓存。如果定义了自定义 ConfigurationBuilder bean,则用于自定义缓存。

[Note] Note

在 Spring Boot 中,Infinispan 的支持局限于嵌入式模式,是非常基础的。如果你想要更多的选择,你应该使用官方的 Infinispan Spring Boot starter 来代替。有关更多细节,请参阅 Infinispan 的文档。

31.1.6 Couchbase

如果 Couchbase Java 客户端和 couchbase-spring-cache 实现可用,并且 Couchbase 被配置,则自动配置一个 CouchbaseCacheManager。还可以通过设置 spring.cache.cache-names 属性来在启动时创建额外的缓存。这些缓存操作在自动配置的 Bucket 上。还可以使用定制器在另一个 Bucket 上创建额外的缓存。假设在你在主 Bucket 上需要两个缓存(cache1 和 cache2)和一个自定义在另一个 Bucket 上存活2秒时间的缓存(cache3)。你可以通过配置创建前两个缓存,如下所示:

spring.cache.cache-names=cache1,cache2

然后,你可以定义一个 @Configuration 类来配置额外的 Bucket 和 cache3 缓存,如下:

@Configuration
public class CouchbaseCacheConfiguration {

	private final Cluster cluster;

	public CouchbaseCacheConfiguration(Cluster cluster) {
		this.cluster = cluster;
	}

	@Bean
	public Bucket anotherBucket() {
		return this.cluster.openBucket("another", "secret");
	}

	@Bean
	public CacheManagerCustomizer<CouchbaseCacheManager> cacheManagerCustomizer() {
		return c -> {
			c.prepareCache("cache3", CacheBuilder.newInstance(anotherBucket())
					.withExpiration(2));
		};
	}

}

此示例配置重用通过自动配置创建的群集。

31.1.7 Redis

如果 Redis 是可用的和配置的,则自动配置 RedisCacheManager。通过设置 spring.cache.cache-names 可以在启动时创建额外的缓存,并且默认值可以通过使用 spring.cache.redis.* 属性来配置。例如,以下配置创建 cache1 和 cache2 缓存,时间为10分钟:

spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=600000
[Note] Note

默认情况下,添加一个密钥前缀,这样,如果两个单独的缓存使用相同的密钥,Redis 就没有重叠的密钥,并且不能返回无效的值。我们强烈建议,如果你创建自己的 RedisCacheManager,请保持此设置。

[Tip] Tip

你可以通过添加一个 RedisCacheConfiguration @Bean 来完全控制配置。如果你正在寻找定制序列化策略,这可能是有用的。

31.1.8 Caffeine

Caffeine 是 Java 8 重写的 Guava 缓存,取代了对 Guava 的支持。如果 Caffeine 存在,CaffeineCacheManager(由 spring-boot-starter-cache 启动器提供)是自动配置的。可以通过 spring.cache.cache-names 属性以在启动时创建缓存,并且可以由以下之一定制(以指示的顺序):

  1. 由 spring.cache.caffeine.spec 定义的缓存规格
  2. 定义的 com.github.benmanes.caffeine.cache.CaffeineSpec bean
  3. 定义的 com.github.benmanes.caffeine.cache.Caffeine bean

例如,以下配置创建 cache1 和 cache2 缓存,最大大小为500,存在时间为10分钟

spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s

如果定义一个 com.github.benmanes.caffeine.cache.CacheLoader bean,它与 CaffeineCacheManager 自动关联。由于 CacheLoader 将与缓存管理器所管理的所有缓存相关联,所以必须将其定义为 CacheLoader<Object, Object>。自动配置忽略任何其它泛型类型。

31.1.9 Simple

如果找不到其它提供者,则配置使用 ConcurrentHashMap 作为缓存存储的简单实现。如果应用程序中没有缓存库,这作为为默认值。默认情况下,根据需要创建缓存,但可以通过设置 cache-names 属性来限制可用缓存的列表。例如,如果只需要 cache1 和 cache2 缓存,则将 cache-names 属性设置为:

spring.cache.cache-names=cache1,cache2

如果这样做,并且应用程序使用未列出的缓存,那么在需要缓存时,它将在运行时失败,而不是在启动时。这与使用“未声明缓存”的“真正”缓存提供者的行为类似。

31.1.10 None

当你的配置中存在 @EnableCaching 时,还需要一个合适的缓存配置。如果需要在某些环境中完全禁用缓存,则将缓存类型强制为 none 以使用 no-op 实现,如下面的示例所示:

spring.cache.type=none