本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

Spring Boot集成了许多Data技术,包括SQL和NoSQL。

1. SQL 数据库

Spring框架 为与SQL数据库的整合提供了广泛的支持,从使用 JdbcTemplate 的直接JDBC访问到完整的 “对象关系映射” (ORM)技术,如Hibernate。 Spring Data 提供了额外的功能:直接从接口创建 Repository 实现,并使用惯例从你的方法名中生成查询。

1.1. 配置一个 DataSource

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

参见 “How-to” "部分,以了解更多的高级例子,通常是对数据源的配置进行完全控制。

1.1.1. 嵌入式数据库的支持

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

“How-to” 部分包括一个关于如何初始化数据库的章节

Spring Boot可以自动配置嵌入式 H2HSQLDerby 数据库。你不需要提供任何连接URL。你只需要包括一个你想使用的嵌入式数据库的构建依赖。如果在classpath上有多个嵌入式数据库,设置 spring.datasource.embedded-database-connection 配置属性来控制使用哪一个。将该属性设置为 none,可以禁用嵌入式数据库的自动配置。

如果你在测试中使用这个功能,你可能会注意到,无论你使用多少个application context,整个测试套件都在重复使用同一个数据库。 如果你想确保每个上下文都有一个单独的嵌入式数据库,你应该把 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>
你需要 spring-jdbc 依赖,才能自动配置嵌入式数据库。 在这个例子中,它是通过 spring-boot-starter-data-jpa 过渡性依赖的。
如果出于某种原因,你确实为一个嵌入式数据库配置了连接URL,请注意确保数据库的自动关机功能被禁用。 如果你使用H2,你应该使用 DB_CLOSE_ON_EXIT=FALSE 来做到这一点。 如果你使用HSQLDB,你应该确保不使用 shutdown=true。 禁用数据库的自动关闭让Spring Boot控制数据库的关闭时间,从而确保一旦不再需要对数据库的访问,就会发生关闭。

1.1.2. 连接到生产数据库

生产数据库连接也可以通过使用池化的 DataSource 来自动配置。

1.1.3. 数据库配置

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

Properties
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
Yaml
spring:
  datasource:
    url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    password: "dbpass"
你至少应该通过设置 spring.datasource.url 属性来指定URL。 否则,Spring Boot会尝试自动配置一个嵌入式数据库。
Spring Boot可以从URL中推断出大多数数据库的 JDBC driver类。 如果你需要指定一个特定的类,你可以使用 spring.datasource.driver-class-name 属性。
为了创建一个池化的 DataSource,我们需要能够验证一个有效的 Driver 类是可用的,所以我们在做任何事情之前都要检查这个。 换句话说,如果你设置了 spring.datasource.driver-class-name=com.mysql.jdbc.Driver ,那么这个类就必须是可加载的。

参见 DataSourceProperties 以了解更多支持的选项。 这些是标准的选项,不管实际的实现是什么,都可以工作。 也可以通过使用各自的前缀(spring.datasource.hikari.*spring.datasource.tomcat.*spring.datasource.dbcp2.*,和 spring.datasource.oracleucp.*)来微调特定实现的设置。 更多细节请参见你所使用的连接池实现的文档。

例如,如果你使用 Tomcat连接池,你可以定制许多额外的设置,如下例所示。

Properties
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.test-on-borrow=true
Yaml
spring:
  datasource:
    tomcat:
      max-wait: 10000
      max-active: 50
      test-on-borrow: true

这将设置连接池在没有连接可用时等待10000ms后抛出一个异常,限制最大连接数为50,并在从连接池中获取连接前验证连接是否可用。

1.1.4. 支持的连接池

Spring Boot使用以下算法来选择特定的实现。

  1. 我们更喜欢 HikariCP,因为它的性能和并发性。如果HikariCP可用,我们总是选择它。

  2. 否则,如果 Tomcat DataSource 可用,我们就使用它。

  3. 否则,如果 Commons DBCP2 是可用的,我们就使用它。

  4. 如果HikariCP、Tomcat和DBCP2都不可用,如果Oracle UCP可用,我们就使用它。

如果你使用 spring-boot-starter-jdbcspring-boot-starter-data-jpa “starter”,你会自动依赖 HikariCP

你可以完全绕过这种算法,通过设置 spring.datasource.type 属性指定要使用的连接池。 如果你在Tomcat容器中运行你的应用程序,这一点尤其重要,因为 tomcat-jdbc 是默认提供的。

额外的连接池总是可以手动配置,使用 DataSourceBuilder。 如果你定义了你自己的 DataSource bean,自动配置就不会发生。 DataSourceBuilder 支持以下连接池。

  • HikariCP

  • Tomcat pooling Datasource

  • Commons DBCP2

  • Oracle UCP & OracleDataSource

  • Spring Framework’s SimpleDriverDataSource

  • H2 JdbcDataSource

  • PostgreSQL PGSimpleDataSource

  • C3P0

1.1.5. 连接到 JNDI 数据源

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

spring.datasource.jndi-name 属性可以作为spring.datasource.urlspring.datasource.usernamespring.datasource.password 属性的替代品,从特定JNDI位置访问 DataSource。 例如,application.properties 中的以下部分显示了如何访问 JBoss AS 定义的 DataSource

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

1.2. 使用 JdbcTemplate

Spring的 JdbcTemplateNamedParameterJdbcTemplate 类是自动配置的,你可以将它们直接 @Autowire 到你自己的Bean中,如下例所示。

Java
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final JdbcTemplate jdbcTemplate;

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

    public void doSomething() {
        this.jdbcTemplate ...
    }

}
Kotlin
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Component

@Component
class MyBean(private val jdbcTemplate: JdbcTemplate) {

    fun doSomething() {
        jdbcTemplate.execute("delete from customer")
    }

}

你可以通过使用 spring.jdbc.template.* 属性来定制模板的一些属性,如以下例子所示。

Properties
spring.jdbc.template.max-rows=500
Yaml
spring:
  jdbc:
    template:
      max-rows: 500
NamedParameterJdbcTemplate 在幕后重复使用同一个 JdbcTemplate 实例。 如果定义了一个以上的 JdbcTemplate,并且没有主要的候选者,NamedParameterJdbcTemplate 就不会被自动配置。

1.3. JPA 和 Spring Data JPA

Java Persistence API 是一项标准技术,它可以让你把对象 “映射” 到关系型数据库。 spring-boot-starter-data-jpa POM提供了一个快速入门的方法。 它提供了以下关键的依赖。

  • Hibernate:最流行的JPA实现之一。

  • Spring Data JPA:帮助你实现基于JPA的Repository。

  • Spring ORM:来自Spring框架的核心ORM支持。

我们在此不对JPA或 Spring Data 的细节进行过多的讨论。你可以参考 "用JPA访问数据" 指南,并阅读 Spring Data JPA 和Hibernate参考文档。

