Published on InterSystems Developer Community (https://community.intersystems.com)

主页 > OpenAPI-Suite(从 OpenAPI 3.0 生成 ObjectScript 代码的工具集):介绍 InterSystems 开发人员工具大赛 2023 获奖者

文章
Tete Zhang · 二月 20, 2023 阅读大约需 11 分钟

OpenAPI-Suite(从 OpenAPI 3.0 生成 ObjectScript 代码的工具集):介绍 InterSystems 开发人员工具大赛 2023 获奖者

开发者您好!

这里向介绍@Lorenzo Scalese的OpenAPI-Suite (一个用于从OpenAPI 3.0生成 ObjectScript 代码的工具集)。这个工具集在 2023 年 InterSystems 开发工具大赛的21 个参赛作品中获得专家提名第三名。

目前 IRIS 最高支持OpenAPI 2.0 ,但是这个工具支持 OpenAPI 3.0 !

提供的功能如下。

  1. 在服务器端创建类(与 OpenAPI 2.0相同,首先创建使用 API First理念创建的 REST 调度类所需的类。)
  2. 创建客户端 HTTP 类
  3. 创建客户端Production(业务服务、业务流程、业务操作、Ens.Request、Ens.Response)
  4. 一个 Web 界面,允许您指定要从此工具生成哪些功能
  5. 从 OpenAPI 1.x、2.x 到 3.0 版的转换工具

关于各个功能的详细介绍,请参考@Lorenzo Scales撰写的文章《 OpenAPI Suite - Part 1 》和《 OpenAPI Suite - Part 2 》。

在本文中,我尝试了 1 个功能。其中,以下的应对方案非常好。

  1. 根据OpenAPI 3.0新增的Components对象的内容自动生成类的定义(在指定包下创建一个模型包,在那里创建可以实例化的类)
  2. 在POST或PUT的情况下,为了较为轻松地使用实施类(impl.cls)处理HTTP请求中传递的信息,我将Body中接收到的JSON数据设为了1中生成的类的实例,
    • 目前,虽然需要进行一些手动更改,但是仅使用按原样创建的实例在 impl.cls 中叫 %Save() 方法也可以保存成功。 )

IRIS 提供了一种根据 OpenAPI 2.0 规范创建 REST 调度类的方法,但实际使用中它只创建要使用的类和根URL。

仅作为参考,这里是使用 IRIS 支持的 OpenAPI 2.0 创建的内容。

(以下示例使用了根据 OpenAPI2.0 规范创建的 JSON 示例。)

在下面的示例中,/crud 是根 URL,类是在 crud 包下创建的。
​​​​​​

生成的类如下(左:impl.cls,右:spec.cls)

由于调度类(disp.cls)是一个不需要改动的类,所以这里展示了studio的这部分代码。

接下来介绍一下@Lorenzo Scalese的OpenAPI-Suite的成果。

使用它的过程非常简单。

从管理门户或Studio导入IPM (InterSystems Package Manager,以前称为 ZPM)客户端工具后,您只需运行以下命令,工具就可以使用了。

客户端工具导入可以导入到任意命名空间中。

从管理门户导入时,使用以下菜单:

管理门户 -> 系统资源管理器 -> 类 -> 选择要导入的命名空间 -> 单击导入按钮

转到您希望 REST 调度类存在的命名空间,并使用 ZPM 命令安装工具。

 zpm "install openapi-suite"
 
安装过程中的画面显示
USER>zpm “安装 openapi-suite”

