面向 Jython 的 Web 服务框架简介-3 编写 Jython Web 服务客户端
 
- UID
- 1066743
|

面向 Jython 的 Web 服务框架简介-3 编写 Jython Web 服务客户端
编写 Jython Web 服务客户端您已经了解了如何在 Jython 中编写 Web 服务。现在,我们将展示如何编写一个 Jython 服务客户端来使用服务。客户端需要准备工作负载,向服务发送请求,然后接收并处理响应。在实现 Jython Web 服务时应遵循的步骤如下:
- 设定所需的请求负载和选项。可以使用纯文本或 WSMessage 的形式来设定所需的负载。
- 创建一个 WSClient 实例。您可以创建一个 WSClient 实例来使用服务。然后,通过构造函数的参数来设置选项。
- 发送请求和接收响应。调用 request() 方法,将消息作为参数传递。此方法将返回一个 WSMessage 实例,它代表响应消息。
- 使用响应。遵循客户端业务逻辑处理响应。
清单 5. 准备请求消息1
| req_message = WSMessage(req_payload_string, {"to" :END_POINT})
|
以上代码片段创建了一个 WSMessage 实例,并指定了将在请求和服务端点中发送的负载。选项散列的 "to" 元素将映射到服务的地址位置。换句话说,"to" 地址表示发送请求的目标位置。
清单 6. 发送请求和接收响应1
2
| client = WSClient({}, LOG_FILE_NAME)
res_message = client.request(req_message)
|
要发送请求连同之前创建的输入消息,我们需要一个 WSClient 实例。我们将需要发送给服务的消息传递给 request() 方法。这会发送包含在指定消息中的负载并接收响应,同时返回包含响应负载的消息实例。
通过 WSF/Jython API 使用 Web 服务的最低需求是负载和服务端点 URI。在上一节中,我们已经讨论了如何实现此任务。使用 WSF/Jython 扩展的优势是它并不是仅支持 SOAP。您在使用 Web 服务时还可以使用 WS-Addressing、MTOM 和 WS-Security 。您还可以采用 REST 的风格来调用服务。将这些选项关联到 WSMessage 和 WSClient 的方法如下。
使用 SOAP您可以使用 "use_soap" 选项在客户端的层面上指定所使用的 SOAP 版本。
清单 7. 使用 SOAP1
| client = WSClient({"use_soap" : "true"}, LOG_FILE_NAME)
|
使用 REST要实现使用 REST 风格调用的 Web 服务,可以将 "use_soap" 选项设置为 "false"。在 REST 风格的调用中,您可以使用 HTTP POST 方法或 HTTP GET 方法。
清单 8. 使用 REST1
2
3
4
5
6
7
8
9
10
11
| # REST with HTTP POST
client = WSClient({ "to" : END_POINT,
"http_method" : "POST",
"use_soap" : "false"},
LOG_FILE_NAME)
# REST with HTTP GET
client = WSClient({ "to" : END_POINT,
"http_method" : "GET",
"use_soap" : "false"},
LOG_FILE_NAME)
|
通过 MTOM 发送附件清单 9. 通过 MTOM 发送附件1
2
3
| req_message = WSMessage(req_payload_string, {"to" :END_POINT,
"attachments" : {"myid1" : "first attachment",
"myid2" : "second attachment"}})
|
在发送附件时,您可以配置客户端采用经过优化或未经优化的格式来发送附件。如果使用经过二进制优化的格式发送附件,则会使用 MIME 头部在 SOAP 主体外部按原样发送文件内容,并且负载将包含一个 XOP:Include 元素,用于指示包含二进制附件的 MIME 部分。如果采用未经二进制优化的格式,则附件内容将通过负载本身作为 base64 编码的字符串发送。
清单 10. 配置优化格式或未经优化的格式1
2
3
4
5
| # send attachments binary optimized
client = WSClient({"use_mtom" : "true"})
# send attachments binary non-optimized
client = WSClient({"use_mtom" : "false"})
|
使用 WS-Addressing在客户端上结合使用 WSF/Jython 和 WS-Addressing 时需要满足两个基本需求。其一是需要在提供一个消息级的 WS-Addressing 操作。其二是需要支持在客户端的层面上使用 WS-Addressing。
清单 11. WS-Addressing1
2
3
4
5
| req_message = WSMessage(req_payload_string,
{"to" : "http://localhost/echo_service_addr/echo",
"action" : "http://jython.wsf.wso2.org/samples/echoString"})
client = WSClient({"use_wsa" : "true"})
|
在以上示例代码片段中,WS-Addressing 操作是通过将选项字典中的 "action" 元素传递给 WSMessage 构造函数而设定的。传递给 WSClient 构造函数的 "use_wsa" 选项启用了 WS-Addressing。
除了操作之外,还可以在消息中发送其他与 WS-Addressing 相关的 SOAP 头部。WSF/Jython 支持这些头部在消息级作为属性使用,并在客户端级作为选项使用。下面提供了一个例子:
清单 12. 消息级的属性或客户端级的选项1
2
3
4
5
6
7
8
| req_message = WSMessage(req_payload_string,
{"to" : "http://www.company.com/order_processing/process",
"action" : "http://jython.wsf.wso2.org/samples/order",
"from" : "http://www.company.com/order_placing/place",
"reply_to" : "http://www.company.com/billing/bill",
"fault_to" : "http://www.company.com/re_odering/order"})
client = WSClient({"use_wsa" : "true"})
|
使用 WS-Security注意,要启动安全客户端或服务,您应该将 WS-Addressing 考虑在内,然后使用策略对象来创建客户端。
清单 13. WS-Security1
2
3
4
5
6
7
8
| req_message = WSMessage(req_payload_string,
{"to" : "http://localhost/samples/security_service/callback",
"action" : "http://jython.axis2.org/samples/echoString"})
client = WSClient({"use_wsa" : "true",
"policy" : "Policy_Path"})
res_message = client.request(req_message)
|
运行示例首先需要设置环境。将 Jython jar 和必要的 axis2 jar 添加到类路径。然后,将 WSF/Jython jar 添加到类路径。正确设置环境之后,您应该能够运行兼容 WSF/Jython API 规范的 Jython 脚本。WSF/Jython 随带的 shell 脚本可以帮助您设置此环境。只样,只需要提供它的绝对路径就可以执行客户端脚本。以下三个清单展示了一个例子。
清单 14. 运行示例的命令1
2
| sh wsfjython.sh /home/heshan/wsf-jython/jython/
distribution/target/wsf-jython-SNAPSHOT-bin/samples/amazon.py
|
清单 15. Amazon Web 服务客户端1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| from org.wso2.wsf.jython.client import WSClient
from org.wso2.wsf.jython.client import WSFault
from org.wso2.wsf.jython.client import WSMessage
req_payload_string = "<ItemSearch><Service>AWSECommerceService</Service>
<SearchIndex>Books</SearchIndex>
<AWSAccessKeyId>XXXXXXXXXXXXXXXXXXX</AWSAccessKeyId>
<Operation>ItemSearch</Operation>
<Keywords>sri lanka travel books</Keywords></ItemSearch>"
LOG_FILE_NAME = "/home/heshan/IdeaProjects/MRclient/src/python_amazon.log"
END_POINT = "http://webservices.amazon.com/onca/xml"
try:
client = WSClient({ "http_method" : "GET",
"use_soap" : "false"},
LOG_FILE_NAME)
req_message = WSMessage(req_payload_string, {"to" :END_POINT})
print " Sending OM : " , req_payload_string
res_message = client.request(req_message)
print " Response Message: " , res_message
except WSFault, e:
e.printStackTrace();
|
清单 16. 响应1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2005-10-05">
<OperationRequest>
<HTTPHeaders><Header Name="UserAgent" Value="Axis2" /></HTTPHeaders>
<RequestId>114HR356NB5H18RR5WNM</RequestId>
<Arguments><Argument Name="SearchIndex" Value="Books" />
<Argument Name="Service" Value="AWSECommerceService" />
<Argument Name="Keywords" Value="sri lanka travel books" />
<Argument Name="Operation" Value="ItemSearch" />
<Argument Name="AWSAccessKeyId" Value="XXXXXXXXXXXXXXXXXXX" />
</Arguments><Errors><Error>
<Code>AWS.InvalidParameterValue</Code>
<Message>XXXXXXXXXXXXXXXXXXX is not a valid value for AWSAccessKeyId.
Please change this value and retry your request.</Message>
</Error></Errors>
</OperationRequest>
</ItemSearchResponse>
|
|
|
|
|
|
|