1.3.1. 实体类(Entity Classes)

传统上,JPA的 “Entity” 类是在 persistence.xml 文件中指定的。 在Spring Boot中,这个文件是不必要的,而是使用 “Entity Scanning”。 默认情况下,你的main配置类(用 @EnableAutoConfiguration@SpringBootApplication 注解的那个类)下面的所有包都会被搜索到。

任何用 @Entity@Embeddable@MappedSuperclass 注解的类都被考虑。 一个典型的实体类类似于下面的例子。

Java
import java.io.Serializable;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

@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 should not be used directly
    }

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

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

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

    // ... etc

}
Kotlin
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.Id
import java.io.Serializable

@Entity
class City : Serializable {

    @Id
    @GeneratedValue
    private val id: Long? = null

    @Column(nullable = false)
    var name: String? = null
        private set

    // ... etc
    @Column(nullable = false)
    var state: String? = null
        private set

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

    protected constructor() {
        // no-args constructor required by JPA spec
        // this one is protected since it should not be used directly
    }

    constructor(name: String?, state: String?) {
        this.name = name
        this.state = state
    }

}
你可以通过使用 @EntityScan 注解来定制实体扫描位置。参见 “howto.html” 的操作指南。

1.3.2. Spring Data JPA Repository

Spring Data JPA Repository 是你可以定义的接口,用于访问数据。JPA查询是由你的方法名称自动创建的。例如,一个 CityRepository 接口可能会声明一个 findAllByState(String state) 方法来查找给定州内的所有城市。

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

Spring Data Repository 通常继承自 RepositoryCrudRepository。如果你使用自动配置,会从包含你的main配置类(用 @EnableAutoConfiguration@SpringBootApplication 注解的那个类)的包中向下搜索 Repository。

下面的例子显示了一个典型的 Spring Data Repository 接口定义。

Java
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;

public interface CityRepository extends Repository<City, Long> {

    Page<City> findAll(Pageable pageable);

    City findByNameAndStateAllIgnoringCase(String name, String state);

}
Kotlin
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository

interface CityRepository : Repository<City?, Long?> {

    fun findAll(pageable: Pageable?): Page<City?>?

    fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): City?

}

Spring Data JPA Repository 支持三种不同的引导(bootstrap)模式:default, deferred(延迟) 和 lazy(懒加载)。 要启用 deferred 或lazy 引导,请将 spring.data.jpa.repositories.bootstrap-mode 属性分别设置为 deferredlazy。 当使用 deferred 或 lazy 引导时,自动配置的 EntityManagerFactoryBuilder 将使用上下文的 AsyncTaskExecutor(如果有)作为引导执行器。 如果存在多个,将使用名为 applicationTaskExecutor 的那个。

当使用延迟或懒惰引导时,确保在application context引导阶段后推迟对JPA基础设施的任何访问。 你可以使用 SmartInitializingSingleton 来调用任何需要JPA基础设施的初始化。 对于作为Spring Bean创建的JPA组件(如converter),使用 ObjectProvider 来延迟解决依赖关系(如果有)。

这里关于 Spring Data JPA 的内容仅仅是浅尝辄止。 关于完整的细节,请参阅 Spring Data JPA参考文档

1.3.3. Spring Data Envers Repository

如果 Spring Data Envers 可用,JPA Repository 会自动配置为支持典型的 Envers 查询。

要使用Spring Data Envers,请确保你的存储库扩展自 RevisionRepository,如以下例子所示。

Java
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.history.RevisionRepository;

public interface CountryRepository extends RevisionRepository<Country, Long, Integer>, Repository<Country, Long> {

    Page<Country> findAll(Pageable pageable);

}
Kotlin
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository
import org.springframework.data.repository.history.RevisionRepository

interface CountryRepository :
        RevisionRepository<Country?, Long?, Int>,
        Repository<Country?, Long?> {

    fun findAll(pageable: Pageable?): Page<Country?>?

}
更多细节,请查看 Spring Data Envers参考文档

1.3.4. 创建和删除JPA数据库

默认情况下,只有当你使用嵌入式数据库(H2、HSQL或Derby)时,才会自动创建JPA数据库。 你可以通过使用 spring.jpa.* 属性明确地配置JPA设置。 例如,为了创建和删除表,你可以在你的 application.properties 中添加以下一行。

Properties
spring.jpa.hibernate.ddl-auto=create-drop
Yaml
spring:
  jpa:
    hibernate.ddl-auto: "create-drop"
Hibernate自己的内部属性名称(如果你碰巧记得比较清楚的话)是 hibernate.hbm2ddl.auto。 你可以通过使用 spring.jpa.properties.* 来设置它,以及其他Hibernate的本地属性(在将它们添加到实体管理器(EntityManager)之前,前缀被剥离)。 下面一行显示了一个为Hibernate设置JPA属性的例子。
Properties
spring.jpa.properties.hibernate[globally_quoted_identifiers]=true
Yaml
spring:
  jpa:
    properties:
      hibernate:
        "globally_quoted_identifiers": "true"

前面的例子中的一行将 hibernate.globally_quoted_identifiers 属性的值 true 传递给Hibernate实体管理器(EntityManager)。

默认情况下,DDL的执行(或验证)会推迟到 ApplicationContext 启动之后。 还有一个 spring.jpa.generate-ddl 标志,但如果Hibernate自动配置处于激活状态,它就不会被使用,因为 ddl-auto 的设置更加细化。

1.3.5. 在视图(View)中打开EntityManager

如果你正在运行一个Web应用程序,Spring Boot默认注册 OpenEntityManagerInViewInterceptor 来应用 “Open EntityManager in View” 模式,以允许在Web视图中进行懒散加载。 如果你不想要这种行为,你应该在你的 application.properties 中把 spring.jpa.open-in-view 设置为 false

1.4. Spring Data JDBC

Spring Data包括对JDBC的Repository支持,并将为 CrudRepository 上的方法自动生成SQL。 对于更高级的查询,提供了一个 @Query 注解。

当必要的依赖在classpath上时,Spring Boot将自动配置Spring Data的JDBC Repository。 你可以单独添加 spring-boot-starter-data-jdbc 依赖来使用它们。 如果有必要,你可以通过添加 @EnableJdbcRepositories 注解或 JdbcConfiguration 子类到你的应用程序来控制Spring Data JDBC的配置。

关于Spring Data JDBC的完整细节,请参阅 参考文档

1.5. 使用H2的WEB控制台

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

  • 你正在开发一个基于Servlet的Web应用程序。

  • com.h2database:h2 位于classpath上。

  • 你正在使用Spring Boot的开发者工具

