SpringBoot多数据源的两种实现方式实例

下面我就为你详细讲解一下“SpringBoot多数据源的两种实现方式实例”的完整攻略。

SpringBoot多数据源的两种实现方式实例

为什么需要多数据源

在实际开发中,我们可能会遇到这样的情况:业务系统需要同时连接多个数据库进行数据操作。此时单数据源的方式已无法满足需求,必须使用多数据源来进行解决。

方案一:使用@Primary注解

1.添加多数据源配置项

application.yml文件中添加多个数据源配置项,例如:

spring:
  datasource:
    primary:
      url: jdbc:mysql://localhost:3306/primary?useUnicode=true&characterEncoding=UTF-8&useSSL=false
      username: root
      password: 123456
    secondary:
      url: jdbc:mysql://localhost:3306/secondary?useUnicode=true&characterEncoding=UTF-8&useSSL=false
      username: root
      password: 123456

2.创建两个数据源Bean

DataSourceConfig类中创建两个数据源Bean,代码如下:

@Configuration
public class DataSourceConfig {

    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix="spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondaryDataSource")
    @Qualifier("secondaryDataSource")
    @ConfigurationProperties(prefix="spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

}

需要注意的是,@Primary注解表示优先使用该数据源,可以避免出现无法确定使用哪个数据源的情况。

3.配置JdbcTemplate

JdbcTemplateConfig类中配置两个JdbcTemplate,代码如下:

@Configuration
public class JdbcTemplateConfig {

    @Bean(name = "primaryJdbcTemplate")
    public JdbcTemplate primaryJdbcTemplate(
            @Qualifier("primaryDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean(name = "secondaryJdbcTemplate")
    public JdbcTemplate secondaryJdbcTemplate(
            @Qualifier("secondaryDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

}

4.编写访问多数据源的Controller

最后我们编写一个Controller来测试两个数据源是否能正常访问。

@RestController
public class UserController {

    @Autowired
    @Qualifier("primaryJdbcTemplate")
    private JdbcTemplate primaryJdbcTemplate;

    @Autowired
    @Qualifier("secondaryJdbcTemplate")
    private JdbcTemplate secondaryJdbcTemplate;

    @GetMapping("/users")
    public List<Map<String, Object>> getUsers() {
        String sql = "select * from user";
        List<Map<String, Object>> userList = primaryJdbcTemplate.queryForList(sql);
        sql = "select * from user";
        List<Map<String, Object>> userList2 = secondaryJdbcTemplate.queryForList(sql);
        userList.addAll(userList2);
        return userList;
    }

}

上面这个Controller中,我们使用了@Qualifier注解来指定使用哪个JdbcTemplate

方案二:动态切换数据源

1.添加多数据源配置项

与方案一相同,在application.yml文件中添加多个数据源配置项。

2.创建自定义注解

datasource包下创建一个自定义注解DataSourceType

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSourceType {
    String value() default "";
}

3.创建数据源切换AOP切面

创建一个DataSourceAspect类,代码如下:

@Component
@Aspect
public class DataSourceAspect {

    @Pointcut("@annotation(com.example.datasource.DataSourceType)")
    public void dataSourcePointCut() { }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        DataSourceType dataSourceType = signature.getMethod().getAnnotation(DataSourceType.class);
        if (null == dataSourceType) {
            DynamicDataSourceContextHolder.clearDataSourceType();
        } else {
            DynamicDataSourceContextHolder.setDataSourceType(dataSourceType.value());
        }
        try {
            return point.proceed();
        } finally {
            DynamicDataSourceContextHolder.clearDataSourceType();
        }
    }
}

该类使用了@Aspect注解来表示它是一个切面类,同时使用了@Component注解来将它加入到Spring容器中。

@Pointcut注解用来定义切点,该处定义了所有使用了@DataSourceType注解的方法或类。

@Around注解用来定义环绕通知,当使用了@DataSourceType注解时,切面会根据注解所指定的数据源类型来切换数据源。

4.创建自定义数据源

创建一个DynamicDataSource类,该类继承AbstractRoutingDataSource,并重写determineCurrentLookupKey()方法来动态切换数据源。

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceType();
    }

}

5.创建动态数据源配置

@Configuration
public class DynamicDataSourceConfig {

