用cxf发布和调用web service

用cxf发布和调用web service
http://cxf.apache.org/docs/jax-ws-configuration.html  官方API helloword地址


  用CXF来做web service是比较简单的,本文就简单介绍一下如何一步步发布web service,以及调用现有的web service。另外如果系统已经使用了Spring MVC,那么引入CXF需要额外的步骤,见本人另外一篇博客http://kyfxbl.iteye.com/blog/1432920。如果展现层没有用spring mvc,而是用struts2之类的,可以省去这一步  

首先介绍怎么发布web service: 

第1步是创建一个普通的java接口,然后用@WebService注解声明这是一个web service 
Java代码   收藏代码
  1. package com.huawei.framework.webservice;  
  2.   
  3. import javax.jws.WebService;  
  4.   
  5. import com.huawei.framework.model.User;  
  6.   
  7. @WebService  
  8. public interface HelloWorld {  
  9.   
  10.     String sayHi(User user);  
  11.   
  12. }  

可以看到,这个接口非常普通,不需要继承什么额外的接口,只需要注解一个@WebService就可以 

第2步当然是需要给这个接口提供一个实现类 
Java代码   收藏代码
  1. package com.huawei.framework.webservice;  
  2.   
  3. import com.huawei.framework.model.User;  
  4.   
  5. public class HelloWorldImpl implements HelloWorld {  
  6.   
  7.     public String sayHi(User theUser) {  
  8.         return "Hello " + theUser.getName() + " ,your age is "  
  9.                 + theUser.getAge();  
  10.     }  
  11.   
  12. }  

这个类更加简单,连注解都省了,但是如果这个类实现了不止一个接口,那么就需要加上@WebService注解,不过一般不会这样 

第3步就到了cxf出场的时候了,需要在spring配置文件中加上cxf的配置 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  ;
  6.                             http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  ;
  7.                             http://cxf.apache.org/jaxws   ;
  8.                             http://cxf.apache.org/schemas/jaxws.xsd">  
  9.   
  10.     <import resource="classpath:META-INF/cxf/cxf.xml" />  
  11.     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
  12.   
  13.     <jaxws:endpoint id="helloWorld"  
  14.         implementorClass="com.huawei.framework.webservice.HelloWorldImpl"  
  15.         address="/HelloWorld" />  
  16.   
  17. </beans>  

这里只写了CXF所需的配置,spring配置文件的其他内容已省略。用到的元素是<jaxws:endpoint>,implementorClass属性就是我们提供的实现类,然后address属性是这个web service对外暴露的路径 

