原创

Spring Boot 2.0+ MyBatis-Plusg通过注解动态切换数据源

温馨提示:
本文最后更新于 2024年02月07日,已超过 18 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

Spring Boot 2.0+ ByBatis-Plus动态切换数据源)中我们介绍了如何实现多个数据源的切换。但是我们切换数据源时,是通过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(net.xiangcaowuyu.dynamicdatasource.annotation.DataSource) || @within(net.xiangcaowuyu.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<>());
}

QQ截图20210424190137.png

获取数据源2的数据

@DataSource(value = "dynamicDataSourceTwo")
@GetMapping("listTableTwo")
public List<TableTwo> listTableTwo(){
    return tableTwoMapper.selectList(new QueryWrapper<>());
}

根据参数,系统动态切换数据源

@DataSource
@GetMapping("tableList")
public String tableList(){
    return "当前数据源为:"+DynamicDataSourceContextHolder.getDataSourceKey();
}
正文到此结束
本文目录