0
回答
面向 Jython 的 Web 服务框架简介
滴滴云服务器,限时包月0.9元,为开发者而生>>>   

开源 SOA 公司 WSO2 推出的面向 Jython 的 Web 服务框架 (WSF/Jython) 提供了一种简单的在 Jython 中创建和使用 Web 服务的方法。此框架将 Apache Axis2 Web 服务引擎集成到了 Jython 中 ,从而将 Axis2 引擎的所有强大功能扩展到了 Jython。现在,只需少许代码,Jython 用户就可以在使用 Web 服务时获得面向服务的体系架构(Service-Oriented Architecture,SOA)的益处。使用 WSF/Jython 框架编写的 Web 服务客户端可以调用需要 WS-Security 的企业 Web 服务。WSF/Jython 还支持将二进制附件作为 MTOM 发送。

面向服务的体系架构是一种架构风格,用于指导创建松散耦合且独立于实现技术的协作式服务。SOA 概念是早期分布式和模块编程概念的扩展和延伸。在 SOA 模型中,功能可以分解成许多不同的单元,即服务。而服务又可以归类为一种自动计算操作,用于为内容提供计算逻辑。SOA 的基本元素就是服务。Web 服务是一种实现方法,它采用一些标准的协议来执行 SOA。Web 服务旨在将瓦解的中间件领域重新紧密连接在一起,使互操作性的重要性提升到首位。在迅速发展的云计算领域中,我们看到基于软件即服务(SaaS)、硬件即 服务(Haas)和平台即服务(Paas)的组件化软件生态系统是整个行业的发展趋势。因此,了解 SOA 的基本构成对于掌握云计算的概念至关重要。

要阅读本文,您应该掌握 Apache Axis2 的基本知识,以便更好地理解解决方案的体系结构。虽然具备 Axis2 知识是一项优势,但您也可以使用 WSF/Jython 来公开和使用 Jython Web 服务。

WSF/Jython 体系结构

Apache Axis2 是一种 SOAP 处理引擎。它接收传入的 SOAP 消息并检索其中的信息。此信息将提供给 Web 服务业务逻辑。然后,根据从业务逻辑获取的结果生成一条 SOAP 消息并将其返回给客户端。但是,如果业务逻辑包含在 Jython 中,则会产生一个问题。

针对需要在 Axis2 中公开 Jython Web 服务这一问题的解决方案蕴含在 Axis2 的可拔插式部署程序的概念中。部署程序支持通过 Axis2 的动态特性来部署服务。要公开使用 Jython 编写的公开,需要编写一个自定义部署程序和一个 Jython 消息接收程序。与 XML 模式中的静态数据类型不同,Python 数据类型是动态的。因此,在部署程序中,需要在 Python 数据类型与 XML 模式数据类型之间建立映射关系。此过程被称作数据绑定。然后,借助数据绑定和方法注释,为 Jython 服务生成一个 XML 模式。此 XML 模式连同与 Axis 服务相关的元数据将被传递给 Axis2 引擎。Axis2 引擎将创建 Web Service Description Language (WSDL),因此 Jython 将作为 Web 服务公开给外界。

此解决方案方法需要在 Jython 脚本和 Java™ 类之间进行通信。作为 Python 编程语言的 Java 实现,Jython 可以用实现此目的。它是一种编程混合体。它同时具备 Java 和 Python 的优势。由于 Jython 是完全使用 Java 编写的,因此使用 Jython 编写的脚本可以在任何兼容的 Java Virtual Machine (JVM) 上运行。Jython 解释器还支持许多快捷方式,这为它能够使用已有 Java 库提供了保障。

这种体系结构认为 SOAP 处理器应该两种基本操作:发送和接收 SOAP 消息。它提供了两个管道(或流)来执行这两种基本操作:这些管道用于发送和接收数据。Axis 引擎实现了这两个管道,分别是 In PipeOut Pipe。Complex Message Exchange Patterns (MEPs) 就是通过结合这两个管道而建立的。


图 1. WSF/Jython 体系结构
WSF/Jython 体系结构

