springboot配置mongo多数据源方案
技术本质为制作多个mongo上下文,利用切面,在不同注解切点时切换上下文,达到多数据源的效果,以下为具体实现方案
一、修改配置文件的mongo配置方式
1 2 3 4 5 6 7 | mongo: datasource: dblist: - uri: mongodb: //{user}:{pwd}@{ip}:{port}/{database}?authSource=admin database: discover_center #对应MongoSwitch注解的值 - uri: mongodb: //{user}:{pwd}@{ip}:{port}/{database}?authSource=admin database: terminal_data #对应MongoSwitch注解的值 |
二、启动类上增加配置扫描注解@ConfigurationPropertiesScan
@SpringBootApplication @ConfigurationPropertiesScan @EnableDiscoveryClient public class FalconDataCollectApplication { public static void main(String[] args) { SpringApplication.run(FalconDataCollectApplication.class, args); } }
三、增加mongo配置读取类MongoListProperties
1 2 3 4 5 6 7 8 9 10 11 | @Data @ConfigurationProperties (prefix = "mongo.datasource" ) public class MongoListProperties { private List<MongoList> dblist; @Data public static class MongoList { private String uri; private String database; } } |
四、编写mongo上下文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | @Component public class MongoDbContext { private static final Map<String, MongoDatabaseFactory> MONGO_CLIENT_DB_FACTORY_MAP = new HashMap<>(); private static final ThreadLocal<MongoDatabaseFactory> MONGO_DB_FACTORY_THREAD_LOCAL = new ThreadLocal<>(); @Resource MongoListProperties mongoListProperties; public static MongoDatabaseFactory getMongoDbFactory() { return MONGO_DB_FACTORY_THREAD_LOCAL.get(); } public static void setMongoDbFactory(String name) { MONGO_DB_FACTORY_THREAD_LOCAL.set(MONGO_CLIENT_DB_FACTORY_MAP.get(name)); } public static void removeMongoDbFactory() { MONGO_DB_FACTORY_THREAD_LOCAL.remove(); } @PostConstruct public void afterPropertiesSet() { if (!CollectionUtils.isEmpty(mongoListProperties.getDblist())) { mongoListProperties.getDblist().forEach(info->{ MONGO_CLIENT_DB_FACTORY_MAP.put(info.getDatabase(), new SimpleMongoClientDatabaseFactory(info.getUri())); }); } } @Bean (name = "mongoTemplate" ) public MultiMongoTemplate dynamicMongoTemplate() { Iterator<MongoDatabaseFactory> iterator = MONGO_CLIENT_DB_FACTORY_MAP.values().iterator(); return new MultiMongoTemplate(iterator.next()); } @Bean (name = "mongoDbFactory" ) public MongoDatabaseFactory mongoDbFactory() { Iterator<MongoDatabaseFactory> iterator = MONGO_CLIENT_DB_FACTORY_MAP.values().iterator(); return iterator.next(); } } |
五、增加MongoSwitch注解
1 2 3 4 5 6 7 8 9 10 11 | @Target ({ElementType.METHOD}) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface MongoSwitch { /** * mongo数据库名称 * * @return */ String value() default "" ; } |
六、增加切面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @Component @Aspect @Order (value = - 99 ) @Slf4j public class MongoDbSwitch { @Pointcut ( "@annotation(com.vcolco.falcon.config.mongo.MongoSwitch)" ) public void mongoSwitch() {} @Before ( "mongoSwitch()" ) public void before(JoinPoint point) { try { MethodSignature methodSignature = (MethodSignature) point.getSignature(); Method method = point.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes()); MongoSwitch mongoSwitch = method.getAnnotation(MongoSwitch. class ); MongoDbContext.setMongoDbFactory(mongoSwitch.value()); } catch (Exception e) { log.error( "==========>前置mongo数据源切换异常" , e); } } @After ( "mongoSwitch()" ) public void after(JoinPoint point) { try { MongoDbContext.removeMongoDbFactory(); } catch (Exception e) { log.error( "==========>后置mongo数据源切换异常" , e); } } } |
七、动态mongo数据源
1 2 3 4 5 6 7 8 9 10 11 | public class MultiMongoTemplate extends MongoTemplate { public MultiMongoTemplate(MongoDatabaseFactory mongoDbFactory) { super (mongoDbFactory); } @Override protected MongoDatabase doGetDatabase() { MongoDatabaseFactory mongoDbFactory = MongoDbContext.getMongoDbFactory(); return mongoDbFactory == null ? super .doGetDatabase() : mongoDbFactory.getMongoDatabase(); } } |
八、封装mongo基础方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | public abstract class MongoDbDao<T> { /** * 反射获取泛型类型 * * @return */ protected abstract Class<T> getEntityClass(); /** * 数据库模板 */ @Autowired protected MongoTemplate mongoTemplate; /*** * 保存一个对象,若唯一性索引冲突,则直接覆盖 * @param t */ public T save(T t) { return this .mongoTemplate.save(t); } /** * 保存一个对象,若唯一性索引冲突,则新增失败 * * @param t */ public T insert(T t) { return this .mongoTemplate.insert(t); } /*** * 保存对象列表 * * @param batch */ public Collection<T> batchInsert(Collection<T> batch) { return this .mongoTemplate.insert(batch, this .getEntityClass()); } /*** * 根据id从几何中查询对象 * @param id * @return */ public T getById(String id) { Query query = new Query(Criteria.where( "_id" ).is(id)); return this .mongoTemplate.findOne(query, this .getEntityClass()); } /** * 根据自定义条件查询集合 * * @param query * @return */ public List<T> list(Query query) { return mongoTemplate.find(query, this .getEntityClass()); } /** * 根据条件查询只返回一个文档 * * @param query * @return */ public T getOne(Query query) { return mongoTemplate.findOne(query.skip( 0 ).limit( 1 ), this .getEntityClass()); } /*** * 根据条件分页查询 * @param query * @param start 查询起始值 * @param size 查询大小 * @return */ public List<T> getPage(Query query, int start, int size) { return this .mongoTemplate.find(query.skip(start).limit(size), this .getEntityClass()); } /*** * 根据条件查询库中符合条件的记录数量 * @param query * @return */ public int count(Query query) { return ( int ) this .mongoTemplate.count(query, this .getEntityClass()); } /** * 根据自定义条件删除集合 * * @param query * @return */ public int deleteBatch(Query query) { return ( int ) mongoTemplate.remove(query, this .getEntityClass()).getDeletedCount(); } /** * 根据id删除 * * @param id */ public int deleteById(String id) { Query query = new Query(Criteria.where( "_id" ).is(id)); return ( int ) this .mongoTemplate.remove(query, this .getEntityClass()).getDeletedCount(); } /** * 修改匹配到的第一条记录 * * @param query * @param update */ public UpdateResult updateFirst(Query query, Update update) { return this .mongoTemplate.updateFirst(query, update, this .getEntityClass()); } /** * 修改匹配到的所有记录 * * @param query * @param update */ public UpdateResult updateMulti(Query query, Update update) { return this .mongoTemplate.updateMulti(query, update, this .getEntityClass()); } /** * 聚合查询统计 * * @param * @return */ public <O> AggregationResults<O> aggregate(Aggregation aggregation, Class<O> outputType) { return mongoTemplate.aggregate(aggregation, this .getEntityClass(), outputType); } /** * 聚合查询统计 * * @param * @return */ public <O> AggregationResults<O> aggregate(TypedAggregation aggregation, Class<O> outputType) { return mongoTemplate.aggregate(aggregation, outputType); } } |
九、使用方式
dao层继承MongoDbDao抽象类即可
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Repository public class AlarmDataDao extends MongoDbDao<AlarmData> { @Override protected Class<AlarmData> getEntityClass() { return AlarmData. class ; } @MongoSwitch ( "discover_center" ) public int countAnInt(Query query){ return super .count(query); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
2019-02-22 JVM运行时的内存划分--JDK1.8