SpringBoot自定义注解使用读写分离Mysql数据库实例教程

网友投稿 835 2023-03-16

SpringBoot自定义注解使用读写分离Mysql数据库的实例教程

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,

/**wXsBqzx

* 从库,进行读操作

*/

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<>();

/**

* 设置数据源http://的变量

*/

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();

总结

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:小程序中如何加入插件(小程序中如何加入插件功能)
下一篇:JDBC插入数据返回数据主键代码实例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~