SOAP 处理模型的可扩展性将通过处理程序体现出来。在处理 SOAP 消息时,所注册的处理程序将被执行。这些处理程序可以注册为全局、服务或操作作用域,并且最终的处理程序链将通过结合所有作用域的处理程序得出。

处 理程序的作用是充当拦截器。它们将处理 SAOP 消息的各部分,并提供增值服务。处理程序通常操作 SOAP 的头部,但它们也可以访问或更改 SOAP 的主体部分。

通过 Client API 发送 SOAP 消息时会激活 Out Pipe。Out Pipe 将调用处理程序,并通过 Transport Sender 将 SOAP 消息发送给目标端点。目标端点的 Transport Receiver 接收到 SOAP 消息之后将读取 SOAP 消息并启动 In Pipe。In Pipe 由一系列处理程序组成,而位于末端的是 Jython Message Receiver,它使用 SOAP 消息并将其传递给应用程序。

总的来说,传入的 SOAP 消息在被 Transport Listener 接收之后将在处理程序链上传递。然后,它被传递给 Jython Message Receiver,后者将遍历 AXIs Object Model (AXIOM) 结构并检索所需的信息。AXIOM 是为 Apache Axis2 开发的信息集模型。检索到的信息将被传递给 Jython 服务,该服务根据所返回的对象创建一个 AXIOM。然后,AXIOM 按原路经由处理程序链传回 Transport Sender。Transport Sender 又将 SOAP 消息发送给目标 SOAP 端点。上述过程适用于所有经过交换的 SOAP 消息。

WSF/Jython 特性

下面列出了 WSF/Jython 的服务器端和客户端特性。

服务器端特性

  • 支持使用 Jython 编写的服务

  • DataBinding 支持使用简单的注释机制

  • 自动 WSDL 生成

  • 支持将 Axis2 的所有企业特性公开给使用 Jython 编写的服务

客户端特性

  • 支持以简单、简洁的方式调用 Web 服务

  • 支持在调用服务时使用 WS-Addressing

  • 支持调用需要 WS-Security 的服务

  • 支持使用 MTOM 发送二进制附件

编写 Jython 服务

现在,我们将编写一个简单的 Jython 脚本,在其中实现一个名为 deduct 的操作。它接收两个输入变量,并返回这两个数值的差。由于我们需要执行 XML 模式生成,因此必须为 Jython 脚本添加注释。添加了注释的 Jython 方法如下例所示。


清单 1. 简单服务

				
#@annotate("returns=int", "operationName=deduct", var1="integer", var2="integer")
def deduct(var1,var2):
var3 = var1 - var2
return var3

 

在注释 Jython 脚本时应该遵循的步骤如下:

  1. 注释以 #@annotate 作为开头。
  2. 每个属性都应该包含在双引号中。
  3. return 属性应该与方法的返回类型相同。
  4. operationName 属性应该与方法的操作名称相同。
  5. 各输入参数应该有自己的变量名和值。
  6. 各参数应该有一个唯一的引用名。


清单 2. 注释

				
#@annotate("returns=int", "operationName=deduct", var1="integer", var2="integer")

 

使用限制

在部署 Jython 脚本时,必须遵循以下指导方针:

  1. 应依照上述注释机制对脚本进行注释。
  2. 参数名(引用变量)应该使用唯一的名称。
  3. 如果没有返回类型,则必须将它指定为 hashNone
  4. 在 axis.xml 中添加以下内容(清单 3):


清单 3. 添加到 axis.xml 中的内容

				

class="org.wso2.wsf.jython.deployer.JythonDeployer">

 

一个简单的服务

依照上述关于注释的说明,您可以编写一个简单的 Jython 服务(如下所示),并借助 Jython 部署程序将它公开为 Web 服务。


清单 4. 示例服务

				
#@annotate("returns=double", "operationName=f", a="double")
def f(a):
return a

#@annotate("returns=int", "operationName=add", var1="integer", var2="integer")
def add(var1,var2):
return var1+var2

#@annotate("returns=double", "operationName=deduct", var1="double", var2="double")
def deduct(var1,var2):
return var1-var2

#@annotate("returns=int", "operationName=addTwo", var1="integer", var2="integer",
var3=(a="string", b="integer"))
def addTwo(var1,var2,var3):
return var1+var2

