几年来,IBM i用户已经能够使用操作系统的一部分针对IBM i支持的集成Web服务服务器,基于SOAP协议将ILE程序和服务程序作为Web服务部署为Web服务。 仅仅一年多的时间,用户就可以将ILE程序和服务程序部署为RESTful Web服务。
2015年7月,进行了一系列增强,以消除将ILE程序对象作为Web服务部署到集成Web服务服务器时的一些细微差别和局限性。 已进行以下更新:
- 支持嵌套输出数组
- 改进对非常大的输出字符字段的处理
- 保留标识符的区分大小写
- 保留现场订购
- 允许RESTful服务返回用户定义的媒体类型
- 允许将新的传输元数据值传递到Web服务
- 安装针对SOAP服务更新的Web服务脚本
- 允许基于Java™的Web服务
为了获取更新,您将需要加载最新的超文本传输协议(HTTP)组程序临时修订(PTF)。 表1列出了IBM i操作系统的每个受支持版本所需要的HTTP组PTF。
表1.软件先决条件
IBM i发布 | HTTP组PTF |
---|---|
我7.2 | SF99713(9级或更高) |
我7.1 | SF99368(级别35或更高) |
我6.1 | SF99115(45级或更高) |
请注意,本文中讨论的所有更新都适用于集成Web服务服务器2.6或更高版本,但安装Web服务脚本增强功能除外,该功能适用于服务器的所有版本。 此外,REST更新不适用于IBM i 6.1版本,因为6.1不支持REST。
支持嵌套输出数组
一直存在这样的情况,在ILE程序对象(即程序或服务程序)的Web服务部署期间,您可以将整数类型的参数指定为变量,该变量指示要在其中返回多少个元素。输出参数,其中输出参数是数组。 例如,清单1显示了一个简单的RPG过程,该过程具有三个参数: requestCount
, array_LENGTH
和array
。 第一个参数requestCount
是一个输入参数,指示应返回多少个元素。 第二个参数array_LENGTH
是一个输出参数,指示实际返回了多少个元素。 第三个参数array
是一个输出参数,它是一个大小为10的数组,其中包含要返回的元素。
清单1.以数组为参数的RPG过程
h nomain PGMINFO(*PCML:*MODULE:*DCLCASE)
D rpgarray Pr
D requestCount...
D 10i 0
D array_LENGTH 10i 0
D array 20 DIM(10)
P rpgarray B EXPORT
D Pi
D requestCount...
D 10i 0
D array_LENGTH 10i 0
D array 20 DIM(10)
D i S 10i 0
/Free
if (requestCount < 0 or requestCount > 10);
requestCount = 0;
endif;
array_LENGTH = requestCount;
clear array;
for i = 1 to requestCount;
array(i) = 'element-' + %CHAR(i);
endfor;
return;
/End-Free
p rpgarray e
部署服务程序时,将显示一个Web面板(请参见图1),要求您指定要输入的参数和要输出的参数。
图1.部署新服务-导出过程以外部化为Web服务
从图1可以看出,有一个Count列,您可以在其中指示包含数组中元素实际数量的参数。 默认情况下,它设置为阵列的最大大小。 如果我们按原样部署服务程序并调用Web服务,则返回的XML文档将包括数组中的所有元素,即使我们只是要求返回2(请参见清单2)。
清单2.未设置计数的SOAP响应
<soap:Body>
<ns2:rpgarrayResponse xmlns:ns2="http://rpgarray.wsbeans.iseries/">
<return>
<array>element-1</array>
<array>element-2</array>
<array/>
<array/>
<array/>
<array/>
<array/>
<array/>
<array/>
<array/>
<array_LENGTH>2</array_LENGTH>
</return>
</ns2:rpgarrayResponse>
</soap:Body>
现在,如果我们重新部署服务程序并指定一个指示输出数组中实际元素数量的参数,如图2所示,您将看到一个响应,其中不包含清单2中的空元素。
图2.部署新服务-导出过程以外部化为具有计数集的Web服务
需要注意的是,您只能对程序或过程参数执行此操作。 让我们看一下清单3中的示例,它是对清单1中所示示例的略微修改。
清单3.将数组作为数据结构中的字段的RPG过程
h nomain PGMINFO(*PCML:*MODULE:*DCLCASE)
D arrayOfStrDS DS qualified template
D array_LENGTH 10i 0
D array 20 DIM(10)
D rpgarray2 Pr
D requestCount...
D 10i 0
D arrayOfStr likeds(arrayOfStrDS)
P rpgarray2 B EXPORT
D Pi
D requestCount...
D 10i 0
D arrayOfStr likeds(arrayOfStrDS)
D i S 10i 0
/Free
if (requestCount < 0 or requestCount > 10);
requestCount = 0;
endif;
arrayOfStr.array_LENGTH = requestCount;
clear arrayOfStr.array;
for i = 1 to requestCount;
arrayOfStr.array(i) = 'element-' + %CHAR(i);
endfor;
return;
/End-Free
p rpgarray2 e
所做的更改是使array_LENGTH
和arrayOf
Str
DS
结构中的array
子字段以及输出参数arrayOfStr
定义为arrayOf
StrDS
类型的参数。 现在,当我们尝试部署服务程序时,由于数组不是第一级参数,因此无法设置count字段,如图3所示。
图3.部署新服务–导出过程以外部化为Web服务,并且输出参数是一个结构
如果调用Web服务,则响应将包含空元素,如清单4所示。
清单4. SOAP响应输出结构和计数未设置
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:rpgarray2Response xmlns:ns2="http://rpgarray2.wsbeans.iseries/">
<return>
<arrayOfStr>
<array>element-1</array>
<array>element-2</array>
<array/>
<array/>
<array/>
<array/>
<array/>
<array/>
<array/>
<array/>
<array_LENGTH>2</array_LENGTH>
</arrayOfStr>
</return>
</ns2:rpgarray2Response>
</soap:Body>
</soap:Envelope>
至少可以说不是很好。 好了,现在已经解决了!
在指示输入哪些参数和输出哪些参数的面板中,有一个新的复选框字段(请参见图4),默认情况下已选中“ 检测长度字段” 。
图4.部署新服务并选择“检测长度”字段
选择“ 检测长度”字段时 ,将假定紧跟在数组字段之后且名称与_LENGTH
附加的数组字段同名的所有整数(int)字段将是一个长度字段,用于指示元素的实际数量在数组中。 在此实例中,阵列场标识符被命名为array
,那么该阵列字段长度将是a
rray_LENGTH
。 另一个好处是,长度字段对客户端是隐藏的,并且不会在客户端响应中返回。 清单5显示了选择“ 检测长度”字段时的响应。
清单5.选择了“检测长度”字段的SOAP响应输出结构
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:rpgarray2Response xmlns:ns2="http://rpgarray2.wsbeans.iseries/">
<return>
<arrayOfStr>
<array>element-1</array>
<array>element-2</array>
</arrayOfStr>
</return>
</ns2:rpgarray2Response>
</soap:Body>
</soap:Envelope>
注意 :如果选择了“ 检测长度”字段 ,则只能指定输入或输出参数,而不能指定输入输出参数。 此外,还支持保留参数顺序和标识符的区分大小写,这将在本文后面讨论。
改进对非常大的输出字符字段的处理
长度字段支持已扩展到字符字段。 输出字符字段很大(我说的是1000个字节)需要花费一些时间来处理,因为确定返回的字符串大小是通过一次从右到左遍历一个字节来完成的,第一个非空白字符。
为了改善对这些大字符字段的处理,您可以指定一个整数(int)字段长度,该长度紧接在字符字段之前,其名称与后面加上_LENGTH
的字符字段_LENGTH
(类似于处理具有字段长度的输出数组时所做的操作)。 如果存在字段长度,并且选择了“ 检测长度”字段 ,则不会遍历该字段来确定大小,从而提高了性能。 此外,长度字段对客户端是隐藏的,并且不会在客户端响应中返回。
保留标识符的区分大小写
过去,编译器生成了程序调用标记语言(PCML)文档,并将其存储在ILE模块对象中,标识符完全大写。 因此,SOAP和REST请求和响应中的标识符必须大写。 2014年下半年,RPG编译器进行了增强,在生成PCML文档时保留了标识符的大小写。 这允许集成的Web服务在一定程度上保留标识符大小写。 根据过程名称,结构名称和结构中的字段名称生成XML元素名称和JSON字段名称的标识符。 除非前两个字符是大写的,否则标识符中的第一个字符将从大写更改为小写,在这种情况下,标识符将保留不变。
如果选中“ 检测长度字段”复选框,那么将使用ILE程序对象中定义的标识符名称。 例如,如果标识符以大写字母开头,后接小写字母,则XML或JSON文档中的标识符也将以大写字母开头,后接小写字母。 如果未选择“ 检测长度”字段 ,则标识符将以小写字母开头。
保留现场订购
在最新的集成Web服务更新之前,部署ILE程序或服务程序时,不会保留参数字段和结构内字段的顺序,并且在大多数情况下,该顺序是基于字母顺序的(有时是基于某种顺序的)我什至无法理解!)。 以清单6中所示的RPG过程为例。
清单6.说明字段顺序的RPG过程
h nomain PGMINFO(*PCML:*MODULE:*DCLCASE)
D ordertest Pr
D oneParam 10i 0
D twoParam 10i 0
D threeParam 10i 0
P ordertest B EXPORT
D Pi
D oneParam 10i 0
D twoParam 10i 0
D threeParam 10i 0
/Free
oneParam = 1;
twoParam = 2;
threeParam = 3;
return;
/End-Free
p orderTest e
如果部署了服务程序,并且将所有三个参数都指定为输出参数,则您可能会认为XML响应将按以下顺序包括三个参数: oneParam
, twoParam
和threeParam
。 但是,清单7中显示了返回的SOAP XML响应。
清单7. SOAP XML响应–无序字段
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<a:ordertestResponse xmlns:a="http://ordertest.wsbeans.iseries/">
<return>
<twoParam>2</twoParam>
<oneParam>1</oneParam>
<threeParam>3</threeParam>
</return>
</a:ordertestResponse>
</soap:Body>
</soap:Envelope>
如果选中了“ 检测长度字段”复选框,那么将保留顺序,清单8中将显示您将获得的响应。
清单8. SOAP XML响应–有序字段
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<a:ordertestResponse xmlns:a="http://ordertest.wsbeans.iseries/">
<return>
<oneParam>1</oneParam>
<twoParam>2</twoParam>
<threeParam>3</threeParam>
</return>
</a:ordertestResponse>
</soap:Body>
</soap:Envelope>
允许RESTful服务返回用户定义的媒体类型
添加了支持以允许RESTful服务返回用户定义的内容。 在进行此增强之前,返回的响应可能是XML或JSON内容。
要返回用户定义的媒体类型,必须有一个输出参数(如果选择了“ 检测长度”字段 ,则必须有两个,而一个参数是另一个参数的字段长度,必须是字符类型)。 输出参数必须是原始类型,例如integer,char,float等。 在大多数情况下,输出参数将为字符类型。 设置了REST属性的部署面板已更新,以允许设置用户定义的媒体类型。 在图2中,您可以看到为输出媒体类型设置了plain/html
的面板。 这意味着程序将返回一个包含HTML文档的字符串。
图5.部署新服务-设置REST属性
通过确保每种媒体类型都用逗号分隔,可以指定多个媒体类型值。 如果指定了多个,则ILE程序对象将需要根据返回的内容将HTTP标头的content-type字段设置为适当的值。 要了解如何设置HTTP标头,请参阅使用适用于IBM i的集成Web服务服务器构建REST服务,第3部分 。
允许将新的传输元数据值传递到Web服务
在进行增强之前,可以将REMOTE_ADDR(客户端的远程地址)传输元数据值作为环境变量传递到ILE Web服务实现代码。 添加了其他传输元数据值:
- QUERY_STRING:返回路径后面的请求URL中包含的查询字符串。
- REQUEST_METHOD:返回发出此请求的HTTP方法的名称,例如GET,POST或PUT。
- REQUEST_URI:返回此请求的URL的一部分,从协议名称到HTTP请求第一行中的查询字符串。
- REQUEST_URL:重建客户端用于发出请求的URL。
- SERVER_NAME:返回请求发送到的服务器的主机名。 它是
Host
头值(如果有)中“:”之前的部分的值,或者是解析的服务器名称或服务器IP地址。 - SERVER_PORT:返回请求发送到的端口号。 它是
Host
头值(如果有)中“:”之后的部分的值,或者是接受客户端连接的服务器端口。
注意 :如果在应用包括集成Web服务更新的HTTP组PTF之前部署了Web服务,则您将需要重新部署Web服务,以便将新的传输元数据传递到Web服务实现代码。
安装针对SOAP服务更新的Web服务脚本
已对installWebservice.sh QShell脚本(位于/ qibm / proddata / os / webservices / bin中)进行了增强,以便您现在可以在部署时部署ILE程序对象并指定参数用法(即输入,输出和输入输出) SOAP服务。 parameterUsage
选项是用冒号分隔的列表,其中包含与要部署的过程或程序相对应的参数使用值。 对于每个程序或过程,您需要指定过程或程序名称,后跟一个冒号,然后是一个逗号分隔的用法描述符列表(“ i”表示输入,“ o”表示输出,或“ io”表示输入输出)对于每个参数。 例如,如果服务程序包含两个过程,即带有两个参数的“ PROC1”和带有三个参数的“ PROC2”,则可能的值为:
-parameterUsage PROC1:i,o:PROC2:i,i,io
请注意,只有列出的那些过程将被外部化为Web服务操作。 此参数是可选的。 如果未指定,则默认为使用在与程序对象关联的PCML中指定的参数使用值。
另外,您现在可以指示是否要将Web服务部署为SOAP 1.1或SOAP 1.2 Web服务。 本-
serviceType
选择要安装服务的类型。 *SOAP11
或*SOAP12
值指示应分别将程序对象作为SOAP 1.1或SOAP 1.2服务安装。 此参数是可选的。 如果未指定,则使用默认值*SOAP11
。
允许基于Java的Web服务
我已将这些信息作为集成的Web服务服务器更新的一部分包括在内,但实际上,它是集成的应用程序服务器中的增强功能。 集成的Web服务服务器将始终是可用于将ILE程序和服务程序部署为Web服务的服务器。 但是,我们意识到用户需要将Java Web服务部署到服务器,因此对集成应用程序服务器进行了增强,使您可以在集成应用程序服务器中启用JAX-WS和JAX-RS功能。 启用这些功能后,可以将JAX-WS和JAX-RS Web服务部署到服务器。
要启用该功能,请转至IBM Web Administration GUI,然后选择集成的应用程序服务器(必须为8.5或更高版本)。 如果你点击在S erver性能在导航面板链接,将显示包含各种选项卡页面。 在“ 功能”选项卡上,您将找到可以为服务器启用的各种功能,如图6所示。
图6.集成应用程序服务器的“功能”选项卡
如果要部署基于JAX-WS的SOAP Web服务,则可以选择jaxws-2.2(基于XML的Web服务2.2的Java API)功能,然后单击指向右侧的双向箭头,然后单击单击确定或应用。 如果要基于JAX-RS部署REST Web服务,您将做相同的事情,除了要添加的功能是jaxrs-1.1(RESTful Web Services 1.1的Java API)。
摘要
集成的Web服务服务器支持为基于ILE程序或IBM i平台上的服务程序创建和部署Web服务奠定了坚实的基础。 您现在也可以将基于Java的Web服务部署到集成的应用程序服务器中! 我们一直在努力改善集成的Web服务体验,我们希望收到您的来信。
翻译自: https://www.ibm.com/developerworks/ibmi/library/i-integrated-web-services-server/index.html