All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.db.nosql.mongo.MongoDS Maven / Gradle / Ivy

Go to download

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

There is a newer version: 5.8.34
Show newest version
package cn.hutool.db.nosql.mongo;

import cn.hutool.core.exceptions.NotInitedException;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.DbRuntimeException;
import cn.hutool.log.Log;
import cn.hutool.setting.Setting;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.connection.ConnectionPoolSettings;
import com.mongodb.connection.SocketSettings;
import org.bson.Document;

import java.io.Closeable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * MongoDB4工具类
 *
 * @author VampireAchao
 */
public class MongoDS implements Closeable {

	private final static Log log = Log.get();

	/**
	 * 默认配置文件
	 */
	public final static String MONGO_CONFIG_PATH = "config/mongo.setting";

	// MongoDB配置文件
	private Setting setting;
	// MongoDB实例连接列表
	private String[] groups;
	// MongoDB单点连接信息
	private ServerAddress serverAddress;
	// MongoDB客户端对象
	private MongoClient mongo;

	// --------------------------------------------------------------------------- Constructor start

	/**
	 * 构造MongoDB数据源
* 调用者必须持有MongoDS实例,否则会被垃圾回收导致写入失败! * * @param host 主机(域名或者IP) * @param port 端口 */ public MongoDS(String host, int port) { this.serverAddress = createServerAddress(host, port); initSingle(); } /** * 构造MongoDB数据源
* 调用者必须持有MongoDS实例,否则会被垃圾回收导致写入失败! * * @param mongoSetting MongoDB的配置文件,如果是null则读取默认配置文件或者使用MongoDB默认客户端配置 * @param host 主机(域名或者IP) * @param port 端口 */ public MongoDS(Setting mongoSetting, String host, int port) { this.setting = mongoSetting; this.serverAddress = createServerAddress(host, port); initSingle(); } /** * 构造MongoDB数据源
* 当提供多个数据源时,这些数据源将为一个副本集或者多个mongos
* 调用者必须持有MongoDS实例,否则会被垃圾回收导致写入失败! 官方文档: http://docs.mongodb.org/manual/administration/replica-sets/ * * @param groups 分组列表,当为null或空时使用无分组配置,一个分组使用单一模式,否则使用副本集模式 */ public MongoDS(String... groups) { this.groups = groups; init(); } /** * 构造MongoDB数据源
* 当提供多个数据源时,这些数据源将为一个副本集或者mongos
* 调用者必须持有MongoDS实例,否则会被垃圾回收导致写入失败!
* 官方文档: http://docs.mongodb.org/manual/administration/replica-sets/ * * @param mongoSetting MongoDB的配置文件,必须有 * @param groups 分组列表,当为null或空时使用无分组配置,一个分组使用单一模式,否则使用副本集模式 */ public MongoDS(Setting mongoSetting, String... groups) { if (mongoSetting == null) { throw new DbRuntimeException("Mongo setting is null!"); } this.setting = mongoSetting; this.groups = groups; init(); } // --------------------------------------------------------------------------- Constructor end /** * 初始化,当给定分组数大于一个时使用 */ public void init() { if (groups != null && groups.length > 1) { initCloud(); } else { initSingle(); } } /** * 初始化
* 设定文件中的host和端口有三种形式: * *
	 * host = host:port
	 * 
* *
	 * host = host
	 * port = port
	 * 
* *
	 * host = host
	 * 
*/ synchronized public void initSingle() { if (setting == null) { try { setting = new Setting(MONGO_CONFIG_PATH, true); } catch (Exception e) { // 在single模式下,可以没有配置文件。 } } String group = StrUtil.EMPTY; if (null == this.serverAddress) { //存在唯一分组 if (groups != null && groups.length == 1) { group = groups[0]; } serverAddress = createServerAddress(group); } final MongoCredential credentail = createCredentail(group); try { MongoClientSettings.Builder clusterSettingsBuilder = MongoClientSettings.builder() .applyToClusterSettings(b -> b.hosts(Collections.singletonList(serverAddress))); buildMongoClientSettings(clusterSettingsBuilder, group); if (null != credentail) { clusterSettingsBuilder.credential(credentail); } mongo = MongoClients.create(clusterSettingsBuilder.build()); } catch (Exception e) { throw new DbRuntimeException(StrUtil.format("Init MongoDB pool with connection to [{}] error!", serverAddress), e); } log.info("Init MongoDB pool with connection to [{}]", serverAddress); } /** * 初始化集群
* 集群的其它客户端设定参数使用全局设定
* 集群中每一个实例成员用一个group表示,例如: * *
	 * user = test1
	 * pass = 123456
	 * database = test
	 * [db0]
	 * host = 192.168.1.1:27117
	 * [db1]
	 * host = 192.168.1.1:27118
	 * [db2]
	 * host = 192.168.1.1:27119
	 * 
*/ synchronized public void initCloud() { if (groups == null || groups.length == 0) { throw new DbRuntimeException("Please give replication set groups!"); } if (setting == null) { // 若未指定配置文件,则使用默认配置文件 setting = new Setting(MONGO_CONFIG_PATH, true); } final List addrList = new ArrayList<>(); for (String group : groups) { addrList.add(createServerAddress(group)); } final MongoCredential credentail = createCredentail(StrUtil.EMPTY); try { MongoClientSettings.Builder clusterSettingsBuilder = MongoClientSettings.builder() .applyToClusterSettings(b -> b.hosts(addrList)); buildMongoClientSettings(clusterSettingsBuilder, StrUtil.EMPTY); if (null != credentail) { clusterSettingsBuilder.credential(credentail); } mongo = MongoClients.create(clusterSettingsBuilder.build()); } catch (Exception e) { log.error(e, "Init MongoDB connection error!"); return; } log.info("Init MongoDB cloud Set pool with connection to {}", addrList); } /** * 设定MongoDB配置文件 * * @param setting 配置文件 */ public void setSetting(Setting setting) { this.setting = setting; } /** * @return 获得MongoDB客户端对象 */ public MongoClient getMongo() { return mongo; } /** * 获得DB * * @param dbName DB * @return DB */ public MongoDatabase getDb(String dbName) { return mongo.getDatabase(dbName); } /** * 获得MongoDB中指定集合对象 * * @param dbName 库名 * @param collectionName 集合名 * @return DBCollection */ public MongoCollection getCollection(String dbName, String collectionName) { return getDb(dbName).getCollection(collectionName); } @Override public void close() { mongo.close(); } // --------------------------------------------------------------------------- Private method start /** * 创建ServerAddress对象,会读取配置文件中的相关信息 * * @param group 分组,如果为{@code null}或者""默认为无分组 * @return ServerAddress */ private ServerAddress createServerAddress(String group) { final Setting setting = checkSetting(); if (group == null) { group = StrUtil.EMPTY; } final String tmpHost = setting.getByGroup("host", group); if (StrUtil.isBlank(tmpHost)) { throw new NotInitedException("Host name is empy of group: {}", group); } final int defaultPort = setting.getInt("port", group, 27017); return new ServerAddress(NetUtil.buildInetSocketAddress(tmpHost, defaultPort)); } /** * 创建ServerAddress对象 * * @param host 主机域名或者IP(如果为空默认127.0.0.1) * @param port 端口(如果为空默认为) * @return ServerAddress */ private ServerAddress createServerAddress(String host, int port) { return new ServerAddress(host, port); } /** * 创建{@link MongoCredential},用于服务端验证
* 此方法会首先读取指定分组下的属性,用户没有定义则读取空分组下的属性 * * @param group 分组 * @return {@link MongoCredential},如果用户未指定用户名密码返回null * @since 4.1.20 */ private MongoCredential createCredentail(String group) { final Setting setting = this.setting; if (null == setting) { return null; } final String user = setting.getStr("user", group, setting.getStr("user")); final String pass = setting.getStr("pass", group, setting.getStr("pass")); final String database = setting.getStr("database", group, setting.getStr("database")); return createCredentail(user, database, pass); } /** * 创建{@link MongoCredential},用于服务端验证 * * @param userName 用户名 * @param database 数据库名 * @param password 密码 * @return {@link MongoCredential} * @since 4.1.20 */ private MongoCredential createCredentail(String userName, String database, String password) { if (StrUtil.hasEmpty(userName, database, database)) { return null; } return MongoCredential.createCredential(userName, database, password.toCharArray()); } /** * 构件MongoDB连接选项
* * @param group 分组,当分组对应的选项不存在时会读取根选项,如果也不存在使用默认值 * @return Builder */ private MongoClientSettings.Builder buildMongoClientSettings(MongoClientSettings.Builder builder, String group) { if (setting == null) { return builder; } if (StrUtil.isEmpty(group)) { group = StrUtil.EMPTY; } else { group = group + StrUtil.DOT; } // 每个主机答应的连接数(每个主机的连接池大小),当连接池被用光时,会被阻塞住 Integer connectionsPerHost = setting.getInt(group + "connectionsPerHost"); if (StrUtil.isBlank(group) == false && connectionsPerHost == null) { connectionsPerHost = setting.getInt("connectionsPerHost"); } ConnectionPoolSettings.Builder connectionPoolSettingsBuilder = ConnectionPoolSettings.builder(); if (connectionsPerHost != null) { connectionPoolSettingsBuilder.maxSize(connectionsPerHost); log.debug("MongoDB connectionsPerHost: {}", connectionsPerHost); } // 被阻塞线程从连接池获取连接的最长等待时间(ms) --int Integer connectTimeout = setting.getInt(group + "connectTimeout"); if (StrUtil.isBlank(group) == false && connectTimeout == null) { setting.getInt("connectTimeout"); } if (connectTimeout != null) { connectionPoolSettingsBuilder.maxWaitTime(connectTimeout, TimeUnit.MILLISECONDS); log.debug("MongoDB connectTimeout: {}", connectTimeout); } builder.applyToConnectionPoolSettings(b -> b.applySettings(connectionPoolSettingsBuilder.build())); // 套接字超时时间;该值会被传递给Socket.setSoTimeout(int)。默以为0(无穷) --int Integer socketTimeout = setting.getInt(group + "socketTimeout"); if (StrUtil.isBlank(group) == false && socketTimeout == null) { setting.getInt("socketTimeout"); } if (socketTimeout != null) { SocketSettings socketSettings = SocketSettings.builder().connectTimeout(socketTimeout, TimeUnit.MILLISECONDS).build(); builder.applyToSocketSettings(b -> b.applySettings(socketSettings)); log.debug("MongoDB socketTimeout: {}", socketTimeout); } return builder; } /** * 检查Setting配置文件 * * @return Setting配置文件 */ private Setting checkSetting() { if (null == this.setting) { throw new DbRuntimeException("Please indicate setting file or create default [{}]", MONGO_CONFIG_PATH); } return this.setting; } // --------------------------------------------------------------------------- Private method end }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy