中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot動態數據源的使用

發布時間:2020-06-06 16:17:38 來源:億速云 閱讀:917 作者:Leah 欄目:編程語言

這篇文章運用了實例代碼展示springboot動態數據源的使用方法,代碼非常詳細,可供感興趣的小伙伴們參考借鑒,希望對大家有所幫助。

一.應用案例

我們的數據庫A為主庫,其他數據庫配置在主庫中,從庫B,C,D的數量是不固定的,會根據業務的需要動態的把配置寫入到主庫中并動態在創建新的數據庫,也就是說在項目中我們只需要配置主庫的數據源,其他從庫都需要從主庫中讀出配置并動態創建數據源,動態的注入到Spring容器中,在使用的時候動態的切換數據源以實現相應的功能邏輯

二.環境配置

Springboot:2.0.4
Mybatis-plus:3.0.7.1
JDK:1.8

三.方案實踐

1.項目啟動類修改

在啟動類添加@Import({DynamicDataSourceRegister.class})注解用于代替默認的數據源配置

2.代碼結構

代碼結構如下:
springboot動態數據源的使用

@Component
public class ApplicationContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtil.applicationContext = applicationContext;
    }

    /**
     * 取得存儲在靜態變量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        checkApplicationContext();
        return applicationContext;
    }

    /**
     * 從靜態變量ApplicationContext中取得Bean, 自動轉型為所賦值對象的類型.
     */
    public static <T> T getBean(String name) {
        checkApplicationContext();
        if (applicationContext.containsBean(name)) {
            return (T) applicationContext.getBean(name);
        }
        return null;
    }

    /**
     * 從靜態變量ApplicationContext中取得Bean, 自動轉型為所賦值對象的類型.
     */
    public static <T> T getBean(Class<T> clazz) {
        checkApplicationContext();
        return (T) applicationContext.getBeansOfType(clazz);
    }

    private static void checkApplicationContext() {
        if (applicationContext == null)
            throw new IllegalStateException("applicaitonContext未注入,請在applicationContext.xml中定義SpringContextUtil");
    }
    public synchronized static void registerSingletonBean(String beanName,Class clzz,Map<String,Object> original) {
        checkApplicationContext();
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ApplicationContextUtil.getApplicationContext().getAutowireCapableBeanFactory();
        if(beanFactory.containsBean(beanName)){
            removeBean(beanName);
        }
        GenericBeanDefinition definition = new GenericBeanDefinition();
        //類class
        definition.setBeanClass(clzz);
        //屬性賦值
        definition.setPropertyValues(new MutablePropertyValues(original));
        //注冊到spring上下文
        beanFactory.registerBeanDefinition(beanName, definition);
    }
    public synchronized static void registerSingletonBean(String beanName, Object obj, Map<String,Object> original) {
        checkApplicationContext();
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ApplicationContextUtil.getApplicationContext().getAutowireCapableBeanFactory();
        if(beanFactory.containsBean(beanName)){
            removeBean(beanName);
        }
        GenericBeanDefinition definition = new GenericBeanDefinition();
        //類class
        definition.setBeanClass(obj.getClass());
        //屬性賦值
        definition.setPropertyValues(new MutablePropertyValues(original));
        //注冊到spring上下文
        beanFactory.registerBeanDefinition(beanName, definition);
    }
    public synchronized static void registerSingletonBean(String beanName,Object obj) {
        registerSingletonBean(beanName,obj,BeanUtils.transBean2Map(obj));
    }
    /**
     * 刪除spring中管理的bean
     * @param beanName
     */
    public static void removeBean(String beanName){
        ApplicationContext ctx = ApplicationContextUtil.getApplicationContext();
        DefaultListableBeanFactory acf = (DefaultListableBeanFactory) ctx.getAutowireCapableBeanFactory();
        if(acf.containsBean(beanName)) {
            acf.removeBeanDefinition(beanName);
        }
    }
}
public class BeanUtils {
public static Map<String, Object> transBean2Map(Object obj) {
    if(obj == null){
    return null;
    }
    Map<String, Object> map = new HashMap<>();
    try {
         BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
         PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 過濾class屬性
                if (!key.equals("class")) {
                // 得到property對應的getter方法
                Method getter = property.getReadMethod();
                Object value = getter.invoke(obj);
                map.put(key, value);
                }
            }
         } catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
         }
        return map;
    }
}
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceType();
    }

    public  void updateTargetDataSource(Map<String,DataSource> customDataSources){
        Map<Object,Object> customDS=new HashMap<Object, Object>();
        customDS.putAll(customDataSources);
        setTargetDataSources(customDS);
        afterPropertiesSet();
    }
}
public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    public static List<String> dataSourceIds = new ArrayList<>();

    public static String getDataSourceType() {
        return contextHolder.get();
    }

    public static void setDataSourceType(String dataSourceType) {
        if(!containsDataSource(dataSourceType)){
            DynamicDataSourceRegister.addSlaveDataSource(dataSourceType);
        }
        contextHolder.set(dataSourceType);
    }

    public static void clearDataSourceType() {
        contextHolder.remove();
    }

    /**
     * 判斷指定DataSrouce當前是否存在
     */
    public static boolean containsDataSource(String dataSourceId) {
        return dataSourceIds.contains(dataSourceId);
    }
}
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceRegister.class);

    //默認數據源
    public static DataSource defaultDataSource;
    //用戶自定義數據源
    public static Map<String, DataSource> slaveDataSources = new HashMap<>();

    public static BeanDefinitionRegistry beanDefinitionRegistry=null;

    public static String driverName;
    public static String userName;
    public static String password;
    public static String type;
    public static String url;

    @Override
    public  void setEnvironment(Environment environment) {
        initDefaultDataSource(environment);
    }

    private void initDefaultDataSource(Environment env) {
        // 讀取主數據源
        driverName=env.getProperty("spring.datasource.driver-class-name");
        userName=env.getProperty("spring.datasource.username");
        password=env.getProperty("spring.datasource.password");
        type=env.getProperty("spring.datasource.type");
        url=env.getProperty("spring.datasource.url");

        Constant.defaultDbName="a";

        Map<String, Object> dsMap = new HashMap<>();
        dsMap.put("driver",driverName);
        dsMap.put("url",url);
        dsMap.put("username",userName);
        dsMap.put("password",password);
        dsMap.put("type",type);
        defaultDataSource = buildDataSource(dsMap);
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        DynamicDataSourceContextHolder.dataSourceIds.add("dataSource");
        Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
        //添加默認數據源
        targetDataSources.put("dataSource", this.defaultDataSource);

        this.beanDefinitionRegistry=beanDefinitionRegistry;
        beanDefinitionRegistry(defaultDataSource,targetDataSources);
        logger.info("Dynamic DataSource Registry");
    }

    public static void addSlaveDataSource(String dataSourceType){
        BeanDefinition beanDefinition=beanDefinitionRegistry.getBeanDefinition("dataSource");
        PropertyValue propertyValue=beanDefinition.getPropertyValues().getPropertyValue("targetDataSources");
        Map<String,DataSource> oldTargetDataSource=(Map<String,DataSource>) propertyValue.getValue();

        String newUrl=firstStr+dataSourceType+secondStr;

        Map<String, Object> dsMap = new HashMap<>();
        dsMap.put("driver",driverName);
        dsMap.put("url",newUrl);
        dsMap.put("username",userName);
        dsMap.put("password",password);
        dsMap.put("type",type);
        DataSource ds = buildDataSource(dsMap);

        oldTargetDataSource.put(dataSourceType,ds);
        DynamicDataSource dynamicDataSource =ApplicationContextUtil.getBean("dataSource");
        dynamicDataSource.updateTargetDataSource(oldTargetDataSource);
        DynamicDataSourceContextHolder.dataSourceIds.add(dataSourceType);
    }

    public void beanDefinitionRegistry(DataSource defaultDataSource,Map<Object,Object> targetDataSources){
        //創建DynamicDataSource
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(DynamicDataSource.class);
        beanDefinition.setSynthetic(true);
        MutablePropertyValues mpv = beanDefinition.getPropertyValues();
        mpv.addPropertyValue("defaultTargetDataSource", defaultDataSource);
        if(targetDataSources.size()>0){
            mpv.addPropertyValue("targetDataSources", targetDataSources);
        }
        //注冊 - BeanDefinitionRegistry
        beanDefinitionRegistry.registerBeanDefinition("dataSource", beanDefinition);
    }

    public static DataSource buildDataSource(Map<String, Object> dataSourceMap) {
        try {
            Object type = dataSourceMap.get("type");
            Class<? extends DataSource> dataSourceType;
            dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);
            String driverClassName = dataSourceMap.get("driver").toString();
            String url = dataSourceMap.get("url").toString();
            String username = dataSourceMap.get("username").toString();
            String password = dataSourceMap.get("password").toString();
            // 自定義DataSource配置
            DataSourceBuilder factory = DataSourceBuilder.create().driverClassName(driverClassName).url(url)
                    .username(username).password(password).type(dataSourceType);
            return factory.build();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

3.使用實例

DynamicDataSourceContextHolder.setDataSourceType("B");
Integer lProductUv=dataVisitCollectionMapper.getProductUv(dDate);
DynamicDataSourceContextHolder.setDataSourceType(Constant.defaultDbName);

在setDataSourceType的時候判斷是否存在此數據源,如果存在就直接切換,不存在就動態創建并加入到Spring容器中,從而實現動態創建數據源的目的

關于springboot動態數據源的使用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

巴中市| 南昌县| 赤峰市| 库车县| 探索| 榆中县| 襄垣县| 丰原市| 西乡县| 双峰县| 绥中县| 志丹县| 东港市| 资中县| 盘山县| 南京市| 丹江口市| 岑巩县| 和硕县| 彰化市| 阿克| 雅安市| 台东市| 中山市| 中方县| 金沙县| 太谷县| 聂拉木县| 佛坪县| 万盛区| 屏南县| 兰坪| 醴陵市| 新晃| 漳平市| 万荣县| 福泉市| 大安市| 武功县| 太谷县| 怀集县|