本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
昨天,我发了一篇关于 Spring 脑图的学习知识体系,包括原理,源码解析,结合设计模式等。没想到非常的火爆,微信通讯录里一下子多了很多好友。我预计在今年 5 月份左右通讯录会达到 5000 人的上限。目的还是希望大家相互交流,共同进步,相互鼓励!
在互联网技术飞速发展的今天,各种技术已经非常成熟,尤其是像读写分离这样的架构,以及这样的项目显得非常的常见。那么今天我就和大家一起来,手把手的教大家利用 SpringBoot + Mybatis 实现一个读写分库的 demo 项目。
首先,我们这个项目要使用 SpringBoot,因为 SpringBoot 是现阶段最火的框架之一了;第二,我们要使用 Mybatis;第三,我们还要使用自定义注解。
下面我介绍几个主要的类实现,需要源码的可以加我微信号:xmtxtt 为好友,我免费发给大家!
先创建一个 DataSources 数据源接口。比如,我们假设是一主一从。
public interface DataSources {
String MASTER_DB = "masterDB";
String SLAVE_DB = "slaveDB";
}
第二步,创建一个切换数据源的 RoutingDataSource 注解类。
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.METHOD
})
public @interface RoutingDataSource {
String value() default DataSources.MASTER_DB;
}
注解的使用我就不在过多的解释了,就当大家都会吧,如果不会加群交流,好了。
第三步,在 application.yml 中配置多个数据源。
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/xttblog
username: xttblog
password: xttblog
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
datasourceSlave:
url: jdbc:mysql://127.0.0.1:3306/xttblog
username: xttblog
password: xttblog
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
第四步,配置多个 Datasource。
@Configuration
public class DatasourceConfig {
@Bean(destroyMethod = "close", name = DataSources.MASTER_DB)
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().type(DruidDataSource.class).build();
}
@Bean(destroyMethod = "close", name = DataSources.SLAVE_DB)
@ConfigurationProperties(prefix = "spring.datasourceSlave")
public DataSource dataSourceSlave() {
return DataSourceBuilder.create().type(DruidDataSource.class).build();
}
}
第五步,定义一个 DataSourceHolder,切换数据源。
public class DataSourceHolder {
/**
* 默认数据源
*/
public static final String DEFAULT_DATASOURCE = DataSources.MASTER_DB;
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
// 设置数据源名
public static void setDB(String dbType) {
System.out.println("切换到" + dbType + "数据源");
contextHolder.set(dbType);
}
// 获取数据源名
public static String getDB() {
return (contextHolder.get());
}
// 清除数据源名
public static void clearDB() {
contextHolder.remove();
}
}
第六步,定义一个动态数据源。
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDB();
}
}
第七步,Mybatis 整合动态数据源。
@Configuration
public class MybatisDynamicDataSourceConfig {
@Autowired
@Qualifier(DataSources.MASTER_DB)
private DataSource masterDB;
@Autowired
@Qualifier(DataSources.SLAVE_DB)
private DataSource slaveDB;
/**
* 动态数据源
*/
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 默认数据源
dynamicDataSource.setDefaultTargetDataSource(masterDB);
// 配置多数据源
Map<Object, Object> dsMap = Maps.newHashMap();
dsMap.put(DataSources.MASTER_DB, masterDB);
dsMap.put(DataSources.SLAVE_DB, slaveDB);
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
@Bean
@ConfigurationProperties(prefix = "mybatis")
public SqlSessionFactoryBean sqlSessionFactoryBean() {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// 配置数据源,此处配置为关键配置,如果没有将 dynamicDataSource 作为数据源则不能实现切换
sqlSessionFactoryBean.setDataSource(dynamicDataSource());
return sqlSessionFactoryBean;
}
}
第八步,也是最重要的一步,拦截所有有 @RoutingDataSource 注解的方法。动态的给它指定数据源。
@Aspect
@Component
public class XttblogDynamicDataSourceAspect {
@Before("@annotation(com.xttblog.sharding.RoutingDataSource)")
public void doBeforeSwitchDataSource(ProceedingJoinPoint point){
//获得当前访问的class
Class<?> className = point.getTarget().getClass();
//获得访问的方法名
String methodName = point.getSignature().getName();
Signature signature =point.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
//得到方法的参数的类型
Class[] argClass = methodSignature.getMethod().getParameterTypes();
String dataSource = DataSourceHolder.DEFAULT_DATASOURCE;
try {
// 得到访问的方法对象
Method method = className.getMethod(methodName, argClass);
// 判断是否存在@DS注解
if (method.isAnnotationPresent(RoutingDataSource.class)) {
RoutingDataSource annotation = method.getAnnotation(RoutingDataSource.class);
// 取出注解中的数据源名
dataSource = annotation.value();
}
} catch (Exception e) {
e.printStackTrace();
}
// 切换数据源
DataSourceHolder.setDB(dataSource);
}
@After("@annotation(com.xttblog.sharding.RoutingDataSource)")
public void doAfterSwitchDataSource(JoinPoint point){
DataSourceHolder.clearDB();
}
}
第九步,要取消自动配置数据源,不要让 SpringBoot 自动的使用 DataSourceAutoConfiguration 了。
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class XttblogApplication {
public static void main(String[] args) {
SpringApplication.run(XttblogApplication.class,args);
}
}
最后就是如何使用了,插入我们使用主库,查询我们使用从库。
@Service
public class XttblogService {
@Autowired
private XttblogMapper xttblogMapper;
@RoutingDataSource(DataSources.MASTER_DB)
public int insert(Xttblog xttblog) {
return xttblogMapper.insertXttblog(xttblog.getName());
}
@RoutingDataSource(DataSources.SLAVE_DB)
public Xttblog select(Long id) {
return xttblogMapper.selectXttblogById(id);
}
}
以上源码,需要的可以加我微信号:xmtxtt 为好友,我免费发给大家!
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » 手把手教你利用 SpringBoot + Mybatis 实现一个读写分库项目