diff --git a/src/main/java/META-INF/root-context.xml b/src/main/java/META-INF/root-context.xml index e215ba63fcd64cd2b6cf92ca29b60cb83fcc2a3b..050bd2316ae4c444ab761a837e24060da98bb592 100644 --- a/src/main/java/META-INF/root-context.xml +++ b/src/main/java/META-INF/root-context.xml @@ -140,15 +140,6 @@ along with this program. If not, see .--> - - - - - - - - - diff --git a/src/main/java/neatlogic/framework/asynchronization/thread/NeatLogicThread.java b/src/main/java/neatlogic/framework/asynchronization/thread/NeatLogicThread.java index 22e9bacb97ac2f45474d0efd9941b130a2fc029d..8958eef6c69ce0b8f716d0ea71196360fb743bae 100644 --- a/src/main/java/neatlogic/framework/asynchronization/thread/NeatLogicThread.java +++ b/src/main/java/neatlogic/framework/asynchronization/thread/NeatLogicThread.java @@ -30,6 +30,7 @@ import java.util.concurrent.Semaphore; public abstract class NeatLogicThread implements Runnable, Comparable { private static final Logger logger = LoggerFactory.getLogger(NeatLogicThread.class); protected UserContext userContext; + protected MongodbSessionContext mongodbSessionContext; private String tenantUuid; private List activeModuleList; protected InputFromContext inputFromContext; @@ -97,6 +98,7 @@ public abstract class NeatLogicThread implements Runnable, Comparable. + */ + +package neatlogic.framework.asynchronization.threadlocal; + +import com.mongodb.client.ClientSession; + +public class MongodbSessionContext { + private ClientSession session; + // ThreadLocal 存储当前线程的 Session 对象 + private static final ThreadLocal sessionThreadLocal = new ThreadLocal<>(); + + public static MongodbSessionContext init(ClientSession _session) { + MongodbSessionContext context = new MongodbSessionContext(); + context.setSession(_session); + sessionThreadLocal.set(context); + return context; + } + + public static MongodbSessionContext get() { + return sessionThreadLocal.get(); + } + + public ClientSession getSession() { + return session; + } + + public void setSession(ClientSession session) { + this.session = session; + } + + public void release() { + sessionThreadLocal.remove(); + } +} diff --git a/src/main/java/neatlogic/framework/common/config/Config.java b/src/main/java/neatlogic/framework/common/config/Config.java index 4cf235041254f61e35597aa031c8603334a3b98e..28f58e93b9bc13511b2022956bdec6120948e57d 100644 --- a/src/main/java/neatlogic/framework/common/config/Config.java +++ b/src/main/java/neatlogic/framework/common/config/Config.java @@ -75,11 +75,6 @@ public class Config { private static int LOGIN_CAPTCHA_EXPIRED_TIME; //验证码超时时间(秒) private static int LOGIN_FAILED_TIMES_CAPTCHA; //设置需要验证码的登录错误次数 - private static String MONGO_HOST; - private static String MONGO_PASSWORD; - private static String MONGO_USERNAME; - private static String MONGO_DATABASE; - private static String JMS_URL; private static String KAFKA_URL; @@ -269,22 +264,6 @@ public class Config { return DATASOURCE_IDLE_TIMEOUT; } - public static String MONGO_HOST() { - return MONGO_HOST; - } - - public static String MONGO_PASSWORD() { - return MONGO_PASSWORD; - } - - public static String MONGO_DATABASE() { - return MONGO_DATABASE; - } - - public static String MONGO_USERNAME() { - return MONGO_USERNAME; - } - public static String JMS_URL() { return JMS_URL; } @@ -605,10 +584,6 @@ public class Config { DB_URL = prop.getProperty("db.url"); DB_HOST = prop.getProperty("db.host", "localhost"); DB_PORT = Integer.parseInt(prop.getProperty("db.port", "3306")); - MONGO_HOST = prop.getProperty("mongo.host", "localhost:27017"); - MONGO_USERNAME = prop.getProperty("mongo.username", "root"); - MONGO_PASSWORD = prop.getProperty("mongo.password", "root"); - MONGO_DATABASE = prop.getProperty("mongo.database", "neatlogic"); JMS_URL = prop.getProperty("jms.url"/*, "tcp://localhost:61616"*/); KAFKA_URL = prop.getProperty("kafka.url"/*, "localhost:9092"*/); diff --git a/src/main/java/neatlogic/framework/common/config/LocalConfig.java b/src/main/java/neatlogic/framework/common/config/LocalConfig.java index 1ac22e6951f88ea7a9ca1c135e884e5b26be5f13..77e8d45cea2657da871e064e4025a0902ccf01eb 100644 --- a/src/main/java/neatlogic/framework/common/config/LocalConfig.java +++ b/src/main/java/neatlogic/framework/common/config/LocalConfig.java @@ -180,12 +180,6 @@ public class LocalConfig implements BeanFactoryPostProcessor, EnvironmentAware, // dbConfigMap.put("conn.testOnBorrow", prop.getProperty("conn.testOnBorrow", "true")); // dbConfigMap.put("conn.maxIdle", prop.getProperty("conn.maxIdle", "16")); // dbConfigMap.put("conn.initialSize", prop.getProperty("conn.initialSize", "4")); - String mongoHost = prop.getProperty("mongo.host", "localhost:27017"); - String mongoUser = prop.getProperty("mongo.username", "root"); - String mongoPwd = prop.getProperty("mongo.password", "root"); - String mongoDb = prop.getProperty("mongo.database", "admin"); - mongoPwd = RC4Util.decrypt(mongoPwd); - dbConfigMap.put("mongo.url", "mongodb://" + mongoUser + ":" + mongoPwd + "@" + mongoHost + "/" + mongoDb); dbConfigMap.put("jms.url", prop.getProperty("jms.url", "tcp://localhost:61616")); dbConfigMap.put("jms.user", prop.getProperty("jms.user", "neatlogic")); dbConfigMap.put("jms.password", prop.getProperty("jms.password", "123456")); diff --git a/src/main/java/neatlogic/framework/dao/mapper/runner/RunnerMapper.xml b/src/main/java/neatlogic/framework/dao/mapper/runner/RunnerMapper.xml index eba7bfc7fa375dffabd3c04bc65c1510c1f19807..6c575380635b9f144c79b94ef6b347f1dff9f7b2 100644 --- a/src/main/java/neatlogic/framework/dao/mapper/runner/RunnerMapper.xml +++ b/src/main/java/neatlogic/framework/dao/mapper/runner/RunnerMapper.xml @@ -582,9 +582,8 @@ along with this program. If not, see .--> - INSERT INTO `runner_map` (`id`, `runner_id`) + INSERT IGNORE INTO `runner_map` (`id`, `runner_id`) VALUES (#{runnerMapId}, #{id}) - ON DUPLICATE KEY UPDATE `runner_id` = #{id} ; diff --git a/src/main/java/neatlogic/framework/listener/ThreadlocalClearListener.java b/src/main/java/neatlogic/framework/listener/ThreadlocalClearListener.java index 3e46d1b5cc253069ae14b8ada8ddb391958b42b1..ebd4404b13246f0cb50d255ef81808fd5d093c8b 100644 --- a/src/main/java/neatlogic/framework/listener/ThreadlocalClearListener.java +++ b/src/main/java/neatlogic/framework/listener/ThreadlocalClearListener.java @@ -43,6 +43,9 @@ public class ThreadlocalClearListener implements ServletRequestListener { if (LicensePolicyContext.get() != null) { LicensePolicyContext.get().release(); } + if (MongodbSessionContext.get() != null) { + MongodbSessionContext.get().release(); + } CacheContext.release(); } diff --git a/src/main/java/neatlogic/framework/store/mongodb/MongoConfig.java b/src/main/java/neatlogic/framework/store/mongodb/MongoConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..3b3ad498b96f71dfc41dfe4f0aeff2d65327bcc7 --- /dev/null +++ b/src/main/java/neatlogic/framework/store/mongodb/MongoConfig.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package neatlogic.framework.store.mongodb; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.data.mongodb.core.MongoTemplate; + +@Configuration +public class MongoConfig { + + @Bean + public NeatlogicMongoDatabaseFactory neatlogicMongoDatabaseFactory() { + return new NeatlogicMongoDatabaseFactory(); + } + + @Bean + public MongoTemplate mongoTemplate(NeatlogicMongoDatabaseFactory factory) { + return new MongoTemplate(factory); + } + + @Bean + public MongoTransactionManager transactionManagerMongoDb(NeatlogicMongoDatabaseFactory factory) { + return new MongoTransactionManager(factory); // 使用标准事务管理器‌:ml-citation{ref="2,3" data="citationList"} + } +} diff --git a/src/main/java/neatlogic/framework/store/mongodb/MongoDbManager.java b/src/main/java/neatlogic/framework/store/mongodb/MongoDbManager.java index 4f78b61f0278680567c4939e91248558e4aaf4d0..6f3e5cf39f775c9bc50d3383db507d47e9d46227 100644 --- a/src/main/java/neatlogic/framework/store/mongodb/MongoDbManager.java +++ b/src/main/java/neatlogic/framework/store/mongodb/MongoDbManager.java @@ -15,12 +15,14 @@ along with this program. If not, see .*/ package neatlogic.framework.store.mongodb; +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.WriteConcern; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import neatlogic.framework.common.RootComponent; import neatlogic.framework.dao.mapper.MongoDbMapper; import neatlogic.framework.dto.MongoDbVo; -import org.apache.commons.lang3.StringUtils; import javax.annotation.PostConstruct; import javax.annotation.Resource; @@ -47,7 +49,17 @@ public class MongoDbManager { } public static void addDynamicDataSource(MongoDbVo mongoDbVo) { - MongoClient client = MongoClients.create("mongodb://" + mongoDbVo.getUsername() + ":" + mongoDbVo.getPasswordPlain() + "@" + mongoDbVo.getHost() + "/" + mongoDbVo.getDatabase() + (StringUtils.isNotBlank(mongoDbVo.getOption()) ? "?" + mongoDbVo.getOption() : "")); + MongoClientSettings settings = MongoClientSettings.builder() + .applyConnectionString(new ConnectionString("mongodb://" + + mongoDbVo.getUsername() + ":" + + mongoDbVo.getPasswordPlain() + "@" + + mongoDbVo.getHost() + "/" + + mongoDbVo.getDatabase() + "?" + + mongoDbVo.getOption())) + .writeConcern(WriteConcern.MAJORITY) // 添加这一行 + .build(); + MongoClient client = MongoClients.create(settings); + mongoDbMap.put(mongoDbVo.getTenantUuid(), client); mongoDatabaseMap.put(mongoDbVo.getTenantUuid(), mongoDbVo.getDatabase()); } diff --git a/src/main/java/neatlogic/framework/store/mongodb/NeatLogicMongoDbFactory.java b/src/main/java/neatlogic/framework/store/mongodb/NeatLogicMongoDbFactory.java deleted file mode 100644 index 1a3fc2204cf08e4b237bce534baa473e15224cf1..0000000000000000000000000000000000000000 --- a/src/main/java/neatlogic/framework/store/mongodb/NeatLogicMongoDbFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/*Copyright (C) 2024 深圳极向量科技有限公司 All Rights Reserved. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see .*/ - -package neatlogic.framework.store.mongodb; - -import com.mongodb.client.MongoDatabase; -import neatlogic.framework.asynchronization.threadlocal.TenantContext; -import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; - -public class NeatLogicMongoDbFactory extends SimpleMongoClientDatabaseFactory { - - public NeatLogicMongoDbFactory(String connectionString) { - super(connectionString); - } - - - @Override - protected MongoDatabase doGetMongoDatabase(String dbName) { - return MongoDbManager.getMongoClient(TenantContext.get().getTenantUuid()).getDatabase(MongoDbManager.getDatabase(TenantContext.get().getTenantUuid())); - } - - -} diff --git a/src/main/java/neatlogic/framework/store/mongodb/NeatlogicMongoDatabaseFactory.java b/src/main/java/neatlogic/framework/store/mongodb/NeatlogicMongoDatabaseFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..c6a4b17a778c642f8a3a14c8406d1855867129e0 --- /dev/null +++ b/src/main/java/neatlogic/framework/store/mongodb/NeatlogicMongoDatabaseFactory.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package neatlogic.framework.store.mongodb; + +import com.mongodb.ClientSessionOptions; +import com.mongodb.client.ClientSession; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoDatabase; +import neatlogic.framework.asynchronization.threadlocal.TenantContext; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; + +@Component +@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) +public class NeatlogicMongoDatabaseFactory implements MongoDatabaseFactory { + + @Override + public @NonNull MongoDatabase getMongoDatabase() { + return getMongoDatabase(MongoDbManager.getDatabase(TenantContext.get().getTenantUuid())); + } + + @Override + public @NonNull MongoDatabase getMongoDatabase(@NonNull String dbName) { + return MongoDbManager.getMongoClient(TenantContext.get().getTenantUuid()).getDatabase(dbName); + } + + @Override + public @NonNull ClientSession getSession(@NonNull ClientSessionOptions options) { + // 确保 MongoClient 是从租户管理中获取的 + return MongoDbManager.getMongoClient(TenantContext.get().getTenantUuid()).startSession(options); + } + + @Override + public @NonNull MongoExceptionTranslator getExceptionTranslator() { + return new MongoExceptionTranslator(); + } + + @Override + public @NonNull MongoDatabaseFactory withSession(@NonNull ClientSession session) { + MongoClient mongoClient = MongoDbManager.getMongoClient(TenantContext.get().getTenantUuid()); + + return new MongoDatabaseFactory() { + @Override + public @NonNull MongoDatabase getMongoDatabase() { + return getMongoDatabase(MongoDbManager.getDatabase(TenantContext.get().getTenantUuid())); + } + + @Override + public @NonNull MongoDatabase getMongoDatabase(@NonNull String dbName) { + return mongoClient.getDatabase(dbName); + } + + @Override + public @NonNull ClientSession getSession(@NonNull ClientSessionOptions options) { + return session; + } + + @Override + public @NonNull MongoExceptionTranslator getExceptionTranslator() { + return new MongoExceptionTranslator(); + } + + @Override + public @NonNull MongoDatabaseFactory withSession(@NonNull ClientSession session) { + return this; + } + }; + } +} +