[USER|sslclient] 重新加载开始 (/usr/irissys/mgr/.modules/USER/sslclient/1.0.4/)
[用户|sslclient] 重新加载成功
[sslclient] 模块对象已刷新。
[USER|sslclient] 验证开始
[USER|sslclient] 验证成功
[USER|sslclient] 编译开始
[用户|sslclient] 编译成功
[USER|sslclient] 激活开始
[USER|sslclient] 配置开始
[用户|sslclient] 配置成功
[USER|sslclient] 激活成功
[USER|yaml-utils] 重新加载开始 (/usr/irissys/mgr/.modules/USER/yaml-utils/0.1.2/)
[USER|yaml-utils] 重新加载成功
[yaml-utils] 模块对象已刷新。
[USER|yaml-utils] 验证开始
[USER|yaml-utils] 验证成功
[USER|yaml-utils] 编译开始
[USER|yaml-utils] 编译成功
[USER|yaml-utils] 激活开始
[USER|yaml-utils] 配置开始
[USER|yaml-utils] 配置成功
[USER|yaml-utils] 激活成功
[USER|swagger-validator-cli] 重新加载开始 (/usr/irissys/mgr/.modules/USER/swagger-validator-cli/0.0.1/)
[USER|swagger-validator-cli] 重新加载成功
[swagger-validator-cli] 模块对象已刷新。
[USER | swagger-validator-cli] 验证开始
[USER|swagger-validator-cli] 验证成功
[USER|swagger-validator-cli] 编译开始
[USER|swagger-validator-cli] 编译成功
[USER|swagger-validator-cli] 激活 START
[USER|swagger-validator-cli] 配置开始
[USER|swagger-validator-cli] 配置成功
[USER|swagger-validator-cli] 激活成功
[USER|swagger-converter-cli] 重新加载开始 (/usr/irissys/mgr/.modules/USER/swagger-converter-cli/0.0.2/)
[USER|swagger-converter-cli] 重新加载成功
[swagger-converter-cli] 模块对象已刷新。
[USER | swagger-converter-cli] 验证开始
[USER|swagger-converter-cli] 验证成功
[USER|swagger-converter-cli] 编译开始
[USER|swagger-converter-cli] 编译成功
[USER|swagger-converter-cli] 激活开始
[USER|swagger-converter-cli] 配置开始
[USER|swagger-converter-cli] 配置成功
[USER|swagger-converter-cli] 激活成功
[USER|objectscript-openapi-definition] 重新加载开始 (/usr/irissys/mgr/.modules/USER/objectscript-openapi-definition/1.3.1/)
[USER|objectscript-openapi-definition] 重新加载成功
[objectscript-openapi-definition] 模块对象已刷新。
[USER|objectscript-openapi-definition] 验证开始
[USER|objectscript-openapi-definition] 验证成功
[USER|objectscript-openapi-definition] 编译开始
[USER|objectscript-openapi-definition] 编译成功
[USER|objectscript-openapi-definition] 激活开始
[USER|objectscript-openapi-definition] 配置开始
[USER|objectscript-openapi-definition] 配置成功
[USER|objectscript-openapi-definition] 激活成功
[USER|io-redirect] 重新加载开始 (/usr/irissys/mgr/.modules/USER/io-redirect/1.0.2/)
[USER|io-redirect] 重新加载成功
[io-redirect] 模块对象已刷新。
[USER|io-redirect] 验证开始
[USER|io-redirect] 验证成功
[USER|io-redirect] 编译开始
[USER|io-redirect] 编译成功
[USER|io-redirect] 激活开始
[USER|io-redirect] 配置开始
[USER|io-redirect] 配置成功
[USER|io-redirect] 激活成功
[USER|openapi-common-lib] 重新加载开始 (/usr/irissys/mgr/.modules/USER/openapi-common-lib/1.0.0/)
[用户|openapi-common-lib] 重新加载成功
[openapi-common-lib] 模块对象已刷新。
[USER|openapi-common-lib] 验证开始
[USER|openapi-common-lib] 验证成功
[USER|openapi-common-lib] 编译开始
[USER|openapi-common-lib] 编译成功
[USER|openapi-common-lib] 激活开始
[USER|openapi-common-lib] 配置开始
[USER|openapi-common-lib] 配置成功
[USER|openapi-common-lib] 激活成功
[USER|openapi-server-gen] 重新加载开始 (/usr/irissys/mgr/.modules/USER/openapi-server-gen/1.0.0/)
[USER|openapi-server-gen] 重新加载成功
[openapi-server-gen] 模块对象已刷新。
[USER|openapi-server-gen] 验证开始
[USER|openapi-server-gen] 验证成功
[USER|openapi-server-gen] 开始编译
[USER|openapi-server-gen] 编译成功
[USER|openapi-server-gen] 激活开始
[USER|openapi-server-gen] 配置开始
[USER|openapi-server-gen] 配置成功
[USER|openapi-server-gen] 激活成功
[USER|openapi-client-gen] 重新加载开始 (/usr/irissys/mgr/.modules/USER/openapi-client-gen/2.1.0/)
[USER|openapi-client-gen] 重新加载成功
[openapi-client-gen] 模块对象已刷新。
[USER|openapi-client-gen] 验证开始
[USER|openapi-client-gen] 验证成功
[USER|openapi-client-gen] 编译开始
[USER|openapi-client-gen] 编译成功
[USER|openapi-client-gen] 激活开始
[USER|openapi-client-gen] 配置开始
[USER|openapi-client-gen] 配置成功
[USER|openapi-client-gen] 激活成功
[USER|openapi-suite] 重新加载开始 (/usr/irissys/mgr/.modules/USER/openapi-suite/1.0.0/)
[用户|openapi-suite] 重新加载成功
[openapi-suite] 模块对象已刷新。
[USER | openapi-suite] 验证开始
[USER|openapi-suite] 验证成功
[USER|openapi-suite] 编译开始
[USER|openapi-suite] 编译成功
[USER | openapi-suite] 激活开始
[USER|openapi-suite] 配置开始
[USER|openapi-suite] 配置成功
[USER|openapi-suite] 激活成功
用户>