如果你不使用Spring Boot的开发者工具,但仍想利用H2的控制台,你可以配置 spring.h2.console.enabled 属性,设置 true
H2控制台只在开发过程中使用,所以你应该注意确保 spring.h2.console.enabled 在生产中不被设置为`true`。

1.5.1. 修改H2WEB控制台的访问路径(Path)

默认情况下,控制台的路径是 /h2-console。 你可以使用 spring.h2.console.path 属性来定制控制台的路径。

1.5.2. 在Spring Security应用中访问H2控制台

H2 Console使用Frame,由于它只用于开发,所以没有实施CSRF保护措施。 如果你的应用程序使用 Spring Security,你需要将其配置为

  • 禁用针对控制台的请求的CSRF保护。

  • 在来自控制台的响应中,将Header X-Frame-Options 设置为 SAMEORIGIN

关于 CSRFX-Frame-Options 头的更多信息可以在 Spring Security 参考指南中找到。

在简单的设置中,可以使用类似以下的 SecurityFilterChain

Java
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Profile("dev")
@Configuration(proxyBeanMethods = false)
public class DevProfileSecurityConfiguration {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    SecurityFilterChain h2ConsoleSecurityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher(PathRequest.toH2Console());
        http.authorizeHttpRequests(yourCustomAuthorization());
        http.csrf((csrf) -> csrf.disable());
        http.headers((headers) -> headers.frameOptions((frame) -> frame.sameOrigin()));
        return http.build();
    }


}
Kotlin
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain

@Profile("dev")
@Configuration(proxyBeanMethods = false)
class DevProfileSecurityConfiguration {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    fun h2ConsoleSecurityFilterChain(http: HttpSecurity): SecurityFilterChain {
        return http.authorizeHttpRequests(yourCustomAuthorization())
            .csrf { csrf -> csrf.disable() }
            .headers { headers -> headers.frameOptions { frameOptions -> frameOptions.sameOrigin() } }
            .build()
    }


}
H2控制台仅用于开发期间。 在生产中,禁用CSRF保护或允许网站使用Frame可能会产生严重的安全风险。
PathRequest.toH2Console() 在控制台的路径被定制后也会返回正确的请求匹配器(request matcher)。

1.6. 使用 jOOQ

jOOQ面向对象查询( jOOQ)是Data Geekery的一个流行产品,它从你的数据库中生成Java代码,让你通过其fluent的API建立类型安全的SQL查询。商业版和开源版都可以与Spring Boot一起使用。

1.6.1. 代码生成

为了使用jOOQ类型安全的查询,你需要从你的数据库schema中生成Java类。 你可以按照 jOOQ用户手册 中的说明进行操作。 如果你使用 jooq-codegen-maven 插件,同时使用 spring-boot-starter-parent “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>

1.6.2. 使用 DSLContext

jOOQ提供的fluent的API是通过 org.jooq.DSLContext 接口启动的。 Spring Boot将 DSLContext 自动配置为Spring Bean,并将其连接到你的应用程序 DataSource。 要使用 DSLContext,你可以注入它,如下面的例子所示。

Java
import java.util.GregorianCalendar;
import java.util.List;

import org.jooq.DSLContext;

import org.springframework.stereotype.Component;

import static org.springframework.boot.docs.data.sql.jooq.dslcontext.Tables.AUTHOR;

@Component
public class MyBean {

    private final DSLContext create;

    public MyBean(DSLContext dslContext) {
        this.create = dslContext;
    }


}
Kotlin
import org.jooq.DSLContext
import org.springframework.stereotype.Component
import java.util.GregorianCalendar