#@annotate("returns=int", "operationName=doComplexStuff", var1="integer",
var2="(a="integer", b="integer")", var3="(a="string", b="integer")")
def doComplexStuff(var1,var2,var3):
return var1

class MyClass:
#@annotate("returns=integer", "operationName=MyClass.multiply", var1="integer",
var2="integer")
def multiply(var1,var2):
return var1*var2

 

编写 Jython Web 服务客户端

您已经了解了如何在 Jython 中编写 Web 服务。现在,我们将展示如何编写一个 Jython 服务客户端来使用服务。客户端需要准备工作负载,向服务发送请求,然后接收并处理响应。在实现 Jython Web 服务时应遵循的步骤如下:

  1. 设定所需的请求负载和选项。可以使用纯文本或 WSMessage 的形式来设定所需的负载。
  2. 创建一个 WSClient 实例。您可以创建一个 WSClient 实例来使用服务。然后,通过构造函数的参数来设置选项。
  3. 发送请求和接收响应。调用 request() 方法,将消息作为参数传递。此方法将返回一个 WSMessage 实例,它代表响应消息。
  4. 使用响应。遵循客户端业务逻辑处理响应。


清单 5. 准备请求消息

				
req_message = WSMessage(req_payload_string, {"to" :END_POINT})

 

以上代码片段创建了一个 WSMessage 实例,并指定了将在请求和服务端点中发送的负载。选项散列的 "to" 元素将映射到服务的地址位置。换句话说,"to" 地址表示发送请求的目标位置。


清单 6. 发送请求和接收响应

				
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. 使用 SOAP

				
client = WSClient({"use_soap" : "true"}, LOG_FILE_NAME)

 

使用 REST

要实现使用 REST 风格调用的 Web 服务,可以将 "use_soap" 选项设置为 "false"。 在 REST 风格的调用中,您可以使用 HTTP POST 方法或 HTTP GET 方法。


清单 8. 使用 REST

				
# 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 发送附件

				
req_message = WSMessage(req_payload_string, {"to" :END_POINT,
"attachments" : {"myid1" : "first attachment",
"myid2" : "second attachment"}})

 

在发送附件时,您可以配置客户端采用经过优化或未经优化的格式来发送附 件。如果使用经过二进制优化的格式发送附件,则会使用 MIME 头部在 SOAP 主体外部按原样发送文件内容,并且负载将包含一个 XOP:Include 元素,用于指示包含二进制附件的 MIME 部分。如果采用未经二进制优化的格式,则附件内容将通过负载本身作为 base64 编码的字符串发送。


清单 10. 配置优化格式或未经优化的格式

				
# 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-Addressing

				
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. 消息级的属性或客户端级的选项

				
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-Security

				
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. 运行示例的命令

				
sh wsfjython.sh /home/heshan/wsf-jython/jython/
distribution/target/wsf-jython-SNAPSHOT-bin/samples/amazon.py



清单 15. Amazon Web 服务客户端

				
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 = "AWSECommerceService
Books
XXXXXXXXXXXXXXXXXXX
ItemSearch
sri lanka travel books"
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. 响应

				



114HR356NB5H18RR5WNM






AWS.InvalidParameterValue
XXXXXXXXXXXXXXXXXXX is not a valid value for AWSAccessKeyId.
Please change this value and retry your request.



 

结束语

此框架集成了 Apache Axis2 引擎和 Jython,使您能够在 Jython 中利用 Apache Axis2 Web 服务中间件的各种强大功能。由于此框架支持代码优先的方法,因此只需少许代码,您就可以轻而易举地让客户端和服务正常运行。由于框架本身已集成到 Apache Axis2 中,因此您可以使用 Axis2 所支持的广泛功能。所支持的特性包括 MTOM、SOAP、REST 以及 WS-* 标准,比如 WS-Addressing 和 WS-Security。此外,它是一种开源发行版,因此您不需要支付许可或订阅费用。如果没有包含您所需的特性,那么可以通过邮件列表请求它,或者自己 设计并贡献给社区。

举报
红薯
发帖于8年前 0回/1K+阅
顶部