SpringBoot利用自定义注解实现多数据源_全球新资讯
自定义多数据源SpringBoot利用自定义注解实现多数据源,前置知识:注解、Aop、SpringBoot整合Mybaits 1、
SpringBoot利用自定义注解实现多数据源,前置知识:注解、Aop、SpringBoot整合Mybaits
创建一个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
/** * 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;}
这个类用来存储当前线程所使用的数据源名称
【资料图】
/** * 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(); }}
@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); }}
/** * 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; }}
/** * 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; }}
当系统需要调用数据源的时候,数据源以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";}
创建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利用自定义注解实现多数据源,前置知识:注解、Aop、SpringBoot整合Mybaits 1、
每经AI快讯,中国保险资管业协会执行副会长兼秘书长曹德云5月21日在2023清华五道口全球金融论坛上表示,当
自2020年8月中国太保发布大健康发展规划以来始终以打造国内领先的健康保障综合服务供应商为发展目标积极发
吉利在全球范围内买买买。创业邦(ID:ichuangyebang)原创作者丨潘磊编辑丨海腰
1、陈奕迅的伤感情歌实在太多了,我给你推荐几首经典的:2、1夕阳无限好歌曲是为了缅怀梅艳芳而作。即便是
长阳土家族自治县气象台2023年05月21日10时26分发布大风蓝色预警信号:预计未来24小时,我县沿江河谷及高海
老矿山呈现新面貌重庆:探索多元化治理模式破解废矿修复难题正义网讯(记者满宁通讯员彭静刘乔月)“之前这里
拉菲尼亚:我想在巴萨待很多年红蓝色新发型?我早有此意,巴西,巴萨,新发型,拉菲尼亚,皇家社会,法国足球,巴
作者:广州医科大学附属第一医院扶宇这天,中药师小李正在门诊中药房窗口发药,有位老年患者手里拿着几袋药
1、建筑垃圾制砖机整体结构紧凑,坚固耐用,安全可靠。2、全过程PLC智能控制,操作简单、明了。3、高校的液
今天来聊聊关于范冰冰杨贵妃马戏未删减视频,范冰冰马震完整视频的文章,现在就为大家来简单介绍下范冰冰杨
1、陈腐、陈谷子烂芝麻、陈词滥调、陈醋、陈放、陈列、陈规、陈货、陈旧、陈酒、陈粮、陈酿、陈皮、陈设、
1、技工学校简称为“技校”。2、技校属于人社部门或劳动部门主管,发技工证和技工学校毕业证书以及职业资格
【解说】5月19日“骨肉天亲血脉相连”海峡两岸家书特展,在位于福建泉州的中国闽台缘博物馆开幕,通过一千
藏历四月被称为“萨嘎达瓦”“佛月”,是佛祖释迦牟尼诞生、成佛和涅槃的殊胜月。当日一早,在环绕大昭寺主
温暖夏日,“塞外江南”新疆伊犁河谷生机萌发,鲜花盛开,游人如织。
用上比亚迪刀片电池特斯拉ModelY首批样车充电实测:功率贼猛
17 98万元起新一代本田雅阁上市:买它还是比亚迪汉?
炖老鸡汤要想汤好喝,最好是纯正散养的老母鸡,而且要至少要养上两年以上的。做法也简单,把大枣和鸡肉一起
Al自营小时购服务将在北京、上海、广州、杭州等150多个城市上线,商品包括几乎Al自营所有品类。京东表示,
百度网盘删除的文件如何恢复?相信有很多用户现在都有使用过百度网盘来存储一些文件,那么当我们在使用网盘
上海博物馆藏宋元古籍展“玉楮流芳”近日开幕,与“波提切利与文艺复兴”“西方人物绘画400年”等西方艺术
5月19日,“北京西三旗万象汇杯”首届首都高等学校模拟本垒打挑战赛在西三旗万象汇完美九人棒垒球体验
热火G2逆转绿军!巴特勒太强硬,热巴+2替补齐爆,文森特杀死比赛,洛瑞,绿军,文森特,热火队,罗宾逊,美国篮球
栀子花叶子发黄了,水里加点“醋”,浇灌在花土里,避免叶子发黄栀子花是很多花友都非常喜欢的一种花卉哈哈
Copyright 2015-2022 北冰洋酒业网 版权所有 备案号:沪ICP备2020036824号-3 联系邮箱:562 66 29@qq.com