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);
    }
}

  

posted @   阳光、大地和诗歌  阅读(1130)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
历史上的今天:
2019-02-22 JVM运行时的内存划分--JDK1.8
点击右上角即可分享
微信分享提示