@Component
class MyBean(private val create: DSLContext) {


}
jOOQ手册倾向于使用一个名为 create 的变量来保存`DSLContext'。

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

Java
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);
Kotlin
fun authorsBornAfter1980(): List<GregorianCalendar> {
    return create.selectFrom<Tables.TAuthorRecord>(Tables.AUTHOR)
        .where(Tables.AUTHOR?.DATE_OF_BIRTH?.greaterThan(GregorianCalendar(1980, 0, 1)))
        .fetch(Tables.AUTHOR?.DATE_OF_BIRTH)
}

1.6.3. jOOQ SQL 方言(Dialect)

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

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

1.6.4. 定制 jOOQ

更高级的定制可以通过定义你自己的 DefaultConfigurationCustomizer bean来实现,它将在创建 org.jooq.Configuration @Bean 之前被调用。 这优先于任何由自动配置应用的东西。

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

1.7. 使用 R2DBC

响应式关系型数据库连接( R2DBC)项目为关系型数据库带来了响应式编程API。 R2DBC的 io.r2dbc.spi.Connection 提供了一种处理非阻塞数据库连接的标准方法。 连接是通过使用 ConnectionFactory 提供的,类似于jdbc的 DataSource

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

Properties
spring.r2dbc.url=r2dbc:postgresql://localhost/test
spring.r2dbc.username=dbuser
spring.r2dbc.password=dbpass
Yaml
spring:
  r2dbc:
    url: "r2dbc:postgresql://localhost/test"
    username: "dbuser"
    password: "dbpass"
你不需要指定driver class名称,因为Spring Boot从R2DBC的连接工厂发现中获取驱动。
至少应该提供URL。 在URL中指定的信息优先于单个属性,即 name, username, passwordpassword 和连接池选项。
“How-to” 部分包括一个关于如何初始化数据库的章节。

要定制由 ConnectionFactory 创建的连接,即设置你不想(或不能)在中央数据库配置中配置的特定参数,你可以使用 ConnectionFactoryOptionsBuilderCustomizer @Bean。 下面的例子显示了如何手动覆盖数据库端口,而其余的选项则来自应用程序的配置。

Java
import io.r2dbc.spi.ConnectionFactoryOptions;

import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyR2dbcConfiguration {

    @Bean
    public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer() {
        return (builder) -> builder.option(ConnectionFactoryOptions.PORT, 5432);
    }

}
Kotlin
import io.r2dbc.spi.ConnectionFactoryOptions
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyR2dbcConfiguration {

    @Bean
    fun connectionFactoryPortCustomizer(): ConnectionFactoryOptionsBuilderCustomizer {
        return ConnectionFactoryOptionsBuilderCustomizer { builder ->
            builder.option(ConnectionFactoryOptions.PORT, 5432)
        }
    }

}

下面的例子显示了如何设置一些PostgreSQL的连接选项。

Java
import java.util.HashMap;
import java.util.Map;

import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider;

import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyPostgresR2dbcConfiguration {

    @Bean
    public ConnectionFactoryOptionsBuilderCustomizer postgresCustomizer() {
        Map<String, String> options = new HashMap<>();
        options.put("lock_timeout", "30s");
        options.put("statement_timeout", "60s");
        return (builder) -> builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options);
    }

}
Kotlin
import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyPostgresR2dbcConfiguration {

    @Bean
    fun postgresCustomizer(): ConnectionFactoryOptionsBuilderCustomizer {
        val options: MutableMap<String, String> = HashMap()
        options["lock_timeout"] = "30s"
        options["statement_timeout"] = "60s"
        return ConnectionFactoryOptionsBuilderCustomizer { builder ->
            builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options)
        }
    }

}

当一个 ConnectionFactory bean可用时,常规的JDBC DataSource 自动配置就会退缩。 如果你想保留JDBC的 DataSource 自动配置,并能接受在响应式应用程序中使用阻塞的JDBC API的风险,在你的应用程序中的 @Configuration 类上添加 @Import(DataSourceAutoConfiguration.class) 来重新启用它。

1.7.1. 嵌入式数据库的支持

JDBC支持类似,Spring Boot可以自动配置嵌入式数据库以实现响应式使用。 你不需要提供任何连接URL。 你只需要包括一个你想使用的嵌入式数据库的构建依赖,如下面的例子所示。

<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-h2</artifactId>
    <scope>runtime</scope>
</dependency>

如果你在测试中使用这个功能,你可能会注意到,无论你使用多少个application context,整个测试套件都在重复使用同一个数据库。 如果你想确保每个上下文都有一个单独的嵌入式数据库,你应该把 spring.r2dbc.generate-unique-name 设置为 true

1.7.2. 使用 DatabaseClient

一个 DatabaseClient bean是自动配置的,你可以使用 @Autowire 注入到你自己的Bean中,如下面的例子所示。

Java
import java.util.Map;

import reactor.core.publisher.Flux;

import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final DatabaseClient databaseClient;

    public MyBean(DatabaseClient databaseClient) {
        this.databaseClient = databaseClient;
    }

    // ...

    public Flux<Map<String, Object>> someMethod() {
        return this.databaseClient.sql("select * from user").fetch().all();
    }

}
Kotlin
import org.springframework.r2dbc.core.DatabaseClient
import org.springframework.stereotype.Component
import reactor.core.publisher.Flux

@Component
class MyBean(private val databaseClient: DatabaseClient) {

    // ...

    fun someMethod(): Flux<Map<String, Any>> {
        return databaseClient.sql("select * from user").fetch().all()
    }

}

1.7.3. Spring Data R2DBC Repository

Spring Data R2DBC Repository 是你可以定义的访问数据的接口。 查询是由你的方法名称自动创建的。 例如,一个 CityRepository 接口可能会声明一个 findAllByState(String state) 方法,以找到一个给定州的所有城市。

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

Spring Data Repository 通常从 RepositoryCrudRepository 接口继承而来。 如果你使用自动配置,存储库将从包含你main配置类(用 @EnableAutoConfiguration@SpringBootApplication 注解的那个类)的包开始向下搜索。

下面的例子显示了一个典型的Spring Data Repository 接口定义。

Java
import reactor.core.publisher.Mono;

import org.springframework.data.repository.Repository;

public interface CityRepository extends Repository<City, Long> {

    Mono<City> findByNameAndStateAllIgnoringCase(String name, String state);

}
Kotlin
import org.springframework.data.repository.Repository
import reactor.core.publisher.Mono

interface CityRepository : Repository<City?, Long?> {

    fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): Mono<City?>?

}
这里仅仅介绍到了Spring Data R2DBC的皮毛。关于完整的细节,请参阅 Spring Data R2DBC参考文档

2. 使用NOSQL技术

Spring Data提供了额外的项目,帮助你访问各种如下的NoSQL技术。

Spring Boot为Redis、MongoDB、Neo4j、Elasticsearch、Cassandra、Couchbase、LDAP和InfluxDB提供自动配置。 此外, Spring Boot for Apache Geode 为Apache Geode提供自动配置。 你可以利用其他项目,但你必须自己配置它们。 参见 spring.io/projects/spring-data 的相应参考文档。

2.1. Redis

Redis 是一个缓存、message broker和功能丰富的kv数据库。Spring Boot为 LettuceJedis 客户端库以及Spring Data Redis(在这俩客户端之上提供的抽象)提供了基本的自动配置。

有一个 spring-boot-starter-data-redis “Starter”,用于以一种方便的方式收集依赖。 默认情况下,它使用 Lettuce。 该启动器可以处理传统的和响应式的应用程序。

我们还提供了一个 spring-boot-starter-data-redis-reactive “Starter”,以便与其他支持reactive的store一致。

2.1.1. 连接到 Redis

你可以像其他Spring Bean一样,注入一个自动配置的 RedisConnectionFactoryStringRedisTemplate 或 vanilla RedisTemplate 实例。

下面的列表显示了这样一个Bean的例子。

Java
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final StringRedisTemplate template;

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

    // ...

    public Boolean someMethod() {
        return this.template.hasKey("spring");
    }

}
Kotlin
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.stereotype.Component

@Component
class MyBean(private val template: StringRedisTemplate) {

    // ...

    fun someMethod(): Boolean {
        return template.hasKey("spring")
    }

}

默认情况下,实例会尝试连接到 localhost:6379 的 Redis 服务器。你可以使用 spring.data.redis.* 属性指定自定义的连接细节,如下面的例子中所示。

Properties
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.database=0
spring.data.redis.username=user
spring.data.redis.password=secret
Yaml
spring:
  data:
    redis:
      host: "localhost"
      port: 6379
      database: 0
      username: "user"
      password: "secret"
你也可以注册任意数量的实现 LettuceClientConfigurationBuilderCustomizer 的bean,以进行更高级的定制。 ClientResources 也可以使用 ClientResourcesBuilderCustomizer 进行定制。 如果你使用Jedis, JedisClientConfigurationBuilderCustomizer 也可用。 另外,你可以注册一个 RedisStandaloneConfigurationRedisSentinelConfigurationRedisClusterConfiguration 类型的bean来完全控制配置。

如果你添加你自己的任何自动配置类型的 @Bean,它将取代默认的类型(除了在 RedisTemplate 的情况下,当排除是基于bean名称 redisTemplate,而不是其类型)。

默认情况下,如果 commons-pool2 在classpath上,则自动配置一个连接池类型的connection factory。

自动配置的 RedisConnectionFactory 可以通过设置本例中所示的属性来配置为使用SSL与服务器进行通信:

Properties
spring.data.redis.ssl.enabled=true
Yaml
spring:
  data:
    redis:
      ssl:
        enabled: true

自定义SSL信任材料可以在 SSL bundle 中配置,并应用于 RedisConnectionFactory,如本例所示:

Properties
spring.data.redis.ssl.bundle=example
Yaml
spring:
  data:
    redis:
      ssl:
        bundle: "example"

2.2. MongoDB

MongoDB 是一个开源的NoSQL文档数据库,使用类似JSON的模式,而不是传统的基于表格的关系数据。Spring Boot为与MongoDB合作提供了一些便利,包括 spring-boot-starter-data-mongodbspring-boot-starter-data-mongodb-reactive “Starters”。

2.2.1. 连接到 MongoDB 数据库

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

Java
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final MongoDatabaseFactory mongo;

    public MyBean(MongoDatabaseFactory mongo) {
        this.mongo = mongo;
    }

    // ...

    public MongoCollection<Document> someMethod() {
        MongoDatabase db = this.mongo.getMongoDatabase();
        return db.getCollection("users");
    }

}
Kotlin
import com.mongodb.client.MongoCollection
import org.bson.Document
import org.springframework.data.mongodb.MongoDatabaseFactory
import org.springframework.stereotype.Component

@Component
class MyBean(private val mongo: MongoDatabaseFactory) {

    // ...

    fun someMethod(): MongoCollection<Document> {
        val db = mongo.mongoDatabase
        return db.getCollection("users")
    }

}

如果你定义了自己的 MongoClient,它将被用来自动配置一个合适的 MongoDatabaseFactory

自动配置的 MongoClient 是使用 MongoClientSettings bean创建的。 如果你已经定义了你自己的 MongoClientSettings ,它将被使用而无需修改, spring.data.mongodb 属性将被忽略。 否则,MongoClientSettings 将被自动配置,并将有 spring.data.mongodb 属性应用到它。 在这两种情况下,你可以声明一个或多个 MongoClientSettingsBuilderCustomizer Bean来微调 MongoClientSettings 的配置。 每一个都将与用于构建 MongoClientSettingsMongoClientSettings.Builder 一起被依次调用。

你可以设置 spring.data.mongodb.uri 属性来改变URL和配置额外的设置,如 replica set,如下例所示。

Properties
spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test
Yaml
spring:
  data:
    mongodb:
      uri: "mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test"

另外,你可以使用离散的properties指定连接细节。 例如,你可以在你的 application.properties 中声明以下设置。

Properties
spring.data.mongodb.host=mongoserver1.example.com
spring.data.mongodb.port=27017
spring.data.mongodb.additional-hosts[0]=mongoserver2.example.com:23456
spring.data.mongodb.database=test
spring.data.mongodb.username=user
spring.data.mongodb.password=secret
Yaml
spring:
  data:
    mongodb:
      host: "mongoserver1.example.com"
      port: 27017
      additional-hosts:
      - "mongoserver2.example.com:23456"
      database: "test"
      username: "user"
      password: "secret"

自动配置的 MongoClient 可以通过设置本例中所示的属性来配置为使用SSL与服务器进行通信:

Properties
spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test
spring.data.mongodb.ssl.enabled=true
Yaml
spring:
  data:
    mongodb:
      uri: "mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test"
      ssl:
        enabled: true

自定义SSL信任材料可以配置在一个 SSL bundle 中,并应用于 MongoClient,如本例所示:

Properties
spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test
spring.data.mongodb.ssl.bundle=example
Yaml
spring:
  data:
    mongodb:
      uri: "mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test"
      ssl:
        bundle: "example"

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

你也可以使用 host:port 语法,将端口作为主机地址的一部分来指定。 如果你需要改变一个 additional-hosts entry的端口,应该使用这种格式。

如果你不使用Spring Data MongoDB,你可以注入一个 MongoClient bean,而不是使用 MongoDatabaseFactory。 如果你想完全控制建立MongoDB连接,你也可以声明你自己的 MongoDatabaseFactoryMongoClient bean。
如果你使用的是响应式驱动,SSL需要Netty。 如果Netty是可用的,并且要使用的factory还没有被定制,自动配置会自动配置这个factory。

2.2.2. MongoTemplate

Spring Data MongoDB 提供了一个 MongoTemplate 类,其设计与Spring的 JdbcTemplate 非常相似。 与 JdbcTemplate 一样,Spring Boot为你自动配置了一个Bean来注入template,如下所示。

Java
import com.mongodb.client.MongoCollection;
import org.bson.Document;

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final MongoTemplate mongoTemplate;

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

    // ...

    public MongoCollection<Document> someMethod() {
        return this.mongoTemplate.getCollection("users");
    }

}
Kotlin
import com.mongodb.client.MongoCollection
import org.bson.Document
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.stereotype.Component

@Component
class MyBean(private val mongoTemplate: MongoTemplate) {

    // ...

    fun someMethod(): MongoCollection<Document> {
        return mongoTemplate.getCollection("users")
    }

}

请参阅 MongoOperations Javadoc 以了解完整的细节。

2.2.3. Spring Data MongoDB Repository

Spring Data包括对MongoDB的Repository支持。 与前面讨论的JPA Repository一样,其基本原则是根据方法名称自动构建查询。

事实上,Spring Data JPA和Spring Data MongoDB都共享相同的公共基础设施。 你可以采用前面的JPA例子,假设 City 现在是MongoDB的数据类,而不是JPA的 @Entity,它的工作方式也是一样的,如下例所示。

Java
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;

public interface CityRepository extends Repository<City, Long> {

    Page<City> findAll(Pageable pageable);

    City findByNameAndStateAllIgnoringCase(String name, String state);

}
Kotlin
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository

interface CityRepository :
    Repository<City?, Long?> {
    fun findAll(pageable: Pageable?): Page<City?>?
    fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): City?
}
你可以通过使用 @EntityScan 注解来定制文件扫描位置。
关于Spring Data MongoDB的完整细节,包括其丰富的对象映射技术,请参阅其 参考文档

2.3. Neo4j

Neo4j 是一个开源的NoSQL图数据库,它使用由第一类关系连接的节点的丰富数据模型,比传统的RDBMS方法更适合连接大数据。Spring Boot为与Neo4j的合作提供了一些便利,包括 spring-boot-starter-data-neo4j “Starter”。

2.3.1. 连接到 Neo4j 数据库

为了访问Neo4j服务器,你可以注入一个自动配置的 org.neo4j.driver.Driver。 默认情况下,实例会尝试使用Bolt协议连接到 localhost:7687 的Neo4j服务器。 下面的例子显示了如何注入一个Neo4j的 Driver`,让你可以访问 Session,除此之外。

