Connecting to MongoDB

基于 Java 的元数据方法注册 MongoClient 实例时使用 @Bean 注解,而基于 XML 的元数据方法使用 MongoDB-specific XML 架构。

本文还提供了使用 FactoryBean 注册 MongoClient 实例的示例,该实例提供异常转换功能。此外,本文介绍了 MongoDatabaseFactory 和 ReactiveMongoDatabaseFactory 接口,用于引导连接到特定数据库实例,以及在 IoC 容器中注册它们的示例。最后,它讨论了使用 SimpleMongoClientDbFactory 连接到数据库时的身份验证选项。

使用 MongoDB 和 Spring 时,首要任务之一是使用 IoC 容器创建一个 MongoClient 对象。有两种主要方法来执行此操作,要么使用基于 Java 的 Bean 元数据,要么使用基于 XML 的 Bean 元数据。

One of the first tasks when using MongoDB and Spring is to create a MongoClient object using the IoC container. There are two main ways to do this, either by using Java-based bean metadata or by using XML-based bean metadata.

对于那些不熟悉如何使用基于 Java 的 Bean 元数据而不是基于 XML 的元数据配置 Spring 容器的人,请参阅参考文档 here 中的高级介绍以及详细文档 here

For those not familiar with how to configure the Spring container using Java-based bean metadata instead of XML-based metadata, see the high-level introduction in the reference docs here as well as the detailed documentation here.

Registering a Mongo Instance

以下示例显示注册 MongoClient 实例的示例:

The following example shows an example to register an instance of a MongoClient:

Registering MongoClient
  • Imperative

  • Reactive

  • XML

@Configuration
public class AppConfig {

  /*
   * Use the standard Mongo driver API to create a com.mongodb.client.MongoClient instance.
   */
   public @Bean com.mongodb.client.MongoClient mongoClient() {
       return com.mongodb.client.MongoClients.create("mongodb://localhost:27017");
   }
}
@Configuration
public class AppConfig {

  /*
   * Use the standard Mongo driver API to create a com.mongodb.client.MongoClient instance.
   */
   public @Bean com.mongodb.reactivestreams.client.MongoClient mongoClient() {
       return com.mongodb.reactivestreams.client.MongoClients.create("mongodb://localhost:27017");
   }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation=
"
http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- Default bean name is 'mongo' -->
    <mongo:mongo-client host="localhost" port="27017"/>

</beans>

这种方法使您能够使用标准 MongoClient 实例,同时容器使用 Spring 的 MongoClientFactoryBean/ReactiveMongoClientFactoryBean。与直接实例化 MongoClient 实例相比,FactoryBean 具有额外的优势,因为它还为容器提供了 ExceptionTranslator 实现,该实现将 MongoDB 异常转换为 Spring 可移植 DataAccessException 层次结构中适用于使用 @Repository 注解注释了的数据访问类的异常。此层次结构和 @Repository 的使用在 Spring’s DAO support features 中进行了描述。

This approach lets you use the standard MongoClient instance, with the container using Spring’s MongoClientFactoryBean/ReactiveMongoClientFactoryBean. As compared to instantiating a MongoClient instance directly, the FactoryBean has the added advantage of also providing the container with an ExceptionTranslator implementation that translates MongoDB exceptions to exceptions in Spring’s portable DataAccessException hierarchy for data access classes annotated with the @Repository annotation. This hierarchy and the use of @Repository is described in Spring’s DAO support features.

以下示例显示基于 Java 的 Bean 元数据的示例,它支持对 @Repository 注释的类的异常转换:

The following example shows an example of a Java-based bean metadata that supports exception translation on @Repository annotated classes:

Registering a MongoClient via MongoClientFactoryBean / ReactiveMongoClientFactoryBean
  • Imperative

  • Reactive

@Configuration
public class AppConfig {

    /*
     * Factory bean that creates the com.mongodb.client.MongoClient instance
     */
     public @Bean MongoClientFactoryBean mongo() {
          MongoClientFactoryBean mongo = new MongoClientFactoryBean();
          mongo.setHost("localhost");
          return mongo;
     }
}
@Configuration
public class AppConfig {

