springboot配置多个mongodb实现动态切换

      日志平台要连接多个mongo库做日志统一查询,使用springboot的多Template模式不能做到动态切换,所以这里做一个动态模板实现自动切换。

DynamicMongoTemplate继承 MongoTemplate重写doGetDatabase方法,这个方法是protected修饰的,一看就知道是提供给咱们重写的。

 

import com.mongodb.client.MongoDatabase;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;

/**
 * @author DAI
 * @date 2020/5/30 12:51
 * @Description 动态mongo模板
 */
public class DynamicMongoTemplate extends MongoTemplate {

    public DynamicMongoTemplate(MongoDbFactory mongoDbFactory) {
        super(mongoDbFactory);
    }


    @Override
    protected MongoDatabase doGetDatabase() {
        MongoDbFactory mongoDbFactory = MongoContext.getMongoDbFactory();
        return mongoDbFactory == null ? super.doGetDatabase() : mongoDbFactory.getDb();
    }
}

注册DynamicMongoTemplate替换springboot自动配置的MongoTemplate

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author DAI
 * @date 2020/5/30 13:55
 * @Description TODO
 */
@Component
public class MongoContext {

    private static final Map MONGO_CLIENT_DB_FACTORY_MAP = new HashMap<>();
    private static final ThreadLocal MONGO_DB_FACTORY_THREAD_LOCAL = new ThreadLocal<>();
    @Autowired
    MongoListProperties mongoListProperties;

    @PostConstruct
    public void afterPropertiesSet() {
        if (!CollectionUtils.isEmpty(mongoListProperties.getList())) {
            mongoListProperties.getList().forEach(info->{
                MONGO_CLIENT_DB_FACTORY_MAP.put(info.getDatabase(), new SimpleMongoClientDbFactory(info.getUri()));
            });
        }
    }

    @Bean(name = "mongoTemplate")
    public DynamicMongoTemplate dynamicMongoTemplate() {
        Iterator iterator = MONGO_CLIENT_DB_FACTORY_MAP.values().iterator();
        return new DynamicMongoTemplate(iterator.next());
    }

    @Bean(name = "mongoDbFactory")
    public MongoDbFactory mongoDbFactory() {
        Iterator iterator = MONGO_CLIENT_DB_FACTORY_MAP.values().iterator();
        return iterator.next();
    }

    public static void setMongoDbFactory(String name) {
        MONGO_DB_FACTORY_THREAD_LOCAL.set(MONGO_CLIENT_DB_FACTORY_MAP.get(name));
    }

    public static MongoDbFactory getMongoDbFactory() {
        return MONGO_DB_FACTORY_THREAD_LOCAL.get();
    }


    public static void removeMongoDbFactory(){
        MONGO_DB_FACTORY_THREAD_LOCAL.remove();
    }

}

 

mongo的配置类

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.List;

/**
 * @author DAI
 * @date 2020/5/30 20:05
 * @Description TODO
 */
@Data
@ConfigurationProperties(prefix = "message.mongo")
public class MongoListProperties {

    private List list;

    @Data
    public static class MongoList {
        private String uri;
        private String database;
    }
}

 

springboot配置多个mongodb实现动态切换_第1张图片

自定义数据源切换注解


/**
 * 数据源切换
 * @author daiwenlong
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MongoSwitch {

    String value() default "";

}

 自动切换切面

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;


/**
 * @author DAI
 * @date 2020/5/30 18:43
 * @Description 数据源切换切面
 */
@Slf4j
@Aspect
@Component
public class MongoAspect {

    @Pointcut("@annotation(com.dwl.message.monitor.annotation.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);
            MongoContext.setMongoDbFactory(mongoSwitch.value());
        } catch (Exception e) {
            log.error("==========>前置数据源切换异常", e);
        }
    }



    @After("mongoSwitch()")
    public void after(JoinPoint point) {
        try {
            MongoContext.removeMongoDbFactory();
        } catch (Exception e) {
            log.error("==========>后置数据源切换异常", e);
        }
    }
    

}

 

 关于使用的问题,可以直接在方法上使用@MongoAspect("dbName")注解,dbName为你要切换的数据库名称。

也可以使用在代码里直接使用MongoContext.setMongoDbFactory(dto.getDataBase())进行数据源切换。

springboot配置多个mongodb实现动态切换_第2张图片

pom依赖

  
            org.springframework.boot
            spring-boot-starter-data-mongodb
        

 

你可能感兴趣的:(mongo,springboot)