Java
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.Values;

import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final Driver driver;

    public MyBean(Driver driver) {
        this.driver = driver;
    }

    // ...

    public String someMethod(String message) {
        try (Session session = this.driver.session()) {
            return session.executeWrite(
                    (transaction) -> transaction
                        .run("CREATE (a:Greeting) SET a.message = $message RETURN a.message + ', from node ' + id(a)",
                                Values.parameters("message", message))
                        .single()
                        .get(0)
                        .asString());
        }
    }

}
Kotlin
import org.neo4j.driver.*
import org.springframework.stereotype.Component

@Component
class MyBean(private val driver: Driver) {

    // ...

    fun someMethod(message: String?): String {
        driver.session().use { session ->
            return@someMethod session.executeWrite { transaction: TransactionContext ->
                transaction
                    .run(
                        "CREATE (a:Greeting) SET a.message = \$message RETURN a.message + ', from node ' + id(a)",
                        Values.parameters("message", message)
                    )
                    .single()[0].asString()
            }
        }
    }

}

你可以使用 spring.neo4j.* 属性来配置driver程序的各个方面。 下面的例子显示了如何配置要使用的URI和凭证。

Properties
spring.neo4j.uri=bolt://my-server:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
Yaml
spring:
  neo4j:
    uri: "bolt://my-server:7687"
    authentication:
      username: "neo4j"
      password: "secret"

