Rest模式

​ 有(yǒu)些(xiē)時(shí)候客戶端環境可(kě)能比較複雜,如采用非Java語言編寫的客戶端,如Javascript、C++或C#等,或者是客戶端不希望加入URule Pro的相關Jar包等等,但(dàn)這些(xiē)客戶端也需要調用規則引擎進行(xíng)業務規則的計(jì)算(suàn),這個(gè)時(shí)候傳統的獨立服務模式就有(yǒu)了用武之地。

​ 在URule Pro中提供了統一的Restful服務調用接口,通(tōng)過在知識包上(shàng)進行(xíng)簡單的配置,即可(kě)實現将業務規則計(jì)算(suàn)暴露成Restful接口,對于客戶端來(lái)說,調用接口時(shí),隻需要符合要求的JSON格式數(shù)據即可(kě)實現業務規則計(jì)算(suàn),同時(shí)Restful接口也會(huì)返回統一的JSON格式數(shù)據作(zuò)為(wèi)計(jì)算(suàn)結果輸出。

這裏需要特别強調的是,如果您當前打算(suàn)把URule Pro用在一個(gè)構建于SpringBoot之上(shàng)的項目中,那(nà)麽在配置知識包的Rest服務前需要重寫SpringBoot中的HiddenHttpMethodFilter攔截器(qì)

SpringBoot在運行(xíng)時(shí)會(huì)自動加入這個(gè)HiddenHttpMethodFilter攔截器(qì),在這個(gè)攔截器(qì)裏又調用了HttpServletRequest的getParameter方法, 這就導緻後續在URule Pro中用于處理(lǐ)Rest服務請(qǐng)求的Servlet通(tōng)過HttpServletRequest獲取到的InputStream參數(shù)值為(wèi)null,從而會(huì)産生(shēng)輸入數(shù)據為(wèi)空(kōng)的異常。

要解決這一問題就需要重寫這個(gè)HiddenHttpMethodFilter攔截器(qì),具體(tǐ)大(dà)家(jiā)可(kě)以打開(kāi)百度,搜索關鍵詞“SpringBoot中request.getInputStream()”,就可(kě)以看到大(dà)量關于這一問題的討(tǎo)論和(hé)解決辦法,這裏就不再贅述。

如果您單獨使用了SpringMVC框架,那(nà)麽也會(huì)存在上(shàng)面的問題,解決方法大(dà)家(jiā)同樣可(kě)以在百度中搜索關鍵詞“SpringMVC中request.getInputStream()”,就可(kě)以看到對應的解決問題的辦法。

配置Restful接口

​ 打開(kāi)知識包管理(lǐ)頁面,選中某一具體(tǐ)的知識包項目(知識包狀态處于啓用時(shí)可(kě)操作(zuò),停用狀态的知識無法配置),在目标知識包上(shàng)點擊右鍵,在彈出的菜單中選擇Rest服務配置菜單項,即可(kě)彈出配置窗口,如下圖所示:

​ 配置窗口比較簡單,我們需要做(zuò)的就是配置好輸入、輸出數(shù)據以及調用時(shí)是否啓用用戶名密碼驗證即可(kě)。需要注意的是,輸入輸出數(shù)據必須要都配置好後才能保存,不能隻配置輸入數(shù)據不配置輸出數(shù)據,反過來(lái)也是一樣。

​ 輸入、輸出信息配置完成,點擊配置窗口下方的的“查看Restful描述”按鈕,就可(kě)以看到當前知識包已配置好的Restful服務接口的描述數(shù)據,描述服務的格式為(wèi)JSON,內(nèi)容如下所示:

{
    "output": [
        {
            "name": "會(huì)員",
            "clazz": "com.bstek.entity.Customer",
            "fields": [
                {
                    "name": "address",
                    "label": "地址",
                    "type": "List"
                },
                {
                    "name": "level",
                    "label": "等級",
                    "type": "String"
                },
                {
                    "name": "name",
                    "label": "名稱",
                    "type": "String"
                }
            ]
        }
    ],
    "input": [
        {
            "name": "會(huì)員",
            "clazz": "com.bstek.entity.Customer",
            "fields": [
                {
                    "name": "age",
                    "label": "年齡",
                    "type": "Integer"
                },
                {
                    "name": "gender",
                    "label": "性别",
                    "type": "Boolean"
                }
            ]
        }
    ],
    "url": "http://localhost:8080/urule-pro-test/urule/rest/7",
    "authentication": false
}

為(wèi)減少(shǎo)內(nèi)容占用,上(shàng)面的JSON中"......"代表隐去的部分數(shù)據。

​ 在上(shàng)面的JSON格式調用描述數(shù)據當中,“input”和(hé)“output”屬性值分别表示輸入和(hé)輸出數(shù)據,“url”表示的是調用的URL;“authentication”屬性值表示的是當前Restful服務調用是否需要用戶名密碼驗證,這裏的值是false,表示不需要驗證。

