CXF学习

来源:互联网 发布:淘宝卖家开店客服电话 编辑:程序博客网 时间:2024/05/23 15:06
CXF的实现
服务器与客户端对于服务,怎么映射。

是以类名?
http://blog.csdn.net/segen_jaa/article/details/12947305 
http://blog.csdn.net/pingyongpy/article/details/6752835 

配置Spring与CXF的集成,主要是利用jetty容器发布webservice,然后客户端消费service。
Apache CXF 提供方便的Spring整合方法,可以通过注解、Spring标签式配置来暴露Web Services和消费Web Services:
   
 1、 所需jar包:
  CXF+Spring所需jar包
 2、 spring配置:
  "在Spring的配置文件中,需要对其进行配置:
首先在ApplicationContext.xml(Spring的配置文件)中引入CXF的XML Scheam 配置文件),如下:
<beans xmlns=""http://www.springframework.org/schema/beans"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:jaxws=""http://cxf.apache.org/jaxws"" xsi:schemaLocation=""http://www.springframework.org/schema/beans      http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd""> <!—还需要引入以下3个关于CXF的资源文件,这三个文件在cxf.jar中--> <import resource=""classpath:META-INF/cxf/cxf.xml"" /> <import resource=""classpath:META-INF/cxf/cxf-extension-soap.xml""/> <import resource=""classpath:META-INF/cxf/cxf-servlet.xml"" /> …… …… …… …… …… …… …… …… …… ……</bean>

 3、 修改web.xml文件:
<servlet>  <servlet-name>CXFServlet</servlet-name>  <servlet-class>   org.apache.cxf.transport.servlet.CXFServlet  </servlet-class></servlet><servlet-mapping>  <servlet-name>CXFServlet</servlet-name>  <url-pattern>/services/*</url-pattern></servlet-mapping>注意<url-pattern>/ services /*</url-pattern>配置,CXFServlet会拦截此类url,进行处理。

 4、 写webservice接口:
package com.dqm.demo.service;import javax.jws.WebMethod;import javax.jws.WebResult;import javax.jws.WebService;import org.apache.cxf.annotations.EndpointProperty;/** * webservice接口 *  * @author dongqm * @since 2013-2-26 * @lastChange $Author$ * @lastChangeDate $Date$ * @version $Rev$ */@WebServicepublic interface IHelloWorld { @WebMethod(operationName = ""SayHelloWorld"") @WebResult(name = ""result"") public String sayHelloWorld(WebParam(name=""name"") String name);}

Java Web Service (JWS) 注解类型
 
级别注解参数含义类级别WebService(targetNamespace = "", name = "",serviceName = "")targetNamespace 生成的 WSDL 中使用的名称空间
默认为:接口所在的包的路径的反序nameWeb Service 的名称
映射到 WSDL 文件中的 <wsdl:portType> 元素
默认为:接口名称serviceNameWeb Service 的服务名
映射到 WSDL 文件<wsdl:service>元素。
默认为:接口名称 + "Service"SOAPBinding(style = Style.RPC, use = Use.LITERAL)style 定义发送到 Web Service 的消息和从 Web Service 发送的消息的编码样式。
Document和RPC两种形式    
默认值:javax.jws.soap.SOAPBinding.Style.DOCUMENTuse  定义发送到 Web Service 的消息和从 Web Service 发送的消息的格式样式。          
ENCODED和 LITERAL两种形式
默认值:javax.jws.soap.SOAPBinding.Use.LITERAL方法级别WebResult(name = "", targetNamespace = "")name指定生成的 WSDL 中的操作结果的名称
默认名称“return”WebMethod(action="sayHello",operationName="")action此操作的动作。 对于 SOAP 绑定,此方法可确定 soap 动作的值。
WSDL中: <soap:operation soapAction="" style="document"/>
默认为:""operationName指定方法公开的公共操作名,映射到 WSDL 文件中的 <wsdl:operation> 元素
默认名称将与方法名相同WebParam(name="",targetNamespace="")name指定输入参数名,而不是该参数的Java名称“input”
默认为方法参数名
5、 接口实现类:

package com.dqm.demo.service;/** * webservice接口实现类 *  * @author dongqm * @since 2013-2-26 * @lastChange $Author$ * @lastChangeDate $Date$ * @version $Rev$ */public class HelloWorld implements IHelloWorld { /*  * (non-Javadoc)  * @see com.dqm.demo.IHelloWorld#sayHelloWorld(String name)  */ @Override public String sayHelloWorld(String name) {  return name + ""Say:Hello World!""; }}

 6、 Spring的配置文件中配置webservice:
<jaxws:endpoint address=""/Hello"" implementorClass=""com.dqm.demo.service.IHelloWorld"">        <jaxws:implementor>            <bean class=""com.dqm.demo.service.HelloWorld""/>        </jaxws:implementor> </jaxws:endpoint>注意:①、address 为webservice发布的地址②、implementorClass 为该webservice实现的接口③、<jaxws:implementor></jaxws:implementor>之间定义的是implementorClass 指定接口的实现类

对于服务器端webService的暴露还有另一种方法(如下):
<jaxws:server id="helloWebService" serviceClass="com.dqm.demo.service.IHelloWorld"  address="/Hello">  <jaxws:serviceBean>  <ref bean="helloService"/>  </jaxws:serviceBean>  </jaxws:server>
 7、 完成之后将项目部署到tomcat下,启动tomcat
  "输入URL:http://ip地址:tomcat端口/项目名称/services(web.xml里面配置的拦截的地址)/Hello(地址)?wsdl
