WebService CXF学习

更新时间:2024-01-28 14:50:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

WebService CXF学习(入门篇1):CXF由来

WebService介绍

WebService让一个程序可以透明地调用互联网程序,不用管具体的实现细节。只要WebService公开了服务接口,远程客户端就可以调用服务。WebService是基于http协议的组件服务,WebService是分散式应用程序的发展趋势。

WebService的开源实现

WebService更多是一种标准,而不是一种具体的技术。不同的平台,不同的语言大都提供WebService的开发实现。在JAVA领域,WebService的框架很多,例如:AXIS,XFire,CXF等。AXIS,XFire相对比较成熟,资料相对较多。在这里我们只对CXF进行讲解,其他大家想学习到互联网找相关资料学习。

CXF框架由来

ApacheCXF项目是由ObjectWeb Celtix和CodeHaus XFire合并成立。ObjectWeb Celtix是由IONA公司赞助,于2005年成立的开源Java ESB产品,XFire则是业界知名的SOAP堆栈。合并后的ApacheCXF融合该两个开源项目的功能精华,提供了实现SOA所需要的核心ESB功能框架,包括SOA服务创建,服务路由,及一系列企业级QoS功能。

ApacheCXF架框的目标 1.概述 <>高性能 <>可扩展 <>直观易用 2.支持标准

<> JAX-WS, JSR-181, SAAJ, JAX-RS

<> SOAP 1.1, 1.2, WS-I BasicProfile, WS-Security, WS-Addressing, WS-RM, WS-Policy <> WSDL 1.1 <> MTOM

3.传输方式,绑定,数据绑定,传送数据格式 <> 绑定: SOAP, REST/HTTP

<> 数据绑定: JAXB 2.x, Aegis, XMLBeans, SDO <> 传送数据格式: XML, JSON, FastInfoset <> 传输方式: HTTP, Servlet, JMS 4.部署灵活

<> 轻量级: 可以将服务部署到 Tomcat或其支持Spring的容器中

<> JBI整合: 部署一个服务引擎到JBI容器,例如: ServiceMix, OpenESB or Petals

<> J2EE集成: 可以将服务部署到J2EE应用服务器上,例如:Geronimo, JOnAS, JBoss, WebLogic, 及WebSphere

<> Java 客户端/服务端可以独立性 5.支持多种编程语言

<> 完全支持 JAX-WS 2.x 客户端/服务端模式

<> JAX-WS 2.x synchronous, asynchronous and one-way API's <> JAX-WS 2.x Dynamic Invocation Interface (DII) API <> 支持 wrapped and non-wrapped 数据格式 <> XML messaging API

<> 支持JavaScript 和 ECMAScript 4 XML (E4X) <> 支持CORBA

<> 支持JBI及ServiceMix 6.可编程环境 <> Java to WSDL <> WSDL to Java <> XSD to WSDL <> WSDL to XML <> WSDL to SOAP <> WSDL to service

WebService CXF学习(入门篇2):HelloWorld 理论联系实际,单单只讲理论那就成了纸上谈兵,用一个HelloWorld Demo可来说明事更加直观。那下面咱们就开始进行讲解:

首先到apache官方网下载apache-cxf-2.2.2,地址:http://cxf.apache.org/ 新建一个Java Project,导入cxf常用.jar包 Java代码

1. commons-logging-1.1.1.jar

