Ruoyi는 데이터베이스에서 동적 데이터 소스 전환을 구현합니다.

현재 프로젝트의 요구 사항 중 하나는 데이터를 동적으로 쿼리할 수 있고 프런트 엔드 페이지 구성에 데이터 소스를 추가한 다음 데이터 소스를 비즈니스에 바인딩할 수 있다는 것입니다. yml 구성 파일은 고정되어 있지 않으며, 데이터베이스 구성은 비즈니스에 바인딩된 데이터베이스 테이블에 저장된 데이터 소스 기반 연결을 기반으로 합니다.

 Ruoyi는 데이터 소스 전환을 캡슐화하고 AOP를 통해 데이터 소스를 지정했지만 Ruoyi의 원래 방법은 구성 파일의 기존 데이터 소스만 전환할 수 있습니다. 즉, 새 데이터 소스를 구성에 추가하려면 데이터 소스를 구성에 추가해야 합니다. 파일을 수정하는 경우에도 마찬가지인데 이는 분명히 매우 번거로운 작업입니다. 우리의 요구를 충족하지 않습니다.

 

/**
 * 自定义多数据源切换注解
 *
 * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
 *
 * @author ruoyi
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource
{
    /**
     * 切换数据源名称
     */
    public DataSourceType value() default DataSourceType.MASTER;
}

그런 다음 내 생각은 Ruoyi의 원본을 기반으로 처리 계층을 추가하고, 원래 Ruoyi가 작성한 주변 알림을 주석 처리하고, 처리를 위해 @Before() 사전 알림을 사용하는 것입니다.

 전환 데이터 소스를 식별하려면 데이터 소스 열거에 새 열거 OTHER를 추가합니다.

/**
 * 数据源
 * 
 * @author ruoyi
 */
public enum DataSourceType
{
    /**
     * 主库
     */
    MASTER,

    /**
     * 从库
     */
    SLAVE,

    /**
     * 其他
     */
    OTHER
}

 지정된 유형은 Aspect 사전 알림에서 판단되며, 마스터인 경우 기본 데이터소스를 사용하고, 슬레이브는 구성 파일에 구성된 슬레이브 라이브러리를 사용하고, 기타 방법은 데이터베이스 테이블에 존재하는 데이터소스를 사용하는 방식이다. 요청에 따라 메소드의 매개 변수는 비즈니스 ID를 얻은 후 데이터베이스로 이동하여 바인딩된 데이터 소스 정보를 쿼리한 다음 이를 현재 데이터 소스로 설정합니다. 사용 후 데이터 소스는 게시를 통해 삭제됩니다. @After알림.

/**
 * 多数据源处理
 * 
 * @author ruoyi
 */
@Log4j2
@Aspect
@Order(1)
@Component
public class DataSourceAspect
{
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private ISysDataSourceService sysDataSourceService;
    @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
            + "|| @within(com.ruoyi.common.annotation.DataSource)")
    public void dsPointCut()
    {

    }

    @Before("dsPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        logger.info("方法名称: " + method.getName());
        DataSource dataSource = method.getAnnotation(DataSource.class);
        DruidConfig dynamicDataSourceConfig = SpringContextUtils.getBean(DruidConfig.class);
        Map<Object, Object> map = dynamicDataSourceConfig.getTargetDataSources();
        log.info("TargetDataSources==="+map.toString());

        // 通过判断 DataSource 中的值来判断当前方法应用哪个数据源
        String value = String.valueOf(dataSource.value());
        boolean flag;
        String name = "";
        switch (value) {
            case "MASTER":
                flag = true;
                name = DataSourceType.MASTER.name();
                break;
            case "SLAVE":
                flag = true;
                name = DataSourceType.SLAVE.name();
                break;
            case "OTHER":
                flag = true;
               
                name = "OTHER";
                if (map.get(name) != null) {
                    break;
                } else {
                    //获取传入参数
                    Object[] args = joinPoint.getArgs();
                    JSONObject json = (JSONObject) args[0];
                    Long dataSourceId = json.getLong("dataSourceId");
                    log.info("获取的数据源ID=="+dataSourceId);
                    //从传入参数获取业务ID查找数据源信息,设置数据源信息
                    SysDataSource source = sysDataSourceService.getById(dataSourceId);
                    String url = source.getDbUrl();
                    String username = source.getDbUsername();
                    //密码解密
                    String password = SecurityUtil.jiemi(source.getDbPwd());
                    log.info("解密后密码=="+password);
                    log.info("数据源切换:" + url);

                    DruidDataSource s = dynamicDataSourceConfig.createDataSource(name, url, username,
                            password, source.getDbDriver());
                }
                break;
            default:
                flag = false;
                break;
        }

        if (!flag) {
            logger.error("************注意************");
            name = DataSourceType.MASTER.name();
            logger.info("加载到未知数据源,系统自动设置数据源为默认数据源!");
        }
        DynamicDataSource.setDataSource(name);
        //设置成数据源
        DynamicDataSourceContextHolder.setDataSourceType(name);
        logger.info("当前数据源: " + name);
        logger.info("当前数据源: " + ((DruidDataSource) map.get(name)).getUrl());
        logger.info("set datasource is " + name);
    }


    @After("dsPointCut()")
    public void doAfter() {
        logger.info("*********准备清除数据源*********");
        DynamicDataSource.clearDataSource();
        DynamicDataSourceContextHolder.clearDataSourceType();
        logger.info("*********数据源清除成功*********");
    }

새로 추가된 열거 유형이 druidConfig 구성 파일에 추가된다는 점에 유의해야 합니다.

 데이터 소스를 전환해야 할 경우 클래스나 메소드에 주석을 추가하기만 하면 됩니다.

@DataSource(값 = DataSourceType.OTHER)

추천

출처blog.csdn.net/weixin_53160419/article/details/131373123