

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 MongoDB Java 驱动程序连接到 Amazon DocumentDB
<a name="java-pg-connect-mongo-driver"></a>

本节提供使用 Java 驱动程序连接亚马逊文档数据库的 step-by-step指南。这将使您开始将 DocumentDB 集成到 Java 应用程序中。

**Topics**
+ [第 1 步：设置您的 项目](#step1-set-up)
+ [步骤 2：创建连接字符串](#step2-create-connection-string)
+ [步骤 3：编写连接代码](#step3-write-connect-code)
+ [步骤 4：处理连接异常](#step4-handle-connect-exceptions)
+ [步骤 5：运行代码](#step5-running-code)
+ [连接最佳实践](#java-connect-best-practices)

## 第 1 步：设置您的 项目
<a name="step1-set-up"></a>

1. 使用 Maven 创建 Java 项目：

   ```
   mvn archetype:generate -DgroupId=com.docdb.guide -DartifactId=my-docdb-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
   ```

1. 将 MongoDB Java 驱动程序作为项目的依赖项添加到您的“pom.xml”文件中：

   ```
   <dependency>
       <groupId>org.mongodb</groupId>
       <artifactId>mongodb-driver-sync</artifactId> 
       <version>5.3.0</version> 
   </dependency>
   ```

## 步骤 2：创建连接字符串
<a name="step2-create-connection-string"></a>

Amazon DocumentDB 连接字符串对于在您的应用程序与 DocumentDB 集群之间建立连接至关重要。此字符串封装了重要信息，例如集群端点、端口、身份验证详细信息以及各种连接选项。要构建 DocumentDB 连接字符串，通常需从基本格式开始：

```
"mongodb://{{username}}:{{password}}@cluster-endpoint:port/?[connection options]"
```

您需要将“用户名”和“密码”替换为您的实际凭证。你可以在中找到集群的终端节点和端口号 Amazon Web Services 管理控制台 ，也可以通过 Amazon CLI。要查找集群的集群端点，请参阅[查找集群的端点](db-cluster-endpoints-find.md)。DocumentDB 的默认端口为 27017。

**连接字符串示例**
+ 使用传输中加密建立到 DocumentDB 的连接，并确保将读取请求发送到只读副本，将写入请求发送到主项：

  ```
  "mongodb://username:password@cluster-endpoint:27017/?tls=true& 
     tlsCAFile=global-bundle.pem& 
     readPreference=secondaryPreferred&
     retryWrites=false"
  ```
+ 使用 IAM 身份验证建立到 DocumentDB 的连接：

  ```
  "mongodb://cluster-endpoint:27017/?tls=true& 
     tlsCAFile=global-bundle.pem& 
     readPreference=secondaryPreferred&
     retryWrites=false&
     authSource=%24external&
     authMechanism=MONGODB-AWS"
  ```

可用于连接字符串的不同选项如下：
+ [TLS 证书](#connection-string-tls)
+ [从只读副本读取](#connection-string-read-rep)
+ [写入关注和日志](#connection-string-write-journal)
+ [RetryWrites](#connection-string-retry-writes)
+ [IAM 身份验证](#connection-string-iam-auth)
+ [连接池](#connection-string-pool)
+ [连接超时参数](#connection-string-timeout)

### TLS 证书
<a name="connection-string-tls"></a>

**`tls=true|false`**：此选项将启用或禁用传输层安全性协议（TLS）。默认情况下，在 Amazon DocumentDB 集群上启用传输中加密，因此，除非在集群级别禁用 TLS，否则此选项的值应为 `true`。

如果使用 TLS，在创建到 DocumentDB 集群的连接时，代码需要提供 SSL 证书。下载建立到集群的安全连接时所需要的证书：[https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem](https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem)。可通过两种方式使用 `global-bundle.pem` 文件。
+ **选项 1**：从 `global-bundle.pem` 文件中提取所有证书，然后使用 Java 的 keytool 将其存储在 `.jks` 文件中，以便稍后在代码中使用。有关显示如何执行此操作的脚本，请参阅 [启用了 TLS 的情况下的连接](connect_programmatically.md#connect_programmatically-tls_enabled) 中的 Java 选项卡。
+ **选项 2**：在代码中动态添加 `global-bundle.pem` 文件，构建内存密钥库，并在建立连接时使用 `SSLContext` 提供证书。

### 从只读副本读取
<a name="connection-string-read-rep"></a>

**`replicaSet=rs0&readPreference=secondaryPreferred`**：指定这两个选项会将所有读取请求路由到只读副本，将写入请求路由到主实例。在连接字符串中使用 `replicaSet=rs0` 可使 MongoDB 驱动程序维护自动更新的集群拓扑视图，从而允许应用程序在添加或移除实例时维护当前节点配置的可见性。未提供这些选项或指定 `readPreference=primary` 则会将所有读取和写入请求发送到主实例。有关 `readPreference` 的更多选项，请参阅 [读取首选项选项](how-it-works.md#durability-consistency-isolation)。

### 写入关注和日志
<a name="connection-string-write-journal"></a>

写入关注决定了针对写入操作从数据库请求的确认级别。MongoDB 驱动程序提供了调整写入关注和日志文件的选项。Amazon DocumentDB 不希望您设置写入关注和日志，并且会忽略为 `w` 和 `j`（`writeConcern` 和 `journal`）发送的值。DocumentDB 始终使用 `writeConcern`：`majority` 和 `journal`：`true` 写入数据，因此在向客户端发送确认之前，写入会持久记录在大多数节点上。

### RetryWrites
<a name="connection-string-retry-writes"></a>

**`retryWrites=false`**：DocumentDB 不支持可重试写入，因此应始终将该属性设置为 `false`。

### IAM 身份验证
<a name="connection-string-iam-auth"></a>

**`authSource=%24external`和 `authMechanism=MONGODB-AWS`** — 这两个参数用于使用进行身份验证 Amazon Identity and Access Management。IAM 身份验证目前仅在基于实例的集群版本 5.0 中可用。有关更多信息，请参阅 [使用 IAM 身份进行身份验证](iam-identity-auth.md)。

### 连接池
<a name="connection-string-pool"></a>

以下选项可用于连接池：
+ **`maxPoolSize`**：设置可以在池中创建的最大连接数。当所有连接都在使用中并且有新请求进来时，新请求需等待连接变为可用。MongoDB Java 驱动程序的默认值为 100。
+ **`minPoolSize`**：表示应始终在池中维护的最小连接数。MongoDB Java 驱动程序的默认值为 0。
+ **`maxIdleTimeMS`**：确定连接在被关闭和移除之前可以在池中保持空闲状态的时长。MongoDB Java 驱动程序的默认值为 100 毫秒。
+ **`waitQueueTimeoutMS`**：配置当池达到其最大大小时，线程应等待连接变为可用的时长。如果连接未在此时间内变为可用，则抛出异常。MongoDB Java 驱动程序的默认值为 120000 毫秒（2 分钟）。

### 连接超时参数
<a name="connection-string-timeout"></a>

超时是一种机制，用于限制操作或连接尝试在被认为失败之前所花费的时间量。以下超时参数可用于防止无限期等待及管理资源分配：
+ **`connectTimeoutMS`**：配置驱动程序建立到集群的连接时的等待时长。默认值为 10,000 毫秒（10 秒）。
+ **`socketTimeoutMS`**：指定驱动程序等待服务器对非写入操作的响应的时间长度。默认值为 0（无超时或无限期）。
+ **`serverSelectionTimeoutMS`**：指定驱动程序在集群中查找可用服务器时的等待时长。此设置的默认值为 30 秒，足以在失效转移期间选择新的主实例。

## 步骤 3：编写连接代码
<a name="step3-write-connect-code"></a>

以下代码示例显示了如何建立到 Amazon DocumentDB 的 TLS 连接：
+ 将创建 Java 的 [https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.html](https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.html) 和 [`SSLContext`>](https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLContext.html) 对象。
+ 还将创建 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoClientSettings.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoClientSettings.html) 对象，方式是将其传递给 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/ConnectionString.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/ConnectionString.html) 对象。要建立 TLS 连接，必须使用 `MongoClientSettings` 对象绑定 `connectionstring` 和 `sslcontext`。
+ 使用 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClients.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClients.html) 获取 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html) 对象。

```
public static MongoClient makeDbConnection(String dbName, String DbUserName, String DbPassword,
    String DbClusterEndPoint, String keyStorePass) throws Exception {
    MongoClient connectedClient;
    String connectionOptions = "?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false";
    String connectionUrl = "mongodb://" + DbUserName + ":" + DbPassword + "@" + DbClusterEndPoint + ":27017/" +
        dbName + connectionOptions;

    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        try (FileInputStream fis = new FileInputStream("src/main/resources/certs/truststore.jks")) {
            trustStore.load(fis, keyStorePass.toCharArray());
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(trustStore);

            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
            ConnectionString connectionString = new ConnectionString(connectionUrl);
            MongoClientSettings settings = MongoClientSettings.builder()
                .applyConnectionString(connectionString)
                .applyToSslSettings(builder - > {
                    builder.enabled(true);
                    builder.context(sslContext);
                })
                .build();
            connectedClient = MongoClients.create(settings);
        }
        return connectedClient;
    } catch (MongoException e5) {
        throw new RuntimeException(e5);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
```

## 步骤 4：处理连接异常
<a name="step4-handle-connect-exceptions"></a>

在 Java 应用程序中使用 DocumentDB 时，处理连接异常对于保持稳健可靠的数据库操作而言至关重要。如果管理得当，这些异常不仅有助于快速诊断问题，还可以确保您的应用程序能够妥善处理临时网络中断或服务器不可用情况，从而提升稳定性和用户体验。与建立连接相关的一些关键异常包括：
+ **`MongoException`**：一般异常，可能在各种未被更具体异常涵盖的场景中触发。请确保在处理所有其他具体异常后再处理此异常，因为这是一般的捕获所有 MongoDB 异常。
+ **`MongoTimeoutException`**：在操作超时后触发。例如，查询不存在的集群端点。
+ **`MongoSocketException`**：针对网络相关问题触发。例如，操作期间网络突然断开连接。
+ **`MongoSecurityException`**：在身份验证失败时触发。例如，使用不正确的凭证进行连接。
+ **`MongoConfigurationException`**：当客户端配置中存在错误时触发。例如，使用无效的连接字符串。

## 步骤 5：运行代码
<a name="step5-running-code"></a>

以下代码示例将创建 Amazon DocumentDB 连接并打印所有数据库：

```
public static void TestConnection() {
    try (MongoClient mongoClient = makeDbConnection(DATABASE_NAME, DB_USER_NAME, DB_PASSWORD, DB_CLUSTER_ENDPOINT, KEYSTORE_PASSWORD)) {
        List < String > databases = mongoClient.listDatabaseNames().into(new ArrayList < > ());
        System.out.println("Databases: " + databases);
    } catch (MongoException e) {
        System.err.println("MongoDB error: " + e.getMessage());
        throw new RuntimeException(e);
    }
}
```

## 连接最佳实践
<a name="java-connect-best-practices"></a>

以下是使用 MongoDB Java 驱动程序连接到 Amazon DocumentDB 时应考虑的最佳实践：
+ 当您不再需要客户端释放资源时，请务必关闭您的 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html)。
+ 适当地处理异常并实现正确的错误日志记录。
+ 使用环境变量或 Amazon Secrets Manager 存储敏感信息，例如用户名和密码。