下面我就为你详细讲解一下“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
注解来指定默认使用的数据源,同时将primaryDataSource
和secondaryDataSource
注入到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技术站