SpringBoot中動態(tài)數(shù)據(jù)源是實現(xiàn)與用途
一、應用場景
- 主從復制
- 讀寫分離
- 分庫分表
主從復制與讀寫分離通常是一起使用的。
二、實現(xiàn)方式
1、技術棧
- SpringBoot 2.6.13
- Druid 1.2.16
- Spring JDBC
- MySQL 8.0
- AOP動態(tài)代理
2、Maven 依賴
下邊依賴放入同一個pom.xml文件就可以
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>3、數(shù)據(jù)庫結(jié)構(gòu)
數(shù)據(jù)庫結(jié)構(gòu)非常簡單,主要實現(xiàn)思想,復雜的都是同一個操作方式。

(1)數(shù)據(jù)庫:db_dynamic1
DROP TABLE IF EXISTS `tb_user`; CREATE TABLE `tb_user` ( `id` bigint NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; BEGIN; INSERT INTO `tb_user` (`id`, `username`) VALUES (1, '張三'); INSERT INTO `tb_user` (`id`, `username`) VALUES (2, '李四'); INSERT INTO `tb_user` (`id`, `username`) VALUES (3, '王五'); COMMIT; SET FOREIGN_KEY_CHECKS = 1;
(2)數(shù)據(jù)庫:db_dynamic2
DROP TABLE IF EXISTS `tb_user`; CREATE TABLE `tb_user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; BEGIN; INSERT INTO `tb_user` (`id`, `username`) VALUES (1, 'Vker'); INSERT INTO `tb_user` (`id`, `username`) VALUES (2, 'Jack'); INSERT INTO `tb_user` (`id`, `username`) VALUES (3, 'Lucy'); COMMIT; SET FOREIGN_KEY_CHECKS = 1;
4、application.yml 配置文件
將下面配置文件的url, username, password換成你自己的
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/db_dynamic1?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
username: root
password: root_root
slave:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/db_dynamic2?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
username: root
password: root_root
initial-size: 1
min-idle: 1
max-active: 20
test-on-borrow: true5、定義一個 DataSources 注解
這個注解主要用于多數(shù)據(jù)源的選擇,默認是 master
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSources {
String value() default "master";
}6、配置一下動態(tài)數(shù)據(jù)源
這個類主要用于配置多數(shù)據(jù)源,不要忘記@Primary注解,否則會報錯。
@Component
@Primary
public class DynamicDataSources extends AbstractRoutingDataSource {
public static ThreadLocal<String> name = new ThreadLocal<>();
@Resource
DataSource master;
@Resource
DataSource slave;
@Override
protected Object determineCurrentLookupKey() {
return name.get();
}
@Override
public void afterPropertiesSet() {
Map<Object, Object> ds = new HashMap<>();
ds.put("master", master);
ds.put("slave", slave);
super.setTargetDataSources(ds);
super.setDefaultTargetDataSource(master);
super.afterPropertiesSet();
}
}7、寫一個基于 DataSources 注解的動態(tài)代理
這個動態(tài)代理用于檢查類或者方法上的@DataSources注解,取到注解中的value值,將值傳入動態(tài)數(shù)據(jù)源配置類DynamicDataSources的ThreadLocal中,用于選擇數(shù)據(jù)源。
@Component
@Aspect
public class DynamicDataSourcesAspect {
Logger logger = LoggerFactory.getLogger(DynamicDataSourcesAspect.class);
@Before("@annotation(dataSources)")
public void before(DataSources dataSources) {
String value = dataSources.value();
DynamicDataSources.name.set(value);
logger.info("進入AOP代理: {}", value);
}
}8、再來寫一個讀數(shù)據(jù)庫配置信息的配置類
這個配置類主要將application.yml中的數(shù)據(jù)庫配置信息的配置信息進行加載,然后使用數(shù)據(jù)源事務管理器DataSourceTransactionManager進行注冊。
@Configuration
public class DynamicDataSourcesConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.master")
public DataSource master() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.slave")
public DataSource slave() {
return DruidDataSourceBuilder.create().build();
}
@Bean
public DataSourceTransactionManager dataSourceTransactionManager1(@Qualifier("master") DataSource master) {
DataSourceTransactionManager dataSourceTransactionManager =
new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(master);
return dataSourceTransactionManager;
}
@Bean
public DataSourceTransactionManager dataSourceTransactionManager2(@Qualifier("slave") DataSource slave) {
DataSourceTransactionManager dataSourceTransactionManager =
new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(slave);
return dataSourceTransactionManager;
}
}重點的都做完了,接下來就寫一下基本的業(yè)務層代碼吧,注釋就不寫了,我相信小伙伴們都能看懂。
業(yè)務層代碼
1、實體類
public class User {
private Long id;
private String username;
// 省略了 getter setter
}2、Dao 數(shù)據(jù)層
public interface UserMapper {
List<User> selectAllUser();
}@Repository
public class UserMapperImpl implements UserMapper {
@Resource
private JdbcTemplate jdbcTemplate;
@Override
public List<User> selectAllUser() {
String sql = "select * from tb_user";
return jdbcTemplate.query(sql,
new BeanPropertyRowMapper<>(User.class));
}
}3、Service 服務層
public interface UserService {
List<User> list();
}@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public List<User> list() {
return userMapper.selectAllUser();
}
}4、Controller 控制層
這里說一下,你可以將注解 @DataSources 注解放到你想使用不同數(shù)據(jù)源的方法上,如下,默認 master 可以不寫。
@RestController
public class UserController {
@Resource
private UserService userService;
@GetMapping("list1")
public List<User> list1() {
return userService.list();
}
@GetMapping("list2")
@DataSources("slave")
public List<User> lis2t() {
return userService.list();
}
}5、最后來看一下啟動類
需要把 DataSourceAutoConfiguration 排除掉哦
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DynamicDatasourceDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DynamicDatasourceDemoApplication.class, args);
}
}6、測試結(jié)果
list1接口

list2接口

好了,以上就是動態(tài)數(shù)據(jù)源的實現(xiàn)方式了,歡迎小伙伴們留言,下期我們看看,如何實現(xiàn)主從復制和讀寫分離。
以上就是SpringBoot中動態(tài)數(shù)據(jù)源是實現(xiàn)與用途的詳細內(nèi)容,更多關于SpringBoot動態(tài)數(shù)據(jù)源的資料請關注腳本之家其它相關文章!
- SpringBoot中動態(tài)數(shù)據(jù)源配置與使用詳解
- SpringBoot配置動態(tài)數(shù)據(jù)源的實戰(zhàn)詳解
- SpringBoot自定義動態(tài)數(shù)據(jù)源的流程步驟
- SpringBoot實現(xiàn)動態(tài)數(shù)據(jù)源切換的項目實踐
- SpringBoot動態(tài)數(shù)據(jù)源連接測試的操作詳解
- SpringBoot實現(xiàn)動態(tài)數(shù)據(jù)源切換的方法總結(jié)
- springboot配置多數(shù)據(jù)源(靜態(tài)和動態(tài)數(shù)據(jù)源)
- springboot 動態(tài)數(shù)據(jù)源的實現(xiàn)方法(Mybatis+Druid)
- springboot動態(tài)數(shù)據(jù)源+分布式事務的實現(xiàn)
相關文章
javaSE,javaEE,javaME的區(qū)別小結(jié)
本篇文章小編就為大家簡單說說JavaSE、JavaEE、JavaME三者之間的區(qū)別,需要的朋友可以過來參考下,感興趣的小伙伴們可以參考一下2023-08-08
Mybatis?List列表In查詢實現(xiàn)的注意事項說明
這篇文章主要介紹了Mybatis?List列表In查詢實現(xiàn)的注意事項說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
Mybatis插件+注解實現(xiàn)數(shù)據(jù)脫敏方式
這篇文章主要介紹了Mybatis插件+注解實現(xiàn)數(shù)據(jù)脫敏方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
vue+springboot+shiro+jwt實現(xiàn)登錄功能
這篇文章主要介紹了vue+springboot+shiro+jwt實現(xiàn)登錄功能,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04