2. geronimo-activation_1.1_spec-1.0.2.jar (or Sun's Activation jar) 3. geronimo-annotation_1.0_spec-1.1.1.jar (JSR 250)

4. geronimo-javamail_1.4_spec-1.6.jar (or Sun's JavaMail jar) 5. geronimo-servlet_2.5_spec-1.2.jar (or Sun's Servlet jar) 6. geronimo-ws-metadata_2.0_spec-1.1.2.jar (JSR 181)

7. geronimo-jaxws_2.1_spec-1.0.jar (or Sun's jaxws-api-2.1.jar) 8. geronimo-stax-api_1.0_spec-1.0.1.jar (or other stax-api jar) 9. jaxb-api-2.1.jar 10. jaxb-impl-2.1.12.jar 11. jetty-6.1.21.jar 12. jetty-util-6.1.21.jar 13. neethi-2.0.4.jar 14. saaj-api-1.3.jar 15. saaj-impl-1.3.2.jar 16. wsdl4j-1.6.2.jar 17. wstx-asl-3.2.8.jar 18. XmlSchema-1.4.5.jar 19. xml-resolver-1.2.jar 20. cxf-2.2.2.jar

接下就是HelloWorld Demo开发了 第一步:新建一个webservice接口 Java代码

1. @WebService

2. public interface IHelloWorld {

3. //@WebParam给参数命名,提高可代码可读性。此项可选 4. blic String sayHi(@WebParam(name=\5. }

通过注解@WebService申明为webservice接口 第二步,实现WebService接口 Java代码

1. @WebService

2. public class HelloWorldImpl implements IHelloWorld { 3.

4. public String sayHi(String name) {

5. System.out.println(\6. return \7. } 8. 9. }

第三步,创建服务端 Java代码

1. public class Server { 2.

3. private Server(){

4. IHelloWorld helloWorld = new HelloWorldImpl(); 5. //创建WebService服务工厂

6. JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean(); 7. //注册WebService接口

8. factory.setServiceClass(IHelloWorld.class); 9. //发布接口

10. factory.setAddress(\11. factory.setServiceBean(helloWorld); 12. //创建WebService 13. factory.create(); 14. }; 15.

16. public static void main(String[] args) throws InterruptedException{ 17. //启动服务端

18. new Server();

19. System.out.println(\20. //休眠一分钟,便于测试

21. Thread.sleep(1000*60); 22. System.out.println(\

23. System.exit(0); 24. } 25. }

第四步,创建客户端 Java代码

1. public class Client { 2.

3. private Client(){}; 4.

5. public static void main(String[] args){ 6. //创建WebService客户端代理工厂

7. JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); 8. //注册WebService接口

9. factory.setServiceClass(HelloWorld.class); 10. //设置WebService地址

11. factory.setAddress(\12. IHelloWorld iHelloWorld = (IHelloWorld)factory.create(); 13. System.out.println(\

14. System.out.println(\15. Josen\16. System.exit(0); 17. } 18. } 19.

最后是万事俱备,只欠测试了 首先,运行服务端程序

其次,打开浏览器,在地址栏中输入http://localhost:9000/HelloWorld?wsdl(因为cxf自带了一个jetty服务器),查看接口是否发布成功,如里浏览器页面显示下面内容,证明接口发布成功 Java代码

1.

com/\2.

3.

etNamespace=\4.

7. 9.

10.

13. 15. 16. 17.

18.

19. 21.

22.

23. 25.

26.

28.

30. 32. 33.

34.

37.

41. 44. 45.

46.

47. 50.

1.

3. 6.

这部分定义了服务访问点的调用模式的类型,表明StockQuoteService的某个入口类型是请求/响应模式,请求消息是GetlastTradePriceInput,而响应消息是GetLastTradePriceOutput。 Java代码

1.

2.

>

3.

4.

6.

8. 9.

10.

12. 13. 14. 15. 16.

这部分将服务访问点的抽象定义与SOAP HTTP绑定,描述如何通过SOAP/HTTP来访问按照前面描述的访问入口点类型部署的访问入口。其中规定了在具体SOAP调用时,应当使用的 soapAction是

\,而请求/响应消息的编码风格都应当采用SOAP 规范默认定义的编码风格\。 Java代码

1.

2. 股票查询服务

3. 6.

7.

8.

这部分是具体的Web服务的定义,在这个名为StockQuoteService的Web服务中,提供了一个服务访问入口,访问地址是\,使用的消息模式是由前面的binding所定义的。

按照这个WSDL文档的描述,在具体Web服务的使用中,具体发生的SOAP交互可能如下面所示:

SOAP消息请求:

Java代码

1. POST /StockQuote HTTP/1.1 2. Host: example.com

3. Content-Type: text/xml; charset=\4. Content-Length: nnnn

5. SOAPAction: \6.

7.

\

9.

10. MSFT 12. 13. 14.

SOAP消息响应:

Java代码

1. HTTP/1.1 200 OK

2. Content-Type: text/xml; charset=\3. Content-Length: nnnn 4.

5.

\

7.

8. 74.5 10. 11. 12.

小结

在本文中,我简单介绍了WSDL规范的用途

下面提供几个相关资料的网址 理解 UDDI 注册中心的 WSDL

http://www.ibm.com/developerworks/cn/webservices/ws-uwsdl/part1/index.html Web 服务的(革)创新

http://www.ibm.com/developerworks/cn/webservices/ws-peer4/index.html

WebService CXF学习(进阶篇1):SOAP讲解

SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。或者更简单地说:SOAP 是用于访问网络服务的协议。 您应当具备的基础知识

在继续学习之前,您需要对下面的知识有基本的了解: * XML

* XML 命名空间 Why SOAP?

对于应用程序开发来说,使程序之间进行因特网通信是很重要的。

目前的应用程序通过使用远程过程调用(RPC)在诸如 DCOM 与 CORBA 等对象之间进行通信,但是 HTTP 不是为此设计的。RPC 会产生兼容性以及安全问题;防火墙和代理服务器通常会阻止此类流量。 通过 HTTP 在应用程序间通信是更好的方法,因为 HTTP 得到了所有的因特网浏览器及服务器的支持。SOAP 就是被创造出来完成这个任务的。

SOAP 提供了一种标准的方法,使得运行在不同的操作系统并使用不同的技术和编程语言的应用程序可以互相进行通信。

Microsoft 和 SOAP

SOAP 是微软 .net 架构的关键元素,用于未来的因特网应用程序开发。

SOAP 1.1 被提交到 W3C

在 2000 年 5 月,UserLand、Ariba、Commerce One、Compaq、Developmentor、HP、IBM、IONA、Lotus、Microsoft 以及 SAP 向 W3C 提交了 SOAP 因特网协议,这些公司期望此协议能够通过使用因特网标准(HTTP 以及 XML)把图形用户界面桌面应用程序连接到强大的因特网服务器,以此来彻底变革应用程序的开发。

W3C 正在发展 SOAP 1.2

首个关于 SOAP 的公共工作草案由 W3C 在 2001 年 12 月发布。如需阅读更多有关在 W3C 的 SOAP 活动的内容,请访问我们的《W3C 教程》。

SOAP 构建模块

一条 SOAP 消息就是一个普通的 XML 文档,包含下列元素: * 必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息 * 可选的 Header 元素,包含头部信息

* 必需的 Body 元素,包含所有的调用和响应信息

* 可选的 Fault 元素,提供有关在处理此消息所发生错误的信息

所有以上的元素均被声明于针对 SOAP 封装的默认命名空间中: http://www.w3.org/2001/12/soap-envelope 以及针对 SOAP 编码和数据类型的默认命名空间: http://www.w3.org/2001/12/soap-encoding

语法规则

这里是一些重要的语法规则: * SOAP 消息必须用 XML 来编码

* SOAP 消息必须使用 SOAP Envelope 命名空间 * SOAP 消息必须使用 SOAP Encoding 命名空间 * SOAP 消息不能包含 DTD 引用 * SOAP 消息不能包含 XML 处理指令

SOAP 消息的基本结构 Java代码

1.

3. xmlns:soap=\

4. soap:encodingStyle=\5.

6. 7. ... 8. ...

9. 10.

11. 12. ... 13. ...

14. 15. ... 16. ... 17. 18. 19.

20.

SOAP Envelope 元素

必需的 SOAP 的 Envelope 元素是 SOAP 消息的根元素。它可把 XML 文档定义为 SOAP 消息。 请注意 xmlns:soap 命名空间的使用。它的值应当始终是:

Java代码

1. http://www.w3.org/2001/12/soap-envelope

并且它可把封装定义为 SOAP 封装: Java代码

1.

3. xmlns:soap=\

4. soap:encodingStyle=\5. ...

6. Message information goes here 7. ...

8.

xmlns:soap 命名空间

SOAP 消息必须拥有与命名空间 \相关联的一个 Envelope 元素。

如果使用了不同的命名空间,应用程序会发生错误,并抛弃此消息。

encodingStyle 属性

SOAP 的 encodingStyle 属性用于定义在文档中使用的数据类型。此属性可出现在任何 SOAP 元素中,并会被应用到元素的内容及元素的所有子元素上。SOAP 消息没有默认的编码方式。 语法 Java代码

1. soap:encodingStyle=\ 实例 Java代码

1.

3. xmlns:soap=\

4. soap:encodingStyle=\5. ...

6. Message information goes here 7. ...

8.

SOAP Header 元素

可选的 SOAP Header 元素可包含有关 SOAP 消息的应用程序专用信息(比如认证、支付等)。如果 Header 元素被提供,则它必须是 Envelope 元素的第一个子元素。 注释:所有 Header 元素的直接子元素必须是合格的命名空间。 Java代码

1.

3. xmlns:soap=\

4. soap:encodingStyle=\5.

6. 7.

8. xmlns:m=\9. soap:mustUnderstand=\234 10. 11. 12. ... 13. ... 14.

15.

上面的例子包含了一个带有一个 \元素的头部,它的值是 234,此元素的 \属性的值是 \。

SOAP 在默认的命名空间中 (\定义了三个属性。这三个属性是:actor、 mustUnderstand 以及 encodingStyle。这些被定义在 SOAP 头部的属性可定义容器如何对 SOAP 消息进行处理。

actor 属性

通过沿着消息路径经过不同的端点,SOAP 消息可从某个发送者传播到某个接收者。并非 SOAP 消息的所有部分均打算传送到 SOAP 消息的最终端点,不过,另一个方面,也许打算传送给消息路径上的一个或多个端点。

SOAP 的 actor 属性可被用于将 Header 元素寻址到一个特定的端点。 语法 Java代码

1. soap:actor=\ 实例 Java代码

1.

3. xmlns:soap=\

4. soap:encodingStyle=\5.

6. 7.

8. xmlns:m=\9. soap:actor=\10. 234

11. 12. 13. 14. ... 15. ... 16.

17.

mustUnderstand 属性

SOAP 的 mustUnderstand 属性可用于标识标题项对于要对其进行处理的接收者来说是强制的还是可选的。

假如您向 Header 元素的某个子元素添加了 \,则它可指示处理此头部的接收者必须认可此元素。假如此接收者无法认可此元素,则在处理此头部时必须失效。 语法 Java代码

1. soap:mustUnderstand=\ 实例 Java代码

1.

3. xmlns:soap=\

4. soap:encodingStyle=\5.

6. 7.

8. xmlns:m=\9. soap:mustUnderstand=\10. 234

11. 12.

13. 14. ... 15. ... 16.

17.

encodingStyle 属性

SOAP 的 encodingStyle 属性在上一节中已解释过了。

SOAP Body 元素

必需的 SOAP Body 元素可包含打算传送到消息最终端点的实际 SOAP 消息。 SOAP Body 元素的直接子元素可以是合格的命名空间。SOAP 在默认的命名空间中

(\定义了 Body 元素内部的一个元素。即 SOAP 的 Fault 元素,用于指示错误消息。 Java代码

1.

3. xmlns:soap=\

4. soap:encodingStyle=\5.

6.

7. Apples 9. 10. 11.

12.

上面的例子请求苹果的价格。请注意,上面的 m:GetPrice 和 Item 元素是应用程序专用的元素。它们并不是 SOAP 标准的一部分。 而一个 SOAP 响应应该类似这样: Java代码

1.

3. xmlns:soap=\

4. soap:encodingStyle=\5.

6.

7. 1.90 9.

10. 11.

12.

SOAP Fault 元素

来自 SOAP 消息的错误消息被携带于 Fault 元素内部。

如果已提供了 Fault 元素,则它必须是 Body 元素的子元素。在一条 SOAP 消息中,Fault 元素只能出现一次。

SOAP 的 Fault 元素用于下列子元素: 子元素 描述

供识别故障的代码

SOAP Fault Codes

在下面定义的 faultcode 值必须用于描述故障时的 faultcode 元素中: 错误

描述

可供人阅读的有关故障的说明 有关是谁引发故障的信息

存留涉及 Body 元素的应用程序专用错误信息

VersionMismatch SOAP Envelope 元素的无效命名空间被发现

Header 元素的一个直接子元素(带有设置为 \的 mustUnderstand 属性)无法被理MustUnderstand

解。 Client Server

HTTP 协议

HTTP 在 TCP/IP 之上进行通信。HTTP 客户机使用 TCP 连接到 HTTP 服务器。在建立连接之后,客户机可向服务器发送 HTTP 请求消息: Java代码

消息被不正确地构成,或包含了不正确的信息。 服务器有问题,因此无法处理进行下去。

1. POST /item HTTP/1.1 2. Host: 189.123.345.239 3. Content-Type: text/plain 4. Content-Length: 200

随后服务器会处理此请求,然后向客户机发送一个 HTTP 响应。此响应包含了可指示请求状态的状态代码:

Java代码

1. 200 OK

2. Content-Type: text/plain 3. Content-Length: 200

在上面的例子中,服务器返回了一个 200 的状态代码。这是 HTTP 的标准成功代码。 假如服务器无法对请求进行解码,它可能会返回类似这样的信息: Java代码

1. 400 Bad Request 2. Content-Length: 0

SOAP HTTP Binding

SOAP 方法指的是遵守 SOAP 编码规则的 HTTP 请求/响应。 HTTP + XML = SOAP

SOAP 请求可能是 HTTP POST 或 HTTP GET 请求。

HTTP POST 请求规定至少两个 HTTP 头:Content-Type 和 Content-Length。 Content-Type

SOAP 的请求和响应的 Content-Type 头可定义消息的 MIME 类型,以及用于请求或响应的 XML 主体的字符编码(可选) 语法 Java代码

1. Content-Type: MIMEType; charset=character-encoding 例子 Java代码

1. POST /item HTTP/1.1

2. Content-Type: application/soap+xml; charset=utf-8

Content-Length

SOAP 的请求和响应的 Content-Length 头规定请求或响应主体的字节数。 语法 Java代码

1. Content-Length: bytes

例子 Java代码

1. POST /item HTTP/1.1

2. Content-Type: application/soap+xml; charset=utf-8 3. Content-Length: 250

一个 SOAP 实例

在下面的例子中,一个 GetStockPrice 请求被发送到了服务器。此请求有一个 StockName 参数,而在响应中则会返回一个 Price 参数。此功能的命名空间被定义在此地址中: \SOAP 请求: Java代码

1. POST /InStock HTTP/1.1 2. Host: www.example.org

3. Content-Type: application/soap+xml; charset=utf-8 4. Content-Length: nnn 5.

6.

8. xmlns:soap=\

9. soap:encodingStyle=\10.

11.

13. IBM 14. 15. 16.

17.

SOAP 响应: Java代码

1. HTTP/1.1 200 OK

2. Content-Type: application/soap+xml; charset=utf-8 3. Content-Length: nnn 4.

5.

7. xmlns:soap=\

8. soap:encodingStyle=\9.

10. 12. 34.5 13. 14. 15.

16.

WebService CXF学习(进阶篇2):JAX-WS讲解

JAX-WS规范是一组XML web services的JAVA API。JAX-WS允许开发者可以选择RPC-oriented或者message-oriented 来实现自己的web services。

在 JAX-WS中,一个远程调用可以转换为一个基于XML的协议例如SOAP。在使用JAX-WS过程中,开发者不需要编写任何生成和处理SOAP消息的代码。JAX-WS的运行时实现会将这些API的调用转换成为对于SOAP消息。

在服务器端,用户只需要通过Java语言定义远程调用所需要实现的接口SEI (service endpoint interface),并提供相关的实现,通过调用JAX-WS的服务发布接口就可以将其发布为WebService接口。

在客户端,用户可以通过JAX-WS的API创建一个代理(用本地对象来替代远程的服务)来实现对于远程服务器端的调用。

通过web service所提供的互操作环境,我们可以用JAX-WS轻松实现JAVA平台与其他编程环境(.net等)的互操作。

JAX-WS工作原理如下图所示:

JAX-WS与JAX-RPC之间的关系

Sun最开始的web services的实现是JAX-RPC 1.1 (JSR 101)。这个实现是基于Java的RPC,并不完全支持schema规范,同时没有对Binding和Parsing定义标准的实现。

JAX-WS2.0 (JSR 224)是Sun新的web services协议栈,是一个完全基于标准的实现。在binding层,使用的是the Java Architecture for XML Binding (JAXB, JSR 222),在parsing层,使用的是the Streaming API for XML (StAX, JSR 173),同时它还完全支持schema规范。

WebService CXF学习(进阶篇3):对象传递

前面几节都是讲一些理论知识,现在又用一个例子来说明一下,这一节我们就CXF框架对象传递进行讲解。 第一步:创建传输对象Customer Java代码

1. @XmlRootElement(name=\2. @XmlAccessorType(XmlAccessType.FIELD) 3. @XmlType(propOrder = {\4. public class Customer { 5.

6. private int age; 7. private String name; 8.

9. public int getAge() { 10. return age; 11. } 12.

13. public void setAge(int age) { 14. this.age = age; 15. } 16.

17. public String getName() { 18. return name; 19. } 20.

21. public void setName(String name) { 22. this.name = name; 23. } 24. 25. }

@XmlRootElement-指定XML根元素名称(可选) @XmlAccessorType-控制属性或方法序列化 四种方案:

FIELD-对每个非静态,非瞬变属性JAXB工具自动绑定成XML,除非注明XmlTransient

NONE-不做任何处理

PROPERTY-对具有set/get方法的属性进行绑定,除非注明XmlTransient

PUBLIC_MEMBER -对有set/get方法的属性或具有共公访问权限的属性进行绑定,除非注 明XmlTransient

@XmlType-映射一个类或一个枚举类型成一个XML Schema类型

第二步:创建WebService接口 Java代码

1. @WebService

2. public interface HelloService { 3.

4. public void save(Customer c1,Customer c2); 5.

6. public void test(String args); 7.

8. public Customer get(int id); 9. } 10. 11.

每三步:创建WebService接口实现类 Java代码

1. @WebService

2. public class HelloServiceImpl implements HelloService { 3.

4. public void save(Customer c1, Customer c2) { 5.

6. System.out.println(c1.getAge()+\7. System.out.println(c1.getName()+\8. } 9.

10. public void test(String args) { 11. System.out.println(args); 12. 13. } 14.

15. public Customer get(int id) { 16. Customer cus = new Customer(); 17. cus.setAge(100);

18. cus.setName(\19. return cus; 20. } 21. 22. 23. 24. } 25.

第四步:创建服务端 Java代码

1. public class SoapServer { 2.

3. ublic static void main(String[] args){ 4. //两种方法,任选一种发布WebService接口

5. //Endpoint.publish(\6. HelloServiceImpl());

7. JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean(); 8. factory.setAddress(\9. factory.setServiceClass(HelloServiceImpl.class);

10. factory.getInInterceptors().add(new LoggingInInterceptor()); 11. factory.getOutInterceptors().add(new LoggingOutInterceptor()); 12. factory.create(); 13. 14. } 15.

第五步:创建客户端 Java代码

1. public class SoapClient { 2.

3. public static void main(String[] args){

4. JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); 5. factory.setAddress(\6. factory.setServiceClass(HelloService.class);

7. factory.setServiceClass(HelloServiceImpl.class);

8. factory.getInInterceptors().add(new LoggingInInterceptor());

9. HelloService service = (HelloService)factory.create(); 10.

11. Customer c1 = new Customer(); 12. c1.setAge(1); 13. c1.setName(\14.

15. Customer c2 = new Customer(); 16. c2.setAge(2); 17. c2.setName(\18.

19. service.save(c1, c2);

20. service.test(\21. } 22. } 23.

最后,测试程序

运行服务端程序,在浏览器地址栏输入http://localhost:8080/helloService?wsdl查看接口是否发布成功。成功则运行一下客户端程序,看看对象传输是否成功。

现在我们来分析一下控制打印的日志信息。 引用

信息: Inbound Message ---------------------------- ID: 1

Address: /HelloWorld Encoding: UTF-8

Content-Type: text/xml; charset=UTF-8

Headers: {content-type=[text/xml; charset=UTF-8], connection=[keep-alive],

Host=[localhost:9000], Content-Length=[184], SOAPAction=[\Content-Type=[text/xml; charset=UTF-8], Accept=[*/*], Pragma=[no-cache], Cache-Control=[no-cache]} Payload:

xmlns:soap=\xmlns:ns1=\

Josen --------------------------------------

2010-1-9 20:41:56 org.apache.cxf.interceptor.LoggingOutInterceptor$LoggingCallback onClose 信息: Outbound Message --------------------------- ID: 1

Encoding: UTF-8 Content-Type: text/xml Headers: {}

Payload:

xmlns:soap=\

xmlns=\xmlns:ns1=\--------------------------------------

2010-01-09 20:41:56.578::INFO: seeing JVM BUG(s) - cancelling interestOps==0

当客户端向服器发送请求时,服务端LoggingInInterceptor拉截客户端发送过来的SOAP消息,如下: 引用

Josen

客户端将请求信息封闭在中,当然也可以将其放到

,只要在@WebParam中的header设置成true,默认为false;

服务器接到请求之后,响应客户端。同样以SOAP形式将信息封装好发回客户端,SOAP信息如下: 引用

WebService CXF学习(进阶篇4):JAXB剖析 前面几节我们讲解对象传递,但是通常情况下我们不直接传对象,因为直接传递对象安全性差,而且暴露了实体对象。所以我们选择传递XML文件,当然也可以传递JSON对象。这节我只针对传递XML,那么JAVA绑定成XML,服务端将XML解析成Java对象有什么工具可用吗,其实这样的工具多的是。这里我选择一个比较简单的JAXB工具来讲解一下。

JAXB(Java Architecture for XML Binding)提供了一个快速而方便的方式绑定XML Schemas和java,使java程序员能够很方便的在java应用程序中处理XML数据。JAXB提供了将XML文档解组为java内容树的方法,以及将java内容树重新编组回XML文档的方法。JAXB同样也提供了一种从java对象生成XML Schema的方式。

这里有几个重要的定义:

编组(Marshalling)是把内存中的数据转化到存储媒介上的过程。因此在 Java 和 XML 环境中,编组就是把一些 Java 对象转化成一个(或多个) XML 文档。在数据库环境中,则是把 Java 表示的数据存入数据库。显然,编组的秘密在于把 Java 实例中的面向对象结构转化成适用于 XML 的 扁平结构,或者 RDBMS 中的关系结构(使用 Java 技术转换到 OODBMS 实际上很简单)。工作原理如下图所示:

解组(Unmarshalling) 是把数据从存储媒介转换到内存中的过程--正好与编组相反。因此需要把 XML 文档解组到 Java VM 中。这里的复杂性不是在扁平数据中,因为这不是必需的,而在于从正确的数据到正确的 Java 代码变量的映射。如果映射是错误的,就不可能正确地访问数据。当然,如果再尝试重新编组还会造成更大的问题,并且问题传播得很快。工作原理如下图所示:

往返(Round-tripping)可能是最重要也最容易误解的数据绑定术语。往返用于描述从存储媒介到内存然后回到存储媒介的完整循 环。在 XML 和 Java 技术环境中,这就意味着从 XML 文档到 Java 实例变量,然后再回到 XML 文档。正确的往返要求,如果中间没有修改数据,XML 输入和 XML 输出应该是等同的。

下载地址:http://java.sun.com/developer/technicalArticles/WebServices/jaxb/

我们还以例子来说明它的工作原理,直观点。 第一步,创建一个Customer对象 Java代码

1. @XmlRootElement(name=\

2. @XmlAccessorType(XmlAccessType.FIELD) 3. @XmlType(name = \4. public class Customer { 5.

6. @XmlAttribute(required = true) 7. protected String name;

8. @XmlAttribute(required = true) 9. protected int age; 10. 11. /**

12. * Gets the value of the name property. 13. * 14. * @return

15. * possible object is 16. * {@link String } 17. * 18. */

19. public String getName() { 20. return name; 21. } 22. 23. /**

24. * Sets the value of the name property. 25. *

26. * @param value

27. * allowed object is 28. * {@link String } 29. * 30. */

31. public void setName(String value) { 32. this.name = value; 33. } 34. 35. /**

36. * Gets the value of the age property. 37. * 38. */

39. public int getAge() { 40. return age; 41. } 42. 43. /**

44. * Sets the value of the age property. 45. *

46. */

47. public void setAge(int value) { 48. this.age = value; 49. } 50. 51. } 52. 53.

第二步,创建一个测试类 Java代码

1. public class SoapClient { 2.

3. private final static String MODEL = \

4. public static void main(String[] args) throws ParserConfigurationException, JAXB

Exception, TransformerException{ 5.

6.

7. ObjectFactory factory = new ObjectFactory(); 8. Customer customer = factory.createCustomer(); 9. customer.setAge(20); 10. customer.setName(\11.

12. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 13. dbf.setNamespaceAware(true);

14. DocumentBuilder db = dbf.newDocumentBuilder(); 15. Document doc = db.newDocument(); 16.

17. JAXBContext jaxbContext = JAXBContext.newInstance(MODEL); 18. //Java对象转换成XML

19. Marshaller marshaller = jaxbContext.createMarshaller(); 20. marshaller.marshal(customer, doc); 21.

22. DOMSource domSource = new DOMSource(doc); 23. StringWriter writer = new StringWriter(); 24. StreamResult result = new StreamResult(writer);

25. TransformerFactory tf = TransformerFactory.newInstance(); 26. Transformer transformer = tf.newTransformer(); 27. transformer.transform(domSource, result); 28. String xmlString = writer.toString(); 29. System.out.println(xmlString); 30. //XML转换成Java对象

31. Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 32. StringReader reader = new StringReader(xmlString); 33. Customer cus = (Customer)unmarshaller.unmarshal(reader); 34. System.out.println(\35. System.out.println(\36. 37. 38. } 39. }

第三步,运行一个测试类,看看效果如何。Java与XML之间转换如此简单

编组操作:利用上面生成的java文件执行编组操作。 Java代码

1. JAXBContext jaxbContext = JAXBContext.newInstance(MODEL); 2. //Java对象转换成XML

3. Marshaller marshaller = jaxbContext.createMarshaller(); 4. marshaller.marshal(customer, doc); 5.

6. DOMSource domSource = new DOMSource(doc); 7. StringWriter writer = new StringWriter(); 8. StreamResult result = new StreamResult(writer);

9. TransformerFactory tf = TransformerFactory.newInstance(); 10. Transformer transformer = tf.newTransformer(); 11. transformer.transform(domSource, result); 12. String xmlString = writer.toString(); 13. System.out.println(xmlString);

解组操作:通过xml文件执行解组操作。 Java代码

1. JAXBContext jaxbContext = JAXBContext.newInstance(MODEL); 2. Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 3. StringReader reader = new StringReader(xmlString); 4. Customer cus = (Customer)unmarshaller.unmarshal(reader); 5. System.out.println(\6. System.out.println(\

也可通过Ant配置来解组,如下: Java代码

1.

9.

10.

12.

15.

16. 21. 22.

WebService CXF学习(高级篇1):整合Spring框架

通过前面两节的讲解,相信你对CXF框架开始有一些认识了。在当今项目开发中,Spring框架基上都用到过,那么它怎么与CXF结合呢,这就是我们这一间要讲的内容。好了,闲话少说。 首先,在前面基础上再导入几个spring要用到的几个.jar包: spring-core.jar spring-jdbc.jar spring-context.jar spring-orm.jar spring-beans.jar spring-tx.jar

包导入完之后,我们还不能开如干活,配置几荐参数,便于下一步工作。 配置CXF框架

我的电脑->属性->高级->环境变量

创建一个CXF_HOEM变量,值为CXF框架所在根目录,修改一下

CLASSPATH=%CXF_HOME%/lib;PATH=%CXF_HOME%/bin;这时有会问为什么要配置这两个参数据呢,其实配置这两个参数用途与配置JAVA变量一下,在DOS窗口下直接运行java2ws,wsdl2java等可执行文件。当然你没有配置也可以进到CXF框架的bin目录下远行这个几个可执行文件。

配置好了后,你在DOS窗口下输入java2ws,看看配置是否效。肯定没有成功,原因是使用6.0的JDK,我们还得在%JAVA_HOME%/jre/lib目录下创建一下endorsed文件夹,将jaxb-api.jar,jaxws.jar拷贝进去。现在再运一下java2ws,成功运行,配置生效了。 基本工作做得差不多,整合spring框架正式开始:

第一步:新一个web project,导入要用到.jar包,其实CXF利用

org.apache.cxf.transport.servlet.CXFServlet来拦截所有web请求,将其配置到web.xml中。配置如下: Java代码

1.

2.

3. contextConfigLocation 4.

5. /WEB-INF/classes/applicationContext-*.xml,/WEB-INF/classes/webservice.xm

l

6. 7. 8.

9.

10.

11. org.springframework.web.context.ContextLoaderListener 12. 13. 14.

15. [color=red]

16. CXFServlet 17. CXF Servlet 18.

19. org.apache.cxf.transport.servlet.CXFServlet 20.

21. 1 22. 23.

24.

25. CXFServlet 26. /* 27. [/color] 28.

注意一下绿色字体

CXF框架配置好了,我就来开发一个WebService接口 Java代码

1. @WebService

2. public interface IService { 3.

4. //public void save(@WebParam(name=\

5. public void save(@WebParam(name=\@WebParam(name=\

flag);

6. public void update(@WebParam(name=\7. public void delete(@WebParam(name=\

8. public @WebResult(name=\@WebParam(name=\9. }

这里面有四个方法,其中有一个涉及到对象,这一点前面一节讲到怎么处理它。放在这里是再回顾前节内容。

创建一个WebService接口实现类 Java代码

1. @WebService

2. public class ServiceImpl implements IService {

3. private Logger log = LoggerFactory.getLogger(ServiceImpl.class); 4.

5. public void delete(int id) {

6. log.info(\7. } 8.

9. public void save(UserInfoDTO dto,boolean flag) { 10. System.out.println(\11. } 12.

13. public void update(String xml) { 14. } 15.

16. public String get(int id){ 17. return null; 18. } 19. } 20.

由于本节只讲解与Spring整合,没有涉及到数据库,因就打印一下传递过来的对象内容来证明整合成功。与spring,hibernate整合后面章节会讲到,请留意后面章节。 传递对象,当然创建对象啦 Java代码

1. @XmlType(name=\

2. @XmlAccessorType(XmlAccessType.FIELD)

3. public class UserInfoDTO implements java.io.Serializable { 4.

5. private static final long serialVersionUID = -4666026219400887433L; 6. private Integer id; 7. private String name; 8. private Integer age; 9. private Integer address; 10.

11. public Integer getId() { 12. return id; 13. } 14.

15. public void setId(Integer id) { 16. this.id = id; 17. } 18.

19. public String getName() { 20. return name; 21. } 22.

23. public void setName(String name) { 24. this.name = name; 25. } 26.

27. public Integer getAge() { 28. return age; 29. } 30.

31. public void setAge(Integer age) { 32. this.age = age; 33. } 34.

35. public Integer getAddress() { 36. return address; 37. } 38.

39. public void setAddress(Integer address) { 40. this.address = address; 41. } 42.

43. public UserInfoDTO() { 44. } 45.

46. }

做了这么多工作,有人又会问,怎么现在做的与spring框架就没一点联系,呵呵,确实是这样。开戏开场了,利用Spring来发布WebService接口: Java代码

1.

2.

6. http://www.springframework.org/schema/beans

7. http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 8. http://cxf.apache.org/jaxws

9. http://cxf.apache.org/schemas/jaxws.xsd\10. [color=red]

11.

12.

13.

16. 17.

18. implementor=\19.

20. 21.

服务端开发工作基本结束。现在打包部署到Tomcat6.0.18(本人目前使用的测试服务器,你当然可以使用别的服务器)

服务器启动完成后,打开浏览器在地址栏中输入http://localhost:port/project name/Service?wsdl看看接口是否发成功。

接下来就是开发一个客户端了。

另建一个web project,现在前面的参数配置要起作用了,cmd进入DOS环境下输入wsdl2java -p com.itdcl.service(自定义包名) http://localhost:port/project name/Service?wsdl(前提是服务器没停止)

敲击Enter,wsdl2java工具帮你将发布出来的wsdl文件转换成webservice接口,到指定目录下将com.itdcl.service拷到刚才另建的web project的src目录下。 现在,我们就来创建一个客户端程序: Java代码

1. public class SampleClient { 2.

3. ublic static void main(String[] args) {

4. ApplicationContext context = new ClassPathXmlApplicationContext( 5. \6.

7. IService service = (IService)context.getBean(\8. ServerUserInfo userInfo = new ServerUserInfo(); 9. userInfo.setAddress(1); 10. userInfo.setAge(100); 11. userInfo.setName(\12.

13. service.save(userInfo,true); 14. service.delete(1); 15. 16. 17. }

看得仔细的朋友就会问了,ServerUserInfo 这个类那来的,你进到com.itdcl.service目录下就会看到,是WebService发布出来的。

到目前为止,客户端还没有完成,你没有看到程序中ApplicationContext context = new

ClassPathXmlApplicationContext(\这个bean.xml就是spring框架来注删除WebService接口的。好啦,创建一个bean.xml,内容如下: Java代码

1.

2.

6. http://www.springframework.org/schema/beans

7. http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 8. [color=red]http://cxf.apache.org/jaxws

9. http://cxf.apache.org/schemas/jaxws.xsd[/color]\10.

11. address=\12. serviceClass=\13.

留意一下绿色字体

剩下的事就是运行客户端程序了,没有异常抛出,打印出:name:Josen,则恭喜你CXF框架与Spring整合成功。

WebService CXF学习(高级篇2):CXF+Spring+Hibernate 前一节仅仅只讲了与Spring整合,没有涉及到数据库,而且是直接将Java象传递到服务端。这一节我起到一个回顾前面章节的作用。用在客户端运用JABX将JAVA对象编组成XML文件,在客户端将XML解组成

JAVA并存入数据库。下面我们就着手开发这个Demo: 服务端开发

第一步,编写数据资源层相关接口 DAO编写: Java代码

1. public interface HibernateDao { 2.

3. public void save(UserInfo object); 4. public void delete(UserInfo object); 5. public void update(UserInfo object); 6. public UserInfo get(int id); 7. } 8.

DAO实现类: Java代码

1. public class HibernateDaoImpl extends HibernateDaoSupport implements HibernateDao {

2.

3. public void delete(UserInfo object) {

4. this.getHibernateTemplate().delete(object); 5. } 6.

7. public void save(UserInfo object) {

8. this.getHibernateTemplate().save(object); 9. } 10.

11. public void update(UserInfo object) {

12. this.getHibernateTemplate().update(object); 13. } 14.

15. public UserInfo get(int id) {

16. return (UserInfo) this.getHibernateTemplate().get(UserInfo.class, id); 17. } 18. 19. }

实体对象: Java代码

1. @Entity

2. @Table(name = \

3. public class UserInfo implements java.io.Serializable { 4.

5. private static final long serialVersionUID = 2281022190032353574L; 6. 7. @Id

8. @GeneratedValue(strategy = GenerationType.IDENTITY) 9. private Integer id; 10. private String name; 11. private Integer age; 12. private Integer address; 13.

14. public UserInfo() { 15. } 16.

17. public UserInfo(String name, Integer age) { 18. this.name = name; 19. this.age = age; 20. } 21.

22. public UserInfo(String name, Integer age, Integer address) { 23. this.name = name; 24. this.age = age;

25. this.address = address; 26. } 27.

28. public Integer getId() { 29. return this.id; 30. } 31.

32. public void setId(Integer id) { 33. this.id = id; 34. } 35.

36. public String getName() { 37. return this.name; 38. } 39.

40. public void setName(String name) { 41. this.name = name; 42. } 43.

44. public Integer getAge() {

45. return this.age; 46. } 47.

48. public void setAge(Integer age) { 49. this.age = age; 50. } 51.

52. public Integer getAddress() { 53. return this.address; 54. } 55.

56. public void setAddress(Integer address) { 57. this.address = address; 58. } 59. 60. }

第二步:业务逻辑层接口编写 业务逻辑接口: Java代码

1. @WebService

2. public interface IService { 3.

4. //public void save(@WebParam(name=\

5. public void save(@WebParam(name=\@WebParam(name=\

ean flag);

6. public void update(@WebParam(name=\7. public void delete(@WebParam(name=\

8. public @WebResult(name=\@WebParam(name=\9. }

接口实现类: Java代码

1. @WebService

2. public class ServiceImpl implements IService {

3. private Logger log = LoggerFactory.getLogger(ServiceImpl.class); 4. private HibernateDao dao; 5.

6. // public void setDao(HibernateDao dao) { 7. // this.dao = dao;

8. // } 9.

10. public void delete(int id) {

11. log.info(\12. //UserInfo userInfo = (UserInfo)object;

13. //log.info(\14. //log.info(\15. //dao.delete(userInfo); 16. } 17.

18. // public void save(String xml) {

19. // //UserInfo userInfo = (UserInfo)object; 20. // log.info(\21. // //dao.save(userInfo); 22. // System.out.println(\23. // } 24.

25. public void save(UserInfoDTO dto,boolean flag) { 26. System.out.println(\27. } 28.

29. public void update(String xml){

30. ApplicationContext context = new ClassPathXmlApplicationContext( 31. \

32. this.dao = (HibernateDao)context.getBean(\33. try {

34. JAXBContext jaxbContext = JAXBContext.newInstance(\35. Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 36. StringReader reader = new StringReader(xml);

37. Customers cus = (Customers)unmarshaller.unmarshal(reader); 38. Customer cust = cus.getCustomer(); 39.

40. UserInfo userInfo = new UserInfo();

41. System.out.println(\42. userInfo.setAddress(cust.getAddress()); 43. System.out.println(\44. userInfo.setAge(Integer.valueOf(cust.getAge())); 45. System.out.println(\46. //userInfo.setId(2);

47. userInfo.setName(cust.getName()); 48.

49. dao.save(userInfo); 50. } catch (JAXBException e) { 51. e.printStackTrace();

52. } 53. 54. } 55.

56. public String get(int id){ 57. //return dao.get(id); 58. return null; 59. } 60. }

DAO与Service接口配置: Java代码

1.

2.

8. http://cxf.apache.org/jaxws

9. http://cxf.apache.org/schemas/jaxws.xsd

10. http://www.springframework.org/schema/beans http://www.springframework.org/schem

a/beans/spring-beans-2.0.xsd

11. http://www.springframework.org/schema/tx http://www.springframework.org/schema/t

x/spring-tx-2.0.xsd

12. http://www.springframework.org/schema/aop http://www.springframework.org/schema/

aop/spring-aop-2.0.xsd\13.

14. 15.

16. class=\

r\

17.

19. classpath:jdbc.properties 20. 21. 22. 23.

24.

25. class=\

26.

28. 31.

32.

33. class=\

yBean\

34.

37.

39.

42.

45.

48.

51. 54.

55.

56.

59.

62. 68.

69.

70.

71.

73. 75.

76. 79.

WebService接口发布: Java代码

1.

2.

6. http://www.springframework.org/schema/beans

7. http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 8. http://cxf.apache.org/jaxws

9. http://cxf.apache.org/schemas/jaxws.xsd\10.

11.

14.

16. implementor=\17.

18.

19. implementor=\20.

21.

22. implementor=\23.

5.

10.

12.

14. message=\文件生成wsdl文件,

java2wsdl -Ddir=com/starit/cxf/java2wsdl -Dsrc=com.starit.cxf.java2wsdl.Hello\15.

16. message=\文件生成client,

java2wsdl -Ddir=com/starit/cxf/java2wsdl -Dwsdl=hello.wsdl\17.

18.

19.

20. 22.

24.

25.

26. 29. 30. 31.

32.

33. 43.

第二步:WebService接口注册配置 Java代码

1.

2.

6. http://www.springframework.org/schema/beans

7. http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 8. http://cxf.apache.org/jaxws

9. http://cxf.apache.org/schemas/jaxws.xsd\10.

11.