    /*
     * Factory bean that creates the com.mongodb.reactivestreams.client.MongoClient instance
     */
     public @Bean ReactiveMongoClientFactoryBean mongo() {
          ReactiveMongoClientFactoryBean mongo = new ReactiveMongoClientFactoryBean();
          mongo.setHost("localhost");
          return mongo;
     }
}

要访问由其他 @Configuration 类或你自己的类中的 FactoryBean 所创建的 MongoClient 对象,请使用 private @Autowired MongoClient mongoClient; 字段。

To access the MongoClient object created by the FactoryBean in other @Configuration classes or your own classes, use a private @Autowired MongoClient mongoClient; field.

The MongoDatabaseFactory Interface

尽管 MongoClient 是 MongoDB 驱动程序 API 的入口点,但连接到特定的 MongoDB 数据库实例需要更多信息,例如数据库名称以及可选的用户名和密码。有了这些信息,就可以获取 MongoDatabase 对象,并访问特定 MongoDB 数据库实例的所有功能。Spring 提供 org.springframework.data.mongodb.core.MongoDatabaseFactoryorg.springframework.data.mongodb.core.ReactiveMongoDatabaseFactory 接口,如下列清单所示,用于引导到数据库的连接:

While MongoClient is the entry point to the MongoDB driver API, connecting to a specific MongoDB database instance requires additional information, such as the database name and an optional username and password. With that information, you can obtain a MongoDatabase object and access all the functionality of a specific MongoDB database instance. Spring provides the org.springframework.data.mongodb.core.MongoDatabaseFactory & org.springframework.data.mongodb.core.ReactiveMongoDatabaseFactory interfaces, shown in the following listing, to bootstrap connectivity to the database:

  • Imperative

  • Reactive

public interface MongoDatabaseFactory {

  MongoDatabase getDatabase() throws DataAccessException;

  MongoDatabase getDatabase(String dbName) throws DataAccessException;
}
public interface ReactiveMongoDatabaseFactory {

  Mono<MongoDatabase> getDatabase() throws DataAccessException;

  Mono<MongoDatabase> getDatabase(String dbName) throws DataAccessException;
}

以下小节显示了如何使用基于 Java 或基于 XML 的元数据来配置 MongoDatabaseFactory 接口的实例。然后,可以使用 MongoDatabaseFactory / ReactiveMongoDatabaseFactory 实例来配置 MongoTemplate / ReactiveMongoTemplate

The following sections show how you can use the container with either Java-based or XML-based metadata to configure an instance of the MongoDatabaseFactory interface. In turn, you can use the MongoDatabaseFactory / ReactiveMongoDatabaseFactory instance to configure MongoTemplate / ReactiveMongoTemplate.

除了使用 IoC 容器创建模板实例,还可以在标准 Java 代码中使用它们,如下所示:

Instead of using the IoC container to create an instance of the template, you can use them in standard Java code, as follows:

Imperative
public class MongoApplication {

  public static void main(String[] args) throws Exception {

    MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database"));

    // ...
  }
}

以粗体显示的代码突出了 SimpleMongoClientDbFactory 的使用,并且是 getting started section 中所示列表之间的唯一差异。选择 com.mongodb.client.MongoClient 作为首选入口点时,请使用 SimpleMongoClientDbFactory

The code in bold highlights the use of SimpleMongoClientDbFactory and is the only difference between the listing shown in the getting started section. Use SimpleMongoClientDbFactory when choosing com.mongodb.client.MongoClient as the entrypoint of choice.

Reactive
public class ReactiveMongoApplication {

  public static void main(String[] args) throws Exception {

    ReactiveMongoOperations mongoOps = new MongoTemplate(new SimpleReactiveMongoDatabaseFactory(MongoClients.create(), "database"));

    // ...
  }
}

Registering a MongoDatabaseFactory / ReactiveMongoDatabaseFactory

要使用容器注册 MongoDatabaseFactory / ReactiveMongoDatabaseFactory 实例,需要编写类似于上一部分中突出显示的代码。以下清单显示了一个简单的示例:

To register a MongoDatabaseFactory/ ReactiveMongoDatabaseFactory instance with the container, you write code much like what was highlighted in the previous section. The following listing shows a simple example:

  • Imperative

  • Reactive

@Configuration
public class MongoConfiguration {

  @Bean
  public MongoDatabaseFactory mongoDatabaseFactory() {
    return new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database");
  }
}
@Configuration
public class ReactiveMongoConfiguration {