将会看到生成的wsdl文件,说明webservice发布成功。
WSDL 文档元素
 
元素定义Types定义 web service 使用的数据类型。
为了最大程度的平台中立性,WSDL 使用 XML Schema 语法来定义数据类型。Message定义一个操作的数据元素。
每个消息均由一个或多个部件组成。可以把这些部件比作传统编程语言中一个函数调用的参数。PortType它可描述一个 web service、可被执行的操作,以及相关的消息。
可以把 <portType> 元素比作传统编程语言中的一个函数库(或一个模块、或一个类)。Operation对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对Binding每个端口定义消息格式和协议细节。Service相关服务访问点的集合Port定义为协议/数据格式绑定与具体Web访问地址组合的单个服务访问点
8、至此,服务器端的webservice已经部署完成,完成客户端的消费。
定义beanRefClient.xml客户端配置供Spring加载。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 引入以下3个关于CXF的资源文件,这三个文件在cxf.jar中 --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <jaxws:client id="helloServiceClient" serviceClass="com.dqm.demo.service.IHelloWorld"  address="http://localhost:8080/cxf_spring/services/Hello"></beans>

这与代码加载服务器,其实提供的属性是一样的,setServiceClass/setAddress

9、客户端代码实现
/** * @Title: HelloServiceClient.java * @Package: com.dqm.demo.service * @Project: cxf_spring * @Description: TODO * @author: Administrator * @date: 2014-3-16 下午9:50:03 */package com.dqm.demo.service;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @author: Administrator * @Description: */public class HelloServiceClient { public static void main(String[] args) {  // 加载客户端的配置定义  ApplicationContext context = new ClassPathXmlApplicationContext(    "beanRefClient.xml");  // 获取定义的 Web Service Bean  IHelloWorld surveyService = (IHelloWorld) context    .getBean("helloServiceClient");  // 1、定义调查投票的变量与内容,用来发送给服务  String username = "Test";  int point = 88;  // 调用方法进行服务消费  String result = surveyService.sayHelloWorld(username);  System.out.println("Result:" + result);  // 2、传递不一样的调查投票内容  username = "Michael";  point = 100;  // 再次调用方法进行服务消费,得到不一样的结果  result = surveyService.sayHelloWorld(username);  System.out.println("Result:" + result);  // 3、第三次传递与调用  username = "Jordan";  point = 9;  result = surveyService.sayHelloWorld(username);  System.out.println("Result:" + result); }}

上面返回的由于是基本数据类型,所以可以直接传送。而对于复杂数据类型,如何传送。或者传送时配置安排。


简单介绍下在IMACT中,他是如何使用的:
@WebResult(name = "return", targetNamespace = "") @RequestWrapper(localName = "getNode", targetNamespace = "http://com.core.imact.sysgo.com/", className = "com.sysgo.imact.core.client.internal.com.GetNode") @WebMethod @ResponseWrapper(localName = "getNodeResponse", targetNamespace = "http://com.core.imact.sysgo.com/", className = "com.sysgo.imact.core.client.internal.com.GetNodeResponse") public com.sysgo.imact.core.client.internal.com.NodeDTO getNode(   @WebParam(name = "arg0", targetNamespace = "") com.sysgo.imact.core.client.internal.com.GetNodeDTO arg0)   throws COMException;

上而是要暴露的webService接口方法。注意这是客户端的方法。
GetNodeDTO是作为客户端要传给服务器端的DTO。但作为客户端 代码,这个DTO类,也是在客户端 中的。
@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "getNodeDTO", propOrder = {    "id",    "parentFieldName",    "parentId"})public class GetNodeDTO {。。。。。。。
返回的DTO也是如此。
@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "nodeDTO", propOrder = {    "ableToDelete",    "dbId",    "dirty",    "domainObject",    "fields",    "freezable",    "frozen",    "groupingElement",    "id",    "lockable",    "locked",    "name",    "notExpandable",    "parentFieldName",    "parentId",    "superTypeNames",    "transientNode",    "type",    "typeName"})public class NodeDTO {

而在服务器端中,
@Override @WebMethod public NodeDTO getNode(GetNodeDTO getNodeDTO) throws COMException {  return genericNodeService.getNode(getNodeDTO); }

这里的DTO确是简单的VO对象。没有任何配置。所有的配置都已经在客户端完成了。

具体的配置信息还是需要看源代码的。
程序下载,点我




上面是需要在客户端beanRefClient.xml定义访问的address,需要指定相应的桩,在上面仍然使用的是服务器的代码。

---------------------------------------------------------------------------------------------------------------------------------
String加6种基本数据类型,都是可以的。包括6种的封装类。如int----Integer
http://blog.csdn.net/wlsyn/article/details/8756068 
http://blog.csdn.net/wlsyn/article/details/8755560 
对于复杂类型,只需要定义服务器的端的webService,接口,DTO(VO对象),而对于客户端的桩,则可以自动生成。

http://blog.csdn.net/segen_jaa/article/details/12947305 




所以有理由,可以完成不用管客户端的操作。这样代码就变得简单的多了。


例子程序 点我

0 0