SpringBoot中動(dòng)態(tài)數(shù)據(jù)源是實(shí)現(xiàn)與用途
一、應(yīng)用場(chǎng)景
- 主從復(fù)制
- 讀寫分離
- 分庫(kù)分表
主從復(fù)制與讀寫分離通常是一起使用的。
二、實(shí)現(xiàn)方式
1、技術(shù)棧
- SpringBoot 2.6.13
- Druid 1.2.16
- Spring JDBC
- MySQL 8.0
- AOP動(dòng)態(tài)代理
2、Maven 依賴
下邊依賴放入同一個(gè)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ù)庫(kù)結(jié)構(gòu)
數(shù)據(jù)庫(kù)結(jié)構(gòu)非常簡(jiǎn)單,主要實(shí)現(xiàn)思想,復(fù)雜的都是同一個(gè)操作方式。
(1)數(shù)據(jù)庫(kù):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ù)庫(kù):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: true
5、定義一個(gè) DataSources 注解
這個(gè)注解主要用于多數(shù)據(jù)源的選擇,默認(rèn)是 master
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DataSources { String value() default "master"; }
6、配置一下動(dòng)態(tài)數(shù)據(jù)源
這個(gè)類主要用于配置多數(shù)據(jù)源,不要忘記@Primary
注解,否則會(huì)報(bào)錯(cuò)。
@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、寫一個(gè)基于 DataSources 注解的動(dòng)態(tài)代理
這個(gè)動(dòng)態(tài)代理用于檢查類或者方法上的@DataSources
注解,取到注解中的value
值,將值傳入動(dòng)態(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("進(jìn)入AOP代理: {}", value); } }
8、再來寫一個(gè)讀數(shù)據(jù)庫(kù)配置信息的配置類
這個(gè)配置類主要將application.yml
中的數(shù)據(jù)庫(kù)配置信息的配置信息進(jìn)行加載,然后使用數(shù)據(jù)源事務(wù)管理器DataSourceTransactionManager
進(jìn)行注冊(cè)。
@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; } }
重點(diǎn)的都做完了,接下來就寫一下基本的業(yè)務(wù)層代碼吧,注釋就不寫了,我相信小伙伴們都能看懂。
業(yè)務(wù)層代碼
1、實(shí)體類
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 服務(wù)層
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ù)源的方法上,如下,默認(rèn) 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、最后來看一下啟動(dòng)類
需要把 DataSourceAutoConfiguration
排除掉哦
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class DynamicDatasourceDemoApplication { public static void main(String[] args) { SpringApplication.run(DynamicDatasourceDemoApplication.class, args); } }
6、測(cè)試結(jié)果
list1接口
list2接口
好了,以上就是動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方式了,歡迎小伙伴們留言,下期我們看看,如何實(shí)現(xiàn)主從復(fù)制和讀寫分離。
以上就是SpringBoot中動(dòng)態(tài)數(shù)據(jù)源是實(shí)現(xiàn)與用途的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot動(dòng)態(tài)數(shù)據(jù)源的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot中動(dòng)態(tài)數(shù)據(jù)源配置與使用詳解
- SpringBoot配置動(dòng)態(tài)數(shù)據(jù)源的實(shí)戰(zhàn)詳解
- SpringBoot自定義動(dòng)態(tài)數(shù)據(jù)源的流程步驟
- SpringBoot實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的項(xiàng)目實(shí)踐
- SpringBoot動(dòng)態(tài)數(shù)據(jù)源連接測(cè)試的操作詳解
- SpringBoot實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的方法總結(jié)
- springboot配置多數(shù)據(jù)源(靜態(tài)和動(dòng)態(tài)數(shù)據(jù)源)
- springboot 動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方法(Mybatis+Druid)
- springboot動(dòng)態(tài)數(shù)據(jù)源+分布式事務(wù)的實(shí)現(xiàn)
相關(guān)文章
javaSE,javaEE,javaME的區(qū)別小結(jié)
本篇文章小編就為大家簡(jiǎn)單說說JavaSE、JavaEE、JavaME三者之間的區(qū)別,需要的朋友可以過來參考下,感興趣的小伙伴們可以參考一下2023-08-08Mybatis?List列表In查詢實(shí)現(xiàn)的注意事項(xiàng)說明
這篇文章主要介紹了Mybatis?List列表In查詢實(shí)現(xiàn)的注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Mybatis插件+注解實(shí)現(xiàn)數(shù)據(jù)脫敏方式
這篇文章主要介紹了Mybatis插件+注解實(shí)現(xiàn)數(shù)據(jù)脫敏方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09vue+springboot+shiro+jwt實(shí)現(xiàn)登錄功能
這篇文章主要介紹了vue+springboot+shiro+jwt實(shí)現(xiàn)登錄功能,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04Java判斷2個(gè)List集合是否相等(不考慮元素的順序)
今天小編就為大家分享一篇關(guān)于Java判斷2個(gè)List集合是否相等(不考慮元素的順序)的文章,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法
這篇文章主要為大家詳細(xì)介紹了java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07