SpringBoot 整合mongoDB并自定义连接池

得力于SpringBoot的特性,整合mongoDB是很容易的,我们整合mongoDB的目的就是想用它给我们提供的mongoTemplate,它可以很容易的操作mongoDB数据库。

为了自定义连接池,我们在配置类中主要与MongoClientOptions、MongoCredential、MongoClient、MongoDbFactory打交道。最终的目的就是配置好一个MongoDbFactory的bean交由Spring管理。

Maven 依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

配置文件

mongodb:
database: bfa_mongo
username: "xxx"
password: "xxxxx"
address: "host:port"
authenticationDatabase: [设置你的认证数据库,如果有的话]
# 连接池配置
clientName: ${spring.application.name} # 客户端的标识,用于定位请求来源等
connectionTimeoutMs: 10000 # TCP连接超时,毫秒
readTimeoutMs: 15000 # TCP读取超时,毫秒
poolMaxWaitTimeMs: 3000 #当连接池无可用连接时客户端阻塞等待的时长,单位毫秒
connectionMaxIdleTimeMs: 60000 #TCP连接闲置时间,单位毫秒
connectionMaxLifeTimeMs: 120000 #TCP连接最多可以使用多久,单位毫秒
heartbeatFrequencyMs: 20000 #心跳检测发送频率,单位毫秒
minHeartbeatFrequencyMs: 8000 #最小的心跳检测发送频率,单位毫秒
heartbeatConnectionTimeoutMs: 10000 #心跳检测TCP连接超时,单位毫秒
heartbeatReadTimeoutMs: 15000 #心跳检测TCP连接读取超时,单位毫秒
connectionsPerHost: 20 # 每个host的TCP连接数
minConnectionsPerHost: 5 #每个host的最小TCP连接数
#计算允许多少个线程阻塞等待可用TCP连接时的乘数,算法:threadsAllowedToBlockForConnectionMultiplier*connectionsPerHost,当前配置允许10*20个线程阻塞
threadsAllowedToBlockForConnectionMultiplier: 10

MongoConfig配置类

配置类中使用了lombok,如果你没有用lombok依赖和IDE插件,你要重写getter、Setter方法:

