在Spring Boot 2.0+ ByBatis-Plus动态切换数据源 - 香草物语 (lisen.cc)中我们介绍了如何实现多个数据源的切换。但是我们切换数据源时,是通过DynamicDataSourceContextHolder
手动切换的,如果每次都这么设置,明显不恰当。所以我们这里介绍一下通过注解的方式实现数据源的切换。
定义注解
/**
* 自定义多数据源切换注解
*
* 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
* 如果传递value,则切换到value对应的数据源
*
* @author laughing
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource {
String value() default "";
}
- 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
- 如果传递value,则切换到value对应的数据源
定义切面
/**
* 动态数据源切面拦截
* 请注意:这里order一定要小于tx:annotation-driven的order,即先执行DynamicDataSourceAspectAdvice切面,再执行事务切面,才能获取到最终的数据源
*
* @author laughing
* @version 1.0
*/
@Slf4j
@Aspect
@Component
@Order(1)
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class DynamicDataSourceAspect {
@Pointcut("@annotation(cc.lisen.dynamicdatasource.annotation.DataSource) || @within(cc.lisen.dynamicdatasource.annotation.DataSource)")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
try {
//1.取注解的参数
DataSource dataSource = getDataSource(joinPoint);
if (dataSource != null && !StringUtils.isEmpty(dataSource.value())) {
DynamicDataSourceContextHolder.setDataSourceKey(dataSource.value());
return joinPoint.proceed();
}
//2.模拟参数
String dynamicDataSource = request.getParameter("dynamicDataSource");
if (!StringUtils.isEmpty(dynamicDataSource)) {
DynamicDataSourceContextHolder.setDataSourceKey(dynamicDataSource);
return joinPoint.proceed();
}
return joinPoint.proceed();
} finally {
//每次使用完成,清空数据源
DynamicDataSourceContextHolder.clearDataSourceKey();
}
}
/**
* 获取需要切换的数据源
*/
public DataSource getDataSource(ProceedingJoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
if (Objects.nonNull(dataSource)) {
return dataSource;
}
return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
}
}
测试
获取数据源1的数据
@DataSource(value = "dynamicDataSourceOne")
@GetMapping("listTableOne")
public List<TableOne> listTableOne() {
return tableOneMapper.selectList(new QueryWrapper<>());
}
获取数据源2的数据
@DataSource(value = "dynamicDataSourceTwo")
@GetMapping("listTableTwo")
public List<TableTwo> listTableTwo(){
return tableTwoMapper.selectList(new QueryWrapper<>());
}
根据参数,系统动态切换数据源
@DataSource
@GetMapping("tableList")
public String tableList(){
return "当前数据源为:"+DynamicDataSourceContextHolder.getDataSourceKey();
}
下载试试,谢谢!
解决了我的问题。非常感谢。可能由于版本不同,部分切换数据源代码不同。