全棧低碼設計開源框架 json-script-rule 自定義開發(fā)及擴展接口說明

自定義開發(fā)

說明

本篇的內容是框架的核心思想,較為重要,所有內置的插件也全都是基于這種開發(fā)模式開發(fā)出來的。自定義開發(fā)主要包括自定義模型,自定義插件,自定義數(shù)據(jù)庫字段及函數(shù)。自定義模型包括自定義action,自定義result,自定義controller,自定義模型是實現(xiàn)了IJSRuleCustom接口的bean,有且只能有一個被注冊進spring容器中。自定義插件是開發(fā)者根據(jù)自身業(yè)務場景封裝的代碼片段,它應具有高內聚低耦合的特性,它是腳本代調的基本單位,因此需要一定的抽象設計能力。自定義數(shù)據(jù)庫字段及函數(shù)主要用于映射數(shù)據(jù)庫的函數(shù),如substr(),current_date,sum(),開發(fā)者可以自定義這些函數(shù)的名稱,未定義的函數(shù)將不可用。

自定義action

action對應的擴展對象為edi.rule.model.JSRuleAction,通過繼承這個類并將此類注冊成spring bean開發(fā)者可以自定義一個action。這個action好比一個倉庫,所有的插件類都會在這個倉庫類中被定義成一個實現(xiàn)了edi.rule.extend.interfaces.IJSRuleActionModel接口類型的字段,字段的名字即是插件使用時的屬性,如果要重寫應用框架內置的插件,只需要重寫它內部對應的插件類型的字段就可以了。

@Data
@EqualsAndHashCode(callSuper=false)
@Component
public class MyActions extends JSRuleAction<MyActions>{
    @JSRuleModelPermit(join={"role1"})
    public JSRuleGetCustomModel get;
    public JSRuleAddCustomModel add;
    @JsonAlias({"del"})
    public JSRuleDeleteCustomModel delete;
    public JSRuleEditCustomModel edit;
    private MyTestCustom mtc;
}

上面的例子重寫了父類的get,add,delete,edit插件,因此需要提供get和set方法,當使用json中的get插件時將會直接進入開發(fā)者自定義的JSRuleGetCustomModel這個類里的邏輯。除此之外開發(fā)者還可以定義其它的插件類型,如上面的MyTestCustom,還可以增加一些可用的注解,例如@JSRuleModelPermit(join={"role1"}),此外由于框架是jackson進行序列化的,這里還可以使用jackson注解,例如@JsonAlias({"del"}),它將插件名稱加了一個del的別名,這不會影響重寫的機制,例如@JsonIgnore注解,忽略某個字段的反序列化。

自定義插件

public class MyTestCustom implements IJSRuleActionModel<MyActions>{

    @JSRuleInject
    @JsonIgnore
    private JSRuleGlobalVariable variable;
    @JSRuleModelField
    public List<String> list;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public Date date;

    @Override
    public Object start(MyActions action) {
        return "這里直接返回結果->";
    }
}

注意:由于插件本身以及下面所有的屬性都會經(jīng)過jackson序列化,因此相關的jackson注解在這里也是可以使用的,比如@JsonIgnore,@JsonFormat等等,此外聲明的變量要么是public訪問權限,要么提供public類型的get方法,否則jackson會提示未被承認的屬性


上面的例子是一個自定義插件的例子,插件其實就是一個實現(xiàn)了IJSRuleActionModel 接口的class類,其處理邏輯便是重寫start方法,這里還有一些自定義開發(fā)時需要用到的注解,這些注解僅對插件內部屬性生效,允許遞歸

  • @JSRuleInject:該注解與spring的@Autowired注解類似,用于依賴注入的,使用該注解時通常需要搭配@JsonIgnore注解,用于忽略某些注入字段的反序列化操作,因為被該注解標識的字段只有為空時才會有效。其中names屬性表示獲取指定的bean名稱集合,types屬性表示獲取指定的bean類型集合,這兩個屬性通常用于注入Collection,Map,Array等集合類型的字段,表示獲取多個bean,當用在非集合類型的字段上面時會按照順序進行獲取,當沒有找到任何bean并且屬性required為true的時候此時會報錯,否則只要找到一個bean就會成功注入
    注意:此注解注入帶有@Transactional注解的bean時會報錯,因此不能使用該注解注入JSRuleService,為了避免嵌套循環(huán)調用,邏輯上在model中也不允許注入JSRuleService,如果需要嵌套執(zhí)行action,可以參考接口IJSRuleActionModel中的startActions方法
  • @JSRuleModelField:此注解用于某些字段初始化后的一些后續(xù)處理,處理類需要實現(xiàn)IJSRuleModelFieldProcessor擴展接口并注冊成spring bean。當此注解標記在一個類型為IJSRuleModel的字段時將會產(chǎn)生向下遞歸處理,此時該注解的作用將會失效。type屬性表示該字段將會被哪個類進行處理,默認不進行任何處理
  • @JSRuleCheck:該注解用于校驗字段值的合法性,如果該字段的類型是IJSRuleModel類型,那么它會向下遞歸檢查。
    注意:上面3個任何一個注解標記一個IJSRuleModel類型的字段時都將產(chǎn)生向下遞歸的效果,會遞歸處理IJSRuleModel類型對象中的字段,如果沒有標記則不會遞歸處理
    提示:以上3個注解的執(zhí)行順序是@JSRuleInject,@JSRuleModelField,@JSRuleCheck

