一步一步实现若依框架--2.1实现多数据源
在项目中使用到了若依,想从头实现一下。思路就是把项目中涉及到的知识内容单独拎出来理解和做测试,然后再合到系统里去,重点的地方会将涉及到的知识进行总结和扩展。顺序是由后端到前端。 代码地址:https://github.com/hunji/RYMirror
common模块中的功能,大部分是通过自定义注解+AOP来实现通用功能。第2章节就会逐个实现各注解功能。本篇2.1是实现多数据源。代码中有打tag,跟着步骤来的,可以边看程序边看总结。
1)原理:
mybatis在执行sql前通过数据源去找数据库连接-->determineCurrentLookupKey(AbstractRoutingDataSource);所以通过注解拦截方法,在调用之前动态切换数据源名称即可。切换数据源,就要先给spring注入这些定义好的数据源,也就是程序中自定义的类DynamicDataSource的实例。所以问题就转换成了怎么准备多个数据源。通过DruidConfig中注入数据源,其中共性的属性由DruidProperties设置,各个数据源的特有属性根据注解ConfigurationProperties设置。最后,由于不同的请求是在不同的线程中的,可能去请求不同的数据源,所以这里要使用ThreadLocal保证现场安全来切换数据源名称。
2)ThreadLocal它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)
ThreadLocal 的特点:
-
ThreadLocal可以为当前线程关联一个数据。(它可以像Map一样存取数据,key为当前线程)
-
每一个 ThreadLocal对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个ThreadLocal对象实例。
-
每个ThreadLocal对象实例定义的时候,一般都是static类型
-
ThreadLocal中保存数据,在线程销毁后。会由JVM虚拟自动释放。这里销毁的是threadmap,如果说
这里有可能造成内存溢出,所以切点执行后手动清除一下。
3)@annotation 方法级别@within 对象级别
4)查找注解的方式:
public DataSource getDataSource(ProceedingJoinPoint point) { MethodSignature signature = (MethodSignature) point.getSignature(); // 查找方法上的注解 DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); if (Objects.nonNull(dataSource)) { return dataSource; } // 查找类上的注解 return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); }
这个方法就是为什么DataSource注解优先级是先方法后类
5)关于ConfigurationProperties的使用
有个问题就是各个数据源的name,password,url怎么设置到动态数据源中的。这里其实是ConfigurationProperties的用法。@Configuration注解的配置类中通过@Bean注解在某个方法上将方法返回的对象定义为一个Bean,并使用配置文件中相应的属性初始化该Bean的属性。
@Bean @ConfigurationProperties("spring.datasource.druid.slave") @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true") public DataSource slaveDataSource(DruidProperties druidProperties) { DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); return druidProperties.dataSource(dataSource); } public DruidDataSource dataSource(DruidDataSource datasource)
返回类型DruidDataSource是有这些属性的。
这种方式提供了一个思路,就是解决怎么把既有共性,又有特殊属性的一些配置,读取到同一个类中。可以使用一个map来获取这些属性去处理,也可以像上面这种方式,需用自己去map中遍历,
6) system模块里的mybatis是从哪里引入依赖的?system 依赖 common,conmon中引入了pagehelper,pagehelper中依赖了mybatis
7)mybatis开启驼峰命名自动映射 mapUnderscoreToCamelCase
8)单元测试
复制一个数据库,重命名为ry-vue2,修改sysUser中的数据。在system模块中添加sysUser的相关代码,在admin的test中添加单元测试。
@Service public class SysUserServiceImpl implements ISysUserService { @Autowired private SysUserMapper mapper; @Override @DataSource(DataSourceType.MASTER) public List<SysUser> getAllUsersMaster() { return mapper.getAllUsersMaster(); } @Override @DataSource(DataSourceType.SLAVE) public List<SysUser> getAllUsersSlave() { return mapper.getAllUsersSlave(); } }
==》扩展点(可以扩展的内容):
1.多数据源在yml文件中加上后不需要改程序
2.可以通过前台界面配置指定数据源
代码地址:
https://github.com/hunji/RYMirror/releases/tag/2.1%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异