自动配置的 Driver 是使用 ConfigBuilder 创建的。 为了微调它的配置,声明一个或多个 ConfigBuilderCustomizer Bean。 每一个都将与用于创建 DriverConfigBuilder 一起被依次调用。

2.3.2. Spring Data Neo4j Repository

Spring Data包括对Neo4j的存储库支持。 关于Spring Data Neo4j的完整细节,请参阅 参考文档

Spring Data Neo4j与Spring Data JPA共享共同的基础架构,就像许多其他Spring Data模块那样。 你可以采用前面的JPA例子,将 City 定义为Spring Data Neo4j的 @Node,而不是JPA的 @Entity,Repository的抽象以同样的方式工作,如下例所示。

Java
import java.util.Optional;

import org.springframework.data.neo4j.repository.Neo4jRepository;

public interface CityRepository extends Neo4jRepository<City, Long> {

    Optional<City> findOneByNameAndState(String name, String state);

}
Kotlin
import org.springframework.data.neo4j.repository.Neo4jRepository
import java.util.Optional

interface CityRepository : Neo4jRepository<City?, Long?> {

    fun findOneByNameAndState(name: String?, state: String?): Optional<City?>?

}

spring-boot-starter-data-neo4j “Starter” 实现了 repository 支持和事务管理。 Spring Boot使用 Neo4jTemplateReactiveNeo4jTemplate Bean,支持经典和响应式Neo4j repository。 当Project Reactor在classpath上可用时,响应式也会自动配置。

你可以通过在 @Configuration-bean 上使用 @EnableNeo4jRepositories@EntityScan 分别自定义查找repository和entity的位置。

在使用响应式的应用程序中,ReactiveTransactionManager 不是自动配置的。 为了启用事务管理,必须在你的配置中定义以下Bean。

Java
import org.neo4j.driver.Driver;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;

@Configuration(proxyBeanMethods = false)
public class MyNeo4jConfiguration {

    @Bean
    public ReactiveNeo4jTransactionManager reactiveTransactionManager(Driver driver,
            ReactiveDatabaseSelectionProvider databaseNameProvider) {
        return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider);
    }

}
Kotlin
import org.neo4j.driver.Driver
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager

@Configuration(proxyBeanMethods = false)
class MyNeo4jConfiguration {

    @Bean
    fun reactiveTransactionManager(driver: Driver,
            databaseNameProvider: ReactiveDatabaseSelectionProvider): ReactiveNeo4jTransactionManager {
        return ReactiveNeo4jTransactionManager(driver, databaseNameProvider)
    }
}

2.4. Elasticsearch

Elasticsearch 是一个开源、分布式、RESTful搜索和分析引擎。Spring Boot为Elasticsearch客户端提供了基本的自动配置功能。

Spring Boot支持多个客户端。

  • 官方低级别的REST客户端(low-level REST client)

  • 官方的Java API客户端

  • Spring Data Elasticsearch 提供的 ReactiveElasticsearchClient

Spring Boot提供了一个专门的 "Starter",即 spring-boot-starter-data-elasticsearch

2.4.1. 使用REST客户端连接到Elasticsearch

Elasticsearch提供了两种不同的REST客户端,你可以用它们来查询集群:org.elasticsearch.client:elasticsearch-rest-client 模块的 low-level clientco.elastic.clients:elasticsearch-java 模块的 Java API client。此外,Spring Boot还提供了对 org.springframework.data:spring-data-elasticsearch 模块的响应式客户端的支持。默认情况下,客户端请求 localhost:9200 。你可以使用 spring.elasticsearch.* 属性来进一步调整客户端的配置方式,如下面的例子所示。

Properties
spring.elasticsearch.uris=https://search.example.com:9200
spring.elasticsearch.socket-timeout=10s
spring.elasticsearch.username=user
spring.elasticsearch.password=secret
Yaml
spring:
  elasticsearch:
    uris: "https://search.example.com:9200"
    socket-timeout: "10s"
    username: "user"
    password: "secret"
使用 RestClient 连接到 Elasticsearch

如果你在classpath上有 elasticsearch-rest-client,Spring Boot会自动配置并注册一个 RestClient Bean。 除了前面描述的属性外,为了微调 RestClient,你可以注册任意数量的bean,实现 RestClientBuilderCustomizer,进行更高级的定制。 要完全控制客户端的配置,请定义一个 RestClientBuilder bean。

此外,如果 elasticsearch-rest-client-sniffer 在classpath上,就会自动配置 Sniffer,从运行中的Elasticsearch集群中自动发现节点,并将其设置在 RestClient bean上。 你可以进一步调整 Sniffer 的配置方式,如以下例子所示。

Properties
spring.elasticsearch.restclient.sniffer.interval=10m
spring.elasticsearch.restclient.sniffer.delay-after-failure=30s
Yaml
spring:
  elasticsearch:
    restclient:
      sniffer:
        interval: "10m"
        delay-after-failure: "30s"
使用 ElasticsearchClient 连接到 Elasticsearch

如果你在classpath上有 co.elastic.clients:elasticsearch-java,Spring Boot会自动配置并注册一个 ElasticsearchClient bean。

ElasticsearchClient 使用的是依赖于之前描述的 RestClient 的transport。 因此,前面描述的属性可以用来配置 ElasticsearchClient。 此外,你可以定义一个 TransportOptions bean来进一步控制transport的行为。

使用 ReactiveElasticsearchClient 连接到 Elasticsearch

Spring Data Elasticsearch提供了 ReactiveElasticsearchClient,用于以响应式方式查询Elasticsearch实例。 如果你在classpath上有Spring Data Elasticsearch和Reactor,Spring Boot会自动配置并注册一个 ReactiveElasticsearchClient

ReactiveElasticsearchclient 使用的是依赖于之前描述的 RestClient 的transport。 因此,前面描述的属性可以用来配置 ReactiveElasticsearchClient。 此外,你还可以定义一个 TransportOptions bean来进一步控制transport的行为。

2.4.2. 使用 Spring Data 连接到 Elasticsearch