    @Bean("primaryDataSource")
    @ConfigurationProperties("spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean("secondaryDataSource")
    @ConfigurationProperties("spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean
    public DynamicDataSource dataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource,
                                         @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("primary", primaryDataSource);
        targetDataSources.put("secondary", secondaryDataSource);
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(primaryDataSource);
        return dataSource;
    }

}

在上述代码中,我们使用@Primary注解来指定默认使用的数据源,同时将primaryDataSourcesecondaryDataSource注入到DynamicDataSource类中,最终返回一个DynamicDataSource实例。

6.配置JdbcTemplate

与方案一相同,在JdbcTemplateConfig类中配置两个JdbcTemplate

7.编写使用切面的Controller

@RestController
public class UserController {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @GetMapping("/users")
    @DataSourceType("secondary")
    public List<Map<String, Object>> getUsers() {
        String sql = "select * from user";
        return jdbcTemplate.queryForList(sql);
    }

}

上面这个Controller中,我们使用了@DataSourceType注解来指定使用哪个数据源。

至此,我们已经完成了基于切面的动态数据源切换方案。

总结

本文为你详细讲解了SpringBoot多数据源的两种实现方式。方案一使用了@Primary注解来指定使用哪个数据源,方案二则使用了AOP切面来动态切换数据源。无论你选择哪种方案,都需要了解的是多数据源的加载方式,并且需要配置JdbcTemplate才能够操作多个数据源。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot多数据源的两种实现方式实例 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 详解Http请求中Content-Type讲解以及在Spring MVC中的应用

    详解HTTP请求中Content-Type讲解以及在Spring MVC中的应用 Content-Type是什么? 在HTTP协议中,Content-Type是一个请求头部和响应头部必不可少的属性,用来标识HTTP请求或响应体中的数据类型。常见的Content-Type类型有: text/html (html格式) application/json (jso…

    Java 2023年5月20日
    00
  • java的Jackson将json字符串转换成泛型List

    转换JSON字符串成Java对象是Java程序中经常需要做的一个任务。有很多开源库能够帮助我们完成这一任务,如Jackson。Jackson 是一个高效的 JSON 处理器,能够将 JSON 字符串解析成 Java 对象。 Jackson 支持将 JSON 转换成 Java 对象,也支持将 JSON 转换成泛型 List,本篇攻略将介绍 Jackson 将 …

    Java 2023年5月26日
    00
  • Java获取环境变量(System.getenv)的方法

    获取Java程序中的环境变量可以使用System.getenv()方法。该方法返回一个Map<String, String>对象,该对象包含系统环境变量的键值对。下面是获取环境变量的完整步骤: 步骤一:导入System类 要使用System.getenv()方法,需要先导入java.lang.System类。 import java.lang.S…

    Java 2023年5月30日
    00
  • Java实现多项式除法的代码示例

    当我们需要将多项式 $P(x)$ 除以 $Q(x)$,得到商式 $S(x)$ 和余式 $R(x)$,其中 $P(x)$,$Q(x)$,$S(x)$ 和 $R(x)$ 均为多项式,我们可以使用 Java 来实现多项式除法。下面是 Java 实现多项式除法的代码示例: 1. 实现思路 Java 实现多项式除法的思路是利用多项式的数据结构,通过对多项式进行简化转换…

    Java 2023年5月19日
    00
  • JAVA按字节读取文件的简单实例

    下面是“JAVA按字节读取文件的简单实例”的攻略: 简介 在Java中,可以通过字节流的方式读取文件,即逐个字节地读取文件中的内容。这种方式对于某些特殊情况下的文件操作非常有用。本文将展示Java中如何使用字节流读取文件的简单实例。 步骤 1. 创建File对象 首先,需要创建一个File对象。可以通过File类的构造函数来实现。 File file = n…

    Java 2023年5月19日
    00
  • SpringBoot集成Mybatis+xml格式的sql配置文件操作

    下面是SpringBoot集成Mybatis+xml格式的sql配置文件操作的完整攻略: 首先,在 pom.xml 文件中添加 Mybatis 和 Mybatis-SpringBoot-Starter 的依赖: <dependency> <groupId>org.mybatis</groupId> <artifact…

    Java 2023年6月1日
    00
  • 浅谈java异常处理之空指针异常

    浅谈Java异常处理之空指针异常 Java是一门强类型语言,也就是说变量的类型在声明过后就不能再改变,因此在编程中,经常会遇到空指针异常(NullPointerException)。本文将会对空指针异常进行详细的讲解。 空指针异常的定义 当程序试图访问一个空对象时,就会抛出空指针异常。空对象的意思是没有实例化的对象或者是一个null对象。 空指针异常的出现原…

    Java 2023年5月27日
    00
  • Java如何获取字符串单词个数

    要获取一个字符串中的单词个数,可以使用Java的正则表达式和字符串操作。 具体步骤如下: 将字符串按照空格或标点符号进行分割,得到字符串数组(即每个元素为一个单词)。 统计字符串数组的长度,即为单词的个数。 下面是代码实现: public static int getWordCount(String str) { if (str == null || str…

    Java 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部