Spring Boot通过 spring-boot-starter-data-mongodb 自动配置连接MongoDB,spring.data.mongodb 对外暴露的配置项非常少,网上有很多文章说 Spring Boot没有提供连接池配置的功能,需要自行重写 MongoDbFactory,实际这样的确冤枉且小看了 spring-boot-starter-data-mongodb 的内部封装,连接MongoDb的组件当中内置了连接池的方法,只是我们用的姿势不对,并不需要什么重写搞得这么复杂。抱着尊重原创的想法,从其源码入手看看它是如何使用,官方文档也有一些配置,简单的说,MongoDb的连接方式,不是分开的一项一项的配置,学问都在它的uri里,也就是 spring.data.mongodb.uri, 在最后面放着一个option参数,隐秘而深奥,这里就是所有配置的奥妙所在。这个是官方文档,感兴趣的朋友可以看一下

Connection String URI Format — MongoDB Manualhttps://docs.mongodb.com/manual/reference/connection-string/

我们从org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration 自动配置类看起,可以轻易的找到 org.springframework.boot.autoconfigure.mongo.MongoClientFactorySupport<T>, 从这里,又可以找到,com.mongodb.MongoClientSettings, 顺着这里又可以找到,com.mongodb.connection.ConnectionPoolSettings, 那么和连接池相关的设置就在这里了,进入到这个类,很明显就会看到一堆属性

@Immutable
public class ConnectionPoolSettings {
    private final List<ConnectionPoolListener> connectionPoolListeners;
    private final int maxSize;
    private final int minSize;
    private final int maxWaitQueueSize;
    private final long maxWaitTimeMS;
    private final long maxConnectionLifeTimeMS;
    private final long maxConnectionIdleTimeMS;
    private final long maintenanceInitialDelayMS;
    private final long maintenanceFrequencyMS;

所以我们主要考虑这些地方如何才能产生对应的值即可,从com.mongodb.MongoClientSettings.Builder.applyConnectionString(ConnectionString) 这个方法中我们就可以看到            connectionPoolSettingsBuilder.applyConnectionString(connectionString);    

public Builder applyConnectionString(final ConnectionString connectionString) {
            if (connectionString.getApplicationName() != null) {
                applicationName = connectionString.getApplicationName();
            }
            clusterSettingsBuilder.applyConnectionString(connectionString);
            if (!connectionString.getCompressorList().isEmpty()) {
                compressorList = connectionString.getCompressorList();
            }

            ///  !!!这里是设置连接池的重点
            connectionPoolSettingsBuilder.applyConnectionString(connectionString);


            if (connectionString.getCredential() != null) {
                credential = connectionString.getCredential();
            }
            if (connectionString.getReadConcern() != null) {
                readConcern = connectionString.getReadConcern();
            }
            if (connectionString.getReadPreference() != null) {
                readPreference = connectionString.getReadPreference();
            }
            if (connectionString.getRetryWritesValue() != null) {
                retryWrites = connectionString.getRetryWritesValue();
            }
            if (connectionString.getUuidRepresentation() != null) {
                uuidRepresentation = connectionString.getUuidRepresentation();
            }

            serverSettingsBuilder.applyConnectionString(connectionString);
            socketSettingsBuilder.applyConnectionString(connectionString);
            sslSettingsBuilder.applyConnectionString(connectionString);
            if (connectionString.getWriteConcern() != null) {
                writeConcern = connectionString.getWriteConcern();
            }
            return this;
        }

也就是这句话,实现了连接池的设置,那么他是如何设置的呢,只要进去看一看便知,首先他入参的是connectionString, 通过方法如果往调用方的方向反过来一找,便可知道,他就是 spring.data.mongodb.uri 对应的值,那么重点就是我们再重点进去看看里面的方法,其中 com.mongodb.ConnectionString 这个类就是解析连接字符串的重点。在它的带参构造方法中 

com.mongodb.ConnectionString.ConnectionString(String)

除了解析字符串以外,Map<String, List<String>> connectionStringOptionsMap = parseOptions(connectionStringQueryParamenters);

// !!!这句是重点
Map<String, List<String>> connectionStringOptionsMap = parseOptions(connectionStringQueryParamenters);
Map<String, List<String>> txtRecordsOptionsMap = parseOptions(txtRecordsQueryParameters);

 这个方法中用于对 uri中的option进行解析,uri的结构在最尾部会有一个options选项,也就是对参数选项进行解析。通过一系列的解析实现参数设置,真佩服写代码的人不辞辛苦的这种解析精神,换来的是幸福的各种配置,包括连接池,

    static {
        GENERAL_OPTIONS_KEYS.add("minpoolsize");
        GENERAL_OPTIONS_KEYS.add("maxpoolsize");
        GENERAL_OPTIONS_KEYS.add("waitqueuetimeoutms");
        GENERAL_OPTIONS_KEYS.add("connecttimeoutms");
        GENERAL_OPTIONS_KEYS.add("maxidletimems");
        GENERAL_OPTIONS_KEYS.add("maxlifetimems");
        GENERAL_OPTIONS_KEYS.add("sockettimeoutms");

 这里的配置项就是对应的 option里的值,总结来说就是这样的一个对应关系

minConnectionPoolSize; 最小连接池大小                              —- minPoolSize
maxConnectionPoolSize; 最大连接池大小                             —- maxPoolSize
maxWaitTime; 最大等待时间                                                  —- waitQueueTimeoutMS
maxConnectionIdleTime; 最大空闲时间                                 —- maxIdleTimeMS
maxConnectionLifeTime; 连接池最大生命周期                      —- maxLifeTimeMS
connectTimeout; 连接超时                                                     —- connectTimeoutMS
socketTimeout; 读取超时                                                       —- socketTimeoutMS

如果我们想配置mongoDB的选项,只需要在uri中增加配置内容,否则就会按默认的走

例如我们可以这样配置,实现我们的连接池设置

spring.data.mongodb.uri=mongodb://username:password@192.168.1.1:27017,192.168.1.2:27017,192.168.1.3:27017/?readPreference=secondaryPreferred&maxIdleTimeMS=60000&waitQueueTimeoutMS=2000&minPoolSize=0&maxPoolSize=100&maxLifeTimeMS=0&connectTimeoutMS=2000&socketTimeoutMS=2000

所以以上就是为Spring Boot当中使用mongoDB的组件正名,它并不是没有,也不需要自己实现,应了那句话,生活中不缺少美,缺少的是发现


版权声明:本文为ankeway原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/ankeway/article/details/123258692