要连接到Elasticsearch,必须定义一个 ElasticsearchClient bean。 Spring Boot自动配置或由应用程序手动提供(见前几节)。 有了这个配置,一个 ElasticsearchTemplate 可以像其他Spring Bean一样被注入。 如下面的例子所示。

Java
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final ElasticsearchTemplate template;

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

    // ...

    public boolean someMethod(String id) {
        return this.template.exists(id, User.class);
    }

}
Kotlin
import org.springframework.stereotype.Component

@Component
class MyBean(private val template: org.springframework.data.elasticsearch.client.erhlc.ElasticsearchRestTemplate ) {

    // ...

    fun someMethod(id: String): Boolean {
        return template.exists(id, User::class.java)
    }

}

在有 spring-data-elasticsearch 和Reactor的情况下,Spring Boot还可以自动配置 ReactiveElasticsearchClientReactiveElasticsearchTemplate 作为Bean。它们相当于其他REST客户端的响应式。

2.4.3. Spring Data Elasticsearch Repository

Spring Data包括对Elasticsearch的Repository支持。 与前面讨论的JPA Repository一样,其基本原理是根据方法名称自动为你构建查询。

事实上,Spring Data JPA和Spring Data Elasticsearch共享相同的基础设施。 你可以用前面的JPA例子,假设 City 现在是Elasticsearch的 @Document 类,而不是JPA的 @Entity,它的工作方式是一样的。

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

Spring Boot使用 ElasticsearchRestTemplateReactiveElasticsearchTemplate Bean,支持经典和响应式Elasticsearch Repository。 考虑到所需的依赖,这些Bean很可能是由Spring Boot自动配置的。

如果你想使用你自己的模板来支持Elasticsearch repository,你可以添加你自己的 ElasticsearchRestTemplateElasticsearchOperations @Bean,只要它的名字是 "elasticsearchTemplate"。 同样适用于 ReactiveElasticsearchTemplateReactiveElasticsearchOperations,bean名称为 "reactiveElasticsearchTemplate"

你可以选择用以下属性禁用repository支持。

Properties
spring.data.elasticsearch.repositories.enabled=false
Yaml
spring:
  data:
    elasticsearch:
      repositories:
        enabled: false

2.5. Cassandra

Cassandra 是一个开源的分布式数据库管理系统,旨在处理许多商品服务器上的大量数据。Spring Boot为Cassandra和Spring Data Cassandra提供的上面的抽象提供自动配置。有一个 spring-boot-starter-data-cassandra “Starter”,可以方便地收集依赖关系。

2.5.1. 连接到 Cassandra

你可以像对待其他Spring Bean一样,注入一个自动配置的 CassandraTemplate 或Cassandra CqlSession 实例。 spring.cassandra.* 属性可用于定制连接。 一般来说,你提供 keyspace-namecontact-points 以及本地数据中心名称,如下例所示。

Properties
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.contact-points=cassandrahost1:9042,cassandrahost2:9042
spring.cassandra.local-datacenter=datacenter1
Yaml
spring:
  cassandra:
    keyspace-name: "mykeyspace"
    contact-points: "cassandrahost1:9042,cassandrahost2:9042"
    local-datacenter: "datacenter1"

如果你的所有contact point的端口都是一样的,你可以使用一个快捷方式,只指定主机名,如下例所示。

Properties
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.contact-points=cassandrahost1,cassandrahost2
spring.cassandra.local-datacenter=datacenter1
Yaml
spring:
  cassandra:
    keyspace-name: "mykeyspace"
    contact-points: "cassandrahost1,cassandrahost2"
    local-datacenter: "datacenter1"
这两个例子是相同的,因为端口默认为 9042。 如果你需要配置端口,请使用 spring.cassandra.port

自动配置的 CqlSession 可以被配置为使用SSL与服务器进行通信,方法是如本例中所示设置属性:

Properties
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.contact-points=cassandrahost1,cassandrahost2
spring.cassandra.local-datacenter=datacenter1
spring.cassandra.ssl.enabled=true
Yaml
spring:
  cassandra:
    keyspace-name: "mykeyspace"
    contact-points: "cassandrahost1,cassandrahost2"
    local-datacenter: "datacenter1"
    ssl:
      enabled: true

自定义SSL信任材料可以在 SSL bundle 中配置并应用于 CqlSession,如本例所示:

Properties
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.contact-points=cassandrahost1,cassandrahost2
spring.cassandra.local-datacenter=datacenter1
spring.cassandra.ssl.bundle=example
Yaml
spring:
  cassandra:
    keyspace-name: "mykeyspace"
    contact-points: "cassandrahost1,cassandrahost2"
    local-datacenter: "datacenter1"
    ssl:
      bundle: "example"

Cassandra驱动有自己的配置基础设施,在classpath的根部加载一个 application.conf

Spring Boot默认不会寻找这样的文件,但可以使用 spring.cassandra.config 加载一个文件。 如果一个属性同时存在 于 spring.cassandra.* 和配置文件中,则以 spring.cassandra.* 中的值为优先。

对于更高级的驱动定制,你可以注册任意数量的实现了 DriverConfigLoaderBuilderCustomizer 的bean。 CqlSession 可以用 CqlSessionBuilderCustomizer 类型的Bean来定制。

如果你使用 CqlSessionBuilder 来创建多个 CqlSession Bean,请记住该Builder是可变的,所以确保为每个session注入一个新的副本。

下面的代码列表显示了如何注入一个 Cassandra Bean。

Java
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final CassandraTemplate template;

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

    // ...

    public long someMethod() {
        return this.template.count(User.class);
    }

}
Kotlin
import org.springframework.data.cassandra.core.CassandraTemplate
import org.springframework.stereotype.Component

@Component
class MyBean(private val template: CassandraTemplate) {

    // ...

    fun someMethod(): Long {
        return template.count(User::class.java)
    }

}

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

2.5.2. Spring Data Cassandra Repository

Spring Data 包括对 Cassandra 的 basic repository 支持。 目前,这比前面讨论的JPA repository 更为有限,需要用 @Query 来注解查找方法。

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

2.6. Couchbase

Couchbase 是一个开源的、分布式的、多模型的、面向文档的NoSQL数据库,为交互式应用进行了优化。Spring Boot为Couchbase提供了自动配置,以及 Spring Data Couchbase 所提供的在其之上的抽象。有 spring-boot-starter-data-couchbasespring-boot-starter-data-couchbase-reactive “Starters”,用于以方便的方式收集依赖关系。

2.6.1. 连接到 Couchbase

你可以通过添加Couchbase SDK和一些配置来获得一个 Clusterspring.couchbase.* 属性可以用来定制连接。一般来说,你提供 connection string、用户名和密码,如下例所示。

Properties
spring.couchbase.connection-string=couchbase://192.168.1.123
spring.couchbase.username=user
spring.couchbase.password=secret
Yaml
spring:
  couchbase:
    connection-string: "couchbase://192.168.1.123"
    username: "user"
    password: "secret"