  @Bean
  public ReactiveMongoDatabaseFactory mongoDatabaseFactory() {
    return new SimpleReactiveMongoDatabaseFactory(MongoClients.create(), "database");
  }
}

MongoDB Server 第 3 代在连接到数据库时更改了身份验证模型,因此,某些可用于身份验证的配置选项不再有效。应该使用特定于 MongoClient 的选项通过 MongoCredential 设置凭据,以提供身份验证数据,如下面的示例所示:

MongoDB Server generation 3 changed the authentication model when connecting to the DB. Therefore, some of the configuration options available for authentication are no longer valid. You should use the MongoClient-specific options for setting credentials through MongoCredential to provide authentication data, as shown in the following example:

Java
@Configuration
public class MongoAppConfig extends AbstractMongoClientConfiguration {

  @Override
  public String getDatabaseName() {
    return "database";
  }

  @Override
  protected void configureClientSettings(Builder builder) {

    builder
        .credential(MongoCredential.createCredential("name", "db", "pwd".toCharArray()))
        .applyToClusterSettings(settings  -> {
          settings.hosts(singletonList(new ServerAddress("127.0.0.1", 27017)));
        });
  }
}
XML
<mongo:db-factory dbname="database" />

在基于 XML 的配置中使用的用户名和密码凭证在包含诸如 :%@, 之类的保留字符时必须进行 URL 编码。以下示例展示了编码凭证:m0ng0@dmin:mo_res:bw6},Qsdxx@admin@databasem0ng0%40dmin:mo_res%3Abw6%7D%2CQsdxx%40admin@database 有关更多详细信息,请参阅 section 2.2 of RFC 3986

Username and password credentials used in XML-based configuration must be URL-encoded when these contain reserved characters, such as :, %, @, or ,. The following example shows encoded credentials: m0ng0@dmin:mo_res:bw6},Qsdxx@admin@databasem0ng0%40dmin:mo_res%3Abw6%7D%2CQsdxx%40admin@database See section 2.2 of RFC 3986 for further details.

如果需要针对用于创建 SimpleMongoClientDbFactorycom.mongodb.client.MongoClient 实例配置其他选项,可以参考现有 bean,如下面的示例所示。为了展示另一种常见的用法模式,以下清单显示了属性占位符的使用情况,该属性占位符允许对配置以及 MongoTemplate 的创建进行参数化:

If you need to configure additional options on the com.mongodb.client.MongoClient instance that is used to create a SimpleMongoClientDbFactory, you can refer to an existing bean as shown in the following example. To show another common usage pattern, the following listing shows the use of a property placeholder, which lets you parametrize the configuration and the creation of a MongoTemplate:

  • Java

  • XML

@Configuration
@PropertySource("classpath:/com/myapp/mongodb/config/mongo.properties")
public class MongoAppConfig extends AbstractMongoClientConfiguration {

  @Autowired
  Environment env;

  @Override
  public String getDatabaseName() {
    return "database";
  }

  @Override
  protected void configureClientSettings(Builder builder) {

    builder.applyToClusterSettings(settings -> {
    settings.hosts(singletonList(
          new ServerAddress(env.getProperty("mongo.host"), env.getProperty("mongo.port", Integer.class))));
    });

    builder.applyToConnectionPoolSettings(settings -> {

      settings.maxConnectionLifeTime(env.getProperty("mongo.pool-max-life-time", Integer.class), TimeUnit.MILLISECONDS)
          .minSize(env.getProperty("mongo.pool-min-size", Integer.class))
          .maxSize(env.getProperty("mongo.pool-max-size", Integer.class))
          .maintenanceFrequency(10, TimeUnit.MILLISECONDS)
          .maintenanceInitialDelay(11, TimeUnit.MILLISECONDS)
          .maxConnectionIdleTime(30, TimeUnit.SECONDS)
          .maxWaitTime(15, TimeUnit.MILLISECONDS);
    });
  }
}
<context:property-placeholder location="classpath:/com/myapp/mongodb/config/mongo.properties"/>

<mongo:mongo-client host="${mongo.host}" port="${mongo.port}">
  <mongo:client-settings connection-pool-max-connection-life-time="${mongo.pool-max-life-time}"
    connection-pool-min-size="${mongo.pool-min-size}"
    connection-pool-max-size="${mongo.pool-max-size}"
    connection-pool-maintenance-frequency="10"
    connection-pool-maintenance-initial-delay="11"
    connection-pool-max-connection-idle-time="30"
    connection-pool-max-wait-time="15" />
</mongo:mongo-client>

<mongo:db-factory dbname="database" mongo-ref="mongoClient"/>

<bean id="anotherMongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
  <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>