代码稍长,可以复制在IDEA中查看:

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List; @Slf4j
@Configuration
public class MongoConfig { /**
* monogo 转换器
* @return
*/
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory,
MongoMappingContext context, BeanFactory beanFactory, MongoCustomConversions conversions) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
// 删除 _class field
// mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
mappingConverter.setCustomConversions(conversions);
return mappingConverter;
} /**
* 自定义mongo连接池
* @param properties
* @return
*/
@Bean
public MongoDbFactory mongoDbFactory(MongoClientOptionProperties properties) {
//创建客户端参数
MongoClientOptions options = mongoClientOptions(properties); //创建客户端和Factory
List<ServerAddress> serverAddresses = new ArrayList<>();
for (String address : properties.getAddress()) {
String[] hostAndPort = address.split(":");
String host = hostAndPort[0];
Integer port = Integer.parseInt(hostAndPort[1]);
ServerAddress serverAddress = new ServerAddress(host, port);
serverAddresses.add(serverAddress);
} //创建认证客户端
MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(properties.getUsername(),
properties.getAuthenticationDatabase() != null ? properties.getAuthenticationDatabase() : properties.getDatabase(),
properties.getPassword().toCharArray()); MongoClient mongoClient = new MongoClient(serverAddresses, mongoCredential, options); /** ps: 创建非认证客户端*/
//MongoClient mongoClient = new MongoClient(serverAddresses, mongoClientOptions);
return new SimpleMongoDbFactory(mongoClient, properties.getDatabase());
} /**
* mongo客户端参数配置
* @return
*/
@Bean
public MongoClientOptions mongoClientOptions(MongoClientOptionProperties properties) {
return MongoClientOptions.builder()
.connectTimeout(properties.getConnectionTimeoutMs())
.socketTimeout(properties.getReadTimeoutMs()).applicationName(properties.getClientName())
.heartbeatConnectTimeout(properties.getHeartbeatConnectionTimeoutMs())
.heartbeatSocketTimeout(properties.getHeartbeatReadTimeoutMs())
.heartbeatFrequency(properties.getHeartbeatFrequencyMs())
.minHeartbeatFrequency(properties.getMinHeartbeatFrequencyMs())
.maxConnectionIdleTime(properties.getConnectionMaxIdleTimeMs())
.maxConnectionLifeTime(properties.getConnectionMaxLifeTimeMs())
.maxWaitTime(properties.getPoolMaxWaitTimeMs())
.connectionsPerHost(properties.getConnectionsPerHost())
.threadsAllowedToBlockForConnectionMultiplier(
properties.getThreadsAllowedToBlockForConnectionMultiplier())
.minConnectionsPerHost(properties.getMinConnectionsPerHost()).build();
} @Primary
@Bean
@ConfigurationProperties(prefix = "mongodb")
public MongoClientOptionProperties mongoClientOptionProperties() {
return new MongoClientOptionProperties();
} @Getter
@Setter
@Validated
@Configuration
public static class MongoClientOptionProperties { /** 基础连接参数 */
private String database;
private String username;
private String password;
@NotNull
private List<String> address;
private String authenticationDatabase; /** 客户端连接池参数 */
@NotNull
@Size(min = 1)
private String clientName;
/** socket连接超时时间 */
@Min(value = 1)
private int connectionTimeoutMs;
/** socket读取超时时间 */
@Min(value = 1)
private int readTimeoutMs;
/** 连接池获取链接等待时间 */
@Min(value = 1)
private int poolMaxWaitTimeMs;
/** 连接闲置时间 */
@Min(value = 1)
private int connectionMaxIdleTimeMs;
/** 连接最多可以使用多久 */
@Min(value = 1)
private int connectionMaxLifeTimeMs;
/** 心跳检测发送频率 */
@Min(value = 2000)
private int heartbeatFrequencyMs; /** 最小的心跳检测发送频率 */
@Min(value = 300)
private int minHeartbeatFrequencyMs;
/** 计算允许多少个线程阻塞等待时的乘数,算法:threadsAllowedToBlockForConnectionMultiplier*connectionsPerHost */
@Min(value = 1)
private int threadsAllowedToBlockForConnectionMultiplier;
/** 心跳检测连接超时时间 */
@Min(value = 200)
private int heartbeatConnectionTimeoutMs;
/** 心跳检测读取超时时间 */
@Min(value = 200)
private int heartbeatReadTimeoutMs; /** 每个host最大连接数 */
@Min(value = 1)
private int connectionsPerHost;
/** 每个host的最小连接数 */
@Min(value = 1)
private int minConnectionsPerHost;
}
}

MappingMongoConverter可以自定义mongo转换器,主要自定义存取mongo数据时的一些操作,例如 mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null)) 方法会将mongo数据中的_class字段去掉。

最后通过 new SimpleMongoDbFactory(mongoClient, properties.getDatabase())方法配置了一个MongoDbFactory交由Spring管理,Springboot会拿这个MongoDbFactory工厂bean来new一个MongoTemplate,在MongoDbFactoryDependentConfiguration类下可以看到SpringBoot帮你做得事:

/**
* Configuration for Mongo-related beans that depend on a {@link MongoDbFactory}.
*
* @author Andy Wilkinson
*/
@Configuration
@ConditionalOnBean(MongoDbFactory.class)
class MongoDbFactoryDependentConfiguration { private final MongoProperties properties; MongoDbFactoryDependentConfiguration(MongoProperties properties) {
this.properties = properties;
} //SpringBoot创建MongoTemplate实例
@Bean
@ConditionalOnMissingBean
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter converter) {
return new MongoTemplate(mongoDbFactory, converter);
} @Bean
@ConditionalOnMissingBean(MongoConverter.class)
public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context,
MongoCustomConversions conversions) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
mappingConverter.setCustomConversions(conversions);
return mappingConverter;
} //...
}

SpringBoot利用我们配置好的MongoDbFactory在配置类中生成一个MongoTemplate,之后我们就可以在项目代码中直接@Autowired了。因为用于生成MongoTemplate的MongoDbFactory是我们自己在MongoConfig配置类中生成的,所以我们自定义的连接池参数也就生效了。