也可以定制一些 ClusterEnvironment 的设置。

例如,下面的配置改变了打开一个新 Bucket 的超时时间,并通过对配置的 SSL bundle 的引用来启用SSL支持:

Properties
spring.couchbase.env.timeouts.connect=3s
spring.couchbase.env.ssl.bundle=example
Yaml
spring:
  couchbase:
    env:
      timeouts:
        connect: "3s"
      ssl:
        bundle: "example"
检查 spring.couchbase.env.* 属性以了解更多细节。 为了获得更多的控制权,可以使用一个或多个`ClusterEnvironmentBuilderCustomizer` Bean。

2.6.2. Spring Data Couchbase Repository

Spring Data包括对Couchbase的存储库支持。 关于Spring Data Couchbase的完整细节,请参阅 参考文档

你可以像对待其他Spring Bean一样注入一个自动配置的 CouchbaseTemplate 实例,前提是有一个 CouchbaseClientFactory bean可用。 这发生在如上所述的 Cluster 可用的情况下,并且已经指定了一个bucker的名称。

Properties
spring.data.couchbase.bucket-name=my-bucket
Yaml
spring:
  data:
    couchbase:
      bucket-name: "my-bucket"

下面的例子显示了如何注入一个 CouchbaseTemplate bean。

Java
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final CouchbaseTemplate template;

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

    // ...

    public String someMethod() {
        return this.template.getBucketName();
    }

}
Kotlin
import org.springframework.data.couchbase.core.CouchbaseTemplate
import org.springframework.stereotype.Component

@Component
class MyBean(private val template: CouchbaseTemplate) {

    // ...

    fun someMethod(): String {
        return template.bucketName
    }

}

你可以在自己的配置中定义一些Bean,以覆盖自动配置所提供的Bean。

  • 一个 CouchbaseMappingContext @Bean,名称为 couchbaseMappingContext

  • 一个 CustomConversions @Bean,名字为 couchbaseCustomConversions

  • 一个 CouchbaseTemplate @Bean,名字为 couchbaseTemplate

为了避免在自己的配置中硬编码这些名称,你可以重用Spring Data Couchbase提供的 BeanNames。 例如,你可以自定义要使用的converter,如下所示。

Java
import org.assertj.core.util.Arrays;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;

@Configuration(proxyBeanMethods = false)
public class MyCouchbaseConfiguration {

    @Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
    public CouchbaseCustomConversions myCustomConversions() {
        return new CouchbaseCustomConversions(Arrays.asList(new MyConverter()));
    }

}
Kotlin
import org.assertj.core.util.Arrays
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.couchbase.config.BeanNames
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions

@Configuration(proxyBeanMethods = false)
class MyCouchbaseConfiguration {

    @Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
    fun myCustomConversions(): CouchbaseCustomConversions {
        return CouchbaseCustomConversions(Arrays.asList(MyConverter()))
    }

}

2.7. LDAP

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

LDAP的抽象是由 Spring Data LDAP 提供的。有一个 spring-boot-starter-data-ldap “Starter”,可以方便地收集依赖关系。

2.7.1. 连接到 LDAP 服务器

要连接到LDAP服务器,确保你声明了对 spring-boot-starter-data-ldap “Starter” 或 spring-ldap-core 的依赖,然后在你的 application.properties 中声明服务器的URL,如以下例子所示。

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

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

LdapContextSource 是根据这些设置自动配置的。如果 DirContextAuthenticationStrategy Bean可用,它就会与自动配置的 LdapContextSource 关联。如果你需要定制它,例如使用 PooledContextSource,你仍然可以注入自动配置的 LdapContextSource。请确保将你定制的 ContextSource 标记为 @Primary,以便自动配置的 LdapTemplate 使用它。

2.7.2. Spring Data LDAP Repository

Spring Data包括对LDAP的repository支持。关于Spring Data LDAP的完整细节,请参阅 参考文档

你也可以像对待其他Spring Bean一样,注入一个自动配置的 LdapTemplate 实例,如下例所示。

Java
import java.util.List;

import org.springframework.ldap.core.LdapTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final LdapTemplate template;

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

    // ...

    public List<User> someMethod() {
        return this.template.findAll(User.class);
    }

}
Kotlin
import org.springframework.ldap.core.LdapTemplate
import org.springframework.stereotype.Component

@Component
class MyBean(private val template: LdapTemplate) {

    // ...

    fun someMethod(): List<User> {
        return template.findAll(User::class.java)
    }

}

2.7.3. 嵌入式内存中的LDAP服务器

出于测试目的,Spring Boot支持从 UnboundID 自动配置内存中的LDAP服务器。要配置服务器,请向 com.unboundid:unboundid-ldapsdk 添加依赖关系,并声明spring.ldap.embedded.base-dn 属性,如下所示。

Properties
spring.ldap.embedded.base-dn=dc=spring,dc=io
Yaml
spring:
  ldap:
    embedded:
      base-dn: "dc=spring,dc=io"

可以定义多个base-dn值,但是,由于区分的名称通常包含逗号,所以必须使用正确的符号来定义。

在yaml文件中,你可以使用yaml列表符号。在properties文件中,你必须将索引作为属性名称的一部分。

Properties
spring.ldap.embedded.base-dn[0]=dc=spring,dc=io
spring.ldap.embedded.base-dn[1]=dc=vmware,dc=com
Yaml
spring.ldap.embedded.base-dn:
  - "dc=spring,dc=io"
  - "dc=vmware,dc=com"

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

如果你的classpath上有一个 schema.ldif 文件,它将被用来初始化服务器。 如果你想从不同的资源加载初始化脚本,你也可以使用 spring.ldap.embedded.ldif 属性。

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

2.8. InfluxDB

InfluxDB 是一个开源的时间序列数据库,为快速、高可用性地存储和检索运营监测、应用指标、物联网传感器数据和实时分析等领域的时间序列数据而优化。

2.8.1. 连接到 InfluxDB

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

Properties
spring.influx.url=https://172.0.0.1:8086
Yaml
spring:
  influx:
    url: "https://172.0.0.1:8086"

如果连接到InfluxDB需要用户和密码,你可以相应地设置 spring.influx.userspring.influx.password 属性。

InfluxDB依赖于OkHttp。 如果你需要调整 InfluxDB 在幕后使用的http客户端,你可以注册一个 InfluxDbOkHttpClientBuilderProvider bean。

如果你需要对配置进行更多的控制,可以考虑注册一个 InfluxDbCustomizer bean。

3. 接下来读什么

现在你应该对如何使用Spring Boot与各种Data技术有了感觉。从这里,你可以了解到Spring Boot对各种消息传递技术的支持,以及如何在你的应用程序中启用这些技术。