Rest模式

​ 有些时候客户端环境可能比较复杂,如采用非Java语言编写的客户端,如Javascript、C++或C#等,或者是客户端不希望加入URule Pro的相关Jar包等等,但这些客户端也需要调用规则引擎进行业务规则的计算,这个时候传统的独立服务模式就有了用武之地。

​ 在URule Pro中提供了统一的Restful服务调用接口,通过在知识包上进行简单的配置,即可实现将业务规则计算暴露成Restful接口,对于客户端来说,调用接口时,只需要符合要求的JSON格式数据即可实现业务规则计算,同时Restful接口也会返回统一的JSON格式数据作为计算结果输出。

这里需要特别强调的是,如果您当前打算把URule Pro用在一个构建于SpringBoot之上的项目中,那么在配置知识包的Rest服务前需要重写SpringBoot中的HiddenHttpMethodFilter拦截器

SpringBoot在运行时会自动加入这个HiddenHttpMethodFilter拦截器,在这个拦截器里又调用了HttpServletRequest的getParameter方法, 这就导致后续在URule Pro中用于处理Rest服务请求的Servlet通过HttpServletRequest获取到的InputStream参数值为null,从而会产生输入数据为空的异常。

要解决这一问题就需要重写这个HiddenHttpMethodFilter拦截器,具体大家可以打开百度,搜索关键词“SpringBoot中request.getInputStream()”,就可以看到大量关于这一问题的讨论和解决办法,这里就不再赘述。

如果您单独使用了SpringMVC框架,那么也会存在上面的问题,解决方法大家同样可以在百度中搜索关键词“SpringMVC中request.getInputStream()”,就可以看到对应的解决问题的办法。

配置Restful接口

​ 打开知识包管理页面,选中某一具体的知识包项目(知识包状态处于启用时可操作,停用状态的知识无法配置),在目标知识包上点击右键,在弹出的菜单中选择Rest服务配置菜单项,即可弹出配置窗口,如下图所示:

​ 配置窗口比较简单,我们需要做的就是配置好输入、输出数据以及调用时是否启用用户名密码验证即可。需要注意的是,输入输出数据必须要都配置好后才能保存,不能只配置输入数据不配置输出数据,反过来也是一样。

​ 输入、输出信息配置完成,点击配置窗口下方的的“查看Restful描述”按钮,就可以看到当前知识包已配置好的Restful服务接口的描述数据,描述服务的格式为JSON,内容如下所示:

{
    "output": [
        {
            "name": "会员",
            "clazz": "com.bstek.entity.Customer",
            "fields": [
                {
                    "name": "address",
                    "label": "地址",
                    "type": "List"
                },
                {
                    "name": "level",
                    "label": "等级",
                    "type": "String"
                },
                {
                    "name": "name",
                    "label": "名称",
                    "type": "String"
                }
            ]
        }
    ],
    "input": [
        {
            "name": "会员",
            "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
}

为减少内容占用,上面的JSON中"......"代表隐去的部分数据。

​ 在上面的JSON格式调用描述数据当中,“input”和“output”属性值分别表示输入和输出数据,“url”表示的是调用的URL;“authentication”属性值表示的是当前Restful服务调用是否需要用户名密码验证,这里的值是false,表示不需要验证。

需要注意的是,点击窗口下的任何一个按钮都会触发保存操作。

注意:这里的输入、输出选择会受当前知识包引用的变量库、参数库的用途属性影响,用途为In或InOut类型的变量或参数,会在输入中出现,用途为Out或InOut类型的变量或参数,会在输出中出现。

Restful接口调用测试

​ 回到服务调用配置窗口,点击窗口下方的“Restful服务调用测试”按钮,就可以打开当前知识包的服务调用测试页面,如下图所示:

​ 在测试页面当中,左边为要提交的JSON格式数据,这里引擎已将我们配置中定义好的输入数据转换成标准的JSON格式,我们只需要填充具体数据即可。

​ 从图中可以看出,这里的JSON格式的输入数据,与我们想象中的对象的标准JSON格式略有不同。这里,要提交的输入数据可以有多个,所以JSON以"[ ]"包裹,表示为一个集合类型的数据(当然,如果你配置的输入数据对象只有一个,那就直接提交一个对象就行;这里的“会员”对象,用name属性来标明对象类型,这里的name属性用的是我们规则变量库里定义的对象分类名,实际上,name属性值也可以是变量库里对象类路径全名,无论用哪个引擎都可以正确识别;接下来就是“fields”属性,它是一个对象类型,里面具体的属性用于标明当前对象需要的属性名及属性值,所有的属性值都是一个空的字符串,实际填写时需要根据对应属性数据类型进行具体值的填充。可以看到,这里对象属性名采用的是变量库里具体属性的“字段名”,而非“标题”,实际使用时即可以使用“字段名”,也可以使用“标题”,引擎都能正确识别。

​ 了解输入的JSON数据格式后,接下来就可以填充JSON数据,填充完成后,点击工具栏上的“提交数据”按钮,即可将输入的数据提交到目标知识包所暴露的Restful服务接口。提交数据后结果如下图所示:

​ 可以看到,计算后的输出数据是一个标准的JSON对象格式,“duration”属性值表示当前业务规则计算耗时,单位为毫秒(ms),这里是0,表示时间非常的短(通常第一次计算时间较慢,这由Java特性导致);“output”属性值为一个集合类型,通过“name”属性值来 标明对象名称,与变量库里定义的对象分类名保持一致;“class”属性则标明对象类全名,与变量库里定义的对象类路径一致;“fields”属性值是一个对象类型,用于标明当前对象的具体属性名及其值,这里的属性名采用的是属性的字段名,主要是方便后续JSON数据对象化处理。

​ 上面的测试是通过URule内置的Restful服务测试页面完成,实际使用时也可以用第三方测试工具实现,比如上面的Restful服务就可以通过postman来进行测试,如下图所示:

​ 如截图所示,在postman中,输入好请求的URL,我们这里是http://localhost:8080/urule-pro-test/urule/rest/7,提交类型改为POST(URule Pro提供的Restful服务只接收POST类型的请求),输入要提交的数据,我们这里是要提交的JSON数据,数据格式与上面介绍的保持一致,点击“Send”按钮,就可以得到响应结果。

​ 在配置Restful服务时,还可以打开“用户名密码验证”选项,打开该选项后,我们需要输入用户名及密码信息,保存后再次请求这个Restful服务我们就需要在请求的Header里加上用户和密码信息,否则请求将不被允许,在URule Pro内置的Restful服务测试页面里, 如果当前Restful服务需要用户名密码验证,它会自动加上用户名密码信息;而如果我们使用postman来请求这个Restful服务,若不在Header里提供用户名密码信息,那么请求将会得到如下图所示信息:

​ 我们可以在请求的Header中添加用户名密码信息,Header的Key分别是Username和Password,如下图所示:

实际应用当中,我们会在应用在外层加上业务系统的安全管理功能,比如使用系统需要先进行登录等,这时要保证URule Pro中内置的Restful服务可用,那么就需要让/urule/rest这个URL可匿名访问,这点非常重要。

在使用这个内置的Restful服务过程中,如果出现错误,比如用户名密码不正确或规则计算过程出现异常等,类似这些错误信息也会以一个标准的JSON格式返回,所有的错误消息(如果是异常则是异常的堆栈信息)会放在返回的JSON对象的error属性中, 如果没有错误,则返回的JSON中就不会包含error属性,这点从上面的示例中我们也已经看到。

复杂对象类型的支持

​ 数据“客户”对象里有个名为“cards”属性,这个属性是一个集合类型的属性,所以如果该属性为空时我们需要给该属性添加一个[]字符,表示一个空的集合属性,如下所示:

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

​ 如果我们需要填充这个集合属性,那么需要先看看变量库里定义的“卡”对象以及与卡对象相关的对象的结构,然后仿照上面的JSON写出来就好;还有种简单的方式,那就是在“服务配置”窗口中直接勾选“卡”对象以及与卡对象相关的对象,如下图所示:

保存后再次进入页面,就可以看到如下图所示的输入数据结构:

​ 接下来,我们需要填充“cards”属性,填充好的结构如下图所示:

​ 可以看到,填充后的“cards”属性是一个集合类型,里面由若干个“卡”对象构成,每个卡对象有四个属性,其中“cardDetails”也是一个集合对象,这个集合对象是由若干个“卡明细”对象组成。按照这样的规则, 我们在构建输入数据时就可以把输入数据按照业务的需要构建的足够复杂,可最大限度满足业务需求。

​ 在上面的截图中,“客户”对象还有“company.id”以及“company.level”两个属性,从命名以及变量库里对这两个属性的声名可以看出,“客户”这个对象下还有一个名为company的子对象,“company.id”和“company.level”两个属性 是用来填充company子对象的id以及level属性,这里我们直接输入这两个属性值即可实现对company子对象的id以及level两个属性值的填充。

​ 实际使用时,如果company对象在变量库中也有定义,那么上面的写法可直接改为下面的样子,依次类推:

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

上面的写法中,要求我们在变量库里必须定义好名为“公司”的对象,否则解析的时候产生错误,如果没有定义,那么需要采用“company.id”、“company.level”的定义方式。

results matching ""

    No results matching ""