zoukankan      html  css  js  c++  java
  • SpringBoot--Druid多数据源配置

    最近整理了一下spring boot关于对多数据源的配置,记录下来:

    一, 引入Jar包:

    <dependency> <!-- MySql驱动 -->
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        </dependency>
    <dependency> <!-- 连接池 -->
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.

    二, 配置参数:

    spring:
        datasource:
            type: com.alibaba.druid.pool.DruidDataSource
            driverClassName: com.mysql.jdbc.Driver
            druid:
                one:  #数据源1
                    url: jdbc:mysql://localhost:3306/test1?...
                    username: root
                    password: root
                two: #数据源2
                    url: jdbc:mysql://localhost:3306/test2?...
                    username: root
                    password: root
                initial-size: 10
                max-active: 100
                min-idle: 10
                max-wait: 60000
                pool-prepared-statements: true
                max-pool-prepared-statement-per-connection-size: 20
                time-between-eviction-runs-millis: 60000
                min-evictable-idle-time-millis: 300000
                validation-query: SELECT 1 FROM DUAL
                test-while-idle: true
                test-on-borrow: false
                test-on-return: false
                stat-view-servlet:
                    enabled: true
                    url-pattern: /druid/*
                    #login-username: admin
                    #login-password: admin
                filter:
                    stat:
                        log-slow-sql: true
                        slow-sql-millis: 1000
                        merge-sql: true
                    wall:
                        config:
                            multi-statement-allow: true

    (参数配置,可参考:  https://gitee.com/wenshao/druid/tree/master/druid-spring-boot-starter)

    三, 编写配置文件:

    1,  定义数据源名称常量 : 

    package com.gy.fast.common.config.data;
    
    /**
     * 数据源名称
     * @author geYang
     * @date 2018-05-14
     */
    public interface DataSourceNames {
        String ONE = "ONE";
        String TWO = "TWO";
    }

    2,  创建动态数据源:

    package com.gy.fast.common.config.data;
    
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    
    import javax.sql.DataSource;
    import java.util.Map;
    
    /**
     * 动态数据源
     * @author geYang
     * @date 2018-05-14
     */
    public class DynamicDataSource extends AbstractRoutingDataSource {
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    
        /**
         * 配置DataSource, defaultTargetDataSource为主数据库
         */
        public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
            super.setDefaultTargetDataSource(defaultTargetDataSource);
            super.setTargetDataSources(targetDataSources);
            super.afterPropertiesSet();
        }
    
        @Override
        protected Object determineCurrentLookupKey() {
            return getDataSource();
        }
    
        public static void setDataSource(String dataSource) {
            contextHolder.set(dataSource);
        }
    
        public static String getDataSource() {
            return contextHolder.get();
        }
    
        public static void clearDataSource() {
            contextHolder.remove();
        }
    
    }

    3, 动态数据源配置:

    package com.gy.fast.common.config.data;
    
    import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    
    import javax.sql.DataSource;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 配置多数据源
     * @author geYang
     * @date 2018-05-14
     */
    @Configuration
    public class DynamicDataSourceConfig {
        
        /**
         * 创建 DataSource Bean
         * */
        
        @Bean
        @ConfigurationProperties("spring.datasource.druid.one")
        public DataSource oneDataSource(){
            DataSource dataSource = DruidDataSourceBuilder.create().build();
            return dataSource;
        }
    
        @Bean
        @ConfigurationProperties("spring.datasource.druid.two")
        public DataSource twoDataSource(){
            DataSource dataSource = DruidDataSourceBuilder.create().build();
            return dataSource;
        }
        
        /**
         * 如果还有数据源,在这继续添加 DataSource Bean
         * */
        
        @Bean
        @Primary
        public DynamicDataSource dataSource(DataSource oneDataSource, DataSource twoDataSource) {
            Map<Object, Object> targetDataSources = new HashMap<>(2);
            targetDataSources.put(DataSourceNames.ONE, oneDataSource);
            targetDataSources.put(DataSourceNames.TWO, twoDataSource);
            // 还有数据源,在targetDataSources中继续添加
            System.out.println("DataSources:" + targetDataSources);
            return new DynamicDataSource(oneDataSource, targetDataSources);
        }
    }

    4, 定义动态数据源注解:

    package com.gy.fast.common.config.data;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 多数据源注解
     * @author geYang
     * @date 2018-05-14
     */
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DataSource {
        String value() default DataSourceNames.ONE;
    }

    5, 设置数据源 AOP 代理:

    package com.gy.fast.common.config.data;
    
    import java.lang.reflect.Method;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.Ordered;
    import org.springframework.stereotype.Component;
    
    /**
     * 数据源AOP切面处理
     * @author geYang
     * @date 2018-05-14
     */
    @Aspect
    @Component
    public class DataSourceAspect implements Ordered {
        protected Logger logger = LoggerFactory.getLogger(getClass());
    
        /**
         * 切点: 所有配置 DataSource 注解的方法
         */
        @Pointcut("@annotation(com.gy.fast.common.config.data.DataSource)")
        public void dataSourcePointCut() {}
    
        @Around("dataSourcePointCut()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            DataSource ds = method.getAnnotation(DataSource.class);
            // 通过判断 DataSource 中的值来判断当前方法应用哪个数据源
            DynamicDataSource.setDataSource(ds.value());
            System.out.println("当前数据源: " + ds.value());
            logger.debug("set datasource is " + ds.value());
            try {
                return point.proceed();
            } finally {
                DynamicDataSource.clearDataSource();
                logger.debug("clean datasource");
            }
        }
    
        @Override
        public int getOrder() {
            return 1;
        }
    }

    四, 修改启动文件:

    package com.gy.fast;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.context.annotation.Import;
    
    import com.gy.fast.common.config.data.DynamicDataSourceConfig;
    
    
    /**
     * 动态数据源配置,需要将自有的配置依赖(DynamicDataSourceConfig),将原有的依赖去除(DataSourceAutoConfiguration)
     * @author geYang
     * @date 2018-05-15
     */
    @Import({DynamicDataSourceConfig.class})
    @SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
    public class FastApplication {
        public static void main(String[] args) {
            SpringApplication.run(FastApplication.class, args);
        }
    }

    五, 配置完成, 进行测试:

    package com.gy.fast;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.gy.fast.common.config.data.DataSource;
    import com.gy.fast.common.config.data.DataSourceNames;
    import com.gy.fast.module.sys.entity.SysUser;
    import com.gy.fast.module.sys.service.SysUserService;
    
    /**
     * 测试多数据源
     * @author geYang
     * @date 2018-05-15
     */
    @Service
    public class DataSourceTestService {
        @Autowired
        private SysUserService sysUserService;
    
        public SysUser test1(Long userId){
            return sysUserService.selectById(userId);
        }
    
        @DataSource(DataSourceNames.TWO)
        public SysUser test2(Long userId){
            return sysUserService.selectById(userId);
        }
    }
    package com.gy.fast;
    
    
    import org.apache.commons.lang3.builder.ToStringBuilder;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import com.gy.fast.module.sys.entity.SysUser;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class DynamicDataSourceTest {
        @Autowired
        private DataSourceTestService dataSourceTestService;
        
        @Test
        public void test(){
            // 数据源ONE
            SysUser user1 = dataSourceTestService.test1(1L);
            System.out.println(ToStringBuilder.reflectionToString(user1));
    
            // 数据源TWO
            SysUser user2 = dataSourceTestService.test2(1L);
            System.out.println(ToStringBuilder.reflectionToString(user2));
    
            // 数据源ONE
            SysUser user3 = dataSourceTestService.test1(1L);
            System.out.println(ToStringBuilder.reflectionToString(user3));
        }
        
    }
  • 相关阅读:
    SGU 176.Flow construction (有上下界的最大流)
    POJ 2391.Ombrophobic Bovines (最大流)
    poj 1087.A Plug for UNIX (最大流)
    poj 1273.PIG (最大流)
    POJ 2112.Optimal Milking (最大流)
    SGU 196.Matrix Multiplication
    SGU 195. New Year Bonus Grant
    关于multicycle path
    ppt做gif动图
    codeforces 598A Tricky Sum
  • 原文地址:https://www.cnblogs.com/roak/p/14813109.html
Copyright © 2011-2022 走看看