吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2241|回复: 5
收起左侧

[Java 原创] 使用 Nacos 配置中心 后 项目的多数据源 配置

[复制链接]
我是白小白 发表于 2023-1-17 13:41
本帖最后由 我是白小白 于 2023-1-17 13:47 编辑

可配置 多个源
都需 配置 mapper-locations


[Java] 纯文本查看 复制代码
# 数据源配置

platform:
  datasource:
    #1
    pj:
      id: pj
      mapper-package: com.pj
      mapper-locations: classpath:com/pj/project4sp/*.xml
      primary: true
      pool-name: pj
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/pj?characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
      type: com.zaxxer.hikari.HikariDataSource
      maximumPoolSize: 15
      idleTimeout: 30000
      connectionTimeout: 60000
      validationTimeout: 3000
      loginTimeout: 5
      maxLifetime: 60000

#2
    pp:
      id: pp
      mapper-package: com.pp
      mapper-locations: classpath:com/pp/project4sp/*.xml
      primary: false
      pool-name: pp
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/pp?characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
      type: com.zaxxer.hikari.HikariDataSource
      maximumPoolSize: 15
      idleTimeout: 30000
      connectionTimeout: 60000
      validationTimeout: 3000
      loginTimeout: 5
      maxLifetime: 60000
























代码
[Java] 纯文本查看 复制代码
@Configuration
@Import(DataSourceIntegrationRegistrar.class)
public class DataSourceIntegrationConfig {


}


[Java] 纯文本查看 复制代码
import com.alibaba.cloud.nacos.client.NacosPropertySource;
import com.zaxxer.hikari.HikariDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.cloud.bootstrap.support.OriginTrackedCompositePropertySource;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.*;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;



public class DataSourceIntegrationRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware, BeanFactoryAware {

    private static final Logger logger = LoggerFactory.getLogger(DataSourceIntegrationRegistrar.class);
    //OriginTrackedCompositePropertySource {name='bootstrapProperties', propertySources=[CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='sp-more-dev.yml,DEFAULT_GROUP'}, NacosPropertySource {name='sp-more.yml,DEFAULT_GROUP'}, NacosPropertySource {name='sp-more,DEFAULT_GROUP'}, NacosPropertySource {name='application-common-dev.yml,DEFAULT_GROUP'}, NacosPropertySource {name='application-common.yml,DEFAULT_GROUP'}]}]}
    private static final String CONFIG_PREFIX = "platform.datasource.";

    private Environment env;

    private ConfigurableListableBeanFactory beanFactory;

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AbstractEnvironment aEnv = (AbstractEnvironment) env;
        String profile = aEnv.getProperty("spring.profiles.active");
        MutablePropertySources propertySources = aEnv.getPropertySources();
        Map<String, Object> configMap = new LinkedHashMap<>();
        propertySources.forEach(propertySource -> {

            if (propertySource instanceof MapPropertySource) {
                MapPropertySource mps = (MapPropertySource) propertySource;
                Set<String> keys = mps.getSource().keySet();
                for (String key : keys) {
                    if (key.startsWith(CONFIG_PREFIX)) {
                        configMap.put(key, mps.getProperty(key));
                    }
                }

            }else if (propertySource instanceof OriginTrackedCompositePropertySource) {
                    OriginTrackedCompositePropertySource otcps = (OriginTrackedCompositePropertySource) propertySource;
                    Collection<PropertySource<?>> propertySources1 = otcps.getPropertySources();
                    for (PropertySource<?> propertySource1 : propertySources1) {
                        if (propertySource1 instanceof CompositePropertySource) {
                            CompositePropertySource nps = (CompositePropertySource) propertySource1;
                            Collection<PropertySource<?>> propertySources2 = nps.getPropertySources();
                            for (PropertySource<?> propertySource2 : propertySources2) {
                                if (propertySource2 instanceof NacosPropertySource) {
                                    NacosPropertySource nacosPropertySource = (NacosPropertySource) propertySource2;
                                    Set<String> keys = nacosPropertySource.getSource().keySet();
                                    for (String key : keys) {
                                        if (key.startsWith(CONFIG_PREFIX)) {
                                            configMap.put(key, nacosPropertySource.getProperty(key));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

        });

        Map<String, String> dataSourceItems = new LinkedHashMap<>();
        for (String s : configMap.keySet()) {
            String[] d = StringUtils.tokenizeToStringArray(s, ".");
            String prefix = d[2];
            String id = (String) getProperty(prefix, "id", configMap);
            String env = (String) getProperty(prefix, "env", configMap);
            if (!StringUtils.isEmpty(env)) {
                if (env.contains(profile)) {
                    dataSourceItems.put(id, prefix);
                }
            } else {
                dataSourceItems.put(id, prefix);
            }
        }
        dataSourceItems.forEach((key, value) -> {
            logger.info("数据源ID为:{},载入配置: {}", key, CONFIG_PREFIX + value);
            String dataSourceName = getArtifactName(key, "DataSource");
            String sqlSessionFactoryName = getArtifactName(key, "SqlSessionFactory");
            String sqlSessionTemplateName = getArtifactName(key, "SqlSessionTemplate");
            String transactionManagerName = getArtifactName(key, "TransactionManager");
            String mapperScanName = getArtifactName(key, "MapperScan");
            if (!beanFactory.containsBeanDefinition(dataSourceName)) {
                BeanDefinition dataSourceBeanDefinition = getDataSourceBeanDefinition(dataSourceName, value, configMap);
                registry.registerBeanDefinition(dataSourceName, dataSourceBeanDefinition);
                logger.info("自动注入DataSource:{}", dataSourceName);
            }
            if (!beanFactory.containsBeanDefinition(sqlSessionFactoryName)) {
                BeanDefinition sqlSessionFactoryBeanDefinition = null;
                try {
                    sqlSessionFactoryBeanDefinition = getSqlSessionFactoryBeanDefinition(sqlSessionFactoryName, value, dataSourceName, configMap);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new IllegalArgumentException(e);
                }
                registry.registerBeanDefinition(sqlSessionFactoryName, sqlSessionFactoryBeanDefinition);
                logger.info("自动注入SqlSessionFactory:{}", sqlSessionFactoryName);
            }
            if (!beanFactory.containsBeanDefinition(sqlSessionTemplateName)) {
                registry.registerBeanDefinition(sqlSessionTemplateName, getSqlSessionTemplateBeanDefinition(sqlSessionFactoryName, value, configMap, sqlSessionFactoryName));
                logger.info("自动注入SqlSessionTemplate:{}", sqlSessionTemplateName);
            }
            if (!beanFactory.containsBeanDefinition(transactionManagerName)) {
                registry.registerBeanDefinition(transactionManagerName, getTransactionManagerBeanDefinition(transactionManagerName, value, configMap, dataSourceName));
                logger.info("自动注入TransactionManager:{}", transactionManagerName);
            }
            registry.registerBeanDefinition(mapperScanName, getMapperScannerConfigurer(value, configMap, sqlSessionTemplateName));
        });
    }

    /**
     * 获取数据源BeanDefinition
     */
    private BeanDefinition getDataSourceBeanDefinition(String name, String s, Map<String, Object> configMap) {
        String poolName = String.valueOf(getProperty(s, "pool-name", configMap));
        String username = String.valueOf(getProperty(s, "username", configMap));
        String password = String.valueOf(getProperty(s, "password", configMap));
        String driverClassName = (String) getProperty(s, "driver-class-name", configMap);
        String jdbcUrl = (String) getProperty(s, "jdbc-url", configMap);
        String type = (String) getProperty(s, "type", configMap);
        Integer maximumPoolSize = (Integer) getProperty(s, "maximumPoolSize", configMap);
        Integer prepStmtCacheSize = (Integer) getProperty(s, "prepStmtCacheSize", configMap);
        Integer prepStmtCacheSqlLimit = (Integer) getProperty(s, "prepStmtCacheSqlLimit", configMap);
        Integer idleTimeout = (Integer) getProperty(s, "idleTimeout", configMap);
        Integer connectionTimeout = (Integer) getProperty(s, "connectionTimeout", configMap);
        Integer validationTimeout = (Integer) getProperty(s, "validationTimeout", configMap);
        Integer loginTimeout = (Integer) getProperty(s, "loginTimeout", configMap);
        Integer maxLifetime = (Integer) getProperty(s, "maxLifetime", configMap);
        Boolean cachePrepStmts = (Boolean) getProperty(s, "cachePrepStmts", configMap);
        Boolean useServerPrepStmts = (Boolean) getProperty(s, "useServerPrepStmts", configMap);
        Boolean useLocalSessionState = (Boolean) getProperty(s, "useLocalSessionState", configMap);
        Boolean useLocalTransactionState = (Boolean) getProperty(s, "useLocalTransactionState", configMap);
        Boolean rewriteBatchedStatements = (Boolean) getProperty(s, "rewriteBatchedStatements", configMap);
        Boolean cacheResultSetMetadata = (Boolean) getProperty(s, "cacheResultSetMetadata", configMap);
        Boolean elideSetAutoCommits = (Boolean) getProperty(s, "elideSetAutoCommits", configMap);
        Boolean maintainTimeStats = (Boolean) getProperty(s, "maintainTimeStats", configMap);

        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HikariDataSource.class);
        builder.addPropertyValue("poolName", poolName);
        builder.addPropertyValue("username", username);
        builder.addPropertyValue("password", password);
        builder.addPropertyValue("driverClassName", driverClassName);
        builder.addPropertyValue("jdbcUrl", jdbcUrl);
