mirror of
				https://gitee.com/dromara/hutool.git
				synced 2025-11-01 00:46:56 +08:00 
			
		
		
		
	太棒了!
This commit is contained in:
		| @@ -23,7 +23,8 @@ | |||||||
| 		<tomcat-jdbc.version>10.0.14</tomcat-jdbc.version> | 		<tomcat-jdbc.version>10.0.14</tomcat-jdbc.version> | ||||||
| 		<druid.version>1.2.8</druid.version> | 		<druid.version>1.2.8</druid.version> | ||||||
| 		<hikariCP.version>2.4.13</hikariCP.version> | 		<hikariCP.version>2.4.13</hikariCP.version> | ||||||
| 		<mongo.version>4.5.0</mongo.version> | 		<mongo.version>3.12.10</mongo.version> | ||||||
|  | 		<mongo4.version>4.5.0</mongo4.version> | ||||||
| 		<sqlite.version>3.36.0.3</sqlite.version> | 		<sqlite.version>3.36.0.3</sqlite.version> | ||||||
| 		<!-- 此处固定2.5.x,支持到JDK8 --> | 		<!-- 此处固定2.5.x,支持到JDK8 --> | ||||||
| 		<hsqldb.version>2.5.2</hsqldb.version> | 		<hsqldb.version>2.5.2</hsqldb.version> | ||||||
| @@ -99,10 +100,16 @@ | |||||||
| 		<!-- MongoDB Java客户端 --> | 		<!-- MongoDB Java客户端 --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.mongodb</groupId> | 			<groupId>org.mongodb</groupId> | ||||||
| 			<artifactId>mongodb-driver-sync</artifactId> | 			<artifactId>mongo-java-driver</artifactId> | ||||||
| 			<version>${mongo.version}</version> | 			<version>${mongo.version}</version> | ||||||
| 			<optional>true</optional> | 			<optional>true</optional> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.mongodb</groupId> | ||||||
|  | 			<artifactId>mongodb-driver-sync</artifactId> | ||||||
|  | 			<version>${mongo4.version}</version> | ||||||
|  | 			<optional>true</optional> | ||||||
|  | 		</dependency> | ||||||
| 		<!-- Redis Java客户端 --> | 		<!-- Redis Java客户端 --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>redis.clients</groupId> | 			<groupId>redis.clients</groupId> | ||||||
|   | |||||||
| @@ -6,28 +6,24 @@ import cn.hutool.core.util.StrUtil; | |||||||
| import cn.hutool.db.DbRuntimeException; | import cn.hutool.db.DbRuntimeException; | ||||||
| import cn.hutool.log.Log; | import cn.hutool.log.Log; | ||||||
| import cn.hutool.setting.Setting; | import cn.hutool.setting.Setting; | ||||||
| import com.mongodb.MongoClientSettings; | import com.mongodb.MongoClient; | ||||||
|  | import com.mongodb.MongoClientOptions; | ||||||
|  | import com.mongodb.MongoClientOptions.Builder; | ||||||
| import com.mongodb.MongoCredential; | import com.mongodb.MongoCredential; | ||||||
| import com.mongodb.MongoDriverInformation; |  | ||||||
| import com.mongodb.ServerAddress; | import com.mongodb.ServerAddress; | ||||||
| import com.mongodb.client.MongoClient; |  | ||||||
| import com.mongodb.client.MongoCollection; | import com.mongodb.client.MongoCollection; | ||||||
| import com.mongodb.client.MongoDatabase; | import com.mongodb.client.MongoDatabase; | ||||||
| import com.mongodb.client.internal.MongoClientImpl; |  | ||||||
| import com.mongodb.connection.ConnectionPoolSettings; |  | ||||||
| import com.mongodb.connection.SocketSettings; |  | ||||||
| import org.bson.Document; | import org.bson.Document; | ||||||
|  |  | ||||||
| import java.io.Closeable; | import java.io.Closeable; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.concurrent.TimeUnit; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * MongoDB工具类 |  * MongoDB工具类 | ||||||
|  * |  * | ||||||
|  * @author xiaoleilu |  * @author xiaoleilu | ||||||
|  |  * | ||||||
|  */ |  */ | ||||||
| public class MongoDS implements Closeable { | public class MongoDS implements Closeable { | ||||||
| 	private final static Log log = Log.get(); | 	private final static Log log = Log.get(); | ||||||
| @@ -150,11 +146,11 @@ public class MongoDS implements Closeable { | |||||||
|  |  | ||||||
| 		final MongoCredential credentail = createCredentail(group); | 		final MongoCredential credentail = createCredentail(group); | ||||||
| 		try { | 		try { | ||||||
| 			MongoClientSettings.Builder clusterSettingsBuilder = MongoClientSettings.builder().applyToClusterSettings(b -> b.hosts(Collections.singletonList(serverAddress))); | 			if (null == credentail) { | ||||||
| 			if (null != credentail) { | 				mongo = new MongoClient(serverAddress, buildMongoClientOptions(group)); | ||||||
| 				clusterSettingsBuilder.credential(credentail); | 			} else { | ||||||
|  | 				mongo = new MongoClient(serverAddress, credentail, buildMongoClientOptions(group)); | ||||||
| 			} | 			} | ||||||
| 			mongo = new MongoClientImpl(clusterSettingsBuilder.build(), MongoDriverInformation.builder().build()); |  | ||||||
| 		} catch (Exception e) { | 		} catch (Exception e) { | ||||||
| 			throw new DbRuntimeException(StrUtil.format("Init MongoDB pool with connection to [{}] error!", serverAddress), e); | 			throw new DbRuntimeException(StrUtil.format("Init MongoDB pool with connection to [{}] error!", serverAddress), e); | ||||||
| 		} | 		} | ||||||
| @@ -196,11 +192,11 @@ public class MongoDS implements Closeable { | |||||||
|  |  | ||||||
| 		final MongoCredential credentail = createCredentail(StrUtil.EMPTY); | 		final MongoCredential credentail = createCredentail(StrUtil.EMPTY); | ||||||
| 		try { | 		try { | ||||||
| 			MongoClientSettings.Builder clusterSettingsBuilder = MongoClientSettings.builder().applyToClusterSettings(b -> b.hosts(addrList)); | 			if (null == credentail) { | ||||||
| 			if (null != credentail) { | 				mongo = new MongoClient(addrList, buildMongoClientOptions(StrUtil.EMPTY)); | ||||||
| 				clusterSettingsBuilder.credential(credentail); | 			} else { | ||||||
|  | 				mongo = new MongoClient(addrList, credentail, buildMongoClientOptions(StrUtil.EMPTY)); | ||||||
| 			} | 			} | ||||||
| 			mongo = new MongoClientImpl(clusterSettingsBuilder.build(), MongoDriverInformation.builder().build()); |  | ||||||
| 		} catch (Exception e) { | 		} catch (Exception e) { | ||||||
| 			log.error(e, "Init MongoDB connection error!"); | 			log.error(e, "Init MongoDB connection error!"); | ||||||
| 			return; | 			return; | ||||||
| @@ -252,7 +248,6 @@ public class MongoDS implements Closeable { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// --------------------------------------------------------------------------- Private method start | 	// --------------------------------------------------------------------------- Private method start | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * 创建ServerAddress对象,会读取配置文件中的相关信息 | 	 * 创建ServerAddress对象,会读取配置文件中的相关信息 | ||||||
| 	 * | 	 * | ||||||
| @@ -327,8 +322,8 @@ public class MongoDS implements Closeable { | |||||||
| 	 * @param group 分组,当分组对应的选项不存在时会读取根选项,如果也不存在使用默认值 | 	 * @param group 分组,当分组对应的选项不存在时会读取根选项,如果也不存在使用默认值 | ||||||
| 	 * @return MongoClientOptions | 	 * @return MongoClientOptions | ||||||
| 	 */ | 	 */ | ||||||
| 	private MongoClientSettings buildMongoClientOptions(String group) { | 	private MongoClientOptions buildMongoClientOptions(String group) { | ||||||
| 		return buildMongoClientOptions(MongoClientSettings.builder(), group).build(); | 		return buildMongoClientOptions(MongoClientOptions.builder(), group).build(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -337,7 +332,7 @@ public class MongoDS implements Closeable { | |||||||
| 	 * @param group 分组,当分组对应的选项不存在时会读取根选项,如果也不存在使用默认值 | 	 * @param group 分组,当分组对应的选项不存在时会读取根选项,如果也不存在使用默认值 | ||||||
| 	 * @return Builder | 	 * @return Builder | ||||||
| 	 */ | 	 */ | ||||||
| 	private MongoClientSettings.Builder buildMongoClientOptions(MongoClientSettings.Builder builder, String group) { | 	private Builder buildMongoClientOptions(Builder builder, String group) { | ||||||
| 		if (setting == null) { | 		if (setting == null) { | ||||||
| 			return builder; | 			return builder; | ||||||
| 		} | 		} | ||||||
| @@ -353,9 +348,8 @@ public class MongoDS implements Closeable { | |||||||
| 		if (StrUtil.isBlank(group) == false && connectionsPerHost == null) { | 		if (StrUtil.isBlank(group) == false && connectionsPerHost == null) { | ||||||
| 			connectionsPerHost = setting.getInt("connectionsPerHost"); | 			connectionsPerHost = setting.getInt("connectionsPerHost"); | ||||||
| 		} | 		} | ||||||
| 		ConnectionPoolSettings.Builder connectionPoolSettingsBuilder = ConnectionPoolSettings.builder(); |  | ||||||
| 		if (connectionsPerHost != null) { | 		if (connectionsPerHost != null) { | ||||||
| 			connectionPoolSettingsBuilder.maxConnecting(connectionsPerHost); | 			builder.connectionsPerHost(connectionsPerHost); | ||||||
| 			log.debug("MongoDB connectionsPerHost: {}", connectionsPerHost); | 			log.debug("MongoDB connectionsPerHost: {}", connectionsPerHost); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -365,10 +359,9 @@ public class MongoDS implements Closeable { | |||||||
| 			setting.getInt("connectTimeout"); | 			setting.getInt("connectTimeout"); | ||||||
| 		} | 		} | ||||||
| 		if (connectTimeout != null) { | 		if (connectTimeout != null) { | ||||||
| 			connectionPoolSettingsBuilder.maxWaitTime(connectTimeout, TimeUnit.MILLISECONDS); | 			builder.connectTimeout(connectTimeout); | ||||||
| 			log.debug("MongoDB connectTimeout: {}", connectTimeout); | 			log.debug("MongoDB connectTimeout: {}", connectTimeout); | ||||||
| 		} | 		} | ||||||
| 		builder.applyToConnectionPoolSettings(b -> b.applySettings(connectionPoolSettingsBuilder.build())); |  | ||||||
|  |  | ||||||
| 		// 套接字超时时间;该值会被传递给Socket.setSoTimeout(int)。默以为0(无穷) --int | 		// 套接字超时时间;该值会被传递给Socket.setSoTimeout(int)。默以为0(无穷) --int | ||||||
| 		Integer socketTimeout = setting.getInt(group + "socketTimeout"); | 		Integer socketTimeout = setting.getInt(group + "socketTimeout"); | ||||||
| @@ -376,8 +369,7 @@ public class MongoDS implements Closeable { | |||||||
| 			setting.getInt("socketTimeout"); | 			setting.getInt("socketTimeout"); | ||||||
| 		} | 		} | ||||||
| 		if (socketTimeout != null) { | 		if (socketTimeout != null) { | ||||||
| 			SocketSettings socketSettings = SocketSettings.builder().connectTimeout(socketTimeout, TimeUnit.MILLISECONDS).build(); | 			builder.socketTimeout(socketTimeout); | ||||||
| 			builder.applyToSocketSettings(b -> b.applySettings(socketSettings)); |  | ||||||
| 			log.debug("MongoDB socketTimeout: {}", socketTimeout); | 			log.debug("MongoDB socketTimeout: {}", socketTimeout); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										404
									
								
								hutool-db/src/main/java/cn/hutool/db/nosql/mongo/MongoDS4.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										404
									
								
								hutool-db/src/main/java/cn/hutool/db/nosql/mongo/MongoDS4.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,404 @@ | |||||||
|  | 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.MongoDriverInformation; | ||||||
|  | import com.mongodb.ServerAddress; | ||||||
|  | import com.mongodb.client.MongoClient; | ||||||
|  | import com.mongodb.client.MongoCollection; | ||||||
|  | import com.mongodb.client.MongoDatabase; | ||||||
|  | import com.mongodb.client.internal.MongoClientImpl; | ||||||
|  | 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 MongoDS4 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数据源<br> | ||||||
|  | 	 * 调用者必须持有MongoDS实例,否则会被垃圾回收导致写入失败! | ||||||
|  | 	 * | ||||||
|  | 	 * @param host 主机(域名或者IP) | ||||||
|  | 	 * @param port 端口 | ||||||
|  | 	 */ | ||||||
|  | 	public MongoDS4(String host, int port) { | ||||||
|  | 		this.serverAddress = createServerAddress(host, port); | ||||||
|  | 		initSingle(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 构造MongoDB数据源<br> | ||||||
|  | 	 * 调用者必须持有MongoDS实例,否则会被垃圾回收导致写入失败! | ||||||
|  | 	 * | ||||||
|  | 	 * @param mongoSetting MongoDB的配置文件,如果是null则读取默认配置文件或者使用MongoDB默认客户端配置 | ||||||
|  | 	 * @param host         主机(域名或者IP) | ||||||
|  | 	 * @param port         端口 | ||||||
|  | 	 */ | ||||||
|  | 	public MongoDS4(Setting mongoSetting, String host, int port) { | ||||||
|  | 		this.setting = mongoSetting; | ||||||
|  | 		this.serverAddress = createServerAddress(host, port); | ||||||
|  | 		initSingle(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 构造MongoDB数据源<br> | ||||||
|  | 	 * 当提供多个数据源时,这些数据源将为一个副本集或者多个mongos<br> | ||||||
|  | 	 * 调用者必须持有MongoDS实例,否则会被垃圾回收导致写入失败! 官方文档: http://docs.mongodb.org/manual/administration/replica-sets/ | ||||||
|  | 	 * | ||||||
|  | 	 * @param groups 分组列表,当为null或空时使用无分组配置,一个分组使用单一模式,否则使用副本集模式 | ||||||
|  | 	 */ | ||||||
|  | 	public MongoDS4(String... groups) { | ||||||
|  | 		this.groups = groups; | ||||||
|  | 		init(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 构造MongoDB数据源<br> | ||||||
|  | 	 * 当提供多个数据源时,这些数据源将为一个副本集或者mongos<br> | ||||||
|  | 	 * 调用者必须持有MongoDS实例,否则会被垃圾回收导致写入失败!<br> | ||||||
|  | 	 * 官方文档: http://docs.mongodb.org/manual/administration/replica-sets/ | ||||||
|  | 	 * | ||||||
|  | 	 * @param mongoSetting MongoDB的配置文件,必须有 | ||||||
|  | 	 * @param groups       分组列表,当为null或空时使用无分组配置,一个分组使用单一模式,否则使用副本集模式 | ||||||
|  | 	 */ | ||||||
|  | 	public MongoDS4(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(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 初始化<br> | ||||||
|  | 	 * 设定文件中的host和端口有三种形式: | ||||||
|  | 	 * | ||||||
|  | 	 * <pre> | ||||||
|  | 	 * host = host:port | ||||||
|  | 	 * </pre> | ||||||
|  | 	 * | ||||||
|  | 	 * <pre> | ||||||
|  | 	 * host = host | ||||||
|  | 	 * port = port | ||||||
|  | 	 * </pre> | ||||||
|  | 	 * | ||||||
|  | 	 * <pre> | ||||||
|  | 	 * host = host | ||||||
|  | 	 * </pre> | ||||||
|  | 	 */ | ||||||
|  | 	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))); | ||||||
|  | 			if (null != credentail) { | ||||||
|  | 				clusterSettingsBuilder.credential(credentail); | ||||||
|  | 			} | ||||||
|  | 			mongo = new MongoClientImpl(clusterSettingsBuilder.build(), MongoDriverInformation.builder().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); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 初始化集群<br> | ||||||
|  | 	 * 集群的其它客户端设定参数使用全局设定<br> | ||||||
|  | 	 * 集群中每一个实例成员用一个group表示,例如: | ||||||
|  | 	 * | ||||||
|  | 	 * <pre> | ||||||
|  | 	 * 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 | ||||||
|  | 	 * </pre> | ||||||
|  | 	 */ | ||||||
|  | 	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<ServerAddress> 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)); | ||||||
|  | 			if (null != credentail) { | ||||||
|  | 				clusterSettingsBuilder.credential(credentail); | ||||||
|  | 			} | ||||||
|  | 			mongo = new MongoClientImpl(clusterSettingsBuilder.build(), MongoDriverInformation.builder().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<Document> 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},用于服务端验证<br> | ||||||
|  | 	 * 此方法会首先读取指定分组下的属性,用户没有定义则读取空分组下的属性 | ||||||
|  | 	 * | ||||||
|  | 	 * @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连接选项<br> | ||||||
|  | 	 * | ||||||
|  | 	 * @param group 分组,当分组对应的选项不存在时会读取根选项,如果也不存在使用默认值 | ||||||
|  | 	 * @return MongoClientOptions | ||||||
|  | 	 */ | ||||||
|  | 	private MongoClientSettings buildMongoClientOptions(String group) { | ||||||
|  | 		return buildMongoClientOptions(MongoClientSettings.builder(), group).build(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 构件MongoDB连接选项<br> | ||||||
|  | 	 * | ||||||
|  | 	 * @param group 分组,当分组对应的选项不存在时会读取根选项,如果也不存在使用默认值 | ||||||
|  | 	 * @return Builder | ||||||
|  | 	 */ | ||||||
|  | 	private MongoClientSettings.Builder buildMongoClientOptions(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 | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,120 @@ | |||||||
|  | package cn.hutool.db.nosql.mongo; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.map.MapUtil; | ||||||
|  | import cn.hutool.core.util.ArrayUtil; | ||||||
|  | import cn.hutool.core.util.RuntimeUtil; | ||||||
|  | import cn.hutool.setting.Setting; | ||||||
|  |  | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.concurrent.ConcurrentHashMap; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * MongoDB4工厂类,用于创建 | ||||||
|  |  * @author VampireAchao | ||||||
|  |  */ | ||||||
|  | public class MongoFactory4 { | ||||||
|  |  | ||||||
|  | 	/** 各分组做组合key的时候分隔符 */ | ||||||
|  | 	private final static String GROUP_SEPRATER = ","; | ||||||
|  |  | ||||||
|  | 	/** 数据源池 */ | ||||||
|  | 	private static final Map<String, MongoDS4> DS_MAP = new ConcurrentHashMap<>(); | ||||||
|  |  | ||||||
|  | 	// JVM关闭前关闭MongoDB连接 | ||||||
|  | 	static { | ||||||
|  | 		RuntimeUtil.addShutdownHook(MongoFactory4::closeAll); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// ------------------------------------------------------------------------ Get DS start | ||||||
|  | 	/** | ||||||
|  | 	 * 获取MongoDB数据源<br> | ||||||
|  | 	 * | ||||||
|  | 	 * @param host 主机 | ||||||
|  | 	 * @param port 端口 | ||||||
|  | 	 * @return MongoDB连接 | ||||||
|  | 	 */ | ||||||
|  | 	public static MongoDS4 getDS(String host, int port) { | ||||||
|  | 		final String key = host + ":" + port; | ||||||
|  | 		MongoDS4 ds = DS_MAP.get(key); | ||||||
|  | 		if (null == ds) { | ||||||
|  | 			// 没有在池中加入之 | ||||||
|  | 			ds = new MongoDS4(host, port); | ||||||
|  | 			DS_MAP.put(key, ds); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return ds; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 获取MongoDB数据源<br> | ||||||
|  | 	 * 多个分组名对应的连接组成集群 | ||||||
|  | 	 * | ||||||
|  | 	 * @param groups 分组列表 | ||||||
|  | 	 * @return MongoDB连接 | ||||||
|  | 	 */ | ||||||
|  | 	public static MongoDS4 getDS(String... groups) { | ||||||
|  | 		final String key = ArrayUtil.join(groups, GROUP_SEPRATER); | ||||||
|  | 		MongoDS4 ds = DS_MAP.get(key); | ||||||
|  | 		if (null == ds) { | ||||||
|  | 			// 没有在池中加入之 | ||||||
|  | 			ds = new MongoDS4(groups); | ||||||
|  | 			DS_MAP.put(key, ds); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return ds; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 获取MongoDB数据源<br> | ||||||
|  | 	 * | ||||||
|  | 	 * @param groups 分组列表 | ||||||
|  | 	 * @return MongoDB连接 | ||||||
|  | 	 */ | ||||||
|  | 	public static MongoDS4 getDS(Collection<String> groups) { | ||||||
|  | 		return getDS(groups.toArray(new String[0])); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 获取MongoDB数据源<br> | ||||||
|  | 	 * | ||||||
|  | 	 * @param setting 设定文件 | ||||||
|  | 	 * @param groups 分组列表 | ||||||
|  | 	 * @return MongoDB连接 | ||||||
|  | 	 */ | ||||||
|  | 	public static MongoDS4 getDS(Setting setting, String... groups) { | ||||||
|  | 		final String key = setting.getSettingPath() + GROUP_SEPRATER + ArrayUtil.join(groups, GROUP_SEPRATER); | ||||||
|  | 		MongoDS4 ds = DS_MAP.get(key); | ||||||
|  | 		if (null == ds) { | ||||||
|  | 			// 没有在池中加入之 | ||||||
|  | 			ds = new MongoDS4(setting, groups); | ||||||
|  | 			DS_MAP.put(key, ds); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return ds; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 获取MongoDB数据源<br> | ||||||
|  | 	 * | ||||||
|  | 	 * @param setting 配置文件 | ||||||
|  | 	 * @param groups 分组列表 | ||||||
|  | 	 * @return MongoDB连接 | ||||||
|  | 	 */ | ||||||
|  | 	public static MongoDS4 getDS(Setting setting, Collection<String> groups) { | ||||||
|  | 		return getDS(setting, groups.toArray(new String[0])); | ||||||
|  | 	} | ||||||
|  | 	// ------------------------------------------------------------------------ Get DS ends | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * 关闭全部连接 | ||||||
|  | 	 */ | ||||||
|  | 	public static void closeAll() { | ||||||
|  | 		if(MapUtil.isNotEmpty(DS_MAP)){ | ||||||
|  | 			for(MongoDS4 ds : DS_MAP.values()) { | ||||||
|  | 				ds.close(); | ||||||
|  | 			} | ||||||
|  | 			DS_MAP.clear(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| package cn.hutool.db.nosql; | package cn.hutool.db.nosql; | ||||||
|  |  | ||||||
| import cn.hutool.db.nosql.mongo.MongoFactory; | import cn.hutool.db.nosql.mongo.MongoFactory4; | ||||||
| import com.mongodb.client.MongoDatabase; | import com.mongodb.client.MongoDatabase; | ||||||
| import org.junit.Assert; | import org.junit.Assert; | ||||||
| import org.junit.Ignore; | import org.junit.Ignore; | ||||||
| @@ -14,7 +14,7 @@ public class MongoDBTest { | |||||||
| 	@Test | 	@Test | ||||||
| 	@Ignore | 	@Ignore | ||||||
| 	public void redisDSTest() { | 	public void redisDSTest() { | ||||||
| 		MongoDatabase db = MongoFactory.getDS("master").getDb("test"); | 		MongoDatabase db = MongoFactory4.getDS("master").getDb("test"); | ||||||
| 		Assert.assertEquals("test", db.getName()); | 		Assert.assertEquals("test", db.getName()); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 VampireAchao
					VampireAchao