Apache-shenYu源码阅读09-基于SPI-MatchStrategy扩展的可行性分析

458 阅读3分钟

回顾

在一章中,我们已经知道Soul网关提供了SPI的方式,允许我们扩展MatchStrategy实现,目前Soul的实现主要有AND\OR两种规则,基于上一章的最终问题,我们来判断一下方案是否有可行性?

上一章问题如下图:

先说答案:基于目前的结构是没有可行性的。

无可行性分析

具体原因在ConditionData中,在该类中只定义了paramType、operator、paraName、paramValue四个参数,如果要做到上述问题的方案,势必要有条件与条件之间的关联关系

方案改造

前提 在不考虑相关表结构的情况下,只考虑类模型的更改。

我们要解决什么问题:

目前Soul的匹配规则只能满足类似SQL的

AND 匹配模式
select * from table where a=1 and b=2 and c=3
OR 匹配模式
select * from table where a=1 or b=2 or c=3

我们最终要达成:

select * from table where (a=1) and (b=2 or c=3) or (d=4)

很明显如果要达成上述条件势必要改造ConditionData类:

当前问题有哪些:

  • 条件组内条件与条件没有匹配关系 即上述sql中的(b=2 or c=3)

  • 条件组与条件组之间没有匹配关系 即上述sql中 (a=1) and (b=2 or c=3)中间的and条件符无法维护。

如何解决(以下方案属于个人猜想):

先说条件与条件之间的关系如何维护:

  • 属于一个组代表是有一个通用标识代表为一组,所以只需要在ConditionData类加上一个类似于index的标识,标识相同代表为一组,在增加对应的组内的匹配模式,最终在ConditionData类中增加字段如下。
    //匹配规则 0 代表and 1代表or
    private Integer matchMode;

    //下标 相同下标即为一组
    private Integer index;

条件组与条件组之间没有匹配关系

  • 首先一个条件组可能与多个条件组进行不同模式的匹配,所以一个条件组要考虑关联多个条件组,按照单一职责构想,理论上来说我们要把组与组之间的关联关系单独拆成一个类在对应的match方法上传入集合,但基于扩展考虑,最终选择了改动最小的方案,在ConditionData中,设计一个List对象存储条件组与条件组之间的关联关系,最终在ConditionData类中增加字段如下。
   //条件关联的DTO列表
    private List<ConditionDataRelatedDTO> conditionDataRelatedDTOS;

ConditionDataRelatedDTO实体类详细信息为

/**
     * 关联的模式 and or
     */
    private Integer matchMode;

    /**
     * 关联的条件组下标
     */
    private Integer relatedIndex;

按照上述结构来设计的化,理论上已经支持了上述“复杂SQL”的模型。

ps:这里需要注意的是为了减少上下游服务的更改,将本应单独存放的类都放入了ConditionData字段中,这样做的好处就是假设方案真实可行,那对已有代码改动是最小的,只需要扩充对应的接口,但这样做的坏处在于,本应该由条件组保存的数据变成了条件保存的数据(数据冗余)。

总结

从我个人角度来讲方案理论上是可行的。但在设计上因为兼容的考虑设计的并不是特别的优雅,若上述方案有理论层面漏洞或有更好的更正方案,欢迎一起讨论。