springboot配置mongo多数据源方案
技术本质为制作多个mongo上下文,利用切面,在不同注解切点时切换上下文,达到多数据源的效果,以下为具体实现方案
一、修改配置文件的mongo配置方式
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
@Data
@ConfigurationProperties(prefix = "mongo.datasource")
public class MongoListProperties {
private List<MongoList> dblist;
@Data
public static class MongoList {
private String uri;
private String database;
}
}
四、编写mongo上下文
@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注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MongoSwitch {
/**
* mongo数据库名称
*
* @return
*/
String value() default "";
}
六、增加切面
@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数据源
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基础方法
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抽象类即可
@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);
}
}

浙公网安备 33010602011771号