文章 姚 鑫 · 七月 31, 2022 8m read

第十三章 手动创建 REST 服务(一)

本附录描述了如何通过继承 %CSP.REST 类来手动创建 REST 服务;此过程创建了一个手动编码的 REST 服务,它不能与所有 管理工具一起使用。

手动创建 服务的基础知识

要手动定义 服务,请执行以下操作:

  • 创建一个 REST 服务类 — %CSP.REST 的子类。在子类中:
    • 定义一个 URL 映射,该映射指定为 REST URLHTTP 方法执行的 方法。
    • 可以选择指定 参数。此参数控制每个 调用是在其自己的 Web 会话下执行还是与其他 调用共享一个会话。
    • (可选)覆盖错误处理方法。

如果想将实现代码与调度代码分开,可以在单独的类中定义实现 REST 服务的方法,并从 URL 映射中调用这些方法。

  • 定义一个使用 服务类作为其调度类的 应用程序。

要定义 应用程序及其安全性,请转至 应用程序页面(单击System Administration > Security > Applications > Web Applications)。

定义 应用程序时,将 设置为 REST 服务类的名称。

此外,将应用程序的名称指定为 调用的 的第一部分。示例名称为 或 ,但可以指定 中允许的任何文本。

可以在一个命名空间中定义多个 服务类。每个拥有自己入口点的 服务类都必须拥有自己的

0
0 127
文章 姚 鑫 · 七月 30, 2022 3m read

第十二章 使用中的 OpenAPI 属性

本附录列出了 API 管理工具在生成 REST 服务类时使用的 OpenAPI 2.0 规范的属性。此处未列出的属性将被忽略。有几个扩展属性;它们的名称以 x-ISC 开头。

  • basePath

  • consumes

  • host

  • (请注意, 管理工具在生成代码时不使用 对象的任何属性)

  • (for details, see “Parameter Object”)

  • (for details, see “Path Item Object”)

  • info (for details, see “Info Object”)

  • swagger (must be "2.0")

有关这些属性的详细信息,请参阅 https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object

Info Object

  • title

  • x-ISC_RequiredResource

0
0 210
文章 姚 鑫 · 七月 29, 2022 2m read

第十一章 /api/mgmnt/ API 参考

此参考列出了 /api/mgmnt/ 服务中的端点,所有这些端点都适用于较新的 REST 服务。下表总结了端点并指出它们是否也适用于手动编码的 REST 服务。

Endpoint Summary Applies to NEWER REST Services? Applies to Manually-Coded REST Services?
DELETE /api/mgmnt/v2/:ns/:app 删除 REST 服务 YES no
GET /api/mgmnt/ 列出此服务器上启用 RESTWeb 应用程序 YES YES
GET /api/mgmnt/v1/:ns/restapps 列出命名空间中启用 REST 的 应用程序 YES YES
GET /api/mgmnt/v1/:ns/spec/:app 返回 REST 服务的 规范 no YES
0
0 85
文章 姚 鑫 · 七月 28, 2022 4m read

第十章 发现和记录 REST API

本章讨论如何发现实例上可用的 REST 服务以及如何为 REST 服务生成文档。

使用 /api/mgmnt 服务发现 服务

/api/mgmnt 服务包括可用于发现 服务类和启用 REST 的 应用程序的调用。

发现 服务

要使用 服务来发现实例上可用的 REST 服务,请使用以下 调用:

  • 对于 HTTP 操作,选择或指定 GET
  • 对于 ,请指定以下形式的 :
http://localhost:52773/api/mgmnt/v2/

或者,如果只想检查一个命名空间:

http://localhost:52773/api/mgmnt/v2/:namespace

其中 是服务器的名称, 是运行 的 服务器端口,命名空间是要检查的命名空间。

(请注意,这些调用会忽略手动编码的 服务。要发现手动编码的 应用程序,请使用调用 和 。)

如果调用成功, 以 格式返回一个列出 服务的数组。例如:

[
  {
    "name": "%Api.Mgmnt.v2",
    "webApplications": "/api/mgmnt",
    "dispatchClass": "%Api.Mgmnt.v2.disp",
    "namespace": "%SYS",
    "swaggerSpec": "/api/mgmnt/v2/%25SYS/%Api.Mgmnt.v2"
  },
  {
    "name": "myapp",
    "webApplications": "/api/myapp",
    "dispatchClass": "myapp.disp",
    "namespace": "USER",
    "swaggerSpec": "/api/mgmnt/v2/USER/myapp"
  }
]
0
0 152
文章 姚 鑫 · 七月 27, 2022 3m read

第九章 REST 服务安全

如果 REST 服务正在访问机密数据,应该对服务使用身份验证。如果需要为不同的用户提供不同级别的访问权限,还要指定端点所需的权限。

REST 服务设置身份验证

可以对 IRIS REST 服务使用以下任何形式的身份验证:

  • HTTP 身份验证标头 — 这是 REST 服务的推荐身份验证形式。
  • Web 会话身份验证 — 其中用户名和密码在 URL 中的问号后面指定。
  • 身份验证 - 请参阅以下小节。

