作者:陈鑫 | 来源:互联网 | 2021-11-18 19:53
这篇文章主要给大家介绍了关于SpringBoot自定义注解使用读写分离Mysql数据库的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
需求场景
为了防止代码中有的SQL慢查询,影响我们线上主数据库的性能。我们需要将sql查询操作切换到从库中进行。为了使用方便,将自定义注解的形式使用。
mysql导入的依赖
mysql
mysql-connector-java
8.0.16
代码实现
配置文件
application.yml
spring:
datasource:
master:
username: root
password: 123456
jdbc-url: jdbc:mysql://localhost:3306/master?useUnicode=true&characterEncoding=utf-8&serverTimezOne=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
slave:
username: root
password: 123456
jdbc-url: jdbc:mysql://localhost:3306/slave?useUnicode=true&characterEncoding=utf-8&serverTimezOne=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
DataSourceType
/**
* 数据源类型枚举
* @author yangjc01
* @create 2020/11/02
*/
public enum DataSourceType {
/**
* 主库,主要进行写操作
*/
MASTER,
/**
* 从库,进行读操作
*/
SLAVE
}
DynamicDataSource
/**
* 动态数据源
* @author yangjc01
* @create 2020/11/02
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
public DynamicDataSource(DataSource defaultTargetDataSource,
Map targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDateSourceType();
}
}
DynamicDataSourceContextHolder
public class DynamicDataSourceContextHolder {
/**
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
*/
private static final ThreadLocal CONTEXT_HOLDER =
new ThreadLocal<>();
/**
* 设置数据源的变量
*/
public static void setDateSourceType(String dsType) {
CONTEXT_HOLDER.set(dsType);
}
/**
* 获得数据源的变量
*/
public static String getDateSourceType() {
return CONTEXT_HOLDER.get();
}
/**
* 清空数据源变量
*/
public static void clearDateSourceType() {
CONTEXT_HOLDER.remove();
}
}
DataSource 注解
/**
* @author yangjc01
* @create 2020/11/01
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
/**
* 切换数据源
*/
DataSourceType value() default DataSourceType.MASTER;
}
DataSourceAspect 切面
@Aspect
@Order(1)
@Component
public class DataSourceAspect {
@Pointcut("@annotation(com.jgame.mis.annotation.DataSource)")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource dataSource = method.getAnnotation(DataSource.class);
if (null!=dataSource) {
DynamicDataSourceContextHolder.
setDateSourceType(dataSource.value().name());
}
try {
return point.proceed();
} finally {
// 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDateSourceType();
}
}
}
DataSourceConfig
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dataSource()
{
Map targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource());
targetDataSources.put(DataSourceType.SLAVE.name(), slaveDataSource());
return new DynamicDataSource(masterDataSource(), targetDataSources);
}
}
启动类上添加注解
@Import({DataSourceConfig.class})
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
需要使用的方法上
@DataSource(value = DataSourceType.SLAVE)
DEMO
@Select("select * from user")
@DataSource(value = DataSourceType.SLAVE)
List selectUserList();
总结
到此这篇关于SpringBoot自定义注解使用读写分离Mysql数据库的文章就介绍到这了,更多相关SpringBoot自定义注解使用读写分离Mysql内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!