異常以及國際化處理

異常的處理只需要throw new JSRuleException(msg)即可,如果需要國際化消息,則可以通過JSRuleMessage對象的read方法
例如:throw new JSRuleException(JSRuleMessage.read(key))
如果想要自己捕獲該JSRuleException類異常也可以自定義一個@ControllerAdvice注解的類用于捕獲JSRuleException,可以搭配@Order注解一起使用,或搜索JSRuleExceptionProcess類查看源碼是如何處理的
國際化文件可在application文件中配置屬性edi.rule.config.message,以resources為根目錄,以/開頭輸入國際化文件的位置

自定義result

自定義result模型需要繼承JSResult類,如果需要更改原有的字段名稱,可通過重寫父類的屬性并加上@JsonProperty注解來進行更改,如果需要新增一個屬性,可以直接在子類中新增一個字段,如果需要刪除原有的字段,可通過重寫父類的屬性并加上@JsonIgnore注解來進行刪除,用例如下

@Data
@EqualsAndHashCode(callSuper=false)
@Component
public class TestJSResult extends JSResult{
    @JsonProperty("codeAlias")
    public int code;
    public String msgCustom;
    public LinkedHashMap<String,Object> result;
    @JsonIgnore
    public String log;
    @JsonIgnore
    public Map<String,String> actionSql = new HashMap<String,String>();
    
    public TestJSResult() {
        code = 200;
        msg = "any message";
        result = new LinkedHashMap<String,Object>();
    }
}

構造函數(shù)中用于定義結果集對象內部屬性的默認值,重寫父類屬性意味著要對父類屬性進行更改

自定義controller

json-script-rule內置的控制器為JSRuleController,它的固定訪問路徑為/json/script,當你需要更改這個路徑的時候可以自定義一個控制器,如下

@Data
@RestController
@RequestMapping("/xxx/xxx")
public class MyTestController {
    
    @Autowired
    protected JSRuleService service;
    @Autowired
    protected HttpServletRequest request;
    @Autowired
    protected HttpServletResponse response;

    @PostMapping(value = JSRuleJsonConfig.DEFAULT_REQUEST_START)
    public String start() {
        return service.start(ZSHttp.getJsonStrFromReq(request),ZSHttp.initGlobalArgs(request,response));
    }
}

上面的例子還可以通過繼承JSRuleController來實現(xiàn)一個自定義控制器,與此同時還應該關閉內置的控制器,可以通過以下方法來關閉

edi:
  rule:
    close:
      engineController: true

自定義數(shù)據(jù)庫函數(shù)及字段

自定義函數(shù)

所有的擴展類和接口均位于edi.rule.extend包下,其中JSRuleDBFunctions為自定義函數(shù)的頂級類,它下面有對應的各種數(shù)據(jù)庫的子類,如JSRuleMysqlFunctions,JSRuleOracleFunctions等,通過繼承這些子類來實現(xiàn)一個數(shù)據(jù)庫函數(shù)的映射關系

public class JSRuleMysqlFunctions extends JSRuleDBFunctions{
    static {
        functions.put("abs", new JSRuleFunctionInfo("abs",1));
        functions.put("concat", new JSRuleFunctionInfo("concat"));
        functions.put("now", new JSRuleFunctionInfo("now",0));
    }
}

