码迷,mamicode.com
首页 > 编程语言 > 详细

springboot多数据源

时间:2020-11-10 11:11:29      阅读:11      评论:0      收藏:0      [点我收藏+]

标签:star   ber   before   prope   hash   其它   hold   bst   interface   

springboot多数据源

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.3.5.RELEASE</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.dtg</groupId>
   <artifactId>muldatasource</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>muldatasource</name>
   <description>Demo project for Spring Boot</description>
?
   <properties>
       <java.version>1.8</java.version>
   </properties>
?
   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-jpa</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-jdbc</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
?
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.25</version>
       </dependency>
?
?
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
           <exclusions>
               <exclusion>
                   <groupId>org.junit.vintage</groupId>
                   <artifactId>junit-vintage-engine</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
   </dependencies>
?
   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>
?
</project>

 

application.yml配置文件

增加读和写两个数据源

spring:
datasource:
  write:
  username: root
  password: root
  driver-class-name: com.mysql.jdbc.Driver
  jdbc-url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
  read:
  username: root
  password: root
  driver-class-name: com.mysql.jdbc.Driver
  jdbc-url: jdbc:mysql://127.0.0.1:3308/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

##

 

 

 

 

定义数据源类型

package com.dtg.muldatasource.constants;
?
public enum DataSourceType {
   WRITE,
   READ
}
?

定义数据源holder

holder维护了每个线程所需要的数据源类型,并对外暴露了设置数据源变量的方法。

package com.dtg.muldatasource.config;
?
public class DynamicDataSourceContextHolder {
?
   /**
    * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
    * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
    */
   private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
?
   /**
    * 设置数据源变量
    * @param dataSourceType
    */
   public static void setDataSourceType(String dataSourceType){
       System.out.println("切换到"+dataSourceType+"数据源");
       CONTEXT_HOLDER.set(dataSourceType);
  }
?
   /**
    * 获取数据源变量
    * @return
    */
   public static String getDataSourceType(){
       return CONTEXT_HOLDER.get();
  }
?
   /**
    * 清空数据源变量
    */
   public static void clearDataSourceType(){
       CONTEXT_HOLDER.remove();
  }
}

动态数据源类

通常用 springboot 时都是使用它的默认配置,只需要在配置文件中定义好连接属性就行了,但是现在我们需要自己来配置了,spring 是支持多数据源的,多个 datasource 放在一个 HashMapTargetDataSource中,通过dertermineCurrentLookupKey获取 key 来觉定要使用哪个数据源。因此我们的目标就很明确了,建立多个 datasource 放到 TargetDataSource 中,同时重写 dertermineCurrentLookupKey 方法来决定使用哪个 key。

这里的dertermineCurrentLookupKey 是查询DynamicDataSourceContextHolder中的数据源类型。

package com.dtg.muldatasource.config;
?
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
?
import javax.sql.DataSource;
import java.util.Map;
?
public class DynamicDataSource extends AbstractRoutingDataSource {
?
   /**
    *
    * @param defaultTargetDataSource 默认的数据源
    * @param targetDataSources 支持的所有数据源
    */
   public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
       super.setDefaultTargetDataSource(defaultTargetDataSource);
       super.setTargetDataSources(targetDataSources);
       // afterPropertiesSet()方法调用时用来将targetDataSources的属性写入resolvedDataSources中的
       super.afterPropertiesSet();
  }
?
   /**
    * 重写该方法,根据Key获取数据源的信息
    *
    * @return
    */
   @Override
   protected Object determineCurrentLookupKey() {
       return DynamicDataSourceContextHolder.getDataSourceType();
  }
}

 

数据源配置类DataSourceConfig