最后第4步是在web.xml中加载cxf 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns="http://java.sun.com/xml/ns/javaee"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
  5.     id="MyFramework" version="3.0">  
  6.       
  7.     <display-name>MyFramework</display-name>  
  8.       
  9.     <context-param>  
  10.         <param-name>contextConfigLocation</param-name>  
  11.         <param-value>   
  12.             WEB-INF/beans.xml,   
  13.             WEB-INF/cxf.xml  
  14.         </param-value>   
  15.     </context-param>  
  16.       
  17.     <listener>    
  18.         <listener-class>    
  19.             org.springframework.web.context.ContextLoaderListener    
  20.         </listener-class>    
  21.     </listener>    
  22.       
  23.     <servlet>  
  24.         <servlet-name>framework</servlet-name>  
  25.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  26.         <init-param>    
  27.             <param-name>contextConfigLocation</param-name>    
  28.             <param-value>WEB-INF/spring-mvc.xml</param-value>    
  29.         </init-param>    
  30.         <load-on-startup>1</load-on-startup>  
  31.     </servlet>  
  32.   
  33.     <servlet-mapping>  
  34.         <servlet-name>framework</servlet-name>  
  35.         <url-pattern>/</url-pattern>  
  36.     </servlet-mapping>  
  37.       
  38.     <servlet>    
  39.         <servlet-name>CXFServlet</servlet-name>    
  40.         <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>    
  41.         <load-on-startup>2</load-on-startup>    
  42.     </servlet>    
  43.     
  44.     <servlet-mapping>    
  45.         <servlet-name>CXFServlet</servlet-name>    
  46.         <url-pattern>/webservice/*</url-pattern>    
  47.     </servlet-mapping>   
  48.       
  49. </web-app>  

这里写的比较复杂,是为了兼容spring mvc。这里把/webservice/*作为对外暴露的路径,和上面的web service address要结合起来,比如说http://ip:port/app_name/webservice/HelloWorld,就会指向这个例子里声明的web service接口 

=========================================================================================================
还有另一种配置方式
第3步  需要在applicationContext.xml配置文件中加上cxf的配置 


 
<!-- ant提供给shopping的接口  2016-03-01 by 于瀚韬   这是对外发布 -->
   <cxf:server serviceClass="com.qianhui.ant.web.shoppingInterface.AddUserInAnt" address="/antInterface">
<cxf:serviceBean> 
<bean class="com.qianhui.ant.web.shoppingInterface.AddUserInAntImpl"></bean>
</cxf:serviceBean>
</cxf:server>
<!-- LiteratorsMarkWSInterface  这是接收外部接口 -->
    <cxf:client id="LiteratorsMarkWSInterface" 
    serviceClass="com.qianhui.ant.web.LiteratorsMarkWSInterface.neusoft.LiteratorsMarkWSInterface" 
    address=" http://221.226.179.230/webservice/searchMarkWS"/>

第4步 在web.xml配置中加上
 <!-- cxf webService begin  -->
  <servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ant/*</url-pattern>
</servlet-mapping>
  <!-- cxf webService end  -->  

地址为:url-pattener + 
address
 

 
通过以上4步,就发布了一个web service,在浏览器里输入 http://ip:port/app_name/webservice ,就会看到这个sayHi的web service了,并且cxf已经自动生成了wsdl文件
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------



然后介绍一下怎么通过cxf调用已有的web service 

第一种 获得了wsdl地址

用wsdl2java命令,生成所需的java文件
将生成文件导入工程即可

------------------------------------------------------------------------------------------------------------------------------------------------------------
第二种 获得了wsdl文件

1、首先用wsdl2java命令,生成所需的java文件,当然前提是已经得到了wsdl文件 

wsdl2java -p com.huawei.wfm.czekh.webservice.remedy -d ../../src/remedy -all fileName.wsdl  
用上面这个命令,就可以根据wsdl文件,生成所需的所有java文件,参数说明如下: 

-p 指定生成java文件的package name 
-d 生成java文件的存放路径 
-all 生成客户端和服务端代码,这里还可以用-client生成客户端,用-server生成服务端,不过实际上区别不大,只要用-all就可以了 
最后一个参数就是目标wsdl文件 

2、查看生成的文件列表,可以看到有以下文件: 



大部分都是model类,可以不管。以下文件是比较特殊的: 

ObjectFactory.java 
package-info.java 
这2个文件我也不知道是干嘛的,不过反正是不能删的 

以_Client结尾的那个文件,是一个客户端,没有用,可以删除 
以_Server结尾的那个文件,是启动服务端(貌似是内置的jetty),没有用,可以删除 

以Service结尾的那个文件,不但没有用,还要坏事,因为其中有以下代码: 
Java代码   收藏代码
  1. @WebServiceClient(name = "CIP-B2B_ServiceAssuranceWorkForceClientManagementService", wsdlLocation = "file:CIP-B2B_ServiceAssuranceWorkForceClientManagement.wsdl", targetNamespace = "http://cz.o2.com/systems/integrationinfrastructure/CIP-B2B/CIP-B2B_ServiceAssuranceWorkForceClientManagement/1.0")  

里面有一个"file:CIP-B2B_ServiceAssuranceWorkForceClientManagement.wsdl",因为这些类是根据一个本地的wsdl文件生成的,但是实际部署的时候一般不会放这个文件,所以在加载cxf配置的时候,是会出错的 
实际上试验发现,这个文件可以直接删掉 

以PortType结尾的文件,很关键,是接口类 

以PortTypeImpl结尾的文件,是接口类的实现类,其中也有一行注解: 
Java代码   收藏代码
  1. @javax.jws.WebService(  
  2.                       serviceName = "CIP-B2B_ServiceAssuranceWorkForceClientManagementService",  
  3.                       portName = "CIP-B2B_ServiceAssuranceWorkForceClientManagementPort",  
  4.                       targetNamespace = "http://cz.o2.com/systems/integrationinfrastructure/CIP-B2B/CIP-B2B_ServiceAssuranceWorkForceClientManagement/1.0",  
  5.                       wsdlLocation = "file:CIP-B2B_ServiceAssuranceWorkForceClientManagement.wsdl",  
  6.                       endpointInterface = "com.huawei.wfm.czekh.webservice.remedy.CIPB2BServiceAssuranceWorkForceClientManagementPortType")  

要把这里的 
Java代码   收藏代码
  1. wsdlLocation = "file:CIP-B2B_ServiceAssuranceWorkForceClientManagement.wsdl",  

删除 

所以在用wsdl2java命令生成java类之后,只需要把XXXService.java、XXX_Client.java、XXX_Server.java删除,把XXXPortTypeImpl.java改一下,就能用了 

然后如果是要做客户端的话,就把除了XXXPortTypeImpl.java以外的所有文件拷贝到工程里;如果是做服务端的话,就把所有文件拷贝到工程里,然后根据实际情况修改XXXPortTypeImpl.java就可以了
 

3、最后是cxf的配置文件,这里和http://kyfxbl.iteye.com/blog/1432952提到的方式是一样的,没有区别 

首先是服务端: 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:jaxws="http://cxf.apache.org/jaxws"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans  ;
  7.                             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  ;
  8.                             http://www.springframework.org/schema/context   ;
  9.                             http://www.springframework.org/schema/context/spring-context-3.0.xsd  ;
  10.                             http://cxf.apache.org/jaxws   ;
  11.                             http://cxf.apache.org/schemas/jaxws.xsd">  
  12.   
  13.     <context:component-scan base-package="com.huawei.wfm.czekh" />  
  14.   
  15.     <import resource="classpath:META-INF/cxf/cxf.xml" />  
  16.     <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />  
  17.     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
  18.   
  19.     <jaxws:endpoint id="remedy" implementor="#MyWebserviceServer"  
  20.         address="/RemedyWebService" />  
  21.   
  22. </beans>  

Java代码   收藏代码
  1. @Component("MyWebserviceServer")  
  2. @WebService(serviceName = "CIP-B2B_ServiceAssuranceWorkForceClientManagementService", portName = "CIP-B2B_ServiceAssuranceWorkForceClientManagementPort", targetNamespace = "http://cz.o2.com/systems/integrationinfrastructure/CIP-B2B/CIP-B2B_ServiceAssuranceWorkForceClientManagement/1.0", endpointInterface = "com.huawei.wfm.czekh.webservice.remedy.CIPB2BServiceAssuranceWorkForceClientManagementPortType")  
  3. public class CIPB2BServiceAssuranceWorkForceClientManagementPortTypeImpl  
  4.         implements CIPB2BServiceAssuranceWorkForceClientManagementPortType {  
  5.   
  6.     @Autowired  
  7.     private Test test;  
  8.   
  9.         // 省略无关方法     
  10.   
  11.     public AcknowledgeResponse acknowledge(  
  12.             AcknowledgeRequest body) {  
  13.   
  14.         test.sayHi("somebody");  
  15.   
  16.         AcknowledgeResponseBody responseBody = new AcknowledgeResponseBody();  
  17.         responseBody.setStatus(true);  
  18.         responseBody.setErrorDescription("wcnm");  
  19.   
  20.         AcknowledgeResponse result = new AcknowledgeResponse();  
  21.         result.setResponseBody(responseBody);  
  22.   
  23.         return result;  
  24.     }  
  25.   
  26. }  

可以看到,配置方式没有变化,也可以用spring进行依赖注入 

然后是客户端: 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.     xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans   ;
  6.                         http://www.springframework.org/schema/beans/spring-beans.xsd  ;
  7.                         http://cxf.apache.org/jaxws   ;
  8.                         http://cxf.apache.org/schemas/jaxws.xsd">  
  9.   
  10.     <bean id="propertyConfigurer"  
  11.         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  12.         <property name="locations">  
  13.             <list>  
  14.                 <value>classpath:webservice_address.properties</value>  
  15.             </list>  
  16.         </property>  
  17.     </bean>  
  18.   
  19.     <jaxws:client id="client"  
  20.         serviceClass="com.huawei.wfm.remedy.CIPB2BServiceAssuranceWorkForceClientManagementPortType"  
  21.         address="${remedy_address}" />  
  22.   
  23. </beans>  

Java代码   收藏代码
  1. public class Main {  
  2.   
  3.     public static void main(String[] args) {  
  4.   
  5.         ApplicationContext context = new ClassPathXmlApplicationContext(  
  6.                 "cxf.xml");  
  7.         CIPB2BServiceAssuranceWorkForceClientManagementPortType client = (CIPB2BServiceAssuranceWorkForceClientManagementPortType) context  
  8.                 .getBean("client");  
  9.   
  10.         AcknowledgeRequestBody body = new AcknowledgeRequestBody();  
  11.         body.setCustSysId("123456");  
  12.   
  13.         AcknowledgeRequest request = new AcknowledgeRequest();  
  14.         request.setRequestBody(body);  
  15.   
  16.         AcknowledgeResponse response = client.acknowledge(request);  
  17.         String desc = response.getResponseBody().getErrorDescription();  
  18.         System.out.println(desc);  
  19.   
  20.     }  
  21.   
  22. }  

客户端的配置也是一样的。有一点要注意,好像只能通过getBean("client")拿到实例化的bean,通过@Autowired可能是搞不定的 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值