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

    一, 引入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.9</version>
    </dependency>

    二, 配置参数:

    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.wqy.config.data;
    
    /**
     * 数据源名称
     * @author wqy
     * @date 2019-11-28
     */
    public interface DataSourceNames {
        String ONE = "ONE";
        String TWO = "TWO";
    }

    2,  创建动态数据源:

    package com.wqy.config.data;
    
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    
    import javax.sql.DataSource;
    import java.util.Map;
    
    /**
     * 动态数据源
     * @author wqy
     * @date 2019-11-28
     */
    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.wqy.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 wqy
     * @date 2019-11-28
     */
    @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.wqy.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 wqy
     * @date 2019-11-28
     */
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DataSource {
        String value() default DataSourceNames.ONE;
    }

    5, 设置数据源 AOP 代理:

    package com.wqy.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 wqy
     * @date 2019-11-28
     */
    @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.wqy.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 wqy
     * @date 2019-11-28
     */
    @Import({DynamicDataSourceConfig.class})
    @SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
    public class FastApplication {
        public static void main(String[] args) {
            SpringApplication.run(FastApplication.class, args);
        }
    }

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

    package com.wqy.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 wqy
     * @date 2019-11-28
     */
    @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.wqy.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));
        }
        
    }

    原创文件摘自:https://my.oschina.net/u/3681868/blog/1813011

  • 相关阅读:
    ubuntu 安装eclipse
    java中的ArrayList 、List、LinkedList、Collection关系详解
    JERSEY中文翻译(第三章、模块和依赖)
    JERSEY中文翻译(第一章、Getting Started、2.2)
    JERSEY中文翻译(第三章、JAX-RS Application, Resources and Sub-Resources)
    JERSEY中文翻译(第一章、Getting Started、1.1.7)
    创建一个入门的JAVA WEB站点(REST JERSEY)
    一个JAVA的WEB服务器事例
    一个简单的C/S事例——JAVA-Socket
    FILTER——JAVA
  • 原文地址:https://www.cnblogs.com/wangquanyi/p/11950811.html
Copyright © 2011-2022 走看看