上面的例子展示了如何定義一個函數(shù)映射,其中key "abs"為json中使用的函數(shù)名,它可以是任意名稱,JSRuleFunctionInfo對象為實際的函數(shù)名和參數(shù)個數(shù)。函數(shù)映射定義完成后可以在json中直接通過R表達式來使用,例如:#$now(),這里的now便是key,未定義的函數(shù)不能在json中使用

自定義字段

數(shù)據(jù)庫中存在一些非函數(shù)的字段,例如mysql的currentDate,這些字段不同于表字段,它的結果不屬于任何一個表的結果,因此要定義這個字段必須要用另外的方式??蚣芴峁┝薐SRuleDBFields對象用于這些特殊字段的定義,下面有四個子類對應四種不同的數(shù)據(jù)庫類型,下面先以mysql為例

public class JSRuleMysqlSysFields extends JSRuleDBFields{
    static {
        fields.put("currentDate", "current_date");
        fields.put("currentTime", "current_time");
    }
}

通過上面的例子不難看出,它與自定義函數(shù)沒有什么太大的區(qū)別,因此在這里就不多贅述了

自定義斷言器

在使用shunt插件時,框架內置的JSRuleAssertUsual對象只提供了一些基本的判斷功能,對于一些復雜的判斷還無法實現(xiàn),因此這個時候就需要開發(fā)者自定義一些斷言的邏輯,如下面的例子

@Component
public class TestAsserts implements IJSRuleAssert{
    @Override
    public boolean ifTrue(String name, String path, Object value, boolean ifAnd, JSRuleGlobalVariable variable) {
        if (value instanceof Number) {
            return true;
        }
        return false;
    }
}

斷言器與自定義模型一樣需要注冊成spring bean,斷言器在json調用時可直接寫bean的名字,不是java class的名字

自定義開發(fā)需要了解的

獲取json參數(shù)

Spring bean中可以通過如下方式獲取

@Autowired
private JSRuleArgsVessel v

插件中可以使用如下方式獲取

@JSRuleInject
private JSRuleArgsVessel v

上下文對象

上下文對象JSRuleContext,它提供了如下參數(shù)

  • properties:用于獲取spring application配置屬性
  • beanFactory:spring bean工廠
  • dataSource:框架最終使用的數(shù)據(jù)源,類型為javax.sql.DataSource
  • dbInfo:框架使用的數(shù)據(jù)庫信息,包含數(shù)據(jù)庫名稱、"mapper"類型和function類型等
  • security:框架目前所采用的安全模式信息

擴展接口

  • JSRuleDefaultExtend:該擴展類實現(xiàn)了IJSRequestHandler和IJSRuleRoleHandler以及IJSRuleMappingsInfo接口,因此通過繼承該類可以對上述三個接口方法進行自定義擴展,IJSRuleMappingsInfo接口用于處理非實體類映射的場景,如映射信息來自于xml文件或數(shù)據(jù)庫而非java實體類。IJSRequestHandler用于自定義處理每次請求時json中的body對象的初始化,IJSRuleRoleHandler接口用于處理請求方的角色信息,開發(fā)者需要手動識別請求方的角色并返回一個請求方角色的set集合。該類需要通過注解@Component注解注冊成spring bean或在application中配置edit.rule.processor屬性,并輸入類的全限定名稱,如下
edi:
  rule:
    processor: test.myrule.JSRuleDBProcessor
  • IJSRuleModel:json中所有對象屬性的頂級接口,如果你自定義的類是json中的一個屬性,那么理論上來說應該實現(xiàn)這個接口
  • IJSRuleModelFieldProcessor:注解@JSRuleModelField所標識字段的處理接口,實現(xiàn)該接口的處理類可以在字段反序列化后重新賦值,該接口可以存在多個,重寫order方法將實現(xiàn)排序
  • IJSRuleActionModel:所有插件的頂級接口,自定義插件必須實現(xiàn)該接口,其start方法用于對action邏輯的處理
  • IJSRuleAssert:實現(xiàn)該接口的spring bean可以在shunt插件中進行調用
  • IJSRulePostLaunch:實現(xiàn)該接口的類在框架加載完成后會自動被調用,允許存在多個實現(xiàn)類,重寫order方法將實現(xiàn)排序
  • IJSRuleRoleAuthority:該接口用于初始化框架權限,其內部方法將返回一個"Map"集合,"key"為角色名稱,"value"為權限對象。權限對象包含crud權限以及插件權限,crud權限為表與角色之間的關聯(lián)關系。初始化的crud權限受注解@JSRuleTable中的permit以及roles屬性制約
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容