应用程序和

要通过 OAuth 2.0 对 应用程序进行身份验证,请执行以下所有操作:

  • 将包含 REST 应用程序的资源服务器配置为 OAuth 2.0 资源服务器。
  • 允许对 进行委派身份验证。
  • 确保将 应用程序(用于 应用程序)配置为使用委托身份验证。
  • 在 命名空间中创建一个名为 的例程。 提供了一个示例例程 ,可以复制和修改它。此例程是 GitHub (https://github.com/intersystems/Samples-Security) 上 Samples-Security 示例的一部分。可以按照“下载用于 IRIS 的示例”中的说明下载整个示例,但在 上打开例程并复制其内容可能更方便。

在例程中,修改 的值并根据需要进行其他更改。

指定使用

0
0 142
文章 姚 鑫 · 七月 25, 2022 6m read

第七章 在 REST 服务中支持 CORS

概述

本节提供 CORS 的概述以及如何在 IRIS REST 服务中启用 CORS 的概述。

CORS 简介

跨域资源共享 () 允许在另一个域中运行的脚本访问服务。

通常,当浏览器从一个域运行脚本时,它允许对同一个域进行 调用,但在对另一个域进行调用时不允许它们。此浏览器行为限制某人创建可滥用机密数据的恶意脚本。恶意脚本可能允许用户使用授予用户的权限访问另一个域中的信息,但随后在用户不知道的情况下,将机密信息用于其他用途。为了避免这种安全问题,浏览器一般不允许这种跨域调用。

在不使用跨域资源共享 (CORS) 的情况下,具有访问 REST 服务的脚本的网页通常必须与提供 服务的服务器位于同一域中。在某些环境中,将带有脚本的网页与提供 REST 服务的服务器放在不同的域中是很有用的。 支持这种安排。

下面提供了浏览器如何使用 处理 的简化描述:

  1. DomOne 中的网页中的脚本包含对 DomTwo 域中的IRIS REST 服务的 。 具有 的自定义标头。
  2. 用户查看此网页并运行脚本。用户的浏览器检测到与包含网页的域不同的域的 。
  3. 用户的浏览器向 服务发送一个特殊请求,该请求指示 的 请求方法和原始网页的域,在本示例中为 。
  4. 如果请求被允许,则响应包含请求的信息。否则,响应仅包含指示
0
0 135
文章 姚 鑫 · 七月 24, 2022 2m read

第六章 修改规范(SPEC)类

概述

下表列出了修改规范类的原因并简要总结了所需的更改:

原因 改变
更新或替换规范 手动修改 OpenAPI XData 块或通过重新生成规范类。
启用 REST 服务以支持 CORS 手动修改 OpenAPI XData 块;还添加一个类参数并创建一个自定义调度超类。
启用 服务以支持 Web 会话 添加类参数。
指定使用端点所需的权限 手动修改 OpenAPI XData 块。
覆盖默认内容类型、响应字符集或输入流处理 添加类参数。
为服务方法指定一个非默认名称 手动修改 块。

无论何时编译规范类,编译器都会在同一个包中重新生成调度类并更新实现类。

覆盖内容类型、响应字符集或输入流处理

只需将类参数添加到规范类并重新编译,就可以覆盖 REST 服务的几个关键方面。

  • 默认情况下,REST 服务需要 application/json 内容类型。要覆盖它,请将以下内容添加到规范类:
Parameter CONTENTTYPE = "some-content-type";

其中 some-content-typeMIME 内容类型。

  • 默认情况下,REST 服务的响应消息采用 格式。要覆盖它,请将以下内容添加到规范类:
Parameter CHARSET = "some-character-set";
0
0 157
文章 姚 鑫 · 七月 23, 2022 2m read

第五章 修改实现(IMPL)类

本章讨论如何修改 REST 服务的实现类。

初始方法定义

实现类最初包含存根方法,如下例所示:

/// Returns all pets from the system that the user has access to<br/>
/// The method arguments hold values for:<br/>
///     tags, tags to filter by<br/>
///     limit, maximum number of results to return<br/>
ClassMethod findPets(tags As %ListOfDataTypes(ELEMENTTYPE="%String"), limit As %Integer) As %Stream.Object
{
    //(Place business logic here)
    //Do ..%SetStatusCode(<HTTP_status_code>)
    //Do ..%SetHeader(<name>,<value>)
    //Quit (Place response here) ; response may be a string, stream or dynamic object
}
0
0 143
文章 姚 鑫 · 七月 22, 2022 3m read

第四章 使用 %REST.API 类创建 REST 服务

本章介绍如何使用 %REST.API 类来创建、更新和删除 REST 服务。

使用 %REST.API 类创建或更新 REST 服务

创建 REST 服务的推荐方法是从 服务的 OpenAPI 2.0 规范开始,并使用它来生成 服务类。要使用 类执行此操作:

  1. 获取 REST 服务的 OpenAPI 2.0 规范,采用 格式,并将规范保存为文件。该文件必须是 编码的。
  2. 在要定义 服务的命名空间中,使用该文件创建 的实例。
  3. 然后调用 类的 方法。此方法具有以下签名:
classmethod CreateApplication(applicationName As %String, 
                              swagger As %DynamicObject = "", 
                              ByRef features, 
                              Output newApplication As %Boolean, 
                              Output internalError As %Boolean) 
                              as %Status
0
0 165
文章 姚 鑫 · 七月 21, 2022 3m read

第三章 使用 ^%REST 例程创建 REST 服务

本章介绍如何使用 ^%REST 例程创建和删除 REST 服务。

提示:还可以使用此例程更新REST服务;只需删除服务,然后重新创建它。

使用^%REST例程

^%REST例程是一个简单的命令行界面。在任何提示下,可以输入以下答案:

  • ^ - 使例程跳回上一个问题。
  • ? - 使例程显示一条列出所有当前选项的消息。
  • q或 - 结束例程。

此外,每个问题都会在括号中显示该问题的默认答案。

使用例程创建服务

创建REST服务的推荐方法是从服务的规范开始,并使用该规范生成服务类。要使用例程执行此操作:

  1. 获取JSON格式的服务的规范。将规范另存为文件或记下可访问规范的URL。
  2. 在终端中,更改到要在其中定义服务的名称空间。
  3. 输入以下命令以启动例程:
  1. 在第一个提示符处,输入 REST 服务的名称。该名称用作生成类的包名;使用有效的包名。如果想使用名称列表、l、 或 (在任何情况下都是变体),请将名称用双引号括起来。例如:
  2. 在下一个提示符处,输入 (不区分大小写)以确认您要创建此服务。

然后,该例程会提示输入要使用的 规范的位置。输入完整路径名或 URL

  1. 在下一个提示符处,输入 (不区分大小写)以确认要使用此规范。

该例程在此命名空间中的指定包内创建、 和 类。然后该例程显示如下输出:

接下来,例程会询问否还想创建一个 应用程序。将使用此

0
0 117
文章 姚 鑫 · 七月 20, 2022 4m read

第二章 使用 /api/mgmnt/ 服务

本章介绍如何使用 /api/mgmnt 服务来创建、更新和删除 REST 服务。

/api/mgmnt 服务还提供了可用于发现和记录 服务的选项,如本书后面所述。

使用 /api/mgmnt 服务创建 REST 服务

创建 REST 服务的推荐方法是为 服务创建 OpenAPI 2.0(也称为 )描述,并使用它来生成 服务类。如果您正在实现由第三方定义的 服务,他们可能会提供此 描述。有关 描述格式的详细信息,请参阅 规范。以下主题描述了如何使用 服务来执行此操作。

使用 /api/mgmnt 服务生成类

第一步,生成 服务类,如下所示:

  1. JSON 格式创建或获取 REST 服务的 描述。
  2. 获取 测试工具,例如 (https://www.getpostman.com/)。
  3. 在测试工具中,创建如下 请求消息:
  • 对于 操作,选择或指定 POST
  • 对于 ,请指定以下形式的 :

其中 是服务器的名称,52773 是运行 的 服务器端口, 是要在其中创建 服务的名称空间, 是要在其中创建类的包的名称.

  • 对于请求正文,以 格式粘贴
0
0 156
文章 姚 鑫 · 七月 19, 2022 8m read

第一章 创建 REST 服务简介

本文介绍 IRIS® 中的 RESTREST 服务。

REST 简介

命名自,具有以下属性:

  • REST 是一种架构风格,而不是一种格式。尽管 REST 经常使用 HTTP 来传输消息并使用 来传递数据,但也可以将数据作为 或纯文本传递。 利用现有的 标准,例如 、、 和 。
  • 是面向资源的。通常,资源由 标识并使用基于 HTTP 方法的操作,例如 、、 和 。
  • 通常有少量开销。虽然它可以使用 来描述数据,但它更常用的是 ,它是一种轻量级的数据包装器。 JSON 使用标签标识数据,但标签没有在正式的模式定义中指定,也没有明确的数据类型。

REST 服务简介

在 及更高版本中定义 接口有两种方法:

  • 规范优先定义——首先创建一个 规范,然后使用 管理工具生成 REST 接口的代码。
  • 手动编码 接口。

使用规范优先的定义, 服务正式由以下组件组成:

  • 规范类( 的子类)。此类包含 服务的 规范。 支持可以在规范中使用的几个扩展属性。
  • 调度类( 的子类)。该类负责接收请求并调用实现类中合适的方法。
  • 一个实现类( 的子类)。此类定义实现 调用的方法。

管理工具生成实现类的存根版本,然后可以扩展它以包含必要的应用程序逻辑。 (逻辑当然可以调用此类之外的代码。)

类提供了可以调用的方法,以便设置 HTTP

0
0 152
文章 姚 鑫 · 七月 18, 2022 6m read

第九章 使用嵌入式 Python (六)

异常处理

IRIS 异常处理程序可以处理 Python 异常并将它们无缝传递给 ObjectScript。在前面的 库示例的基础上,如果尝试使用不存在的文件调用 ,并在 中捕获异常,会看到以下内容:

USER>try { do canvas.drawImage("C:\Sample\bad.png", 150, 600) } catch { write "Error: ", $zerror, ! }
Error: <THROW> *%Exception.PythonException <THROW> 230 ^^0^DO canvas.drawImage("W:\Sample\isc.png", 150, 600) 
<class 'OSError'>: Cannot open resource "W:\Sample\isc.png" -

这里 : Cannot open resource "W:\Sample\isc.png"是从 传回的异常。

字节和字符串

Python 对“字节”数据类型的对象和字符串(表示字符串的 字节序列)进行了明确区分,它们是简单的 位字节序列。在

0
0 129
文章 姚 鑫 · 七月 17, 2022 4m read

第八章 使用嵌入式 Python (五)

通过引用传递参数

ObjectScript 编写的方法中的参数可以通过值或引用传递。在下面的方法中,签名中第二个和第三个参数前面的 ByRef 关键字表示它们打算通过引用传递。

ClassMethod SandwichSwitch(bread As %String, ByRef filling1 As %String, ByRef filling2 As %String)
{
    set bread = "whole wheat"
    set filling1 = "almond butter"
    set filling2 = "cherry preserves"
}

从 调用方法时,在参数前放置一个句点以通过引用传递它,如下所示:

USER>set arg1 = "white bread"
 
USER>set arg2 = "peanut butter"
 
USER>set arg3 = "grape jelly"
 
USER>do ##class(User.EmbeddedPython).SandwichSwitch(arg1, .arg2, .arg3)
 
USER>write arg1
white bread
USER>write arg2
almond butter
USER>write arg3
cherry preserves
0
0 139
文章 姚 鑫 · 七月 16, 2022 4m read

第七章 使用嵌入式 Python (四)

弥合 ObjectScript 和嵌入式 Python 之间的差距

由于 ObjectScriptPython 语言之间的差异,将需要了解一些有助于弥合语言之间差距的信息。

ObjectScript 方面, 类允许从 ObjectScript 使用 。

在 方面, 模块允许使用 Python 中的 。在 中,键入 以获取其方法和函数的列表。

使用 Python 内置函数

包在 解释器启动时自动加载,它包含语言的所有内置标识符,例如基对象类和所有内置数据类型类、异常类、函数和常量。

可以将此包导入 ObjectScript 以访问所有这些标识符,如下所示:

set builtins = ##class(%SYS.Python).Import("builtins")

函数实际上是内置模块的一个方法,因此现在可以在 中使用此函数:

USER>do builtins.print("hello world!")
hello world!

然后可以使用 命令检查内置对象,因为它是一个 对象,所以它使用内置包的 方法来获取该对象的字符串表示形式。例如:

出于同样的原因,可以使用 方法创建 列表。

0
0 165
文章 姚 鑫 · 七月 15, 2022 5m read

第六章 使用嵌入式 Python (三)

从 ObjectScript 调用嵌入式 Python 代码

使用 Python 库

嵌入式 Python 让可以轻松访问数以千计的有用库。通常称为“包”,它们需要从 Python 包索引 (PyPI) 安装到 /mgr/python 目录中,然后才能使用。

例如, 是一个用于生成 和图形的开源库。以下命令使用软件包安装程序 irispip 在 系统上安装 :

在基于 的系统上,使用:

$ pip3 install --target /InterSystems/IRIS/mgr/python reportlab

安装包后,可以使用 %SYS.Python 类的 方法在 代码中使用它。

给定一个文件位置,以下 方法 创建一个示例 PDF 文件并将其保存到该位置。

Class Demo.PDF
{

ClassMethod CreateSamplePDF(fileloc As %String) As %Status
{
    set canvaslib = ##class(%SYS.Python).Import("reportlab.pdfgen.canvas")
    set canvas = canvaslib.Canvas(fileloc)
    do canvas.drawImage("C:\Sample\isc.png", 150, 600)
    do canvas.drawImage("C:\Sample\python.png", 150, 200)
    do canvas.setFont("Helvetica-Bold", 24)
    do canvas.drawString(25, 450, "InterSystems IRIS & Python. Perfect Together.")
    do canvas.save()
}

}
0
0 257
文章 姚 鑫 · 七月 14, 2022 3m read

第五章 使用嵌入式 Python (二)

在 Python 脚本文件 (.py) 中

还可以使用 irispython 命令执行 Python 脚本。

考虑 Windows 系统上的文件 ,其中包含以下代码:

# print the members of the Fibonacci series that are less than 10
print('Fibonacci series:')
a, b = 0, 1
while a < 10:
    print(a, end=' ')
    a, b = b, a + b

# import the iris module and show the classes in this namespace
import iris
print('\nInterSystems IRIS classes in this namespace:')
status = iris.cls('%SYSTEM.OBJ').ShowClasses()
print(status)

可以从命令行运行 ,如下所示:

C:\InterSystems\IRIS\bin>set IRISUSERNAME = <username>

C:\InterSystems\IRIS\bin>set IRISPASSWORD = <password>

C:\InterSystems\IRIS\bin>set IRISNAMESPACE = USER

C:\InterSystems\IRIS\bin>irispython \python\test.py
Fibonacci series:
0 1 1 2 3 5 8
InterSystems IRIS classes in this namespace:
User.Company
User.Person
1
0
0 167
文章 姚 鑫 · 七月 13, 2022 3m read

第四章 使用嵌入式 Python (一)

嵌入式 Python 允许使用 Python 作为编程 IRIS 应用程序的本机选项。

预备知识

使用嵌入式 所需的 版本取决于运行的平台。

在 Microsoft Windows 上, 安装工具包安装正确版本的 Python(当前为 ),仅用于嵌入式 。如果在开发机器上并希望将 用于一般用途,建议从 下载并安装相同的版本。

许多基于 UNIX 的操作系统都安装了 。如果需要安装,请使用包管理器为操作系统推荐的版本,例如:

  • macOS:使用 Homebrew 安装 Python 3.9
  • :
  • :

如果收到“无法加载 ”的错误,这意味着没有安装 Python,或者系统上安装了意外版本的 。使用上述方法之一安装或重新安装。

在基于 的系统上,可能希望使用 命令安装 包。如果尚未安装 ,请使用系统的包管理器安装包 。

要防止在运行 时出现 错误,请启用 。在管理门户中,,选择 ,然后选中启用服务框。

运行嵌入式 Python

本节详细介绍了运行 的几种方法:

从Python Shell

可以从终端会话或命令行启动 。

从终端启动 Python Shell

通过调用 类的 方法,从 终端会话启动 。这将以交互模式启动 解释器。终端会话中的用户和命名空间被传递给 。

通过键入命令 退出 。

0
0 323
文章 姚 鑫 · 七月 12, 2022 6m read

第三章 嵌入式Python概述(三)

使用 SQL

IRIS 中的类被投影到 SQL,除了使用类方法或直接全局访问之外,还允许使用查询访问数据。 iris 模块为提供了两种从 运行 语句的不同方式。

以下示例使用 运行 语句以查找类名称以“%Net.LDAP”开头的所有类定义,返回一个包含每个名称和超类的结果集每个班级。在这里,系统类 将 投影为同名表。

>>> rs = iris.sql.exec("SELECT Name, Super FROM %Dictionary.ClassDefinition WHERE Name %STARTSWITH '%Net.LDAP'")

以下示例使用 准备 查询对象,然后执行查询,将“%Net.LDAP”作为参数传入:

>>> stmt = iris.sql.prepare("SELECT Name, Super FROM %Dictionary.ClassDefinition WHERE Name %STARTSWITH ?")
>>> rs = stmt.execute("%Net.LDAP")

无论哪种情况,都可以按如下方式遍历结果集,并且输出相同:

>>> for idx, row in enumerate(rs):                                              
...     print(f"[{idx}]: {row}")                                                
...
[0]: ['%Net.LDAP.Client.EditEntry', '%RegisteredObject']
[1]: ['%Net.LDAP.Client.Entries', '%RegisteredObject,%Collection.AbstractIterator']
[2]: ['%Net.LDAP.Client.Entry', '%RegisteredObject,%Collection.AbstractIterator']
[3]: ['%Net.LDAP.Client.PropList', '%RegisteredObject']
[4]: ['%Net.LDAP.Client.Search.Scope', '%Integer']
[5]: ['%Net.LDAP.Client.Session', '%RegisteredObject']
[6]: ['%Net.LDAP.Client.StringList', '%RegisteredObject']
[7]: ['%Net.LDAP.Client.ValueList', '%RegisteredObject,%Collection.AbstractIterator']
1
0 192
文章 姚 鑫 · 七月 11, 2022 4m read

第二章 嵌入式Python概述(二)

从 Python 调用 IRIS API

如果使用的是嵌入式 Python 并且需要与 IRIS 交互,可以使用 Python shell 中的 模块,或者使用 编写的 类中的方法。要遵循本节中的示例,可以使用 命令 从终端会话启动 。

当启动终端会话时,将被放置在 的 命名空间中,将看到提示 USER>。但是,如果从 加载了示例类,则需要在 命名空间中才能访问它们。

在终端中,更改为 命名空间,然后启动 ,如下所示:

USER>set $namespace = "SAMPLES"
SAMPLES>do ##class(%SYS.Python).Shell()

Python 3.9.5 (default, Jul 19 2021, 17:50:44) [MSC v.1927 64 bit (AMD64)] on win32
Type quit() or Ctrl-D to exit this shell.
>>>

当从终端会话启动 时,Python shell 继承与终端相同的上下文,例如,当前命名空间和用户。局部变量不被继承。

使用类

要从 访问 类,请使用 模块来实例化要使用的类。然后,可以像访问

0
0 157
文章 姚 鑫 · 七月 10, 2022 5m read

第一章 嵌入式Python概述(一)

嵌入式 Python 允许将 Python 与 IRIS 数据平台的本地编程语言 ObjectScript 一起使用。当使用嵌入式 在 类中编写方法时, 源代码与编译后的 代码一起编译为在服务器上运行的目标代码。与使用网关或 的 相比,这允许更紧密的集成。还可以导入 包,无论它们是自定义的还是公开的,并在 代码中使用它们。 对象是 中的一等公民,反之亦然。

  • 使用来自 ObjectScriptPython 库 - 此方案假设 开发人员,并且希望利用 开发人员社区可用的众多 库的强大功能。
  • 从 调用 — 此方案假定您是一名 开发人员,对 IRIS 不熟悉,并且想知道如何访问 。
  • 一起使用 和 — 这个场景假设在一个由 ObjectScript 和 开发人员组成的混合团队中,并且想知道如何一起使用这两种语言。

将需要 或更高版本的正在运行的 实例,以及取决于操作系统的一些先决条件。还需要知道如何访问终端,即 IRIS 命令行工具。

本文档中的一些示例使用来自 上 存储库的类:https://github.com/intersystems/Samples-Data。 建议创建一个名为 的专用命名空间并将样本加载到该命名空间中。如果想查看或修改示例代码,则需要设置集成开发环境 ()。推荐使用 。

0
0 320
文章 姚 鑫 · 七月 10, 2022 7m read

第二十三章 使用 %Status 值

许多类使用 %Status 数据类型类来表示状态信息,并且它们的方法返回表示成功或错误的 %Status 值(状态)。如果状态表示一个错误(或多个错误),则状态值还包括有关错误的信息。

还可以返回自己的状态值。

本文讨论状态值以及如何使用它们。

使用状态值的基础知识

如上所述,许多 类中的方法返回一个状态以指示成功或错误。例如,%Library.Persistent中的%Save()` 方法返回一个状态。对于任何此类方法,请务必获取返回值。然后检查状态,然后适当地继续。基本工具如下:

  • 要检查状态是表示成功还是错误,请使用以下任一方法:

    • $$$ISOK$$$ISERR 宏,在包含文件 %occStatus.inc 中定义。此包含文件在所有对象类中自动可用。
    • 和 方法,它们在终端(不能使用宏)中特别方便。
  • 要显示错误详细信息,请使用 $SYSTEM.OBJ.DisplayError() 或 。这些方法彼此等效。他们将输出写入当前设备。

  • 要获取包含错误详细信息的字符串,请使用 。

示例

/// d ##class(PHA.TEST.AdvancedConcepts).Status()
ClassMethod Status()
{
	s object = ##class(Sample.Person).%New()
	s object.Name = "yao,xin"
	s tSC = object.%Save()
	if $$$ISERR(tSC) {
		d $SYSTEM.OBJ.DisplayError(tSC)
		q
	}
}

0
0 150
文章 姚 鑫 · 七月 8, 2022 2m read

第二十二章 安全自定义 Web 应用程序登录

除了推荐的 REST 应用程序支持之外,产品还支持两种类型的传统 Web 应用程序:CSP 和 。在配置使用 和 的自定义登录页面时,遵循推荐的协议很重要。这些协议提供了更高的安全性,并最大限度地减少了升级到新产品或版本时的不兼容性。

关于创建自定义 CSP 登录页面

创建自定义 登录页面:

  1. 创建 %CSP.Login 页面的子类。
  2. 要自定义应用程序的行为,请覆盖子类的 Draw 方法,以便页面看起来像想要的那样。其中包括修改登录页面外观的方法和修改安全令牌页面外观的方法(如果使用双因素身份验证):
  • 登录页面方法——、DrawHEADDrawSTYLE
  • 安全令牌 (ST) 页面方法 — 、

请注意, 和 DrawSTTitle 方法调用 DrawTitleSection 方法。

  1. 在应用程序中根据需要调用子类。

重要提示:创建自定义登录页面时,必须使用 的子类。在 应用程序中创建登录页面的其他方法可能会导致各种问题。 如果编写了不使用 子类的自定义登录页面,并且应用了来自任何用于升级或保护实例的更改,那么登录页面可能会失败而没有错误消息。例如,用户可能会尝试使用有效的用户名和密码登录,但他们的登录将在没有任何明显原因的情况下失败。这种情况可能表明需要更改自定义登录以使用所需的方法。

关于创建自定义 登录页面

0
0 150
文章 姚 鑫 · 七月 7, 2022 4m read

第二十一章 使用工作队列管理器(四)

分离和附加工作队列

通常,初始化一组工作程序,将工作项排队,然后等待工作程序完成工作项。但是,可能会遇到工作人员作业完成工作项所需的时间比预期更长的情况,或者无法将单个进程专门用于等待。因此,工作队列管理器使能够将工作队列与进程分离,然后将工作队列附加到同一进程或不同的进程。

例如,假设队列引用了初始化的工作队列。还假设向工作队列中添加了几个工作项。在调用 Wait() 或 WaitForComplete() 来确定正在处理的工作的状态之前,可以使用以下方法:

Detach()

method Detach(ByRef token As %String, timeout As %Integer=86400) as Status 从初始化工作队列时创建的对象引用中分离工作队列对象。 Detach() 方法使任何正在进行的工作能够继续并保留工作队列的当前状态。

token 参数表示一个安全令牌,可以使用它随后将工作队列附加到另一个进程。 timeout 参数是可选的,它指示系统保留分离的工作队列对象的时间量(以秒为单位)。超时期限过后,系统会删除与工作队列关联的所有工作人员作业和信息。超时的默认值为 1 天。

调用 Detach() 方法后,对分离对象引用的大多数调用都会返回错误。

0
0 134
文章 姚 鑫 · 七月 6, 2022 4m read

第二十章 使用工作队列管理器(三)

管理类别

一个类别是一个独立的worker jobs池。当初始化一组worker jobs时,可以指定提供worker的类别。如果集合中的任何worker jobs在执行work项时请求额外的worker jobs,则新的worker jobs来自同一类别。

例如,假设系统提供的 SQL 类别分配了最多 8 个worker。然后,假设与BusinessIntelligence相关的流程创建了一个类别,并将最多四个worker分配给该类别。如果 SQL 池中的所有worker在给定时间都参与了工作,则 BusinessIntelligence 类别中的worker可能仍然可以立即处理工作项。

系统包括两个不能删除的类别: 和 。 SQL 类别适用于系统执行的任何 SQL 处理,包括查询的并行处理。当在未指定类别的情况下初始化一组worker jobs时,默认类别提worker jobs。

每个类别都具有影响该类别中每个工作队列的行为的属性。这些属性是:

DefaultWorkers

当创建此类别中的工作队列且未指定worker job 计数时,这将成为工作队列中worker job 的数量。此属性的默认值是核心数。

MaxActiveWorkers

在此类别的job服务请求池中保留的活动worker job的最大数量。

0
0 177
文章 姚 鑫 · 七月 5, 2022 5m read

第十九章 使用工作队列管理器(二)

基本工作流程

可以通过执行以下步骤来使用工作队列管理器:

  1. ObjectScript 代码划分为工作单元,这些工作单元是满足特定要求的类方法或子例程。
  2. 创建一个工作队列,它是 %SYSTEM.WorkMgr 类的一个实例。为此,请调用 %SYSTEM.WorkMgr 类的 %New() 方法。该方法返回一个工作队列。

可以指定要使用的并行worker jobs的数量,也可以使用默认值,这取决于机器和操作系统。此外,如果已创建类别,则可以指定应从中获取job的类别。

创建工作队列时,工作队列管理器会创建以下工件:

  • 包含有关工作队列的信息的全局变量,例如工作队列在哪个命名空间中运行
  • 工作队列必须处理的序列化工作单元的位置和事件队列
  • 在工作队列完成处理工作单元时创建的完成事件的位置和事件队列
  1. 将工作单元(也称为工作项)添加到工作队列。为此,可以调用 Queue()QueueCallback() 方法。作为参数,传递类方法(或子例程)的名称和任何相应的参数。

对添加到队列的项目立即开始处理。

如果队列中的项目多于队列可用的worker jobs,则job会竞争清空队列。例如,如果有 100 个项目和四个job,则每个job从队列的头部移除一个项目,处理它,然后返回到队列的头部以移除并处理另一个项目。这种模式一直持续到队列为空。

0
0 170
文章 姚 鑫 · 七月 4, 2022 7m read

第十八章 使用工作队列管理器(一)

工作队列管理器是的一项功能,使能够通过以编程方式将工作分配给多个并发进程来提高性能。在引入工作队列管理器之前,可能已经使用 JOB 命令在应用程序中启动多个进程并使用自定义代码管理这些进程(以及任何导致的故障)。工作队列管理器提供了一个高效且直接的 API,使能够卸载流程管理。

代码在多个地方内部使用工作队列管理器。可以将它用于自己的需求,如以下部分中的高级描述。

背景

计算机硬件开发的最新创新趋向于高性能、多处理器或多核架构。与此同时,内存和网络设备的速度也只是慢慢地提高了。 开发了工作队列管理器以响应这些趋势并根据以下原则:

  • 硬件资源,包括 CPU 和 I/O、内存和网络设备,都是固定的。
  • 必须尽可能高效地使用硬件资源,以最大限度地提高其执行业务任务的速度。
  • 为了实现最大效率,工作队列管理器必须改善在执行ObjectScript 代码时可能出现的 CPU 利用率不足的问题。
  • 解决 CPU 利用率不足的方法包括排队和优先级划分。

尽管整个数据平台旨在尽可能高效地利用系统中的硬件资源,但该平台的工作队列管理器功能专门设计用于利用现代硬件配置中可用的额外 CPU 资源。工作队列管理器有两个关键用途:

  • 提供一个框架,使能够将大型编程任务分解成更小的块,以便在多个并发进程中执行。通过一次使用多个 CPU,工作队列管理器显着减少了处理大型工作负载所需的时间。
0
0 174
文章 姚 鑫 · 七月 3, 2022 5m read

第十七章 进程内存

介绍

进程使用许多不同的资源来实现其目标。其中包括部分或全部 CPU 周期、内存、外部存储、网络带宽等。这篇文章是关于内存使用的。具体来说,它处理为数据存储分配的内存,例如:

  • 公共和私有变量

当第一次为它们分配值时,它们被分配了内存空间。在局部数组的情况下,局部变量名称加上所有下标的值的组合引用单个变量值。

除了包含极长字符串的变量外,变量会占用与 $STORAGE 相关的空间。包含极长字符串的变量以不同方式存储,并且不占用 $STORAGE 中的空间。

  • 对象实例

每当实例化一个对象时,都会分配空间来保存对象的当前内容以及它所引用的对象。删除最后一个对象引用时返回该空间。

  • 本地 I/O 缓冲区

将与该进程正在使用的设备相关联的 I/O 缓冲区存储在进程空间中。

管理进程空间

进程从用于上述实体的初始内存池开始。当应用程序创建它们时,它们会消耗池中的内存;当应用程序删除它们时,它们的内存将返回到池中。例如,当一个例程开始执行时,总是会创建消耗一些内存的局部变量;当例程返回并且这些变量超出范围时,这些变量使用的内存将被返回并可供重用。

当应用程序需要内存,并且进程在其内存池中没有足够大(连续)的可用内存区域来满足需求时,该进程会从底层操作系统请求额外的内存块以添加到其池中。稍后,如果该内存块完全未使用,它将返回给操作系统。

0
0 166
文章 姚 鑫 · 七月 2, 2022 5m read

第十六章 字符串本地化和消息字典(二)

XML 消息文件

XML 消息文件是消息字典的导出。这也是希望导入的任何消息的必需格式。

只要有可能,XML 消息文件应该使用 UTF-8 编码。但是,在某些情况下,开发人员或翻译人员可能会使用本地平台编码,例如 shift-jis,以便于编辑 XML 消息文件。无论 文件使用何种编码,应用程序的语言环境都必须支持它,并且它必须能够表达该语言的消息。

消息文件可能包含一种语言和多个域的消息。

Element

元素是 XML 消息文件的顶级容器,每个文件只有一个 元素。

元素有一个必需的属性,Language。 属性的值是一个全小写的 代码,用于标识文件的语言。它由一个或多个部分组成:主要语言标签(例如 或 )可选地后跟连字符 () 和次要语言标签( 或 )。

在以下示例中,此语言为(英语)。

<?xml version="1.0" encoding="utf-8" ?>
<MsgFile Language="en">
   <MsgDomain Domain="sample">
       <Message Id="source">Source</Message>
       <Message Id="menu">Samples Menu</Message>
   </MsgDomain>
</MsgFile>
0
0 124
文章 姚 鑫 · 七月 1, 2022 4m read

第十五章 字符串本地化和消息字典(一)

本文概述了字符串本地化,并描述了如何导出、导入和管理消息字典。

字符串本地化

当本地化应用程序的文本时,会创建一种语言的文本字符串清单,然后当应用程序区域设置不同时,建立约定以另一种语言替换这些消息的翻译版本。

支持以下本地化字符串的过程:

  1. 开发人员在他们的代码中包含可本地化的字符串(在REST 应用程序或商业智能模型中)。

这种机制各不相同,但最常见的机制是 $$$Text 宏。代替硬编码的文字字符串,开发人员包含 $$$Text 宏的实例,为宏参数提供如下值:

  • 默认字符串
  • 此字符串所属的域(将字符串分组为域时,本地化更易于管理)
  • 默认字符串的语言代码
write "Hello world"

替换为

write $$$TEXT("Hello world","sampledomain","en-us")
  1. 编译代码时,编译器会在消息字典中为 $$$Text 宏的每个唯一实例生成条目。

消息字典是全局的,因此可以在管理门户中轻松查看(例如)。有一些类方法可以帮助完成常见任务。

  1. 开发完成后,发布工程师导出该域或所有域的消息字典。

结果是一个或多个 XML 消息文件,其中包含原始语言的文本字符串。

  1. 发布工程师将这些文件发送给翻译人员,请求翻译版本。

  2. 翻译人员使用他们喜欢的任何 XML 创作工具来处理 XML 消息文件。

0
0 189