java webservice_cfx学习.doc_第1页
java webservice_cfx学习.doc_第2页
java webservice_cfx学习.doc_第3页
java webservice_cfx学习.doc_第4页
java webservice_cfx学习.doc_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一篇值得一看webservice开发的入门教程,使用的是cxf插件。本文介绍了通过cfx_2.3.2的原理,和spring整合的过程,以及webservice的基本认证,客户端代码的调用,xml传递对象。入门的不错教程哦,绝对值得一看。第一步:新建一个webservice接口WebService public interface IHelloWorld /WebParam给参数命名,提高可代码可读性。此项可选 public String sayHi(WebParam(name=text) String text); 通过注解WebService申明为webservice接口 第二步,实现WebService接口WebService public class HelloWorldImpl implements IHelloWorld public String sayHi(String name) System.out.println(sayHello is called by + name); return Hello + name; 第三步,创建服务端 public class Server private Server() IHelloWorld helloWorld = new HelloWorldImpl(); /创建WebService服务工厂 JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean(); /注册WebService接口 factory.setServiceClass(IHelloWorld.class); /发布接口 factory.setAddress(http:/localhost:9000/HelloWorld); factory.setServiceBean(helloWorld); /创建WebService factory.create(); ; public static void main(String args) throws InterruptedException /启动服务端 new Server(); System.out.println(Server ready); /休眠一分钟,便于测试 Thread.sleep(1000*60); System.out.println(Server exit); System.exit(0); 第四步,创建客户端public class Client private Client(); public static void main(String args) /创建WebService客户端代理工厂 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); /注册WebService接口 factory.setServiceClass(HelloWorld.class); /设置WebService地址 factory.setAddress(http:/localhost:9000/HelloWorld); IHelloWorld iHelloWorld = (IHelloWorld)factory.create(); System.out.println(invoke webservice); System.out.println(message context is:+iHelloWorld.sayHi(Josen); System.exit(0); 首先,运行服务端程序 其次,打开浏览器,在地址栏中输入http:/localhost:9000/HelloWorld?wsdl(因为cxf自带了一个jetty服务器),查看接口是否发布成功,如里浏览器页面显示下面内容,证明接口发布成功本文所引用的资源主要包括两类,一类是Web服务的技术资源网站,包含了大量Web服务的技术信息,另一类是Web服务“stack系列技术规范,他们是一个整体的技术体系,包括UDDI、SOAP、WSDL、XML等。本文的最后给出了这些资源的链接,有兴趣的读者可以通过这些资源链接找到所需的内容。其中,绿色部分是先前已经定义好的并且广泛使用的传输层和网络层的标准:IP、HTTP、SMTP等。而蓝色部分是目前开发的Web服务的相关标准协议,包括服务调用协议SOAP、服务描述协议WSDL和服务发现/集成协议UDDI,以及服务工作流描述语言WSFL。而橙色部分描述的是更高层的待开发的关于路由、可靠性以及事务等方面的协议。黄色部分是各个协议层的公用机制,这些机制一般由外部的正交机制来完成。其中,一个可以使用的Web服务应当按照需要选用若干层次的功能,而无需所有的特性。但是无论如何为了实现一个一般意义上的Web服务,具备Web服务的基础特性:跨平台调用和接口可机器识别,那么必需使用WSDL和SOAP。SOAP是用来最终完成Web服务调用的,而WSDL则是用于描述如何使用 SOAP来调用Web服务的。 WSDL 是一种XML Application,他将Web服务描述定义为一组服务访问点,客户端可以通过这些服务访问点对包含面向文档信息或面向过程调用的服务进行访问(类似远程过程调用)。WSDL首先对访问的操作和访问时使用的请求/响应消息进行抽象描述,然后将其绑定到具体的传输协议和消息格式上以最终定义具体部署的服务访问点。相关的具体部署的服务访问点通过组合就成为抽象的Web服务。 在具体使用中,我们可以对 WSDL 进行扩展(类似SOAP的可扩展性),这样无论通信时使用何种消息格式或网络协议,都可以对服务访问点及其使用的消息格式进行描述。在WSDL的框架中,可以使用任意的消息格式和网络协议,如同SOAP中可以使用任意的网络协议一样。在WSDL规范中,定义了如何使用SOAP消息格式、HTTP GET/POST消息格式以及MIME格式来完成Web服务交互的规范。WSDL 文档将Web服务定义为服务访问点或端口的集合。在 WSDL 中,由于服务访问点和消息的抽象定义已从具体的服务部署或数据格式绑定中分离出来,因此可以对抽象定义进行再次使用:消息,指对交换数据的抽象描述;而端口类型,指操作的抽象集合。用于特定端口类型的具体协议和数据格式规范构成了可以再次使用的绑定。将Web访问地址与可再次使用的绑定相关联,可以定义一个端口,而端口的集合则定义为服务。因此,WSDL 文档在Web服务的定义中使用下列元素: * Types - 数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)。 * Message - 通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构。 * Operation - 对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对。 * PortType - 对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持。 * Binding - 特定端口类型的具体协议和数据格式规范的绑定。 * Port - 定义为协议/数据格式绑定与具体Web访问地址组合的单个服务访问点。 * Service - 相关服务访问点的集合。 大家可以参考下图,来理解一下WSDL文档的结构组织:其中,Types是一个数据类型定义的容器,包含了所有在消息定义中需要的XML元素的类型定义,我将在今后的文章中结合XML Schema来详细说明如何进行类型定义。 Message具体定义了在通信中使用的消息的数据结构,Message元素包含了一组Part元素,每个Part元素都是最终消息的一个组成部分,每个 Part都会引用一个DataType来表示它的结构。Part元素不支持嵌套(可以使用DataType来完成这方面的需要),都是并列出现。 PortType具体定义了一种服务访问入口的类型,何谓访问入口的类型呢?就是传入/传出消息的模式及其格式。一个PortType可以包含若干个 Operation,而一个Operation则是指访问入口支持的一种类型的调用。在WSDL里面支持四种访问入口调用的模式: 1. 单请求; 2. 单响应; 3. 请求/响应; 4. 响应/请求。在这里请求指的是从客户端到Web服务端,而响应指的是从Web服务端到客户端。PortType的定义中会引用消息定义部分的一个到两个消息,作为请求或响应消息的格式。比如,一个股票查询的访问入口可能就会支持两种请求消息,一种请求消息中指明股票代码,而另一种请求消息中则会指明股票的名称,响应消息可能都是股票的价格等等。 以上三种结构描述了调用Web服务的抽象定义,这三部分与具体Web服务部署细节无关,是可复用的描述(每个层次都可以复用)。如果与一般的对象语言做比较的话,这部分可以堪称是IDL描述的对象,描述了对象的接口标准,但是到底对象是用哪种语言实现,遵从哪种平台的细节规范,被部署在哪台机器上则是后面的元素所描述的。 Service描述的是一个具体的被部署的Web服务所提供的所有访问入口的部署细节,一个Service往往会包含多个服务访问入口,而每个访问入口都会使用一个Port元素来描述。 Port描述的是一个服务访问入口的部署细节,包括通过哪个Web地址(URL)来访问,应当使用怎样的消息调用模式来访问等。其中消息调用模式则是使用Binding结构来表示。 Binding结构定义了某个PortType与某一种具体的网络传输协议或消息传输协议相绑定,从这一层次开始,描述的内容就与具体服务的部署相关了。比如可以将PortType与SOAP/HTTP绑定,也可以将PortType与MIME/SMTP相绑定等。 在介绍了WSDL的主要元素之后,大家会发现,WSDL的设计理念完全继承了以XML为基础的当代Web技术标准的一贯设计理念:开放。WSDL允许通过扩展使用其他的类型定义语言(不光是XML Schema),允许使用多种网络传输协议和消息格式(不光是在规范中定义的这些:SOAP/HTTP,HTTP-GET/POST以及MIME等)。同时WSDL也应用了当代软件工程中的复用理念,分离了抽象定义层和具体部署层,使得抽象定义层的复用性大大增加。比如我们可以先使用抽象定义层为一类 Web服务进行抽象定义(比如UDDI Registry,抽象定义肯定是完全一致的遵循了UDDI规范),而不同的运营公司可以采用不同的具体部署层的描述结合抽象定义完成其自身的Web服务的描述。WSDL文档示例 下例是一个提供股票报价的简单Web服务的 WSDL 定义。该服务支持名为 GetLastTradePrice 的单一操作,这个操作是通过在 HTTP 上运行 SOAP 1.1 协议来实现的。该请求接受一个类型为字符串的 tickerSymbol,并返回类型为浮点数的价格。 上面这部分是数据类型的定义,其中为定义了两个元素的结构: * TradePriceRequest(交易价格请求): 将该元素定义为包含一个字符串元素(tickerSymbol)的复合类型元素。 * TradePriceResult(交易价格): 将该元素定义为一个包含一个浮点数元素(price)的复合类型元素。message name=GetLastTradePriceInput 这部分是消息格式的抽象定义,其中定义了两个消息格式: * GetlastTradePriceInput(获取最后交易价格的请求消息格式): 由一个消息片断组成,该消息片断的名字是body,包含的具体元素类型是TradePriceRequest。(前面已经定义过了) * GetLastTradePriceOutput(获取最后交易价格的响应消息格式) : 由一个消息片断组成,该消息片断的名字是body,包含的具体元素类型是TradePriceResult。(前面已经定义过了) 这部分定义了服务访问点的调用模式的类型,表明StockQuoteService的某个入口类型是请求/响应模式,请求消息是GetlastTradePriceInput,而响应消息是GetLastTradePriceOutput。binding name=StockQuoteSoapBinding type=tns:StockQuotePortType 这部分将服务访问点的抽象定义与SOAP HTTP绑定,描述如何通过SOAP/HTTP来访问按照前面描述的访问入口点类型部署的访问入口。其中规定了在具体SOAP调用时,应当使用的 soapAction是/GetLastTradePrice,而请求/响应消息的编码风格都应当采用SOAP 规范默认定义的编码风格 /soap/encoding/。 股票查询服务 这部分是具体的Web服务的定义,在这个名为StockQuoteService的Web服务中,提供了一个服务访问入口,访问地址是/stockquote,使用的消息模式是由前面的binding所定义的。 按照这个WSDL文档的描述,在具体Web服务的使用中,具体发生的SOAP交互可能如下面所示:SOAP消息请求:POST /StockQuote HTTP/1.1 Host: Content-Type: text/xml; charset=utf-8 Content-Length: nnnn SOAPAction: /GetLastTradePrice MSFT SOAP消息响应:HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: nnnn 74.5 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工作原理如下图所示 : 前面几节都是讲一些理论知识,现在又用一个例子来说明一下,这一节我们就CXF框架对象传递进行讲解。XmlRootElement(name=Customer) XmlAccessorType(XmlAccessType.FIELD) XmlType(propOrder = name,age) public class Customer private int age; private String name; public int getAge() return age; public void setAge(int age) this.age = age; public String getName() return name; public void setName(String name) = name; XmlRootElement-指定XML根元素名称(可选) XmlAccessorType-控制属性或方法序列化 FIELD-对每个非静态,非瞬变属性JAXB工具自动绑定成XML,除非注明XmlTransient NONE-不做任何处理 PROPERTY-对具有set/get方法的属性进行绑定,除非注明XmlTransient PUBLIC_MEMBER -对有set/get方法的属性或具有共公访问权限的属性进行绑定,除非注 明XmlTransient XmlType-映射一个类或一个枚举类型成一个XML Schema类型 XmlType-映射一个类或一个枚举类型成一个XML Schema类型第二步:创建WebService接口WebService public interface HelloService public void save(Customer c1,Customer c2); public void test(String args); public Customer get(int id); WebService public class HelloServiceImpl implements HelloService public void save(Customer c1, Customer c2) System.out.println(c1.getAge()+-+c2.getAge(); System.out.println(c1.getName()+-+c2.getName(); public void test(String args) System.out.println(args); public Customer get(int id) Customer cus = new Customer(); cus.setAge(100); cus.setName(Josen); return cus; 第四步:创建服务端public class SoapServer public static void main(String args) /两种方法,任选一种发布WebService接口 /Endpoint.publish(http:/localhost:8080/helloService, new HelloServiceImpl(); JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean(); factory.setAddress(http:/localhost:8080/helloService); factory.setServiceClass(HelloServiceImpl.class); factory.getInInterceptors().add(new LoggingInInterceptor(); factory.getOutInterceptors().add(new LoggingOutInterceptor(); factory.create(); 第五步:创建客户端public class SoapClient public static void main(String args) JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setAddress(http:/localhost:8080/helloService); factory.setServiceClass(HelloService.class); factory.setServiceClass(HelloServiceImpl.class); factory.getInInterceptors().add(new LoggingInInterceptor(); HelloService service = (HelloService)factory.create(); Customer c1 = new Customer(); c1.setAge(1); c1.setName(aaa); Customer c2 = new Customer(); c2.setAge(2); c2.setName(bbb); service.save(c1, c2); service.test(aaaaaaaaaaaaa); 最后,测试程序 运行服务端程序,在浏览器地址栏输入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=, User-Agent=Apache CXF 2.2.2, Content-Type=text/xml; charset=UTF-8, Accept=*/*/*, Pragma=no-cache, Cache-Control=no-cache Payload: Josen - 2010-1-9 20:41:56 erceptor.LoggingOutInterceptor$LoggingCallback onClose 信息: Outbound Message - ID: 1 Encoding: UTF-8 Content-Type: text/xml Headers: Payload: hi Josen - 2010-01-09 20:41:56.578:INFO: seeing JVM BUG(s) - cancelling interestOps=0 当客户端向服器发送请求时,服务端LoggingInInterceptor拉截客户端发送过来的SOAP消息,如下: Josen 客户端将请求信息封闭在中,当然也可以将其放到,只要在WebParam中的header设置成true,默认为false;服务器接到请求之后,响应客户端。同样以SOAP形式将信息封装好发回客户端,SOAP信息如下: hi Josen 前面几节我们讲解对象传递,但是通常情况下我们不直接传对象,因为直接传递对象安全性差,而且暴露了实体对象。所以我们选择传递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 输出应该是等同的。我们还以例子来说明它的工作原理,直观点。 第一步,创建一个Customer对象XmlRootElement(name=customer) XmlAccessorType(XmlAccessType.FIELD) XmlType(name = ) public class Customer XmlAttribute(required = true) protected String name; XmlAttribute(required = true) protected int age; /* */* * Gets the value of the name property. * * return * possible object is * link String * */ public String getName() return name; /* */* * Sets the value of the name property. * * param value * allowed object is * link String * */ public void setName(String value) = value; /* */* * Gets the value of the age property. * */ public int getAge() return age; /* */* * Sets the value of the age property. * */ public void setAge(int value) this.age = value; 第二步,创建一个测试类public class SoapClient private final static String MODEL = com.itdcl.model; public static void main(String args) throws ParserConfigurationException, JAXBException, TransformerException ObjectFactory factory = new ObjectFactory(); Customer customer = factory.createCustomer(); customer.setAge(20); customer.setName(Josen); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.newDocument(); JAXBContext jaxbContext = JAXBContext.newInstance(MODEL); /Java对象转换成XML Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.marshal(customer, doc); DOMSource domSource = new DOMSource(doc); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); transformer.transform(domSource, resu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论