当前位置: 首页 > article >正文

Spring Boot项目里,如何用注解优雅切换ShardingSphere和普通数据源?

Spring Boot项目中基于注解的ShardingSphere与普通数据源无感切换实践在分布式系统架构中数据源管理往往面临一个典型矛盾既要享受分库分表带来的性能提升又要保留对传统单表查询的兼容性。本文将分享一种基于Spring Boot的优雅解决方案通过自定义注解和AOP实现两种模式的声明式切换既保持代码整洁性又避免线程污染风险。1. 核心设计思路与技术选型数据源动态切换的本质是路由决策的时机问题。传统方案通常在DAO层硬编码或通过配置文件指定但这会带来两个问题业务代码与基础设施耦合度高多环境适配困难如测试环境可能不需要分片我们的解决方案基于三个核心组件自定义注解声明式标记数据源类型ThreadLocal上下文保证线程隔离性AOP切面在方法调用边界执行路由切换技术栈选择上除了基础的Spring Boot和MyBatis关键依赖包括dependency groupIdorg.apache.shardingsphere/groupId artifactIdshardingsphere-jdbc-core/artifactId version5.3.2/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-aop/artifactId /dependency2. 注解体系设计与实现注解设计需要考虑两个维度作用范围和优先级。我们定义了一个具有继承特性的注解Target({ElementType.METHOD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Inherited public interface DataRoute { /** * 路由策略类型 */ RouteStrategy value() default RouteStrategy.DEFAULT; /** * 分片键值仅SHARDING策略需要 */ String shardingKey() default ; }配套的枚举定义了支持的策略类型public enum RouteStrategy { DEFAULT, // 默认数据源 SHARDING, // 分片数据源 READ_ONLY // 只读副本可扩展 }优先级规则设计为方法级注解优先于类级注解显式配置优先于默认值缺少分片键时会抛出运行时异常3. 动态路由的核心实现3.1 线程安全的数据源上下文使用ThreadLocal保存当前线程的数据源标识public class DataSourceContextHolder { private static final ThreadLocalRouteContext CONTEXT new NamedThreadLocal(RoutingDataSourceContext); public static void setRouteContext(RouteContext context) { CONTEXT.set(context); } public static RouteContext getRouteContext() { return CONTEXT.get(); } public static void clear() { CONTEXT.remove(); } public static class RouteContext { private final RouteStrategy strategy; private final String shardingKey; // 构造方法等省略... } }3.2 动态数据源扩展继承AbstractRoutingDataSource并重写关键方法public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { RouteContext context DataSourceContextHolder.getRouteContext(); if (context null) { return defaultDataSource; } switch (context.getStrategy()) { case SHARDING: return shardingDataSource; case READ_ONLY: return readOnlyDataSource; default: return defaultDataSource; } } }3.3 AOP切面实现切面需要处理注解解析和上下文管理Aspect Component Order(Ordered.LOWEST_PRECEDENCE - 1) public class DataRouteAspect { Around(within(dataRoute) || annotation(dataRoute)) public Object around(ProceedingJoinPoint joinPoint, DataRoute dataRoute) throws Throwable { DataRoute classAnnotation AnnotationUtils.findAnnotation( joinPoint.getSignature().getDeclaringType(), DataRoute.class); DataRoute methodAnnotation AnnotationUtils.findAnnotation( ((MethodSignature)joinPoint.getSignature()).getMethod(), DataRoute.class); RouteStrategy strategy resolveStrategy(methodAnnotation, classAnnotation); String shardingKey resolveShardingKey(joinPoint, methodAnnotation); RouteContext context new RouteContext(strategy, shardingKey); DataSourceContextHolder.setRouteContext(context); try { return joinPoint.proceed(); } finally { DataSourceContextHolder.clear(); } } private String resolveShardingKey(ProceedingJoinPoint joinPoint, DataRoute annotation) { // 通过SpEL解析分片键值 } }4. 完整配置示例4.1 数据源配置Configuration public class DataSourceConfig { Bean ConfigurationProperties(prefixspring.datasource.default) public DataSource defaultDataSource() { return DruidDataSourceBuilder.create().build(); } Bean public DataSource shardingDataSource() throws SQLException { // ShardingSphere实际配置 return ShardingSphereDataSourceFactory.createDataSource( createDataSourceMap(), Collections.singleton(createShardingRuleConfiguration()), new Properties() ); } Primary Bean public DataSource routingDataSource( Qualifier(defaultDataSource) DataSource defaultDataSource, Qualifier(shardingDataSource) DataSource shardingDataSource) { MapObject, Object targetDataSources new HashMap(); targetDataSources.put(defaultDataSource, defaultDataSource); targetDataSources.put(shardingDataSource, shardingDataSource); DynamicDataSource dataSource new DynamicDataSource(); dataSource.setDefaultTargetDataSource(defaultDataSource); dataSource.setTargetDataSources(targetDataSources); return dataSource; } }4.2 MyBatis集成配置mybatis: mapper-locations: classpath*:mapper/**/*.xml configuration: default-statement-timeout: 30 map-underscore-to-camel-case: true5. 实际应用中的最佳实践5.1 事务管理的特殊处理在事务方法中切换数据源需要特别注意Service public class OrderService { Transactional DataRoute(RouteStrategy.DEFAULT) public void createOrder(Order order) { // 默认数据源操作 orderMapper.insert(order); // 需要分片查询时 queryFromSharding(order.getId()); } DataRoute(RouteStrategy.SHARDING) public Order queryFromSharding(Long id) { return orderMapper.selectById(id); } }重要原则事务边界内不建议切换数据源否则可能导致连接持有时间过长。5.2 性能优化建议连接池配置差异化参数默认数据源分片数据源maxActive2050minIdle510validationQuerySELECT 1SELECT 1 FROM DUAL监控指标分离Bean public DruidStatViewServlet druidStatViewServlet() { DruidStatViewServlet servlet new DruidStatViewServlet(); servlet.setUrlPattern(/druid/*); return servlet; }6. 常见问题排查指南问题1分片键解析失败检查SpEL表达式语法确认方法参数包含所需字段问题2线程污染确保finally块中清理上下文避免使用线程池不清理的异步调用问题3事务不生效检查Transactional注解顺序确认切面执行顺序正确在电商系统订单模块的实践中这套方案使TPS从1200提升到3500同时将代码侵入性降到最低。一个典型的查询服务实现如下RestController RequestMapping(/orders) DataRoute(RouteStrategy.DEFAULT) // 类级别默认策略 public class OrderController { GetMapping(/{id}) public Order getOrder(PathVariable Long id) { return orderService.getById(id); } GetMapping(/sharding/{id}) DataRoute(RouteStrategy.SHARDING) public Order getOrderFromSharding(PathVariable Long id) { return orderService.getById(id); } }

相关文章:

Spring Boot项目里,如何用注解优雅切换ShardingSphere和普通数据源?

Spring Boot项目中基于注解的ShardingSphere与普通数据源无感切换实践 在分布式系统架构中,数据源管理往往面临一个典型矛盾:既要享受分库分表带来的性能提升,又要保留对传统单表查询的兼容性。本文将分享一种基于Spring Boot的优雅解决方案&…...

GUI Guider设计完UI后,如何一步步把代码‘喂’给STM32?保姆级移植与排错指南

GUI Guider设计完UI后,如何一步步把代码‘喂’给STM32?保姆级移植与排错指南 当你用GUI Guider完成精美的UI设计后,真正的挑战才刚刚开始。本文将带你穿越从导出代码到STM32实际运行的完整路径,解决那些官方文档没告诉你的"坑…...

从Arduino到树莓派:CH340G驱动安装与故障排查全指南(Win11/Mac/Linux)

CH340G驱动安装与故障排查全指南:跨越Win11/Mac/Linux的终极解决方案 当你兴奋地拆开新到的Arduino开发板或ESP模块,准备大展身手时,电脑却冷冰冰地提示"无法识别的USB设备"——这种挫败感我太熟悉了。作为一款广泛用于国产开发板的…...

使用 Taotoken 的模型广场在 Ubuntu 开发中快速选型与切换 AI 模型

使用 Taotoken 的模型广场在 Ubuntu 开发中快速选型与切换 AI 模型 1. 模型广场的核心功能 Taotoken 模型广场是开发者进行模型选型的一站式信息中心。通过访问控制台中的模型广场页面,开发者可以查看平台当前支持的所有模型及其关键属性。每个模型条目会展示模型…...

如何彻底清理macOS应用残留文件?专业开源工具Pearcleaner使用指南

如何彻底清理macOS应用残留文件?专业开源工具Pearcleaner使用指南 【免费下载链接】Pearcleaner A free, source-available and fair-code licensed mac app cleaner 项目地址: https://gitcode.com/gh_mirrors/pe/Pearcleaner 你是否曾经在macOS上删除应用后…...

通过模型广场对比主流模型特性并选择适合当前任务的模型进行调用

通过模型广场对比主流模型特性并选择适合当前任务的模型进行调用 1. 模型广场功能概述 Taotoken 模型广场是平台提供的核心功能之一,汇集了多个厂商的大模型服务。通过该功能,开发者可以直观查看不同模型的性能参数、适用场景和计费标准,为…...

手把手教你用U盘搞定VMware ESXi 7.0安装,附网络配置与避坑指南

手把手教你用U盘搞定VMware ESXi 7.0安装,附网络配置与避坑指南 在个人开发者和小团队的实际工作中,搭建一个稳定高效的虚拟化环境往往能极大提升开发效率。对于预算有限但又需要灵活部署的场景,使用U盘安装VMware ESXi 7.0无疑是最经济实惠的…...

Orange Pi OS:融合Windows 11界面与Android生态的桌面系统解析

1. Orange Pi OS:一款融合Windows 11界面与Android生态的桌面操作系统 深圳迅龙软件(Shenzhen Xunlong Software)近期正式发布了基于Android的Orange Pi OS操作系统,这款系统最引人注目的特点是其高度模仿Windows 11的桌面界面设计…...

MC8635盒子救砖记:当晶晨刷机卡在1%时,我用ADB命令成功启动了Armbian U盘

MC8635盒子救砖实战:当晶晨刷机卡在1%时的ADB突围方案 那天晚上,我的工作台堆满了各种数据线和转接头。MC8635电视盒子安静地躺在USB烧录器旁边,屏幕上晶晨刷机助力的进度条固执地停在1%已经三个小时。作为一名常年折腾开发板的嵌入式爱好者&…...

《源·觉·知·行·事·物:生成论视域下的统一认知语法》第十三章 知的净化:从妄知到真知

原创声明:本文为作者周林东原创学术理论著作《源觉知行事物:生成论视域下的统一认知语法》的博客连载版。本书所述技术方案已提交中国发明专利申请,受相关法律保护。任何形式的商业使用,请与作者联系取得授权。欢迎基于学术目的的…...

告别Charles!用Python神器mitmproxy在Windows上抓包模拟器App,保姆级配置避坑指南

告别Charles!用Python神器mitmproxy在Windows上抓包模拟器App,保姆级配置避坑指南 在移动开发与爬虫领域,抓包工具如同开发者的"第三只眼"。传统工具如Charles和Fiddler虽然功能强大,但面对复杂的定制化需求时&#xff…...

从ElementUI到uni-ui:手把手教你为uni-datetime-picker移植‘禁用日期‘功能

从ElementUI到uni-ui:构建跨端日期选择器的禁用日期功能实战指南 当Vue开发者从ElementUI生态转向uni-app跨端开发时,常常会遇到功能模块不对等的挑战。uni-ui作为uni-app官方组件库,虽然提供了基础的uni-datetime-picker组件,但在…...

告别手动测试烦恼:CTS-Verifier实战详解与自动化探索(附APK下载与配置)

告别手动测试烦恼:CTS-Verifier实战详解与自动化探索 在Android设备兼容性测试领域,CTS-Verifier一直是个让人又爱又恨的存在。作为CTS测试中不可或缺的手动验证环节,它像一位严格的考官,专门检验那些自动化测试难以覆盖的硬件功能…...

【2026医疗数据安全生死线】:覆盖DRG/DIP支付场景的8类敏感字段识别模型+实时水印溯源方案(含三甲医院已验证POC代码)

更多请点击: https://intelliparadigm.com 第一章:MCP 2026医疗数据安全防护方法的演进逻辑与合规基线 MCP 2026(Medical Confidentiality Protocol 2026)并非孤立的技术标准,而是对GDPR、HIPAA、中国《个人信息保护法…...

5步掌握Windows系统优化神器:WinUtil完全指南

5步掌握Windows系统优化神器:WinUtil完全指南 【免费下载链接】winutil Chris Titus Techs Windows Utility - Install Programs, Tweaks, Fixes, and Updates 项目地址: https://gitcode.com/GitHub_Trending/wi/winutil WinUtil是一款由Chris Titus Tech开…...

Linux x64 ROP链不够用?试试这个藏在__libc_csu_init里的‘万能’gadget(附Python pwntools脚本)

突破ROP链限制:深入挖掘__libc_csu_init中的通用gadget 在64位Linux系统的漏洞利用开发中,构造可靠的ROP链常常面临一个棘手问题——难以找到控制所有必要寄存器的gadget片段。特别是当需要精确设置rdx、rsi等寄存器时,传统的ROP技术往往会遇…...

MCP 2026智能调度落地实录:从CPU争抢率飙升92%到资源利用率稳定在89.6%的5步闭环优化法

更多请点击: https://intelliparadigm.com 第一章:MCP 2026智能调度落地实录:从CPU争抢率飙升92%到资源利用率稳定在89.6%的5步闭环优化法 在某金融核心交易系统升级MCP 2026调度引擎后,集群CPU争抢率一度飙升至92%,导…...

【AISMM医疗行业实践黄金标准】:基于2026奇点大会12家头部厂商实测报告,锁定唯一通过NMPA III类证预审的架构范式

更多请点击: https://intelliparadigm.com 第一章:AISMM医疗行业实践黄金标准的诞生背景与战略意义 近年来,全球医疗健康数据呈指数级增长,AI模型在影像诊断、药物发现、电子病历分析等场景深度落地,但模型开发、验证…...

5分钟快速上手大麦网自动抢票脚本:告别手动抢票烦恼

5分钟快速上手大麦网自动抢票脚本:告别手动抢票烦恼 【免费下载链接】Automatic_ticket_purchase 大麦网抢票脚本 项目地址: https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase 还在为抢不到心仪的演唱会门票而烦恼吗?每次热门演…...

告别SPI波形抓瞎:S32K3 LPSPI时钟极性(CPOL/CPHA)配置详解与调试技巧

S32K3 LPSPI时钟配置实战:从波形分析到精准调试的完整指南 在嵌入式开发中,SPI通信的稳定性往往决定着整个系统的可靠性。当面对S32K3系列MCU的LPSPI模块时,工程师们最常遇到的挑战莫过于时钟相位(CPOL/CPHA)配置与实际波形不符导致的通信故障…...

SQLCoder终极指南:如何用15行代码让AI帮你写SQL查询

SQLCoder终极指南:如何用15行代码让AI帮你写SQL查询 【免费下载链接】sqlcoder 项目地址: https://ai.gitcode.com/hf_mirrors/defog/sqlcoder 想象一下这个场景:你正盯着复杂的数据库表结构,脑子里有个业务问题,却不知道…...

在 OpenClaw Agent 工作流中集成 Taotoken 统一管理模型调用

在 OpenClaw Agent 工作流中集成 Taotoken 统一管理模型调用 1. 准备工作 在开始集成前,请确保已安装 OpenClaw 框架并具备基础开发环境。同时需要拥有有效的 Taotoken API Key,可在 Taotoken 控制台的「API 密钥」页面创建。模型 ID 可通过模型广场查…...

Docker日志审计必须国产化?27天倒计时!信创替代窗口期仅剩最后47天,这份含SM2签名+时间戳防篡改的配置脚本请立刻保存

更多请点击: https://intelliparadigm.com 第一章:Docker日志审计国产化替代的紧迫性与政策依据 随着《网络安全法》《数据安全法》《关键信息基础设施安全保护条例》及《信创产业发展指南(2023—2035)》的深入实施,容…...

Cat-Catch终极实战指南:5步快速精通网页资源嗅探

Cat-Catch终极实战指南:5步快速精通网页资源嗅探 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否曾在网上看到精彩视频却苦于无法…...

别再盲目布线了!用贪心算法和模拟退火优化多波束测量效率(Python/Matlab双版本)

多波束测量效率革命:贪心算法与模拟退火的黄金组合(Python/Matlab实战) 当海底测绘工程师面对复杂地形时,最头疼的莫过于如何在保证全覆盖的前提下,让测船跑出最短路径。传统经验式布线不仅耗时耗力,还可能…...

EBERLE AD-41/051475000100模拟输入模块

EBERLE AD-41/051475000100模拟输入模块专为工业现场设计,用于采集传感器信号,具备高精度与高可靠性。多通道输入:支持4或8通道,节省空间。信号兼容:可配置接入0-20mA、4-20mA或0-10V信号。高分辨率:12-16位…...

DeepPCB:面向工业级PCB缺陷检测的数据集技术架构深度解析

DeepPCB:面向工业级PCB缺陷检测的数据集技术架构深度解析 【免费下载链接】DeepPCB A PCB defect dataset. 项目地址: https://gitcode.com/gh_mirrors/de/DeepPCB 数据集技术架构设计原理 DeepPCB数据集采用分层架构设计,为印刷电路板缺陷检测提…...

别再只会让RGB灯变色了!用Arduino UNO和PWM玩转呼吸灯、渐变跑马灯(附完整代码)

Arduino PWM灯光艺术:从呼吸灯到智能渐变系统的进阶指南 1. 突破基础RGB控制的技术瓶颈 当你已经能让RGB灯简单地切换颜色时,是否想过这些闪烁的灯光背后隐藏着更丰富的表达可能?PWM(脉冲宽度调制)技术就像一位隐形的灯…...

【2026年6月】英语四级高频核心词汇1500+历年真题pdf电子版

2026年上半年全国大学四级考试将于6月13日举行!帮助广大考生高效备考,小编精心整理了2026年6月英语四级CET4核心词汇1500个,PDF电子版,可下载打印! 资料下载: 资料下载https://pan.quark.cn/s/c0e98156a95…...

VMware虚拟机安装Windows Server 2022 教程

马上就要开学了,想必很多计算机网络专业的同学们要开始接触到Windows Server了,这也是计算机网络技术专业的专业基础课程,想当年我们实训课学习使用的好像是2008版的,也不晓得现在各个学校会用到哪个版本实操,盲猜应该…...