基于原生mongoClient构建多数据源
看了很多基于java构建多mongo多数据源客户端的文章,发现大部分都是通过
Springboot
的mongoTemplate
去实现的,实现方式和mysq多数据源的方式比较类似。但是这种实现方式如果存在很多数据源的情况下一个是实现文件多,二不好管理,三每次都需要单独去继承config
类,太麻烦了。
参考
mongoClient
官方文档写了一个简单、快速构建mongo多数据源
客户端的实现。
本类兼容
SpringBoot2.X
版本和SpringBoot 1.5.x
版本
一、First of all
引入maven依赖,如果原来引入了
spring-boot-starter-data-mongodb
请去掉,不然会出现包冲突。
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.0.5</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-legacy</artifactId>
<version>4.0.5</version>
</dependency>
二、配置文件
uri
里面的值就是每个mongo数据源的名字,名字可以自定义,用于使用mongoClient
的时候获取对应的mongodatabase
对象
每个
uri
里面的值和正常配置mongoTemplate
的时候是一样的
spring.data.mongodb.uri[test1]=mongodb://localhost:17017/test1_dev
spring.data.mongodb.uri[test2]=mongodb://root:root@localhost:27017,localhost:27018/test2_dev
三、配置文件
import site.cnkj.common.utils.data.MongoClientsInit;
import com.mongodb.MongoClientOptions;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
/*
* @author Carol
* @create 2021/3/24 10:51
* @Description
* 1. 使用本bean的时候需要在启动类上加上下面这行注解,否则会自动链接本地mongo出现异常
* <code>@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})</code>
* 2. 使用MongoClient的时候不能同时使用SpringMongo,如果存在SpringMongo的maven依赖需要去除
*/
@Setter
@Configuration
@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoClientConfig {
private HashMap<String, String> uri = new HashMap<>();
private String applicationName;
private Boolean retryWrites = true;
private Boolean retryReads = true;
private Integer minConnectionsPerHost;
private Integer maxConnectionsPerHost = 100;
private Integer serverSelectionTimeout = 1000 * 30;
private Integer maxWaitTime = 1000 * 60 * 2;
private Integer maxConnectionIdleTime;
private Integer maxConnectionLifeTime;
private Integer connectTimeout = 1000 * 10;
private Integer socketTimeout = 0;
private Boolean sslEnabled = false;
private Boolean sslInvalidHostNameAllowed = false;
private Integer heartbeatFrequency = 10000;
private Integer minHeartbeatFrequency = 500;
private Integer heartbeatConnectTimeout = 20000;
private Integer heartbeatSocketTimeout = 20000;
private Integer localThreshold = 15;
private MongoClientOptions.Builder builder(){
//配制连接池
MongoClientOptions.Builder mongoClientBuilder = new MongoClientOptions.Builder();
mongoClientBuilder.applicationName(applicationName);
mongoClientBuilder.connectionsPerHost(maxConnectionsPerHost);
mongoClientBuilder.connectTimeout(connectTimeout);
mongoClientBuilder.heartbeatConnectTimeout(heartbeatConnectTimeout);
mongoClientBuilder.heartbeatFrequency(heartbeatFrequency);
mongoClientBuilder.heartbeatSocketTimeout(heartbeatSocketTimeout);
mongoClientBuilder.localThreshold(localThreshold);
mongoClientBuilder.maxConnectionIdleTime(maxConnectionIdleTime);
mongoClientBuilder.maxConnectionLifeTime(maxConnectionLifeTime);
mongoClientBuilder.maxWaitTime(maxWaitTime);
mongoClientBuilder.minConnectionsPerHost(minConnectionsPerHost);
mongoClientBuilder.minHeartbeatFrequency(minHeartbeatFrequency);
mongoClientBuilder.retryReads(retryReads);
mongoClientBuilder.retryWrites(retryWrites);
mongoClientBuilder.serverSelectionTimeout(serverSelectionTimeout);
mongoClientBuilder.socketTimeout(socketTimeout);
mongoClientBuilder.sslEnabled(sslEnabled);
mongoClientBuilder.sslInvalidHostNameAllowed(sslInvalidHostNameAllowed);
return mongoClientBuilder;
}
@Bean(name = "mongoClientsInit")
public MongoClientsInit mongoClientsInit(){
return new MongoClientsInit(uri, builder());
}
}
四、对象
构建对象,生成bean
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoDatabase;
import java.util.HashMap;
/*
* @author LXW
* @create 2020/8/17 9:50
* @Description
*/
public class MongoClientsInit {
private HashMap<String, MongoDatabase> mongoClientDatabases = new HashMap<>();
public HashMap<String, MongoDatabase> getMongoClientDatabases() {
return mongoClientDatabases;
}
private String getDatabase(String mongoUri) throws Exception{
String databaseName = "";
String substring = mongoUri.substring(10, mongoUri.length());
String[] split = substring.split("/");
String database = split[1];
if (database.contains("?")){
databaseName = database.split("\\?")[0];
}else {
databaseName = database;
}
return databaseName;
}
public MongoClientsInit(HashMap<String, String> uri, MongoClientOptions.Builder mongoClientBuilder){
try {
init(uri, mongoClientBuilder);
} catch (Exception e) {
e.printStackTrace();
}
}
private void init(HashMap<String, String> uri, MongoClientOptions.Builder mongoClientBuilder) throws Exception{
if (uri.size() > 0){
for (String name : uri.keySet()) {
String url = uri.get(name);
//支持ssl连接
MongoClient mongoClient = new MongoClient(new MongoClientURI(url, mongoClientBuilder));
MongoDatabase mongoClientDatabase = mongoClient.getDatabase(getDatabase(url));
mongoClientDatabases.put(name, mongoClientDatabase);
}
}
}
}
五、怎么用
下面以一个带条件的查询作为示例,展示怎么使用这个类
类中的 DateUtil 包在我的github中可以看到
- 在启动类中引入配置信息并注入bean
/*
* @author LXW
* @create 2021/3/23 16:31
* @Description
*/
@ComponentScan(basePackages = "site.cnkj.*",
basePackageClasses = {
MongoClientConfig.class
})
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
@SpringBootApplication
public class TestCommonApplication {
public static void main(String[] args) {
try {
SpringApplication.run(TestCommonApplication.class, args);
}catch (Exception e){
e.printStackTrace();
}
}
@Resource(name = "mongoClientsInit")
private MongoClientsInit mongoClientsInit;
}
- 在实现类中使用MongoClientInit
import com.alibaba.fastjson.JSONObject;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/*
* @author Carol
* @create 2020/8/14 17:40
* @Description
*/
@Service
public class MongoSourceFind {
@Autowired
private MongoClientsInit mongoClientsInit;
public void find(){
String startTime = "2020-08-13 00:00:00";
String endTime = "2020-08-14 00:00:00";
Date start = DateUtil.dateStringToDate(startTime, DateUtil.DATEFORMATE.FULLTIMEBY_yMdHms);
Date end = DateUtil.dateStringToDate(endTime, DateUtil.DATEFORMATE.FULLTIMEBY_yMdHms);
Document document = new Document("lastModifiedTime", new Document("$gte", start).append("$lt", end));
List<JSONObject> sources = new ArrayList<>();
//获取你需要的客户端对象
MongoDatabase mongoDatabase = mongoClientsInit.getMongoClientDatabases().get("test1");
//查询 collection1 表中 lastModifiedTime 字段在 startTime 和 endTime 时间范围内的数据
MongoCursor<Document> documentMongoCursor = mongoDatabase.getCollection("collection1").find(document).iterator();
while (documentMongoCursor.hasNext()){
//对获取到的每一条数据转换成Json对象
JSONObject parseObject = JSONObject.parseObject(documentMongoCursor.next().toJson());
sources.add(parseObject);
}
System.out.println(sources);
}
}
评论区