安装后,您可以通过以下 URL 访问该工具的相关信息。

http://localhost:端口号/openapisuite/ui/index.csp

示例)http://localhost:52773/openapisuite/ui/index.csp

在初始阶段,屏幕右下方的“Install On Server”按钮无法按下。似乎可以通过将值设置为以下全局变量来按下按钮。

(请在你安装工具的命名空间中用ZPM命令设置)

 Set ^openapisuite .config( "web" , "enable-install-onserver" ) = 1

准备工作完成后,进行以下设置。

对于“Application package name”,选择类定义的包名称(示例中的 PetStore);对于“What do you want to generate?”问题,选择“REST Server”;对于“NameSpace”,选择要注册 REST 调度类的命名空间;对于“Web 应用程序名称”,指定已定义的根 URL(Web 应用程序路径)(示例中的 /pet1)。

之后,只需指定根据OpenAPI规范创建的JSON文件即可。示例中默认指定https://petstore3.swagger.io/api/v3/openapi.json ,我们可以直接使用这个文件路径。

最后,单击 Install On Server 按钮。

日志如下图所示,确认正常结束后点击关闭按钮。

通过该工具,将创建一个 Web 应用程序路径:/pet1。

从管理门户 -> 系统管理 -> 安全 -> 应用程序 -> Web 应用程序检查 /pet1 是否存在。

定义完成!

现在,让我们检查是否已经创建了记载输入路径对应的方法的disp(调度类)和实施代码的impl类。

类定义已经在 PetStore 包下创建完成!

与IRIS提供的OpenAPI 2.0的类不同的是,这里包含了model包和requests包。

在这个工具中,OpenAPI 3.0的Components对象中指定的信息被创建为可以生成实例的类定义。 (它继承了 %RegisteredObject 类)

Components对象Pet的信息可以在下方展开查看。

 
Components:Pet的规格
  "Pet":{

        "required":[

          "name",

          "photoUrls"

        ],

        "type":"object",

        "properties":{

          "id":{

            "type":"integer",

            "format":"int64",

            "example":10

          },

          "name":{

            "type":"string",

            "example":"doggie"

          },

          "category":{

            "$ref":"#/components/schemas/Category"

          },

          "photoUrls":{

            "type":"array",

            "xml":{

              "wrapped":true

            },

            "items":{

              "type":"string",

              "xml":{

                "name":"photoUrl"

              }

            }

          },

          "tags":{

            "type":"array",

            "xml":{

              "wrapped":true

            },

            "items":{

              "$ref":"#/components/schemas/Tag"

            }

          },

          "status":{

            "type":"string",

            "description":"pet status in the store",

            "enum":[

              "available",

              "pending",

              "sold"

            ]

          }

        },

        "xml":{

          "name":"pet"

        }

      },