需要注意的是,點擊窗口下的任何一個(gè)按鈕都會(huì)觸發保存操作(zuò)。

注意:這裏的輸入、輸出選擇會(huì)受當前知識包引用的變量庫、參數(shù)庫的用途屬性影(yǐng)響,用途為(wèi)In或InOut類型的變量或參數(shù),會(huì)在輸入中出現,用途為(wèi)Out或InOut類型的變量或參數(shù),會(huì)在輸出中出現。

Restful接口調用測試

​ 回到服務調用配置窗口,點擊窗口下方的“Restful服務調用測試”按鈕,就可(kě)以打開(kāi)當前知識包的服務調用測試頁面,如下圖所示:

​ 在測試頁面當中,左邊為(wèi)要提交的JSON格式數(shù)據,這裏引擎已将我們配置中定義好的輸入數(shù)據轉換成标準的JSON格式,我們隻需要填充具體(tǐ)數(shù)據即可(kě)。

​ 從圖中可(kě)以看出,這裏的JSON格式的輸入數(shù)據,與我們想象中的對象的标準JSON格式略有(yǒu)不同。這裏,要提交的輸入數(shù)據可(kě)以有(yǒu)多(duō)個(gè),所以JSON以"[ ]"包裹,表示為(wèi)一個(gè)集合類型的數(shù)據(當然,如果你(nǐ)配置的輸入數(shù)據對象隻有(yǒu)一個(gè),那(nà)就直接提交一個(gè)對象就行(xíng);這裏的“會(huì)員”對象,用name屬性來(lái)标明(míng)對象類型,這裏的name屬性用的是我們規則變量庫裏定義的對象分類名,實際上(shàng),name屬性值也可(kě)以是變量庫裏對象類路徑全名,無論用哪個(gè)引擎都可(kě)以正确識别;接下來(lái)就是“fields”屬性,它是一個(gè)對象類型,裏面具體(tǐ)的屬性用于标明(míng)當前對象需要的屬性名及屬性值,所有(yǒu)的屬性值都是一個(gè)空(kōng)的字符串,實際填寫時(shí)需要根據對應屬性數(shù)據類型進行(xíng)具體(tǐ)值的填充。可(kě)以看到,這裏對象屬性名采用的是變量庫裏具體(tǐ)屬性的“字段名”,而非“标題”,實際使用時(shí)即可(kě)以使用“字段名”,也可(kě)以使用“标題”,引擎都能正确識别。

​ 了解輸入的JSON數(shù)據格式後,接下來(lái)就可(kě)以填充JSON數(shù)據,填充完成後,點擊工具欄上(shàng)的“提交數(shù)據”按鈕,即可(kě)将輸入的數(shù)據提交到目标知識包所暴露的Restful服務接口。提交數(shù)據後結果如下圖所示:

​ 可(kě)以看到,計(jì)算(suàn)後的輸出數(shù)據是一個(gè)标準的JSON對象格式,“duration”屬性值表示當前業務規則計(jì)算(suàn)耗時(shí),單位為(wèi)毫秒(miǎo)(ms),這裏是0,表示時(shí)間(jiān)非常的短(duǎn)(通(tōng)常第一次計(jì)算(suàn)時(shí)間(jiān)較慢,這由Java特性導緻);“output”屬性值為(wèi)一個(gè)集合類型,通(tōng)過“name”屬性值來(lái) 标明(míng)對象名稱,與變量庫裏定義的對象分類名保持一緻;“class”屬性則标明(míng)對象類全名,與變量庫裏定義的對象類路徑一緻;“fields”屬性值是一個(gè)對象類型,用于标明(míng)當前對象的具體(tǐ)屬性名及其值,這裏的屬性名采用的是屬性的字段名,主要是方便後續JSON數(shù)據對象化處理(lǐ)。

​ 上(shàng)面的測試是通(tōng)過URule內(nèi)置的Restful服務測試頁面完成,實際使用時(shí)也可(kě)以用第三方測試工具實現,比如上(shàng)面的Restful服務就可(kě)以通(tōng)過postman來(lái)進行(xíng)測試,如下圖所示:

​ 如截圖所示,在postman中,輸入好請(qǐng)求的URL,我們這裏是http://localhost:8080/urule-pro-test/urule/rest/7,提交類型改為(wèi)POST(URule Pro提供的Restful服務隻接收POST類型的請(qǐng)求),輸入要提交的數(shù)據,我們這裏是要提交的JSON數(shù)據,數(shù)據格式與上(shàng)面介紹的保持一緻,點擊“Send”按鈕,就可(kě)以得(de)到響應結果。

​ 在配置Restful服務時(shí),還(hái)可(kě)以打開(kāi)“用戶名密碼驗證”選項,打開(kāi)該選項後,我們需要輸入用戶名及密碼信息,保存後再次請(qǐng)求這個(gè)Restful服務我們就需要在請(qǐng)求的Header裏加上(shàng)用戶和(hé)密碼信息,否則請(qǐng)求将不被允許,在URule Pro內(nèi)置的Restful服務測試頁面裏, 如果當前Restful服務需要用戶名密碼驗證,它會(huì)自動加上(shàng)用戶名密碼信息;而如果我們使用postman來(lái)請(qǐng)求這個(gè)Restful服務,若不在Header裏提供用戶名密碼信息,那(nà)麽請(qǐng)求将會(huì)得(de)到如下圖所示信息:

​ 我們可(kě)以在請(qǐng)求的Header中添加用戶名密碼信息,Header的Key分别是Username和(hé)Password,如下圖所示:

實際應用當中,我們會(huì)在應用在外層加上(shàng)業務系統的安全管理(lǐ)功能,比如使用系統需要先進行(xíng)登錄等,這時(shí)要保證URule Pro中內(nèi)置的Restful服務可(kě)用,那(nà)麽就需要讓/urule/rest這個(gè)URL可(kě)匿名訪問,這點非常重要。

在使用這個(gè)內(nèi)置的Restful服務過程中,如果出現錯誤,比如用戶名密碼不正确或規則計(jì)算(suàn)過程出現異常等,類似這些(xiē)錯誤信息也會(huì)以一個(gè)标準的JSON格式返回,所有(yǒu)的錯誤消息(如果是異常則是異常的堆棧信息)會(huì)放在返回的JSON對象的error屬性中, 如果沒有(yǒu)錯誤,則返回的JSON中就不會(huì)包含error屬性,這點從上(shàng)面的示例中我們也已經看到。

複雜對象類型的支持

​ 數(shù)據“客戶”對象裏有(yǒu)個(gè)名為(wèi)“cards”屬性,這個(gè)屬性是一個(gè)集合類型的屬性,所以如果該屬性為(wèi)空(kōng)時(shí)我們需要給該屬性添加一個(gè)[]字符,表示一個(gè)空(kōng)的集合屬性,如下所示:

[
    {
        "name": "客戶",
        "fields": {
            "cards": [],
            "company.id": "",
            "gender": "",
            "company.level": "",
            "degree": "",
            "name": "",
            "company.name": "",
            "salary": "",
            "married": "",
            "age": ""
        }
    },
    {
        "name": "貸款信息",
        "fields": {
            "result": "",
            "money": "",
            "id": ""
        }
    }
]

​ 如果我們需要填充這個(gè)集合屬性,那(nà)麽需要先看看變量庫裏定義的“卡”對象以及與卡對象相關的對象的結構,然後仿照上(shàng)面的JSON寫出來(lái)就好;還(hái)有(yǒu)種簡單的方式,那(nà)就是在“服務配置”窗口中直接勾選“卡”對象以及與卡對象相關的對象,如下圖所示:

保存後再次進入頁面,就可(kě)以看到如下圖所示的輸入數(shù)據結構:

​ 接下來(lái),我們需要填充“cards”屬性,填充好的結構如下圖所示:

​ 可(kě)以看到,填充後的“cards”屬性是一個(gè)集合類型,裏面由若幹個(gè)“卡”對象構成,每個(gè)卡對象有(yǒu)四個(gè)屬性,其中“cardDetails”也是一個(gè)集合對象,這個(gè)集合對象是由若幹個(gè)“卡明(míng)細”對象組成。按照這樣的規則, 我們在構建輸入數(shù)據時(shí)就可(kě)以把輸入數(shù)據按照業務的需要構建的足夠複雜,可(kě)最大(dà)限度滿足業務需求。

​ 在上(shàng)面的截圖中,“客戶”對象還(hái)有(yǒu)“company.id”以及“company.level”兩個(gè)屬性,從命名以及變量庫裏對這兩個(gè)屬性的聲名可(kě)以看出,“客戶”這個(gè)對象下還(hái)有(yǒu)一個(gè)名為(wèi)company的子對象,“company.id”和(hé)“company.level”兩個(gè)屬性 是用來(lái)填充company子對象的id以及level屬性,這裏我們直接輸入這兩個(gè)屬性值即可(kě)實現對company子對象的id以及level兩個(gè)屬性值的填充。

​ 實際使用時(shí),如果company對象在變量庫中也有(yǒu)定義,那(nà)麽上(shàng)面的寫法可(kě)直接改為(wèi)下面的樣子,依次類推:

    {
        "name": "客戶",
        "fields": {
            "cards": [],
              "company":{
                "name":"公司",
                  "fields":{
                     "id":"bstek",
                       "level":12
                }
            },
            "degree": "",
            "name": "",
            "company.name": "bstek",
            "salary": "",
            "married": "",
            "age": ""
        }
    }

上(shàng)面的寫法中,要求我們在變量庫裏必須定義好名為(wèi)“公司”的對象,否則解析的時(shí)候産生(shēng)錯誤,如果沒有(yǒu)定義,那(nà)麽需要采用“company.id”、“company.level”的定義方式。

results matching ""

    No results matching ""