SpringBoot 整合mongoDB并自定义连接池的更多相关文章

  1. (二)SpringBoot整合常用框架Druid连接池

    一,在Pom.xml文件加入依赖 找到<dependencies></dependencies>标签,在标签中添加Druid依赖 <dependency> < ...

  2. java操作mongodb & springboot整合mongodb

    简单的研究原生API操作MongoDB以及封装的工具类操作,最后也会研究整合spring之后作为dao层的完整的操作. 1.原生的API操作 pom.xml <!-- https://mvnre ...

  3. SpringBoot 整合 MongoDB 实战介绍

    一.介绍 在前面的文章中,我们详细的介绍了 MongoDB 的配置和使用,如果你对 MongoDB 还不是很了解,也没关系,在 MongoDB 中有三个比较重要的名词:数据库.集合.文档! 数据库(D ...

  4. Springboot整合MongoDB的Docker开发,其它应用也类似

    1 前言 Docker是容器开发的事实标准,而Springboot是Java微服务常用框架,二者必然是会走到一起的.本文将讲解如何开发Springboot项目,把它做成Docker镜像,并运行起来. ...

  5. Springboot 整合 MongoDB

    Springboot 整合 MongoDB 这节我们将整合 Spring Boot 与 Mongo DB 实现增删改查的功能,并且实现序列递增. Mongo DB 的基本介绍和增删改查的用法可以参考我 ...

  6. mongoDB中的连接池(转载)

    一.mongoDB中的连接池 刚上手MongoDB,在做应用时,受以前使用关系型数据库的影响,会考虑数据库连接池的问题! 关系型数据库中,我们做连接池无非就是事先建立好N个连接(connection) ...

  7. JDBC连接池-自定义连接池

    JDBC连接池 java JDBC连接中用到Connection   在每次对数据进行增删查改 都要 开启  .关闭  ,在实例开发项目中 ,浪费了很大的资源 ,以下是之前连接JDBC的案例 pack ...

  8. java自定义连接池

    1.java自定义连接池 1.1连接池的概念: 实际开发中"获取连接"或“释放资源”是非常消耗系统资源的两个过程,为了姐姐此类性能问题,通常情况我们采用连接池技术来贡献连接Conn ...

  9. SpringBoot整合mongoDB

    MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 这一片文章介绍一个springboot整合mongodb,如果你了解整合mysql之类的 ...

随机推荐

  1. springboot---发送邮件

    1.pom.xml配置 <dependencies> <dependency> <groupId>org.springframework.boot</grou ...

  2. c++数据结构随笔(1)

    创建数据结构单链表的时候,突然碰到基础不牢固的问题,指针问题.就当复习指针了. 问题是如果三个指针a和b和r, b=a; b->next = r; 那么a->next会不会变? 然后写了一 ...

  3. 使用Bind提供域名解析服务(正向解析)

    小知识: 一般来讲域名比IP地址更加的有含义.也更容易记住,所以通常用户更习惯输入域名来访问网络中的资源,但是计算机主机在互联网中只能通过IP识别对方主机,那么就需要DNS域名解析服务了. DNS域名 ...

  4. Bash 内置高效特性

    变量(字符串)变换 定义一个变量t,内容为framE [root@vm1 tmp]# t=framE 查看变量t的内容:echo $t或者是echo ${t} [root@vm1 tmp]# echo ...

  5. 转载:全面理解面向对象的 JavaScript

    来源:DeveloperWorks – 曾滢著 简介: JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来人们对这一门语言的误解,即认为 JavaScript 不是一门面向 ...

  6. nginx篇最初级用法之nginx升级

    在不破坏nginx应用程序和配置文件下时,升级nginx. 下载新版本的nginx对其进行编译 使用nginx -V参数获得当前版本和配置参数 nginx version: nginx/1.10.3b ...

  7. vue-router动态添加路由报错

    [报错] Uncaught Error: [vue-router] route config "component" for path: /home cannot be a str ...

  8. tarjan求lca的神奇

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  9. day 2 上午 挂饰 背包

    #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> us ...

  10. day7-format字符串格式化

    tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18) print ...