Ruoyi はデータベースからの動的なデータ ソース切り替えを実装します。

現在のプロジェクトの要件の 1 つは、データを動的にクエリできること、フロントエンド ページ構成にデータ ソースを追加できること、そしてデータ ソースをビジネスにバインドできることです。データをクエリするときの構成は、 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
}

 指定されたタイプはアスペクト事前通知で判断され、マスターの場合はデフォルトのデータソースが使用され、スレーブの場合は設定ファイルに設定されたスレーブライブラリが使用され、その他の場合はデータベーステーブルに存在するデータソースが使用されます。リクエストに基づいてメソッドのパラメーターはビジネス ID を取得し、データベースに移動してそれにバインドされているデータ ソース情報をクエリし、それを現在のデータ ソースとして設定します。使用後、データ ソースはポストを通じてクリアされます。通知@後。

/**
 * 多数据源处理
 * 
 * @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