- 背景介绍
Spring Boot 是一种基于 Spring 框架的快速开发 Web 应用的微服务框架,它的设计能够使开发者极速创建可独立运行的 Spring 应用程序。而在实际的开发过程中,很多业务场景需要使用多个数据源,并且多个数据源的读写分离也是一种非常常见的数据存储方案,这时候就需要对 Spring Boot 进行多数据源配置。
- Spring Boot 多数据源配置
在 Spring Boot 中实现多数据源配置可以通过以下步骤:
(1)引入相关依赖。
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!--Druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
(2)在 application.yml 文件中进行数据源配置。
spring:
datasource:
master:
url: jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
slave1:
url: jdbc:mysql://localhost:3307/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
(3)自定义多数据源配置类。
@Configuration
public class DataSourceConfig {
@Bean(name = "masterDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.master")
public DruidDataSource masterDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spring.datasource.slave1")
public DruidDataSource slaveDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
@Qualifier("slaveDataSource") DataSource slaveDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.MASTER.getType(), masterDataSource);
targetDataSources.put(DataSourceType.SLAVE.getType(), slaveDataSource);
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setDefaultTargetDataSource(masterDataSource); //默认数据源
dynamicDataSource.setTargetDataSources(targetDataSources);
return dynamicDataSource;
}
}
(4)自定义数据源持有类。
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDataSource();
}
}
(5)定义数据源类型枚举类。
public enum DataSourceType {
MASTER("master"),
SLAVE("slave");
private String type;
DataSourceType(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
(6)定义数据源 Holder 类,用于在线程中存储数据源类型的信息。
public class DataSourceHolder {
/**
* 使用ThreadLocal将数据源与当前线程绑定
*/
private static final ThreadLocal<String> holder = new ThreadLocal<>();
/**
* 绑定数据源
*/
public static void putDataSource(String dataSource) {
holder.set(dataSource);
}
/**
* 获取当前绑定的数据源
*/
public static String getDataSource() {
return holder.get();
}
/**
* 清除绑定的数据源信息
*/
public static void clear() {
holder.remove();
}
}
(7)在 Service 层的方法上加上数据源注解,注明该方法使用哪个数据源。
@Service
@Slf4j
public class UserInfoServiceImpl implements UserInfoService {
@Autowired
private UserInfoMapper userInfoMapper;
/**
* 使用主库进行写操作
*/
@DataSource(value = DataSourceType.MASTER)
@Override
public int addUserInfo(UserInfo userInfo) {
return userInfoMapper.insertSelective(userInfo);
}
/**
* 使用从库进行读操作
*/
@DataSource(value = DataSourceType.SLAVE)
@Override
public UserInfo getUserInfoById(String id) {
return userInfoMapper.selectByPrimaryKey(id);
}
}
- 示例说明
以下是两个示例,分别是对主库进行写操作和对从库进行读操作。
(1)向主库中插入一条用户信息。
@PostMapping("/addUser")
public String addUser(@RequestBody UserInfo userInfo) {
try {
userInfoService.addUserInfo(userInfo);
return "添加成功!";
} catch (Exception e) {
e.printStackTrace();
return "添加失败!";
}
}
(2)从从库中查询一条用户信息。
@GetMapping("/getUser/{id}")
public UserInfo getUser(@PathVariable("id") String id) {
try {
return userInfoService.getUserInfoById(id);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
- 总结
通过以上步骤,我们即可轻松地实现 Spring Boot 的多数据源配置,实现读写分离,提高系统的并发能力和稳定性。需要注意的是,在实际的开发中,我们还需考虑到数据源的负载均衡、事务管理、多数据源切换等问题,需要在实际的生产环境中根据需求进行进一步的配置和调整。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot多数据源读写分离的自定义配置问题及解决方法 - Python技术站