多数据源切换-Druid

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37279783/article/details/82013702

这是实际应用场景中的多数据源切换案例

逻辑思路如下:

1.系统初始化,加载所有数据库中配置的数据源,加载进去spring容器

2.通过两种方法切换数据源:

2.1MultipleDataSource.setDataSourceKey(dataSourceKey);//切换

MultipleDataSource.clearDataSourceKey();//清除当前数据源并且还原到默认数据库

2.2使用@SwitchDataSource(name="dateSourceKey")注解

 


 

    <beans>
        <-- 配置默认数据源 -->
    <context:property-placeholder location="classpath*:jdbc.properties"/>
     
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
     
        <property name="minIdle" value="${rapid.jdbcPool.minPoolSize}"/>
        <property name="maxActive" value="${rapid.jdbcPool.maxPoolSize}"/>
        <property name="initialSize"
                  value="${rapid.jdbcPool.initialPoolSize}"/><!-- 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时,default=0 -->
        <property name="maxWait"
                  value="${rapid.jdbcPool.maxWait}"/><!-- 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁 -->
     
        <property name="timeBetweenEvictionRunsMillis"
                  value="${rapid.jdbcPool.timeBetweenEvictionRunsMillise}"/><!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,毫秒 -->
        <property name="minEvictableIdleTimeMillis"
                  value="${rapid.jdbcPool.minEvictableIdleTimeMillis}"/><!-- 配置一个连接在池中最小生存的时间,毫秒 -->
     
        <!-- 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于 timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效 -->
        <property name="testWhileIdle" value="${rapid.jdbcPool.testWhileIdle}"/>
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>
     
        <!-- 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都无效 -->
        <property name="validationQuery" value="${rapid.jdbcPool.validationQuery}"/>
     
        <!-- #是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭,default=false -->
        <property name="poolPreparedStatements" value="${rapid.jdbcPool.poolPreparedStatements}"/>
        <!-- #要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
             #在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100 -->
        <property name="maxOpenPreparedStatements" value="${rapid.jdbcPool.maxOpenPreparedStatements}"/>
     
        <!-- #属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:
             监控统计用的filter:stat
             日志用的filter:log4j
             防御sql注入的filter:wall -->
        <!--<property name="filters" value="stat"/>-->
        <property name="timeBetweenLogStatsMillis"
                  value="${rapid.jdbcPool.timeBetweenLogStatsMillis}"/><!-- 定时把监控数据输出到日志中,毫秒 -->
        <property name="proxyFilters">
            <list>
                <ref bean="stat-filter"/>
                <ref bean="log-filter"/>
            </list>
        </property>
    </bean>
     
    <!-- 多数据源切换 -->
    <bean id="multipleDataSource" class="cn.core.persistent.hibernate.datasource.MultipleDataSource">
            <property name="defaultTargetDataSource" ref="dataSource"/>
            <property name="targetDataSources">
                <map>
                    <entry key="dataSource" value-ref="dataSource"/>
                </map>
            </property>
    </bean>
     
        <!-- 多数据源注入 -->
    <bean id="loadDataSource" class="cn.core.persistent.hibernate.datasource.LoadDataSource">
            <property name="baseExtendDao" ref="baseExtendDao"/>
    </bean>
    <!-- 声明事务 -->
        <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="dataSource" ref="multipleDataSource"/>
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
     
        <aop:config>
            <aop:pointcut id="myMethod" expression="execution(* cn.*.service..*.*(..))"/>
            <aop:advisor advice-ref="multipleDataSource" order="1"
                         pointcut="execution(* cn.*.service..*.*(..)) and @annotation(cn.core.persistent.hibernate.datasource.SwitchDataSource)"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="myMethod" order="2"/>
        </aop:config>
     
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="add*" propagation="REQUIRED"/>
                <tx:method name="append*" propagation="REQUIRED"/>
                <tx:method name="insert*" propagation="REQUIRED"/>
                <tx:method name="save*" propagation="REQUIRED"/>
     
                <tx:method name="delete*" propagation="REQUIRED"/>
                <tx:method name="remove*" propagation="REQUIRED"/>
                <tx:method name="repair*" propagation="REQUIRED"/>
                <tx:method name="delAndRepair*" propagation="REQUIRED"/>
     
                <tx:method name="update*" propagation="REQUIRED"/>
                <tx:method name="modify*" propagation="REQUIRED"/>
                <tx:method name="edit*" propagation="REQUIRED"/>
     
                <tx:method name="init*" propagation="REQUIRED"/>
                <tx:method name="test*" propagation="REQUIRED"
                           rollback-for="Exception"/><!-- 如果不写 rollback-for它弄死都不给你回滚,这个东西弄了半天 -->
     
                <tx:method name="query*" propagation="SUPPORTS" read-only="true"/>
                <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
                <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
                <tx:method name="load*" propagation="SUPPORTS" read-only="true"/>
                <tx:method name="search*" propagation="SUPPORTS" read-only="true"/>
     
                <!--指定当前方法以非事务方式执行操作,如果当前存在事务,就把当前事务挂起,等我以非事务的状态运行完,再继续原来的事务。查询定义即可 read-only="true"  表示只读-->
                <tx:method name="*" propagation="NOT_SUPPORTED" read-only="true"/>
     
                <!--<tx:method name="logical*" propagation="REQUIRED" />&lt;!&ndash; 一般指逻辑删除 &ndash;&gt;-->
                <!--<tx:method name="batch*" propagation="REQUIRED" />&lt;!&ndash; 批量操作 &ndash;&gt;-->
            </tx:attributes>
        </tx:advice>
    </beans>

    import cn.commons.string.StringUtils;
    import cn.core.model.datasource.DataSource;
    import cn.core.model.logger.DruidSQLLoggerMonitorAppender;
    import cn.core.persistent.hibernate.AbstractHibernateDao;
    import cn.core.persistent.hibernate.extend.BaseExtendDao;
    import com.alibaba.druid.pool.DruidDataSource;
    import org.apache.commons.collections.map.HashedMap;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.util.Assert;
     
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
     
    /**
     * 多数据源加载
     * @bug [nothing]
     * @see [nothing]
     * @备注:
     */
    public class LoadDataSource extends AbstractHibernateDao {
        
        protected final Log logger = LogFactory.getLog(getClass());
        
        private BaseExtendDao baseExtendDao;
        
        /**
         * 加载数据库内配置的数据源
         * */
        public List<DataSource> selectDataSourceForDateBase() {
            Session session = null;
            try {
                session = super.getSessionFactory().openSession();
                            //查询数据库中所有数据源数据
                Query query = session.getNamedQuery("DataSource.findAll");
                return query.list();
            } catch (Exception e) {
                
            } finally {
                if (session != null) {
                    session.flush();
                    session.close();
                }
            }
            
            return new ArrayList();
        }
        
        /**
         * 创建数据源并注入进 spring 容器
         * */
        public void buiderDataSourceToSpring(ApplicationContext applicationContext) {
            //加载数据源
            //根据数据源,创建 DruidDataSource.class
            //重新创建多数据源
            List<DataSource> listDataSource = this.selectDataSourceForDateBase();
            
            if (listDataSource.size() > 0) {
                            //默认数据源bean的id
                DruidDataSource druidDataSourceDefault = applicationContext.getBean(SwitchDataSource.master, DruidDataSource.class);
                
                Map<Object, Object> targetDataSources = new HashedMap();
                targetDataSources.put(SwitchDataSource.master, druidDataSourceDefault);//支撑库
                
                //Bean的实例工厂
                DefaultListableBeanFactory dbf = (DefaultListableBeanFactory) ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
                
                for (Iterator<DataSource> iterator = listDataSource.iterator(); iterator.hasNext(); ) {
                    DataSource ds = iterator.next();
                    
                    //Bean构建  BeanService.class 要创建的Bean的Class对象
                    BeanDefinitionBuilder dataSourceBuider = BeanDefinitionBuilder.genericBeanDefinition(DruidDataSource.class);
                    
                    //向里面的属性注入值,提供get set方法
                    toolBuiderDataSourceToSpring(dataSourceBuider, ds);
                    
                    dataSourceBuider.setInitMethodName("init");
                    dataSourceBuider.setDestroyMethodName("close");
                    
                    //将实例注册spring容器中 key 等同于 id配置
                    dbf.registerBeanDefinition(ds.getDataSourceKey(), dataSourceBuider.getBeanDefinition());
                    
                    
                    DruidDataSource druidDataSource = applicationContext.getBean(ds.getDataSourceKey(), DruidDataSource.class);
                    targetDataSources.put(ds.getDataSourceKey(), druidDataSource);
                    
                    logger.info("加载数据源:名称->[" + ds.getDataSourceKey() + "],url->[" + druidDataSource.getUrl() + "],driver->[" + druidDataSource.getDriverClassName() + "],username->[" + druidDataSource.getUsername() + "]");
                }
                
                //重构多数据源列表
                MultipleDataSource multipleDataSource = applicationContext.getBean("multipleDataSource", MultipleDataSource.class);
                multipleDataSource.setTargetDataSources(targetDataSources);
                multipleDataSource.afterPropertiesSet();
            }
        }
        
        /**
         * 数据库配置的数据源注入容器
         *
         * @title toolBuiderDataSourceToSpring
         * @param dataSourceBuider spring 容器注入实例
         *        ds 数据库配置的数据源
         * @return
         * @throws
         */
        private void toolBuiderDataSourceToSpring(BeanDefinitionBuilder dataSourceBuider, DataSource ds) {
            Assert.notNull(ds, "多数据源注入异常 -> 配置的数据源不能为 null!!");
            Assert.notNull(dataSourceBuider, "多数据源注入异常 -> Spring 容器为 null!!");
            
            Assert.hasText(ds.getDriverClassName(), "多数据源加载异常 -> [" + ds.getDataSourceKey() + "] -> [driverClassName is null]");
            Assert.hasText(ds.getUrl(), "多数据源加载异常 -> [" + ds.getDataSourceKey() + "] -> [url is null]");
            Assert.hasText(ds.getUsername(), "多数据源加载异常 -> [" + ds.getDataSourceKey() + "] -> [username is null]");
            Assert.hasText(ds.getPassword(), "多数据源加载异常 -> [" + ds.getDataSourceKey() + "] -> [password is null]");
            
            dataSourceBuider.addPropertyValue("driverClassName", ds.getDriverClassName());
            dataSourceBuider.addPropertyValue("url", ds.getUrl());
            dataSourceBuider.addPropertyValue("username", ds.getUsername());
            dataSourceBuider.addPropertyValue("password", ds.getPassword());
            
            if (StringUtils.hasText(ds.getConnectPoolProperties())) {
                Map map = StringUtils.parseStringToMap(ds.getConnectPoolProperties(), ",", "=");
                
                if (map.containsKey("minPoolSize")) {//最小连接
                    dataSourceBuider.addPropertyValue("minIdle", map.get("minPoolSize"));
                }
                
                if (map.containsKey("maxPoolSize")) {//最大连接
                    dataSourceBuider.addPropertyValue("maxActive", map.get("maxPoolSize"));
                }
                
                if (map.containsKey("initialPoolSize")) {//初始连接数
                    dataSourceBuider.addPropertyValue("initialSize", map.get("initialPoolSize"));
                }
                
                if (map.containsKey("maxWait")) {//获取连接时最大等待时间
                    dataSourceBuider.addPropertyValue("maxWait", map.get("maxWait"));
                }
                
                if (map.containsKey("timeBetweenEvictionRunsMillis")) {//配置间隔多久才进行一次检测,检测需要关闭的空闲连接,毫秒
                    dataSourceBuider.addPropertyValue("timeBetweenEvictionRunsMillis", map.get("timeBetweenEvictionRunsMillis"));
                }
                
                if (map.containsKey("minEvictableIdleTimeMillis")) {//配置一个连接在池中最小生存的时间,毫秒
                    dataSourceBuider.addPropertyValue("minEvictableIdleTimeMillis", map.get("minEvictableIdleTimeMillis"));
                }
                
                //是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭,default=false
                if (map.containsKey("poolPreparedStatements")) {
                    dataSourceBuider.addPropertyValue("poolPreparedStatements", map.get("poolPreparedStatements"));
                }
                
                //#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
                //#在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
                if (map.containsKey("maxOpenPreparedStatements")) {
                    dataSourceBuider.addPropertyValue("maxOpenPreparedStatements", map.get("maxOpenPreparedStatements"));
                }
                
                //用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都无效
                if (map.containsKey("validationQuery")) {
                    String vq = (String) map.get("validationQuery");
                    if (StringUtils.hasText(vq)) {
                        dataSourceBuider.addPropertyValue("validationQuery", map.get("validationQuery"));
                        
                        //建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于 timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
                        if (map.containsKey("testWhileIdle")) {
                            dataSourceBuider.addPropertyValue("testWhileIdle", map.get("testWhileIdle"));
                        }
                        
                        if (map.containsKey("testOnBorrow")) {
                            dataSourceBuider.addPropertyValue("testOnBorrow", map.get("testOnBorrow"));
                        }
                        
                        if (map.containsKey("testOnReturn")) {
                            dataSourceBuider.addPropertyValue("testOnReturn", map.get("testOnReturn"));
                        }
                    }
                }
                
                //是否日志打印
                if (map.containsKey("statementExecutableSqlLogEnable")) {
                    boolean isStatementExecutableSqlLogEnable = (Boolean) map.get("statementExecutableSqlLogEnable");
                    if (isStatementExecutableSqlLogEnable) {
                        DruidSQLLoggerMonitorAppender log4jFilter = new DruidSQLLoggerMonitorAppender();
                        log4jFilter.setStatementExecutableSqlLogEnable(true);
                        
                        if (map.containsKey("serializationCurrentThreadExecutableSqlLogEnable")) {
                            log4jFilter.setSerializationCurrentThreadExecutableSqlLogEnable((Boolean) map.get("serializationCurrentThreadExecutableSqlLogEnable"));
                        }
                        
                        List list = new ArrayList();
                        list.add(log4jFilter);
                        dataSourceBuider.addPropertyValue("proxyFilters", list);
                    }
                }
            }
        }
        
        public BaseExtendDao getBaseExtendDao() {
            return baseExtendDao;
        }
        
        public void setBaseExtendDao(BaseExtendDao baseExtendDao) {
            this.baseExtendDao = baseExtendDao;
        }
        
    }

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface SwitchDataSource {
        String master = "dataSource";
        
        String dataSourceKey() default SwitchDataSource.master;
        
    }

    import cn.commons.string.StringUtils;
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
     
    import java.lang.reflect.Method;
    import java.lang.reflect.Type;
    import java.lang.reflect.TypeVariable;
    import java.util.*;
     
    /**
     * 多数据源切换
     * @bug [nothing]
     * @see [nothing]
     * @备注:
     */
    public class MultipleDataSource extends AbstractRoutingDataSource implements MethodInterceptor {
        
        //保存当前线程使用的数据源
        private static final ThreadLocal<String> dataSourceKey = new InheritableThreadLocal();
        
        //设置数据源
        public static void setDataSourceKey(String dataSourceName) {
            if (StringUtils.hasText(dataSourceName)) {
                MultipleDataSource.dataSourceKey.set(dataSourceName);
            }
        }
        
        //清除数据源,清除后使用默认的支撑库数据源
        public static void clearDataSourceKey() {
            MultipleDataSource.dataSourceKey.remove();
        }
        
        /**
         *
         * sessionFactory 加载数据源扩展方法
         * 详情请看 AbstractRoutingDataSource.determineTargetDataSource() 方法;
         * 这是一个扩展,返回的是数据源的名称,也就是 spring 配置的 baenName,通过返回的 beanName未找到数据源会直接使用支撑库做为数据源
         * */
        @Override
        protected Object determineCurrentLookupKey() {
            //这里返回 null或""  没有关系,在 bean-core.xml 我们注入了默认数据源
            return MultipleDataSource.dataSourceKey.get();
        }
        
        /**
         * 结合 spring aop 与 annotation 动态切换数据源.
         * 框架通过 Aop 实现了事务管理,那么数据源的切换与事务控制作用于相同的时候方法上,并且优先于事务控制切换数据源.详细配置请参考 beans-core.xml
         *
         * 如何使用:
         * 在需要切换数据源的service层的方法上,配置注解标签,并指定数据源名称,代码如下:
         * <code>
         *  @SwitchDataSource(name="dateSourceKey")
         *  public List getProducts(){
         *      ...
         *  }
         * </code>
         */
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Object result = null;
            SwitchDataSource switchDataSource = null;
            
            try {
                switchDataSource = invocation.getMethod().getAnnotation(SwitchDataSource.class);//接口方法定义的注解
                if (switchDataSource == null) {
    //                Class[] argsClass = new Class[invocation.getArguments().length];
    //                for (int i = 0, j = invocation.getArguments().length; i < j; i++) {
    //                    argsClass[i] = invocation.getArguments()[i].getClass();
    //                }
                    
                    //上面的获取方式有可能来至于接口,这里尝试在实现类获取注解
    //                switchDataSource = invocation.getThis().getClass().getMethod(invocation.getMethod().getName(), argsClass).getAnnotation(SwitchDataSource.class);
                    
                    // 20170526 修改
                    // 在接口中定义方法时,一般的形参都会实现父类或者接口.而实现类传入的实参又会是具体的实现类.所以导致直接使用 getMethod(String name, Class<?>... parameterTypes) 是无法获取方法的.
                    
                    
                    //尝试在实现类获取注解
                    String methodName = invocation.getMethod().getName();
                    Object[] args = invocation.getArguments();//实际参数;如 arraylist
                    
                    Method[] methods = invocation.getThis().getClass().getMethods();
                    for (int i = 0; i < methods.length; i++) {
                        if (methods[i].getName().equals(methodName)) {//方法相同
                            
                            Class[] typeClasss = methods[i].getParameterTypes();//定义的参数类型;如 list
                            if (typeClasss.length == args.length) {//参数数量相等
                                
                                if (typeClasss.length == 0) {//无参情况
                                    switchDataSource = methods[i].getAnnotation(SwitchDataSource.class);
                                    break;
                                } else {
                                    boolean isTrue = false;
                                    //判断所有的参数的类型是否相同
                                    for (int j = 0; j < args.length; j++) {
                                        if (typeClasss[j].isAssignableFrom(args[j].getClass())) {
                                            isTrue = true;
                                        } else {
                                            isTrue = false;
                                            break;
                                        }
                                    }
                                    
                                    if (isTrue) {
                                        switchDataSource = methods[i].getAnnotation(SwitchDataSource.class);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                
                
                if (switchDataSource != null) {
                    MultipleDataSource.setDataSourceKey(switchDataSource.dataSourceKey());
                }
                
                result = invocation.proceed();
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                if (switchDataSource != null) {
                    MultipleDataSource.clearDataSourceKey();//还原数据源;
                }
            }
            
            return result;
        }
        
        public static void main(String[] args) {
            System.out.println(ArrayList.class.isAssignableFrom(List.class));
        }
    }

    //系统初始化加载数据库中的数据源
     
    import javax.servlet.ServletException;
     
    import cn.core.persistent.hibernate.datasource.LoadDataSource;
    import cn.core.persistent.hibernate.datasource.MultipleDataSource;
    import org.apache.commons.collections.map.HashedMap;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.web.servlet.DispatcherServlet;
     
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
     
    /**
     *
     * 提供框架启动初始化扩展功能,继承 DispatcherServlet 并实现 initFrameworkServlet() 方法,该方法原生提供 spring 扩展
     *
     * 目前提供扩展如下:
     * 1.加载多数据源
     * @类名称:RapidFrameWorkServlet
     */
    public class RapidFrameWorkServlet extends DispatcherServlet {
        private static final long serialVersionUID = 1L;
        
        /**
         * 覆写spring的一个方法用来初始化进而得到初始化参数
         */
        @Override
        public void initFrameworkServlet() throws ServletException {
            try {
                //加载多数据源
                super.getWebApplicationContext().getBean("loadDataSource", LoadDataSource.class).buiderDataSourceToSpring(super.getWebApplicationContext());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    <-- 数据库中数据源对象 -->
    CREATE TABLE DATASOURCE
    (
      DATASOURCE_GUID          VARCHAR2(32 BYTE),
      DATASOURCE_NAME          VARCHAR2(128 BYTE),
      DATASOURCE_KEY           VARCHAR2(128 BYTE)   NOT NULL,
      DRIVER_CLASS_NAME        VARCHAR2(256 BYTE)   NOT NULL,
      URL                      VARCHAR2(512 BYTE)   NOT NULL,
      USERNAME                 VARCHAR2(128 BYTE)   NOT NULL,
      PASSWORD                 VARCHAR2(128 BYTE)   NOT NULL,
      CONNECT_POOL_PROPERTIES  VARCHAR2(1024 BYTE),
      OPERATOR_ID              VARCHAR2(64 BYTE),
      CREATE_TIME              DATE,
      MODIFY_TIME              DATE,
      RES_ACT_MAP_ID           VARCHAR2(64 BYTE),
      VALID_SIGN               NUMBER
    )

    //数据源控制层类,在新增数据源后重新加载容器的数据源
    public class DataSourceResource implements ApplicationContextAware {
        
        @Resource
        private IDataSourceService dataSourceService;
     
        @Resource(name="loadDataSource")
        private LoadDataSource loadDataSource;
     
        private ApplicationContext applicationContext;
     
        public void setApplicationContext(ApplicationContext paramApplicationContext) throws BeansException {
            applicationContext=paramApplicationContext;
        }
     
        /**
         * 添加数据
         * @param dataSourceType
         * @return
         */
        @RequestMapping("/put")
        @ResponseBody
        @RepeatSubmitToken
        public boolean addDataSourceTypeAction(DataSource dataSource){
     
           boolean flag= dataSourceService.selectDataSourceName(dataSourceType.getDataSourceName());
           if(flag){
               return false;
           }
           boolean isSuccess = dataSourceService.addDataSourceType(dataSource);
           //数据源添加成功后重新加载数据源
           loadDataSource.buiderDataSourceToSpring(applicationContext);
           return isSuccess;
        }
    }
 ————————————————  
版权声明:本文为CSDN博主「小蜗牛的路」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37279783/article/details/82013702

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值