package com.dtg.muldatasource.config;
?
import com.dtg.muldatasource.constants.DataSourceType;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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;
?
@Configuration
public class DataSourceConfig {
   @Bean
   @ConfigurationProperties("spring.datasource.write")
   public DataSource writeDataSource() {
       return DataSourceBuilder.create().build();
  }
?
   @Bean
   @ConfigurationProperties("spring.datasource.read")
   public DataSource readDataSource() {
       return DataSourceBuilder.create().build();
  }
?
   @Bean(name = "dynamicDataSource")
   @Primary
   public DynamicDataSource dataSource(DataSource writeDataSource, DataSource readDataSource) {
       Map<Object, Object> targetDataSources = new HashMap<>();
       targetDataSources.put(DataSourceType.WRITE.name(), writeDataSource);
       targetDataSources.put(DataSourceType.READ.name(), readDataSource);
       return new DynamicDataSource(writeDataSource, targetDataSources);
  }
?
}

数据源注解

package com.dtg.muldatasource.config;
?
import com.dtg.muldatasource.constants.DataSourceType;
?
import java.lang.annotation.*;
?
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyDataSource {
   /**
    * 切换数据源名称
    */
   DataSourceType value() default DataSourceType.WRITE;
}

数据源切面

package com.dtg.muldatasource.aspect;
?
import com.dtg.muldatasource.config.DynamicDataSourceContextHolder;
import com.dtg.muldatasource.config.MyDataSource;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
?
import java.lang.reflect.Method;
?
@Aspect
@Order(1)
@Component
public class DataSourceAspect {
?
   @Pointcut("@annotation(com.dtg.muldatasource.config.MyDataSource)")
   public void dsPointCut() { }
?
?
   //@Before:在切入点方法执行之前执行该方法。
   @Before("dsPointCut()")
   public void  before(JoinPoint joinPoint){
       System.out.println("dsPointCut @before....");
  }
?
   // @AfterReturning:在切入点方法执行并有返回值才执行该方法。
   @AfterReturning("dsPointCut()")
   public void  AfterReturning(JoinPoint joinPoint){
       System.out.println("dsPointCut @AfterReturning....");
  }
?
   // @After:在执行切入点方法之后执行该方法。
   @After("dsPointCut()")
   public void  After(JoinPoint joinPoint){
       System.out.println("dsPointCut @After....");
  }
?
   @Around("dsPointCut()")
   public Object around(ProceedingJoinPoint point) throws Throwable {
       MethodSignature signature = (MethodSignature) point.getSignature();
       Method method = signature.getMethod();
       MyDataSource dataSource = method.getAnnotation(MyDataSource.class); //方法上获取 数据源的注解
       if (dataSource != null) {
           DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); //获取注解上的value
      }
?
       System.out.println("dsPointCut @Around start....");
?
       Object rs;
       try {
           rs =   point.proceed();
           return rs;
      } finally {
           // 销毁数据源 在执行方法之后
           DynamicDataSourceContextHolder.clearDataSourceType();
      }
?
?
  }
}

 

测试类:

 

package com.dtg.muldatasource.controller;
?
import com.dtg.muldatasource.config.MyDataSource;
import com.dtg.muldatasource.constants.DataSourceType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
?
import java.util.List;
import java.util.Map;
?
?
@RestController
public class EmpController {
?
   @Autowired
   JdbcTemplate jdbcTemplate;
?
   @GetMapping("/write")
   @MyDataSource(value = DataSourceType.WRITE)
   public List<Map<String, Object>> local(){
       List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from customer");
       return maps;
  }
   @GetMapping("/read")
   @MyDataSource(value = DataSourceType.READ)
   public List<Map<String, Object>> remote(){
       List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from customer");
       return maps;
  }
?
}

启动类:

package com.dtg.muldatasource;
?
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
?
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class MuldatasourceApplication {
?
   public static void main(String[] args) {
       SpringApplication.run(MuldatasourceApplication.class, args);
  }
?
}

 

springboot多数据源

标签:star   ber   before   prope   hash   其它   hold   bst   interface   

原文地址:https://www.cnblogs.com/datangguott/p/13950875.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!