Spring Pivotal Cloud Foundry 上的 JPA 如何知道如何连接到绑定的 MySQL 实例?

How does Spring JPA on Pivotal Cloud Foundry know how to connect to a bound MySQL instance?

我在 PCF 上有一个小 API 运行 使用 Spring JPA。当然,在代码中,我可以使用 JDBC 连接 运行 准备好的语句来访问绑定的 MySQL 实例。按照通过 Java.

连接到数据库时的正常标准,这样做需要用户名和密码

但是,使用 Spring JPA,我不必执行任何这些操作。我只需绑定 MySQL 实例,就可以使用 JPA API 执行我的查询。

没有更好的问题了,这是什么魔法?

CloudfoundrySpring Cloud 始终遵循 12-factor app 模式。

对于配置,它也使用 config pattern suggested by 12-factor app 模式。

根据这种模式,我们应该将属性存储在环境中的代码之外,如 environment variables。这样一来,该应用程序包无需任何修改即可部署到任何环境。由于它从环境变量中获取配置,因此不同的环境必须使用不同的值定义相同的环境变量。

每当您使用 cf bind-service 将服务添加到您的应用程序时,Cloudfoundry 会在虚拟机(或容器或它拥有的任何东西)中设置与该服务相关的预定义环境变量。

您可以使用 cf env app-name.(Command Refeference)

检查这些环境变量

cf env app-name

的示例输出
{
 "VCAP_APPLICATION": {
  "application_id": "fa05c1a9-0fc1-4fbd-bae1-139850dec7a3",
  "application_name": "my-app",
  "application_uris": [
    "my-app.10.244.0.34.xip.io"
  ],
  "application_version": "fb8fbcc6-8d58-479e-bcc7-3b4ce5a7f0ca",
  "limits": {
  "disk": 1024,
  "fds": 16384,
  "mem": 256
  },
  "name": "my-app",
  "space_id": "06450c72-4669-4dc6-8096-45f9777db68a",
  "space_name": "my-space",
  "uris": [
    "my-app.10.244.0.34.xip.io"
  ],
  "users": null,
  "version": "fb8fbcc6-8d58-479e-bcc7-3b4ce5a7f0ca"
}

使用 spring actuator endpoints 您可以使用 /env 端点检查所有环境变量。它列出了比 cf env.

更多的属性

当spring检测到

  1. cloud profile 处于活动状态(由 spring.profiles.active 环境 属性 或 spring cloud 中的 spring.profile 属性 设置)
  2. Auto Configuration 已启用(由 @SpringBootApplication 启用)
  3. 类路径上不存在内存数据源依赖项(尽管我假设它会提供云数据源配置首选项,即使存在内存依赖项)
  4. 没有明确配置数据源

Spring 如果数据源服务(如 Postgres)已绑定到应用程序,则使用环境变量创建数据源 bean 本身。

下面是用于创建数据源的环境属性的 link。

https://docs.cloudfoundry.org/buildpacks/java/spring-service-bindings.html

这是仅数据源属性的列表。

cloud.services.<database-service-name>.connection.hostname
cloud.services.<database-service-name>.connection.name
cloud.services.<database-service-name>.connection.password
cloud.services.<database-service-name>.connection.port
cloud.services.<database-service-name>.connection.username
cloud.services.<database-service-name>.plan
cloud.services.<database-service-name>.type

database-service-name定义在Manifest.yml文件中env: block

根据我的经验,如果只向应用程序添加一个数据库服务,则无需在环境变量部分定义数据库服务名称。

注:

By default spring would try to use the servlet container's poolable connection support, however most of the time we our self have to configure some properties that are only supported by connection pool providers like Apache DBCP. In these cases we have to create Datasource bean manually using environment properties (using System.getProperty() or spring Environment.getProperty()).