Spring Boot 3.1中的ConnectionDetails类详解


如果你已经使用了一段时间的Spring Boot,你可能对使用属性设置连接细节很熟悉。例如,你可能已经使用spring.datasource.url来配置JDBC连接。在Spring Boot 3.1中,这仍然像你所期望的那样工作,但Spring在引擎盖下做了一些改变,将自动配置与属性解耦

现在有了一个新的ConnectionDetails抽象。这个接口模拟了连接到远程服务的概念。如果你看一下这个接口,你会发现它是空的。它作为一个标记接口,并由其他多个接口扩展,这些接口对具体的远程服务的连接进行建模,例如,RedisConnectionDetails用于与Redis服务器的连接,JdbcConnectionDetails用于通过JDBC与数据库服务器的连接。

我们添加ConnectionDetails抽象主要是为了支持我们全新的Docker Compose和Testcontainers功能,我们将在随后的博客文章中深入介绍。但这个抽象并不只限于Docker Compose或Testcontainers。
Spring Boot中的自动配置已经改为使用ConnectionDetails,如果它们可用的话。在这种情况下,它们甚至会优先于配置属性。
如果没有这样的ConnectionDetails Bean,那么就会使用属性。

JdbcConnectionDetails:

public interface JdbcConnectionDetails extends ConnectionDetails {

  String getUsername();

  String getPassword();

  String getJdbcUrl();

}

这是Spring Boot需要知道的所有信息,以便连接到JDBC数据库。URL包含要使用的JDBC驱动程序、要连接的主机、要使用的端口等。用户名和密码是认证所需的。这相当于设置 spring.datasource.url、spring.datasource.username 和 spring.datasource.password 属性。

注意,该接口不包括与JDBC连接有关的所有方法。例如,连接池配置不是合同的一部分。这个接口只处理连接到远程服务所需的信息,其他关注的问题,如池的大小等,仍然通过属性配置。

这种抽象很有用,因为在未来的某个时候,其他有趣的集成可以建立在它之上

例如,在VMware Tanzu云中运行的Spring Boot应用程序可以发现与该应用程序相关的数据库,并自动提供一个JdbcConnectionDetails(或R2dbcConnectionDetails,用于反应式应用程序)bean,它知道如何连接到该数据库。对于用户来说,这意味着减少了摆弄Kubernetes配置图和秘密的时间,因为应用程序 "只是知道 "如何连接到数据库。你将有更多的时间专注于生活中的重要事情,如解决业务问题和参加冲刺会议

你可能会想,既然已经可以为连接细节贡献属性,为什么还需要一个新的接口。事实上,在application.properties之外使用连接属性是很常见的。例如,在用Testcontainers编写集成测试时,经常使用@DynamicPropertySource功能。

在应用程序配置之外使用属性的问题是,它们可能会发生变化(过去也曾发生过,比如spring.redis属性),这导致了脆性耦合。如果属性名称改变了,设置这些属性的代码仍然可以编译,因为它都是 "字符串 "类型的。当使用ConnectionDetails来提供如何连接到远程服务的信息时,如果我们做了向后不兼容的改变(我们不会没有一个好的理由,我们保证!),这将导致一个编译错误。这比在生产中发现破绽要好得多。

如果你想自己使用ConnectionsDetails抽象,你所需要做的就是定义一个具有正确类型的Bean,比如说:

@Configuration(proxyBeanMethods = false)
class MyConnectionDetailsConfiguration {

  @Bean
  JdbcConnectionDetails myJdbcConnectionDetails() {
    return new JdbcConnectionDetails() {

      @Override
      public String getUsername() {
        return "myuser";
      }

      @Override
      public String getPassword() {
        return
"3xtr3mly-s3cr3t";
      }

      @Override
      public String getJdbcUrl() {
        return
"jdbc:postgresql://postgres-server.svc.local:5432/mydatabase?ssl=true&sslmode=required";
      }

    };
  }

}

现在,Spring Boot将自动使用这些信息来连接到给定的PostgreSQL数据库。

在写这篇文章的时候,有以下几个子接口:

  • CassandraConnectionDetails for connections to a Cassandra server
  • CouchbaseConnectionDetails for connections to a Couchbase server
  • ElasticsearchConnectionDetails for connections to an Elasticsearch server
  • JdbcConnectionDetails for connections to a database server through JDBC
  • KafkaConnectionDetails for connections to a Kafka server
  • MongoConnectionDetails for connections to a MongoDB server
  • Neo4jConnectionDetails for connections to a Neo4J server
  • R2dbcConnectionDetails for connections to a database server through R2DBC
  • RabbitConnectionDetails for connections to a RabbitMQ server
  • RedisConnectionDetails for connections to a Redis server
  • ZipkinConnectionDetails for connections to a Zipkin server