第 五 讲 Web 服务.

Slides:



Advertisements
Similar presentations
Web 服务 1/66 高级软件工程 第 五 讲 Web 服务. Web 服务 2/66 高级软件工程 内 容 一、 Web 服务简介 二、 SOAP 三、 WSDL 四、支持 Web 服务的 J2EE 应用.
Advertisements

1 Java 语言程序设计 计算机系 鲍金玲. 2 引子 甲骨文 甲骨文是全球最大的信息管理软件及服务供应商,成立于 1977 年,公司总部 设在美国加利福尼亚州的红木城( Redwood Shores ),全球员工达 名, 包括 名开发人员、 7500 多名技术支持人员和.
1 中 间 件 技 术中 间 件 技 术. 2 第 1 章 中间件产生背景及分布式计算环境 主要内容 开放系统 互操作性 中间件.
第 9 章 测试部署  9.1 测试  9.2 部署. 9.1 测试  应用测试:使用 JUnit 单元测试框架 测试的目的是检验开发结果是否满足规定需求,测试是保证软件质量的一个重要手段, 在软件开发过程中是不可缺少的组成部分。 单元测试与集成测试分别有各自的定义:在实际开发中,两者之间的界定是模糊的。
Java 程序设计 案例教程 北京大学出版社 第 01 章. Java 程序设计案例教程 第 01 章 Java 语言与面向对象程序设计 Java 语言的历史 Java 语言的特点 Java 程序的分类 Java 环境配置 Eclipse 的安装 Java 程序的调试 教学目标.
第四章 类、对象和接口.
第三讲 面向对象(上).
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
JAVA 编 程 技 术 主编 贾振华 2010年1月.
6. 6 Overloading methods and constructors 6
第 12 章 SOAP技術.
第16章 代理模式 Website:
Chapter 5: Service-Oriented Architectures for Distributed Computing 面向服务的分布式体系结构 1.
Web服务.
Java 2实用教程(第3版)教学课件 主讲教师:张国平
第一章 JSP概述.
Java程序设计教程 第一讲 Java概述.
四資二甲 第三週作業 物件導向程式設計.
通訊科技教育改進計畫 「網路應用與服務組」 行動電子商務課程 XML之簡介.
數位芝麻網路公司( 軟體工程師
《Java程序设计之网络编程》 教学课件 重庆大学计算机学院
MVC Servlet与MVC设计模式.
J2EE Struts 和Spring 的区别.
建设数字化的卫生监督体系 深 圳 市 卫 生 监 督 所 2006年4月.
大型主机应用上的开放系统和中间件 2011年度教育部-IBM精品课程
第二章 JAVA语言基础.
第1章 java简介及环境搭建 第1章 Java简介及开发环境搭建.
Microsoft .NET 第4組 十月15, 2002 B 陳東傑 B 蔣佳勳
JSP程式設計 基本概論 歐陽芳泉 Fang-Chuan Ou Yang
XML資料傳輸 黃笠宸 4/3.
J2EE 培训课程.
数据库操作示例 import java.sql.*; //导入java.sql包 public class JDBCDemo {
专题4:JSP脚本和指令.
例外處理(Exception Handling)
第五章 信息与系统集成技术 概述 数据流集成技术 信息流集成技术 信息管理集成技术 流程重组与业务流程集成 企业门户集成 企业集成架构
J2EE Course 2018/11/20.
Java基础 JavaSE异常.
JSP自定义标签技术的分析与应用 ----Custom Tag 的分析与应用
以多媒體簡訊服務及智慧型手機建置具物流管理之行動商務系統與 Web Service的應用
實作輔導 日期: 3/11 09:10~16:00 地點:臺北市立大學 臺北市中正區愛國西路一號 (中正紀念堂站7號出口)
崑山科技大學資訊管理系 伺服網頁程式設計 系統開發細部流程 教師:游峰碩.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
高级Web技术 复 习.
在一定程度上 人类的思维产生于 简单个体之间的相互作用 ——Marvin Minsky.
第5章 方案工程(Solutions Engineering)
Java语言程序设计 第五部分 Java异常处理.
JBOSS安装配置及WebWork的集成
王豐緒 銘傳大學資訊工程學系 問題:JAVA 物件檔輸出入.
2018/12/7 Java语言程序设计 教师:段鹏飞.
软件服务生态中的非确定性科学问题、互操作性的应用基础问题
第4章 商务逻辑层及其技术.
第 13 章 體驗Web Service.
第一讲 J2EE基础 博和利初级培训 —开发技能.
第11章 Android客户端与服务器交互.
C/C++/Java 哪些值不是头等程序对象
第11章 系统结构与包模型模型.
电子商务 王素凤
JAVA 编 程 技 术 主编 贾振华 2010年1月.
實作輔導 2 日期: 3/24(星期六) 09:10~16:00 地點:臺北市立大學 臺北市中正區愛國西路一號 (中正紀念堂站7號出口)
张孝祥IT课堂 -深入体验Java Web开发内幕
第十二章 过滤器.
Java程式初體驗大綱 大綱 在學程式之前及本書常用名詞解釋 Hello Java!程式 在Dos下編譯、執行程式
第二章 基于CORBA的分布式平台 苗启广 计算机学院.
Web Service 尹伟铭
第二章 Java基本语法 讲师:复凡.
第16章 天气预报 --Web Service调用
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
Android进程间通讯.
輸出執行結果到螢幕上 如果要將執行結果的文字和數值都「輸出」到電腦螢幕時,程式要怎麼寫? class 類別名稱 {
Presentation transcript:

第 五 讲 Web 服务

内 容 一、Web 服务简介 二、SOAP 三、WSDL 四、支持Web 服务的J2EE应用

一、Web 服务简介 2000年 Microsoft 等提出“Web Services” Web服务(Web Services) 是基于 XML 和 HTTP 的一种服务 服务访问协议: SOAP 服务的描述: WSDL 服务查找与发现: UDDI

SOAP (Simple Object Access Protocol) XML-based (text) 协议 支持远程通信 平台中立 WSDL (Web Services Definition Language) 接口描述 UDDI (Universal Description, Discovery, and Integration) 用于Web Services注册 用于发现Web Services

基本结构: 服务信息注册库 查找 注册 请求/应答 客户/服务请求者 服务提供者

提供了软件模块之间一种松耦合的交互方式 根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署、组合和使用 服务层是SOA的基础,可以直接被应用调用,从而 有效控制系统中与软件代理的人为依赖性 SOA的几个关键特性:一种粗粒度、松耦合服务架构,服务之间通过简单、精确定义适配器进行通讯,不涉及 底层编程适配器和通讯模型

RPC vs. Document RPC Document 耦合密切些 仅仅是调用 耦合松散些 需要额外的设计工作 相对脆弱 对应用修改适应性好 没有序列化/反序列化问题 需要额外的设计工作 需要解释客户消息内容,然后进行相应操作

考虑 Web Services的几个理由 业务上 技术上 管理上 需要与外部客户通信 应用需要与 其它语言编写的 客户程序通信 客户在防火墙之外 管理上 管理托管 web service 应用

什么时候不要使用Web Services 客户程序与应用使用相同语言编写 通信开销大 序列化或者远程访问开销大 Web Services/XML 处理开销大 “Don’t Use XML to Communicate Unless You Really, Really Have To” – Floyd Marinescu, The Middleware Company 永远记住:Web Services/XML 是用于集成的

典型的 Web 服务支持平台 Apache Axis (Apache eXtensible Interaction System) 是Apache WebService项目中的子项目 最初起源于IBM的"SOAP4J“ 最早的一批用于构造基于SOAP应用的Framework JBoss, WAS等重要的应用服务器都集成它

服务器端AXIS 句柄链处理架构 用户配置一系列的 handler,构成 handler chain AXIS 依次调用 handler 处理消息(含 context) 类似于 interceptor(截取器)

客户端AXIS 句柄链处理架构

AXIS的子系统

二、SOAP 1、SOAP概述 2、数据表示 3、消息格式 4、协议映射

1、SOAP概述 许多程序通过使用远程过程调用(RPC) 在诸如 DCOM 与 CORBA 等对象之间进行通信 防火墙和代理服务器通常会阻止此类流量 通过 HTTP 在应用程序间通信是更好的方法 因为 HTTP 得到了所有的因特网浏览器及服务器的支持 SOAP 就是被创造出来完成这个任务的

2000年5月,UserLand、Ariba、Commerce One、Compaq、Developmentor、HP、IBM、IONA、Lotus、Microsoft 以及 SAP 向 W3C 提交了 SOAP 因特网协议 期望此协议能够通过使用因特网标准(HTTP 以及 XML)把图形用户界面桌面应用程序连接到因特网服务器 首个关于 SOAP 的公共工作草案由 W3C 在 2001 年 12 月发布 SOAP 1.2 于 2003 年 6 月 被发布为 W3C 推荐标准

简单对象访问协议(SOAP) 是网络环境中交换信息的简单协议 为网络环境下软件之间结构化、类型化信息的交换 提供了一种基于XML的机制 它可以广泛地用于基于消息的系统和基于RPC的系统 SOAP被设计为可以与各种其它协议结合使用 但目前SOAP主要和HTTP及HTTP扩展框架相结合

简单地讲,SOAP= HTTP+RPC+ XML 以RPC作为一致性的调用途径 以XML作为数据传送的格式 SOAP的设计原则是: 简单、易于扩展 SOAP的设计忽略了如下几方面的功能: (1)分布式垃圾回收 (2)消息的批处理 (3)对象引用 (4)对象激活

2、数据表示 SOAP的数据表示完全不同于以往互操作协议的表示方法 以往的互操作协议都将调用语句编排为 二进制的字节流的形式 SOAP采用XML作为自己的数据表示方法 XML是与HTML类似的基于文本的标记语言 SOAP将调用语句编排为文本式的字符流的形式

3、消息格式 SOAP消息是一个XML文档 包括: 一个必需的SOAP封装 一个可选的SOAP头 一个必需的SOAP体

(1)SOAP封装 SOAP封装定义了描述信息和如何处理信息的框架 用于指定用XMLSchema来描述XML数据的编码规则 封装可以包含名域声明和附加属性 如果包含附加属性,这些属性必须限定名字域 类似的,“Envelope”可以包含附加子元素 这些也必须限定名字域且跟在SOAP体元素之后

(2)SOAP消息头 SOAP消息头是SOAP消息的可选部分 用来扩展其它诸如安全、事务等服务的重要机制

(3)SOAP体 SOAP体在SOAP消息中必须出现 且必须是SOAP封装元素的直接子元素 SOAP体可以包括多个条目

SOAP自然地遵循HTTP的请求/应答消息模型 表示通信状态信息的HTTP状态码的语义 例如,2xx状态码表示 这个包含了SOAP组件的客户请求 已经被成功的收到、理解和接受 下页的代码是一个使用POST的SOAP HTTP例子 该消息通过HTTP发出一条请求 “获取股票代码为ABC的最新交易价格”

POST /StockQuote HTTP/1.1 Host: www.stockquoteserver.com Content-Type: text/xml; charset="utf-8" Content-Length: nnnn SOAPAction: "Some-URI"   <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> <SOAP-ENV:Header> <t:Transaction xmlns:t="some-URI" SOAP-ENV:mustUnderstand="1"> 5 </t:Transaction> </SOAP-ENV:Header> <SOAP-ENV:Body> <m:GetLastTradePrice xmlns:m="Some-URI"> <symbol>ABC</symbol> </m:GetLastTradePrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

与其它协议的比较 1、互操作开销不同 IIOP、JRMP使用二进制的字节流形式编排消息 (CDR、XDR) SOAP采用字符型的XML编排消息 SOAP消息要比IIOP、JRMP消息长得多 SOAP的编排开销大、占用内存空间大 2、表达能力不同 SOAP易于学习、易于开发、易于调试 SOAP不支持消息的批处理、对象引用、对象激活等特性 降低了SOAP的表达能力 并使得基于SOAP的交互受到限制 而IIOP、JRMP等则不存在这种限制

3、适应能力不同 IIOP、JRMP严重制约于防火墙 防火墙一般由两个路由器与一个应用程序网关构成 路由器负责IP层的分组信息 列出可接受、禁止的源端和目标端等信息 应用程序网关在应用程序级进行控制 根据头信息字段、消息长度、消息内容等 决定传送还是丢弃消息 这是IIOP、JRMP的应用受到限制的核心因素之一 SOAP则基本不受其限制 4、适用环境不同 JRMP适用于使用JAVA的应用系统 IIOP、SOAP支持各种语言,因此适用面更广 IIOP适合于同一个防火墙内部之间的交互 而SOAP则适合于跨越防火墙的交互

三、WSDL 1、概述 2、文档结构 3、例子 4、向SOAP的映射

1、概述 WSDL(Web Services Description Language)是一个建议性标准 在Microsoft的SDL(Service Description Language和SCL(SOAP Contract Language)和IBM的NASSL(Network Accessible Service Specification Language)这两项技术的结合,形成了WSDL的基础 2000年9月25日IBM、Microsoft和Ariba提出WSDL1.0 2001年3月15日,他们提交的WSDL1.1成为W3C的Note 2002年7月9日提出 WSDL 1.2 2003年11月10日提出 WSDL 2.0

2、文档结构 WSDL 文档 抽 类型 象 定 义 消息 端口类型 操作 具 绑定 体 操作 说 明 服务 端口 代表依赖关系 代表包含关系

(1)抽象定义 类型:独立于计算机和语言的类型定义 使用某一类型系统(例如XSD)进行数据类型定义的容器 用于描述被交换的消息 消息:对通信数据的一个抽象、类型化定义 一个消息包含多个逻辑部分 每一个都与某一个类型系统中的定义相关联 包含函数参数(输入与输出分开)或文档说明 端口类型:由一个或多个端点支持操作的抽象集合 每个操作对应于一个输入消息与一个输出消息 它引用消息节中的消息定义来说明函数基调 操作名称、输入参数和输出参数 等

(2)具体说明 绑定:为一个由特定端口类型定义的操作与消息 指定具体的协议及数据格式规范 服务:指定每个绑定的端口地址

3、例子 <?xml version="1.0" encoding="UTF-8" ?> <definitions name="FooSample" <types> <schema targetNamespace="http://tempuri.org/xsd" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" elementFormDefault="qualified" > </schema> </types>  <message name="Simple.foo"> <part name="arg" type="xsd:int"/> </message> <message name="Simple.fooResponse"> <part name="result" type="xsd:int"/> <portType name="SimplePortType"> <operation name="foo" parameterOrder="arg" > <input message="wsdlns:Simple.foo"/> <output message="wsdlns:Simple.fooResponse"/> </operation> </portType> 

<binding name="SimpleBinding" type="wsdlns:SimplePortType"> <stk:binding preferredEncoding="UTF-8" /> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="foo"> <soap:operation soapAction="http://tempuri.org/action/Simple.foo"/> <input> <soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> </input> <output> <soap:body use="encoded" </output> </operation> </binding>  <service name="FOOSAMPLEService"> <port name="SimplePort" binding="wsdlns:SimpleBinding"> <soap:address location="http://carlos:8080/FooSample/FooSample.asp"/> </port> </service> </definitions>

用OMG-IDL表示为: interface FooSample { long foo(long arg); }

4、向SOAP的映射 对应的SOAP请求消息为: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <m:foo xmlns:m="http://tempuri.org/message/"> <arg>5131953</arg> </m:foo> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <SOAPSDK1:fooResponse mlns:SOAPSDK1="http://tempuri.org/message/"> <result>5131953</result> </SOAPSDK1:fooResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

与其它描述方法的比较 1、描述对象不同 有的以描述结构化程序的功能为主 例如 RPC-IDL 微软的-IDL 有的以描述对象的功能为主 例如 CORBA的IDL 有的以描述服务为主 例如 web service的WSDL

2、描述方式不同 有的以具体计算机语言的方式表达 例如SUN的Java Interface 有的以独立于具体的计算机语言 但十分类似于计算机语言的方式表达 例如:RPC-IDL 微软的-IDL CORBA的IDL 有的以XML为方式表达 例如:web service的WSDL

3、描述内容不同 有的仅描述接口的语法信息 例如:RPC-IDL 微软的-IDL CORBA的IDL 有的还包括与底层协议的绑定信息 例如:WSDL等 在CORBA中这部分信息包含在IOR中

四、支持Web 服务的J2EE应用 如何为 web 系统增加web services接口 下面模块可以暴露为 Web Services: EJB POJO 后面的例子针对 EJB

JAX-RPC: Java API for XML-based RPC Java世界的 web service 编程模型规范 如何以类似 RPC 的方式调用 web service JAX—RPC的客户端编程模式有以下的三种: Static stub(静态的客户端存根调用) Dynamic proxy (部分动态的代理调用) Dynamic invocation interface (DII)(动态调用接口)

三种JAX—RPC的客户端编程模式

Static stub 1) 首先通过映射转换将服务描述的WSDL文档生成客户端的Java stub 2) 然后实例化服务的locator实例 3) 通过loacator获得服务在客户端的代理 4) 用客户端代理 去调用服务