//        builder.addPropertyValue("type", type);
        builder.addPropertyValue("maximumPoolSize", maximumPoolSize);
//        builder.addPropertyValue("prepStmtCacheSize", prepStmtCacheSize);
//        builder.addPropertyValue("prepStmtCacheSqlLimit", prepStmtCacheSqlLimit);
        builder.addPropertyValue("idleTimeout", idleTimeout);
        builder.addPropertyValue("connectionTimeout", connectionTimeout);
        builder.addPropertyValue("validationTimeout", validationTimeout);
        builder.addPropertyValue("loginTimeout", loginTimeout);
        builder.addPropertyValue("maxLifetime", maxLifetime);
//        builder.addPropertyValue("cachePrepStmts", cachePrepStmts);
//        builder.addPropertyValue("useServerPrepStmts", useServerPrepStmts);
//        builder.addPropertyValue("useLocalSessionState", useLocalSessionState);
//        builder.addPropertyValue("useLocalTransactionState", useLocalTransactionState);
//        builder.addPropertyValue("rewriteBatchedStatements", rewriteBatchedStatements);
//        builder.addPropertyValue("cacheResultSetMetadata", cacheResultSetMetadata);
//        builder.addPropertyValue("elideSetAutoCommits", elideSetAutoCommits);
//        builder.addPropertyValue("maintainTimeStats", maintainTimeStats);
        return handlePrimary(name, builder, s, configMap);
    }

    /**
     * 获取 SqlSessionFactory Bean 定义
     */
    private BeanDefinition getSqlSessionFactoryBeanDefinition(String name, String s, String dataSourceName, Map<String, Object> configMap) throws IOException {
        String mapperLocations = (String) getProperty(s, "mapper-locations", configMap);
        if (StringUtils.isEmpty(mapperLocations)) {
            throw new IllegalArgumentException(s + " mapper-locations配置为空!");
        }
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SqlSessionFactoryBean.class);
        PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = pathMatchingResourcePatternResolver.getResources(mapperLocations);
        builder.addPropertyValue("mapperLocations", resources);
        builder.addPropertyReference("dataSource", dataSourceName);
        return handlePrimary(name, builder, s, configMap);
    }

    /**
     * 获取SqlSessionTemplate Bean 定义
     */
    private BeanDefinition getSqlSessionTemplateBeanDefinition(String name, String s, Map<String, Object> configMap, String sqlSessionFactoryName) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SqlSessionTemplate.class);
        builder.addConstructorArgReference(sqlSessionFactoryName);
        return handlePrimary(name, builder, s, configMap);
    }

    /**
     * 获取TransactionManager Bean 定义
     */
    private BeanDefinition getTransactionManagerBeanDefinition(String name, String s, Map<String, Object> configMap, String dataSourceName) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(DataSourceTransactionManager.class);
        builder.addConstructorArgReference(dataSourceName);
        return handlePrimary(name, builder, s, configMap);
    }

    /**
     * 获取 Mapper扫描注册组件 Bean定义
     */
    private BeanDefinition getMapperScannerConfigurer(String s,
                                                      Map<String, Object> configMap,
                                                      String sqlSessionTemplateBeanName) {
        String mapperPackage = (String) getProperty(s, "mapper-package", configMap);
        if (StringUtils.isEmpty(mapperPackage)) {
            throw new IllegalArgumentException(s + " mapper-package 配置为空!");
        }
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
        builder.addPropertyValue("processPropertyPlaceHolders", true);
        builder.addPropertyValue("sqlSessionTemplateBeanName", sqlSessionTemplateBeanName);
        builder.addPropertyValue("basePackage", mapperPackage);
        return builder.getBeanDefinition();
    }

    /**
     * 处理 是否Primary
     */
    private AbstractBeanDefinition handlePrimary(String name, BeanDefinitionBuilder builder, String prefix, Map<String, Object> configMap) {
        Boolean primary = (Boolean) getProperty(prefix, "primary", configMap);
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        if (primary != null && primary) {
            beanDefinition.setPrimary(true);
            logger.info("Bean: {} 设置为Primary", name);
        }
        return beanDefinition;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.env = environment;
    }

    private String getArtifactName(String key, String artifact) {
        return key + artifact;
    }

    private Object getProperty(String prefix, String key, Map<String, Object> configMap) {
        String s = CONFIG_PREFIX + prefix + ".";
        return configMap.get(s + key);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }
}





112.png

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
luozi1653 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

郭大路2019 发表于 2023-1-17 14:40
事务有没有问题
 楼主| 我是白小白 发表于 2023-1-17 16:54
 楼主| 我是白小白 发表于 2023-1-17 16:55

@Transactional(value = "pjTransactionManager", rollbackFor = {RuntimeException.class, Exception.class})    id+TransactionManager
郭大路2019 发表于 2023-4-3 12:29
所以你是单个数据库实例单个 事务管理器 是吧 如果一个大事务里面包含A数据源和B数据源的事务 你是怎么做的?
郭大路2019 发表于 2023-4-3 12:31
多数据源好配置 但是多数据源统一事务管理不好搞
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 00:09

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表