根据此信息创建的类如下:

它在可以实例化的类中。

如果将super class从 %RegisteredObject 更改为 %Persistent 并编译,则可以将其用作可以在数据库中持久化储存的类。

此外,POST 请求将发送以下格式的 JSON 对象。

 { "id": 0,
  "category": {
    "id": 0,
    "name": "Dog"
  },
  "name": "Hachi",
  "photoUrls": [
    "https://x.gd/1pbYK"
  ],
  "tags": [
    {
      "id": 0,
      "name": "Middle"
    }
  ],
  "status": "available"
}

能够将此 JSON 直接作为 Pet、Tag 和 Category 类下的实例会很好,因此又追加继承了 %JSON.Adaptor 。

另外,如果我要修改 Pet、Tag 和 Category,最好将super class的配置从 %RegisteredObject 更改为 %Persistent 和 %JSON.Adaptor 的多重继承。

在此之后,需要将接收到的Body信息更新到数据库中。

Request包下的类描述了这个过程的概要。以下示例显示了在向 /pet 发出 POST 请求时运行的类 (PetStore.requests.addPet.cls) 的内容。

如果你注意LoadFromRequest()方法,你会发现它在把可以处理HTTP请求的%request传递给参数request(在IRIS的REST调度类内部处理时,HTTP请求存储在%CSP.Request的一个实例中)。

 request.Content

上面的执行可以得到Body中指定的JSON对象。

 Do ..PetNewObject (). %JSONImport (request.Content)

这个类中虽然调用了以上方法,但由于该类中实际上并没有PetNewObject()方法,所以做了如下修改(生成一个Pet实例,将其设置为属性Pet,然后将接收到的JSON分配给实例处理)。

 set ..Pet = ##class (PetStore.model.Pet). %New () 
do ..Pet . %JSONImport (request.Content)


这样就完成了接收到 HTTP 请求时的处理。剩下的就是impl.cls的实现了。

在初始状态下,以下方法没有任何描述。

 ClassMethod addPet(messageRequest As PetStore.requests.addPet) As %Status 
{ ; Implement your service here. 
; Return {} $$$ThrowStatus ( $$$ERROR ( $$$NotImplemented )) 
}

参数 messageRequest 指定了 PetStore.requests.addPet 类的一个实例,该实例在之前的流程中得到确认(根据 HTTP 请求中收到的 JSON 对象创建的实例在该实例的 Pet 属性中设置。)

改写如下,编译,大功告成!

 ClassMethod addPet(messageRequest As PetStore.requests.addPet) As %Status 
{
    ;Implement your service here. 
    ; Return {} //$$$ThrowStatus($$$ERROR($$$NotImplemented)) 
    set status= $$$OK 
    set status=messageRequest.Pet. %Save () 
    return status 
}

让我们来测试 POST 请求。


 

Pet、Category、和Tag都注册并添加数据成功了!

这个用例还是需要一些手动修改,但当我发现类定义是通过 OpenAPI 3.0 Components 对象自动生成的,让我觉得很便利!

大家也请试用一下。

#REST API #开发环境 #InterSystems IRIS #InterSystems IRIS for Health

源 URL:https://cn.community.intersystems.com/post/openapi-suite%EF%BC%88%E4%BB%8E-openapi-30-%E7%94%9F%E6%88%90-objectscript-%E4%BB%A3%E7%A0%81%E7%9A%84%E5%B7%A5%E5%85%B7%E9%9B%86%EF%BC%89%EF%BC%9A%E4%BB%8B%E7%BB%8D-intersystems-%E5%BC%80%E5%8F%91%E4%BA%BA%E5%91%98%E5%B7%A5%E5%85%B7%E5%A4%A7%E8%B5%9B-2023-%E8%8E%B7%E5%A5%96%E8%80%85