最新要闻
- 2尺2是多少毫米(2尺2多少厘米简介介绍)_今日热议
- 杭州现鸭屎香冰淇淋:味道揭秘!原来鸭屎香是一种乌龙茶
- 头条焦点:英国CMA或让步!微软收购动视暴雪新变动
- 天天关注:《英雄联盟》2023 MSI决赛JDG对战BLG!首发名单出炉:萍乡第一中单之争
- 青沼英二坦言自己老了:《王国之泪》将我逼到极限
- 银川市为500名女童免费接种HPV疫苗
- Win7经典“顽疾”:微软确认Win11硬盘可能被错误识别|全球今热点
- “挖呀挖”黄老师开始转型:参与文旅宣传!曾否认辞职带货
- 焦点热文:小李子新片《花月杀手》M站91分 多家媒体给出满分
- 格致男排,夺冠! 每日速递
- 《利益区间》冲击金棕榈大奖
- 4999元起!小牛MQiL电动两轮车开售:顶配能骑170km_世界动态
- 对话盛希泰:“专精特新”企业给二三四线城市带来发展机会_世界视点
- 快报:河南局地大暴雨!女子家中厨房窗户被暴风雨整个吹掉:庆幸无人受伤
- 每日关注!李想:汽车行业规模要求太苛刻 更容易出问题的不是成本而是销量
- 快报:我国南海发现两处古代沉船
广告
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
SpringBoot利用自定义注解实现多数据源
自定义多数据源
SpringBoot利用自定义注解实现多数据源,前置知识:注解、Aop、SpringBoot整合Mybaits
1、搭建工程
创建一个SpringBoot工程,并引入依赖
(资料图片)
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-aop org.mybatis.spring.boot mybatis-spring-boot-starter 2.3.0 com.mysql mysql-connector-j runtime com.alibaba druid-spring-boot-starter 1.2.18 org.springframework.boot spring-boot-starter-test test
2、定义多数据源注解
/** * 1、定义多数据源注解 * @author ss_419 * TODO 这个注解将来可以加在service类上或者方法上,通过value属性来指定类或者方法应该使用那个数据源 */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE, ElementType.METHOD})public @interface DataSource { String value() default DataSourceType.DEFAULT_DS_NAME;}
3、创建一个多数据上下文对象
这个类用来存储当前线程所使用的数据源名称
/** * TODO 这个类用来存储当前线程所使用的数据源名称 * * @author ss_419 * @version 1.0 * @date 2023/5/21 09:21 */public class DynamicDataSourceContextHolder { private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSourceType(String dataSourceType) { CONTEXT_HOLDER.set(dataSourceType); } public static String getDataSourceType() { return CONTEXT_HOLDER.get(); } public static void clearDataSourceType() { CONTEXT_HOLDER.remove(); }}
4、配置aop
@annotation(org.pp.dd.annotation.DataSource) 如果有@DataSource注解就给拦截下来
@within(org.pp.dd.annotation.DataSource) 表示类上有@DataSource注解就将类中的方法给拦截下来
/** * TODO * * @author ss_419 * @version 1.0 * @date 2023/5/21 09:42 */@Component@Aspect@Order(11)public class DataSourceAspect { /** * 定义切点 * * @annotation(org.pp.dd.annotation.DataSource) 如果有@DataSource注解就给拦截下来 * @within(org.pp.dd.annotation.DataSource) 表示类上有@DataSource注解就将类中的方法给拦截下来 */ @Pointcut("@annotation(org.pp.dd.annotation.DataSource) || @within(org.pp.dd.annotation.DataSource)") public void pc() { } /** * 环绕通知 * * @param pjp * @return */ @Around("pc()") public Object around(ProceedingJoinPoint pjp) { // 获取方法上的有效注解 DataSource dataSource = getDataSource(pjp); if (dataSource != null) { // 获取注解中数据源的名称 String value = dataSource.value(); DynamicDataSourceContextHolder.setDataSourceType(value); } try { return pjp.proceed(); } catch (Throwable e) { throw new RuntimeException(e); } finally { DynamicDataSourceContextHolder.clearDataSourceType(); } } private DataSource getDataSource(ProceedingJoinPoint pjp) { MethodSignature signature = (MethodSignature) pjp.getSignature(); // 获取方法上的注解 DataSource annotation = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); if (annotation != null) { // 说明方法上有注解 return annotation; } return (DataSource) AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); }}
5、读取参数DruidProperties
/** * TODO 读取数据源 * * @author ss_419 * @version 1.0 * @date 2023/5/21 10:20 */@ConfigurationProperties(prefix = "spring.datasource")public class DruidProperties { private String type; private String driverClassName; private Map> ds; private Integer initialSize; private Integer minIdle; private Integer maxActive; private Integer maxWait; /** * 在这个方法中设置公共属性 * @param dataSource * @return */ public DataSource dataSource(DruidDataSource dataSource){ dataSource.setInitialSize(initialSize); dataSource.setMinIdle(minIdle); dataSource.setMaxActive(maxActive); dataSource.setMaxWait(maxWait); return dataSource; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } public Map> getDs() { return ds; } public void setDs(Map> ds) { this.ds = ds; } public Integer getInitialSize() { return initialSize; } public void setInitialSize(Integer initialSize) { this.initialSize = initialSize; } public Integer getMinIdle() { return minIdle; } public void setMinIdle(Integer minIdle) { this.minIdle = minIdle; } public Integer getMaxActive() { return maxActive; } public void setMaxActive(Integer maxActive) { this.maxActive = maxActive; } public Integer getMaxWait() { return maxWait; } public void setMaxWait(Integer maxWait) { this.maxWait = maxWait; }}
6、加载数据源LoadDataSource
/** * TODO 加载数据源 * * @author ss_419 * @version 1.0 * @date 2023/5/21 10:30 */@Component@EnableConfigurationProperties(DruidProperties.class)public class LoadDataSource { @Autowired DruidProperties druidProperties; public Map loadAllDataSource() { Map map = new HashMap<>(); Map> ds = druidProperties.getDs(); try { Set keySet = ds.keySet(); for (String key : keySet) { map.put(key, druidProperties.dataSource((DruidDataSource) DruidDataSourceFactory.createDataSource(ds.get(key)))); } } catch (Exception e) { throw new RuntimeException(e); } return map; }}
7、定义数据源管理器
当系统需要调用数据源的时候,数据源以key-value存起来,当需要数据源时调用determineCurrentLookupKey()方法来获取数据源。由于本人实力原因,解答不了大家这里的疑惑。大致功能 通过修改本地线程的值,来实现数据源的切换。
/** * TODO 设置数据源 * 当系统需要调用数据源的时候,数据源以key-value存起来,当需要数据源时调用determineCurrentLookupKey()方法 * @author ss_419 * @version 1.0 * @date 2023/5/21 10:47 */@Componentpublic class DynamicDataSource extends AbstractRoutingDataSource { public DynamicDataSource(LoadDataSource loadDataSource) { //1、设置所有的数据源 Map allDs = loadDataSource.loadAllDataSource(); super.setTargetDataSources(new HashMap<>(allDs)); //2、设置默认数据源 super.setDefaultTargetDataSource(allDs.get(DataSourceType.DEFAULT_DS_NAME)); super.afterPropertiesSet(); } /** * 这个方法用来返回数据源名称,当系统需要获取数据源的时候会自动调用该方法获取数据源名称 * @return */ @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDataSourceType(); }}
定一个用于存储数据库类型的接口,这个接口类似于枚举类:
/** * TODO * * @author ss_419 * @version 1.0 * @date 2023/5/21 10:54 */public interface DataSourceType { String DEFAULT_DS_NAME = "master"; String DS_SESSION_KEY = "ds_session_key";}
8、测试
创建User实体:
/** * TODO * * @author ss_419 * @version 1.0 * @date 2023/5/21 11:15 */public class User { private Integer id; private String username; private String password; @Override public String toString() { return "User{" + "id=" + id + ", username="" + username + "\"" + ", password="" + password + "\"" + "}"; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}
创建UserService:
@Service// 在类上加注解的效果,会使该类的所有方法都切入到新的数据源中//@DataSourcepublic class UserService { @Autowired UserMapper userMapper; // 在方法上加注解的效果,只会让指定的方法切入到另一个数据源中 //@DataSource("slave") public List findUsers(){ return userMapper.findAllUsers(); }}
创建UserMapper:
@Mapperpublic interface UserMapper { @Select("SELECT * FROM user") List findAllUsers();}
测试类:
@SpringBootTestclass DynamicDatasourcesApplicationTests { @Autowired UserService userService; @Test void contextLoads() { List users = userService.findUsers(); users.stream() .forEach(user -> System.out.println(user)); }}
默认选择主库的数据源:
执行结果如下:
在Service上加上注解,指定数据源为从库:执行结果如下:
关键词:
SpringBoot利用自定义注解实现多数据源
2尺2是多少毫米(2尺2多少厘米简介介绍)_今日热议
杭州现鸭屎香冰淇淋:味道揭秘!原来鸭屎香是一种乌龙茶
头条焦点:英国CMA或让步!微软收购动视暴雪新变动
天天关注:《英雄联盟》2023 MSI决赛JDG对战BLG!首发名单出炉:萍乡第一中单之争
青沼英二坦言自己老了:《王国之泪》将我逼到极限
银川市为500名女童免费接种HPV疫苗
IMU 积分进行航迹推算 天天快报
Win7经典“顽疾”:微软确认Win11硬盘可能被错误识别|全球今热点
“挖呀挖”黄老师开始转型:参与文旅宣传!曾否认辞职带货
焦点热文:小李子新片《花月杀手》M站91分 多家媒体给出满分
格致男排,夺冠! 每日速递
CesiumJS 源码杂谈 - 时间与时钟系统_前沿热点
《利益区间》冲击金棕榈大奖
4999元起!小牛MQiL电动两轮车开售:顶配能骑170km_世界动态
对话盛希泰:“专精特新”企业给二三四线城市带来发展机会_世界视点
快报:河南局地大暴雨!女子家中厨房窗户被暴风雨整个吹掉:庆幸无人受伤
每日关注!李想:汽车行业规模要求太苛刻 更容易出问题的不是成本而是销量
04-多路选择器
快报:我国南海发现两处古代沉船
我国深海考古重大进展!首次发现大型古代沉船:水下第一视角太壮观 环球热文
因为AI 让80%的职业原画师下岗
帮助Linux管理员简化任务并实现自动化的七大工具
自己办理深圳创业补贴难吗?创业开饭店有补贴吗深圳
爱驰汽车被曝经营困难:开通员工自费交社保通道 焦点热讯
中国取代日本成全球第一大汽车出口国 俄罗斯为最大买家|天天热门
React闭包陷阱
每日观点:当日快讯:沙特外交大臣表示阿拉伯国家将继续在俄乌冲突中维持中立
全球快报:【财经分析】全球贸易增长正在恢复 应继续加强多边贸易合作
环球短讯!近视可用 特步0~700度专业大框泳镜狂促:12元包邮
店员称衣服掉地上摔个洞需赔款:最终结果让网友不淡定 速看
如何保存新鲜活虾 活虾怎么保存? 全球即时看
全球微动态丨体验阿斯顿·马丁DBX707 看看超跑品牌是怎么做SUV的
比亚迪首家全品牌体验中心开业:几万块到一百万的车全都有 当前简讯
第一批升级iOS 16.5正式版的用户被坑了!_要闻速递
学系统集成项目管理工程师(中项)系列23b_信息系统集成及服务管理(下)
【爬虫数据集】滇西小哥YouTube频道TOP10热门视频的热评数据,共2W条!_世界速看料
又有基金公司宣布:APP停止运营!_环球快看
清华大学女生获选美冠军 网友:全方位优秀
年轻人第一辆后驱SUV 长安深蓝S3预售:16.99万起-热议
全球信息:雨前高山春鲜 谢裕大珍珠绿茶60克到手29元
万达集团紧急声明!
03-点亮LED灯
热搜第一!BLG晋级 LPL提前锁定MSI三连冠 每日信息
全面了解华为全屋智能4.0:体验质变 最新快讯
母亲5点帮女儿排队领证结果走错地方:白排了一个小时队
当前快看:河海大学与华中师范大学签署战略合作协议
无论多少次,还是会为粉色疯狂心动!!!
文心一言 VS 讯飞星火 VS chatgpt (19)-- go语言的slice和rust语言的Vec的扩容流程是什么? 世界热文
阴阳师×GARNiDELiA决定展开合作 或为《极乐净土》高清重制版
索尼宣布将与WNBA达成合作伙伴关系 探索各种营销机会
环球今亮点!年终工作总结会议流程_年终工作总结会议通知
NASA发出警告称巨型小行星正在接近地球 大小为纽约地标自由女神像的两倍
网易旗下Jackalope Games宣布更名 正在开发一部基于“战锤”IP的游戏
苹果App商城现已有178万个应用程序 为有意义的统计数据
,影片《人生路不熟》票房突破9亿元大关 由马丽与乔杉等人主演
电视剧《仙剑奇侠传六》官微发布新海报 由许凯和虞书欣担任
顺丰控股公布4月快递物流业务经营 业务量同比增长29.59%
差价上千元该怎么选?13代酷睿i5和i7实测性能对比
华为把屏幕边框做到了1mm!畅享60 Pro即将开卖:1499元
国网东营供电公司开展全市电力设施和电能保护集中宣传活动
从350nm升到4nm 25年来AMD CPU性能已提升910倍
女子动车上提醒男子小声打电话被怼:你凭什么说我
520当天一女子逼停汽车泼粥骂渣男引围观:网友吐槽不该糟蹋粮食
由于半导体消费持续低迷 三星半导体将推迟平泽工厂4nm生产线设备投资
2023年DPC中国联赛夏季赛开战 Aster战队首秀大放异彩赢得首胜
阅读笔记:Sybilla DLT任务重启判定系统 焦点快看
首款天玑9200旗舰!vivo X90降价:256GB版3799元到手
网红三千哥直播PK饮酒过量去世 友人:喝了至少四瓶|当前通讯
英伟达RTX 4060 Ti显卡降临:关键参数已曝光 就差价格了
初三下册月考复习:第二单元知识点-天天快播报
Java生成二维码及条形码工具
python中的装饰器原理和作用 焦点热议
23款奔驰GLC评测_全球观焦点
有你家吗?杭州人均存款达16万元:全国住户存款最强8大城市 每日消息
华为笔记本性能怪兽!MateBook 16s下周首销:i7+1TB仅7999元 全球即时看
今日精选:20年来x86巨变 Intel将精简CPU架构:转向纯血64位
女子为骗男友结婚定制美颜假身份证引热议:网友感慨太假太美了 焦点报道
情侣筷子卖22元单身筷1元 超市:已下架-环球看点
双鸭山市气象台发布大风蓝色预警【IV级/一般】【2023-05-20】 全球热文
每日看点!Natasha 插件化之dll
天天最资讯丨暴雪又搞砸了 老外批《守望先锋2》太失败:浪费4年开发
桌面RTX 4070玩游戏 显示器选2K还是4K?来看对比实测 全球热推荐
远离元宇宙后 扎克伯格财富暴涨3000亿 全球最多!|全球新视野
小米两大技术接入联发科平台!卢伟冰:天玑芯片影像蜕变
37岁姐姐跟98年男友520领证 网友:羡慕了 天天讯息
全球观察:直通车是什么快递_直通车是什么
虎书 第一章 图形流水线_环球焦点
10.998万元 春风1250TR-G摩托价格公布:用上75°V型双缸发动机
焦点速看:丰田再批电动车毫无意义:烧煤发电不环保 氢燃料才合理
【环球时快讯】瓦伦丁·迪奥曼德_关于瓦伦丁·迪奥曼德介绍
C++ Today01
Kafka未触发消费异常排查实录-全球实时
基于python实现-根据Excel表格指定的UniqueKey的顺序-到另一个参考表格中查找-补全与自己相关的数据
Revit二次开发实战
天天观察:年轻人发完红包看电影 520单日总票房超1.5亿:速激10位列第一
网吧用“蛤蟆”、“天鹅”区分男女厕所 网友点赞直呼有才:官方回应
樱桃自由了!水果贵族樱桃一斤直降30元 六七月份还会继续降
B站CEO陈睿:年轻人爱学习 超8成985、211学生是B站用户 天天速递
三星独占结束!国产手机将用上“鸡血版”二代骁龙8-当前视点