package itso.test; import java.io.*; import java.util.*; import itso.test.*; public class WeatherForecastClient { public static void main(String [] args) { try{ WeatherForecastServiceLocator wsl = new WeatherForecastServiceLocator(); WeatherForecastService ws = (WeatherForecastService) wsl.getWeather(); String temperature = ws.getTemperature(); System.out.println(temperature); System.out.println("WeatherForecastClient completed"); } catch (Exception e) { e.printStackTrace(); }

Dynamic proxy 与Static stub 不同的是可以指定生成的客户端代理 import javax.xml.namespace.QName; import java.io.*; import java.util.*; public class WeatherForecastDynamicProxyClient { public static void main(String [] args){ try{ WeatherForecastServiceLocator wsl = new WeatherForecastServiceLocator(); QName qn = new QName("http://www.somewhere.com", "WeatherForecast"); WeatherForecast ws = (WeatherForecast) wsl.getPort(qn,WeatherForecast.class); String temperature = ws.getTemperature(); System.out.println(temperature); System.out.println("DynamicProxyJavaClient completed"); } catch (Exception e){ e.printStackTrace(); } }

一个汽车网站的例子 例子构成: 暴露对象: InventoryFacadeBean.findAllAvailableCars() JSPs Controller Servlet Stateless Session Bean – InventoryFacadeBean Hibernate DAOs 暴露对象: InventoryFacadeBean.findAllAvailableCars()

服务端点接口 将业务方法暴露为Web Services 类似于服务器端的 stub 类似于 EJB Remote Interface package com.jbossatwork.ws; /** * Service endpoint interface for InventoryFacade. */ public interface InventoryEndpoint extends java.rmi.Remote{ public com.jbossatwork.ws.CarDTOArray findAvailableCars() throws java.rmi.RemoteException; } // InventoryEndpoint.java

修改 ejb-jar.xml <enterprise-beans> … <session> <display-name>InventoryFacadeSB</display-name> <ejb-name>InventoryFacade</ejb-name> <service-endpoint> com.jbossatwork.ws.InventoryEndpoint </service-endpoint> </session> </enterprise-beans>

webservices.xml 定义并注册 InventoryService Web Service 将Service Endpoint Interface class 绑定到InventoryFacadeBean EJB 告诉 J2EE app server 到哪里找WSDL 与JAX-RPC 映射文件(Mapping files, in EJB JAR file)

<?xml version="1.0" encoding="UTF-8"?> <webservices xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd" version="1.1"> <webservice-description> <webservice-description-name> InventoryService </webservice-description-name> <wsdl-file>META-INF/wsdl/InventoryService.wsdl</wsdl-file> <jaxrpc-mapping-file> META-INF/inventory-mapping.xml </jaxrpc-mapping-file> <port-component> <port-component-name>Inventory</port-component-name> <wsdl-port>InventoryEndpointPort</wsdl-port> <service-endpoint-interface> com.jbossatwork.ws.InventoryEndpoint </service-endpoint-interface> <service-impl-bean> <ejb-link>InventoryFacade</ejb-link> </service-impl-bean> </port-component> </webservice-description> </webservices>

JAX-RPC 映射文件 帮助 JAX-RPC 编译器将Java 对象映射到WSDL 对象 复杂的Java 对象导致复杂的JAX-RPC 与WSDL 文件

<?xml version="1.0" encoding="UTF-8"?> <java-wsdl-mapping xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://www.ibm.com/webservices/xsd/j2ee_jaxrpc_mapping_1_1.xsd" version="1.1"> <package-mapping> <package-type>com.jbossatwork.ws</package-type> <namespaceURI>http://localhost:8080/jbossatwork-ws/types</namespaceURI> </package-mapping> <namespaceURI>http://localhost:8080/jbossatwork-ws</namespaceURI> <java-xml-type-mapping> <java-type>com.jbossatwork.dto.CarDTOArray</java-type> <root-type-qname xmlns:typeNS="http://localhost:8080/jbossatwork-ws/types"> typeNS:CarDTOArray </root-type-qname> <qname-scope>complexType</qname-scope> <variable-mapping> <java-variable-name>cars</java-variable-name> <xml-element-name>cars</xml-element-name> </variable-mapping> </java-xml-type-mapping>

<java-xml-type-mapping> <java-type>com.jbossatwork.dto.CarDTO</java-type> <root-type-qname xmlns:typeNS="http://localhost:8080/jbossatwork-ws/types"> typeNS:CarDTO </root-type-qname> <qname-scope>complexType</qname-scope> <variable-mapping> <java-variable-name>id</java-variable-name> <xml-element-name>id</xml-element-name> </variable-mapping> <java-variable-name>make</java-variable-name> <xml-element-name>make</xml-element-name> <java-variable-name>model</java-variable-name> <xml-element-name>model</xml-element-name> <java-variable-name>modelYear</java-variable-name> <xml-element-name>modelYear</xml-element-name>

<variable-mapping> <java-variable-name>status</java-variable-name> <xml-element-name>status</xml-element-name> </variable-mapping> </java-xml-type-mapping> <service-interface-mapping> <service-interface>com.jbossatwork.ws.InventoryService</service-interface> <wsdl-service-name xmlns:serviceNS="http://localhost:8080/jbossatwork-ws"> serviceNS:InventoryService </wsdl-service-name> <port-mapping> <port-name>InventoryEndpointPort</port-name> <java-port-name>InventoryEndpointPort</java-port-name> </port-mapping> </service-interface-mapping>

<service-endpoint-interface-mapping> com.jbossatwork.ws.InventoryEndpoint </service-endpoint-interface> <wsdl-port-type xmlns:portTypeNS="http://localhost:8080/jbossatwork-ws"> portTypeNS:InventoryEndpoint </wsdl-port-type> <wsdl-binding xmlns:bindingNS="http://localhost:8080/jbossatwork-ws"> bindingNS:InventoryEndpointBinding </wsdl-binding> <service-endpoint-method-mapping> <java-method-name>findAvailableCars</java-method-name> <wsdl-operation>findAvailableCars</wsdl-operation> <wsdl-return-value-mapping> <method-return-value>com.jbossatwork.dto.CarDTOArray</method-return-value> <wsdl-message xmlns:wsdlMsgNS="http://localhost:8080/jbossatwork-ws"> wsdlMsgNS:InventoryEndpoint_findAvailableCarsResponse </wsdl-message> <wsdl-message-part-name>result</wsdl-message-part-name> </wsdl-return-value-mapping> </service-endpoint-method-mapping> </service-endpoint-interface-mapping> </java-wsdl-mapping>

WSDL File <?xml version="1.0" encoding="UTF-8"?> <definitions name="InventoryService" targetNamespace="http://localhost:8080/jbossatwork-ws" xmlns:tns="http://localhost:8080/jbossatwork-ws" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://localhost:8080/jbossatwork-ws/types" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"> <types> <schema targetNamespace="http://localhost:8080/jbossatwork-ws/types" xmlns:tns=http://localhost:8080/jbossatwork-ws/types xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://www.w3.org/2001/XMLSchema"> <complexType name="CarDTOArray"> <sequence> <element name="cars" type="tns:CarDTO" nillable="true" minOccurs="0" maxOccurs="unbounded"/></sequence> </complexType>

<complexType name="CarDTO"> <sequence> <element name="id" type="int"/> <element name="make" type="string" nillable="true"/> <element name="model" type="string" nillable="true"/> <element name="modelYear" type="string" nillable="true"/> <element name="status" type="string" nillable="true"/> </sequence> </complexType> </schema> </types> <message name="InventoryEndpoint_findAvailableCars"/> <message name="InventoryEndpoint_findAvailableCarsResponse"> <part name="result" type="ns2:CarDTOArray"/></message> <portType name="InventoryEndpoint"> <operation name="findAvailableCars"> <input message="tns:InventoryEndpoint_findAvailableCars"/> <output message="tns:InventoryEndpoint_findAvailableCarsResponse"/> </operation> </portType>

<binding name="InventoryEndpointBinding" type="tns:InventoryEndpoint"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/> <operation name="findAvailableCars"> <soap:operation soapAction=""/> <input> <soap:body use="literal" namespace="http://localhost:8080/jbossatwork-ws"/> </input> <output> </output> </operation> </binding> <service name="InventoryService"> <port name="InventoryEndpointPort" binding="tns:InventoryEndpointBinding"> <soap:address location="REPLACE_WITH_ACTUAL_URL"/> </port> </service> </definitions>

修改 WSDL URL <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 4.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd"> <jboss> <enterprise-beans> … <session> <ejb-name>InventoryFacade</ejb-name> <port-component> <port-component-name>Inventory</port-component-name> <port-component-uri> jbossatwork-ws/InventoryService </port-component-uri> </port-component> </session> </enterprise-beans> </jboss>

修改 EJB /** * @ejb.bean * name="InventoryFacade" * … * view-type="all" * … * view-type="all" * … * * @wsee.port-component * name="Inventory" * wsdl-port="InventoryEndpointPort" * service-endpoint-interface="com.jbossatwork.ws.InventoryEndpoint" * service-endpoint-bean="com.jbossatwork.ejb.InventoryFacadeBean" * @ejb.interface * service-endpoint-class="com.jbossatwork.ws.InventoryEndpoint" */ public class InventoryFacadeBean implements SessionBean { …

/** * @ejb.interface-method * view-type="all" * … * */ public CarDTOArray findAvailableCars() throws EJBException { CarDTOArray carDTOArray = new CarDTOArray(); CarDTO[] cars = (CarDTO[]) listAvailableCars().toArray(new CarDTO[0]); carDTOArray.setCars(cars); return carDTOArray; } * view-type="both" public List listAvailableCars() throws EJBException { …

Web Services 与 Collections WSDL/XSD 不懂 Java Collections package com.jbossatwork.dto; import java.io.Serializable; import com.jbossatwork.dto.CarDTO; public class CarDTOArray implements Serializable { private CarDTO[] cars; public CarDTOArray() {} public CarDTO[] getCars() { return cars; } public void setCars(CarDTO[] cars) { this.cars = cars;

EJB JAR 文件结构 META-INF/ com/jbossatwork/ws/ ejb-jar.xml jboss.xml webservices.xml inventory-mapping.xml (JAX-RPC Mapping File) wsdl/ InventoryService.wsdl com/jbossatwork/ws/ InventoryEndpoint.class

客户端:产生 Web Service Proxy 代码 <path id="axis.classpath"> <fileset dir="${axis.lib.dir}"> <include name="**/*.jar"/> </fileset> </path> … <target name="run-wsdl2java" description="Generates WS proxy code from WSDL"> <path id="wsdl2java.task.classpath"> <path refid="axis.classpath"/> <wsdl2java output="${gen.source.dir}" url="InventoryService.wsdl" verbose="true"> <mapping namespace="http://localhost:8080/jbossatwork-ws" package="com.jbossatwork.client"/> <mapping namespace="http://localhost:8080/jbossatwork-ws/types" </wsdl2java> </target>

客户代码( J2SE 1.4 ) package com.jbossatwork.client; public class MyAxisClient { public static void main(String [] args) { try { System.out.println("Finding InventoryService ...\n"); InventoryService service = new InventoryServiceLocator(); System.out.println("Getting InventoryEndpoint ...\n"); InventoryEndpoint endpoint=service.getInventoryEndpointPort(); System.out.println("Getting Cars ..."); CarDTOArray carDTOArray = endpoint.findAvailableCars(); CarDTO[] cars = carDTOArray.getCars(); for (int i = 0; i < cars.length; ++i) { System.out.println( "Year = [" + cars[i].getModelYear() + "], Make = [" + cars[i].getMake() + "], Model = [" + ars[i].getModel() + "], status = [" + cars[i].getStatus() + "]"); } } catch(Exception e) { e.printStackTrace(); 客户代码( J2SE 1.4 )