webservice -- cxf客户端调用axis2服务端
背景:
有个项目, 需要由第三方提供用户信息, 实现用户同步操作, 对方给提供webservice接口(axis2实现)并也使用axis2作主客户端调用我方提供的webservice接口
起初, 由于项目使用了spring, 且spring可与cxf较好的集成, 所以也就选用了cxf,
可问题随之出现, 接口可以调用到, 接口的具体方法也可以调用到,
但是,
1. cxf作为客户端, 获取服务端返回值时均为null.
2. cxf作为服务端, 获取axis2客户端传来的参数时, 也均为null.
针对上述问题, 做了大量调试模拟, 如有不妥之处, 敬请指正.
一. axis2服务器搭建
简单起见, axis2r搭建采用较为简单的一种方式, 即将服务类和services.xml打成.aar包发布.
1. 下载部署axis2
http://axis.apache.org/axis2/java/core/
这里选择下载的1.7.0版本, axis2-1.7.0-war.zip
2. 将zip文件中的axis2.war包解压到tomcat的webapps目录中, 启动tomcat,
完成axis2的安装部署, 如下图:
3. 访问 http://localhost/axis2 显示如下页面, 表示axis2部署成功
4. 访问 http://localhost/axis2/services/listServices , 可查看此axis2所发布的webservice服务, 如下图:
其中, Version为axis2默认发布的服务, getVersion是此服务的方法
二. 编写发布webserivce接口
1. 新建java项目myAxis2
2. 创建服务类HelloShooter.java
package com.shooter.webservice; public class HelloShooter { public void getShooterId(String shooterId) {
System.out.println("狙击手编号: " + shooterId);
} public String shoot(int num) {
return "本次出击共狙击 " + num + " 名敌军";
} public String undershoot() {
return "脱靶, 很遗憾!";
} }
3. 新建META-INF目录, 并创建services.xml文件
services.xml源码如下:
<serviceGroup>
<!-- 第一个webservice服务 -->
<service name="HelloShooter" targetNamespace="http://sharp-shooter">
<!-- 命名空间 -->
<schema schemaNamespace="http://sharp-shooter" />
<!-- 发布的服务类全路径 -->
<parameter name="ServiceClass">com.shooter.webservice.HelloShooter
</parameter>
<!-- 对每个方法配置处理器 -->
<operation name="getShooterId">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
</operation>
<operation name="shoot">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</operation>
<operation name="undershoot">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</operation>
</service>
</serviceGroup>
另一种services.xml编写方式, 配置全局处理器, 但此种方法我没有成功过, 如哪位测试成功了, 交流一下
<serviceGroup>
<!-- 第一个webservice服务 -->
<service name="HelloShooter" targetNamespace="http://sharp-shooter.com">
<!-- 命名空间 -->
<schema schemaNamespace="http://sharp-shooter.com" />
<!-- 发布的服务类全路径 -->
<parameter name="ServiceClass">com.shooter.webservice.HelloShooter</parameter>
<messageReceivers>
<!--有返回值的处理器-->
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
<!--无返回值的处理器-->
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
</messageReceivers>
</service>
</serviceGroup>
其中,
1) service元素的name属性为服务名称, 如果没有设置此属性, 那么服务名称为发布包名, 如发布包为shooter.aar, 则服务名为shooter
2) schema配置的为命名空间, 并在service元素中配置同样的命名空间
3) parameter name="ServicesClass"配置的为服务类的全路径
4) 处理器, 第一种方式为全局处理器, 第二各方式为为某个方法配置所需要的处理器
4. 创建.aar包
1) 使用myeclipse的导出功能, 导出编写的服务类和services.xml文件为jar包, 如图:
可去除不必要的文件.
2) 修改包扩展名为.aar
3) 将.aar包拷贝到...\apache-tomcat-6.0.35-80\webapps\axis2\WEB-INF\services目录中(自动部署), 完成服务端发布
4) 访问 http://localhost/axis2/services/listServices , 服务页面显示HelloShooter服务, 则发布成功
三. CXF客户端
1. 新建项目, 引入所需CXF的maven依赖(此处有坑, 后文解释)
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.2.9</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-core</artifactId>
<version>2.2.9</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.2.9</version>
</dependency>
2. 获取HelloShooter的接口信息
访问 http://localhost/axis2/services/HelloShooter?wsdl, 获取如下信息:
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ns="http://sharp-shooter"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
targetNamespace="http://sharp-shooter">
<wsdl:documentation>HelloShooter</wsdl:documentation>
<wsdl:types>
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://sharp-shooter">
<xs:element name="undershoot">
<xs:complexType>
<xs:sequence />
</xs:complexType>
</xs:element>
<xs:element name="undershootResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="shoot">
<xs:complexType>
<xs:sequence>
<xs:element name="num" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="shootResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getShooterId">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="shooterId" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="undershootRequest">
<wsdl:part name="parameters" element="ns:undershoot" />
</wsdl:message>
<wsdl:message name="undershootResponse">
<wsdl:part name="parameters" element="ns:undershootResponse" />
</wsdl:message>
<wsdl:message name="shootRequest">
<wsdl:part name="parameters" element="ns:shoot" />
</wsdl:message>
<wsdl:message name="shootResponse">
<wsdl:part name="parameters" element="ns:shootResponse" />
</wsdl:message>
<wsdl:message name="getShooterIdRequest">
<wsdl:part name="parameters" element="ns:getShooterId" />
</wsdl:message>
<wsdl:message name="getShooterIdResponse" />
<wsdl:portType name="HelloShooterPortType">
<wsdl:operation name="undershoot">
<wsdl:input message="ns:undershootRequest" wsaw:Action="urn:undershoot" />
<wsdl:output message="ns:undershootResponse" wsaw:Action="urn:undershootResponse" />
</wsdl:operation>
<wsdl:operation name="shoot">
<wsdl:input message="ns:shootRequest" wsaw:Action="urn:shoot" />
<wsdl:output message="ns:shootResponse" wsaw:Action="urn:shootResponse" />
</wsdl:operation>
<wsdl:operation name="getShooterId">
<wsdl:input message="ns:getShooterIdRequest" wsaw:Action="urn:getShooterId" />
<wsdl:output message="ns:getShooterIdResponse" wsaw:Action="urn:getShooterIdResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloShooterSoap11Binding" type="ns:HelloShooterPortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<wsdl:operation name="undershoot">
<soap:operation soapAction="urn:undershoot" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="shoot">
<soap:operation soapAction="urn:shoot" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getShooterId">
<soap:operation soapAction="urn:getShooterId" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="HelloShooterSoap12Binding" type="ns:HelloShooterPortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<wsdl:operation name="undershoot">
<soap12:operation soapAction="urn:undershoot" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="shoot">
<soap12:operation soapAction="urn:shoot" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getShooterId">
<soap12:operation soapAction="urn:getShooterId" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="HelloShooterHttpBinding" type="ns:HelloShooterPortType">
<http:binding verb="POST" />
<wsdl:operation name="undershoot">
<http:operation location="undershoot" />
<wsdl:input>
<mime:content type="application/xml" part="parameters" />
</wsdl:input>
<wsdl:output>
<mime:content type="application/xml" part="parameters" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="shoot">
<http:operation location="shoot" />
<wsdl:input>
<mime:content type="application/xml" part="parameters" />
</wsdl:input>
<wsdl:output>
<mime:content type="application/xml" part="parameters" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getShooterId">
<http:operation location="getShooterId" />
<wsdl:input>
<mime:content type="application/xml" part="parameters" />
</wsdl:input>
<wsdl:output>
<mime:content type="application/xml" part="parameters" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloShooter">
<wsdl:port name="HelloShooterHttpSoap11Endpoint" binding="ns:HelloShooterSoap11Binding">
<soap:address location="http://localhost/axis2/services/HelloShooter.HelloShooterHttpSoap11Endpoint/" />
</wsdl:port>
<wsdl:port name="HelloShooterHttpSoap12Endpoint" binding="ns:HelloShooterSoap12Binding">
<soap12:address location="http://localhost/axis2/services/HelloShooter.HelloShooterHttpSoap12Endpoint/" />
</wsdl:port>
<wsdl:port name="HelloShooterHttpEndpoint" binding="ns:HelloShooterHttpBinding">
<http:address location="http://localhost/axis2/services/HelloShooter.HelloShooterHttpEndpoint/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
3. 根据接口信息, 创建客户端接口
package com.shooter.cxf.client; import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService; @WebService(name="HelloShooter", targetNamespace="http://sharp-shooter")
public interface IHelloShooter { @WebMethod(operationName="getShooterId")
public void getShooterId(@WebParam(name="shooterId", targetNamespace="http://sharp-shooter")String shooterId); @WebMethod(operationName="shoot")
public @WebResult(targetNamespace="http://sharp-shooter") String shoot(@WebParam(name="num", targetNamespace="http://sharp-shooter")int num); @WebMethod(operationName="undershoot")
public @WebResult(targetNamespace="http://sharp-shooter") String undershoot(); }
注意重点: 此接口主要在4处添加了注解, 分别是: 类, 方法, 方法参数, 方法返回值,
前面描述的项目中出现的问题, 也正在这里某一处或几处没有添加注解引起的(说实话, 感觉有点怪怪的, 哪位大神有更好的办法, 求赐教)
4. 创建接口调用测试类
package com.shooter.cxf.client; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; public class CXFClient { public static void main(String[] args) {
// 保存返回值
String result = ""; String url = "http://localhost/axis2/services/HelloShooter";
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(IHelloShooter.class);
factory.setAddress(url);
// 创建接口代理对象
IHelloShooter helloServices = (IHelloShooter) factory.create(); // 调用接口方法
helloServices.getShooterId("1123"); System.out.println("-----------------------------");
result = helloServices.shoot(6);
System.out.println(result); System.out.println("-----------------------------");
result = helloServices.undershoot();
System.out.println(result);
}
}
执行main方法:
1) getShooterId()方法, 无返回值, 服务端打印相关信息
2) shoot()和undershoot()方法, 有返回值, 在客户端打印相关信息
运行不粗来? 客户端报异常? getShooterId()方法? 那就对了...
填坑:
调试的时候, 试验N多次, 客户端总报如下异常信息:
Exception in thread "main" org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader.
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:238)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:60)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:801)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1679)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1517)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1425)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:650)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:462)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:365)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:318)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:338)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:324)
at com.jialin.ejb.MyClient.main(MyClient.java:40)
Caused by: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
at [row,col {unknown-source}]: [1,0]
at com.ctc.wstx.sr.StreamScanner.throwUnexpectedEOF(StreamScanner.java:677)
at com.ctc.wstx.sr.BasicStreamReader.handleEOF(BasicStreamReader.java:2116)
at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:2022)
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1114)
at com.ctc.wstx.sr.BasicStreamReader.nextTag(BasicStreamReader.java:1137)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:139)
... 17 more
提炼一下, 就俩信息: Error reading XMLStreamReader.和[row,col {unknown-source}]: [1,0]
客户端出问题(当然也不能这么说, 当时的第一感觉)
各种试, 最后换了CXF的版本, 问题解决了
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.7.16</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-core</artifactId>
<version>2.7.16</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.7.16</version>
</dependency>
网上好像有帖子说服务端的问题, 个人觉得也不好这样说,
暂且说服务端与客户端版本不匹配吧,
如果有更好的解释, 不吝赐教
webservice -- cxf客户端调用axis2服务端的更多相关文章
- 基于Apache CXF的Web Service服务端/客户端
转自:https://www.aliyun.com/zixun/wenji/1263190.html CXF服务端: package com.sean.server; import javax.jws ...
- Silverlight客户端调用WCF服务难题解疑
一:解决办法 Silverlight客户端调用WCF服务在实际使用中经常会出现的问题就是无法直接应用类文件和配置文件.微软针对这一情况已经给出了解决办法.WCF开发框架可以帮助我们实现可靠性较高的跨平 ...
- 利用python多线程实现多个客户端与单个服务端的远程ssh
本次实验设计两个方面的代码,第一个是客户端,代码如下: import os from socket import * c = socket(AF_INET,SOCK_STREAM) c.connect ...
- java版gRPC实战之六:客户端动态获取服务端地址
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Android客户端与PHP服务端交互(一)---框架概述
背景 作为一个普通上班族,总是想做一些自认为有意义的事情,于是乎准备成立一个工作室,尽管目前正在筹备阶段,但是之前有些朋友提出一些需求的时候,我发现自己的能力还是有限,直到最近和一些技术牛朋友聊起这事 ...
- C#使用Thrift简介,C#客户端和Java服务端相互交互
C#使用Thrift简介,C#客户端和Java服务端相互交互 本文主要介绍两部分内容: C#中使用Thrift简介 用Java创建一个服务端,用C#创建一个客户端通过thrift与其交互. 用纯C#实 ...
- SpringCloud系列二:Restful 基础架构(搭建项目环境、创建 Dept 微服务、客户端调用微服务)
1.概念:Restful 基础架构 2.具体内容 对于 Rest 基础架构实现处理是 SpringCloud 核心所在,其基本操作形式在 SpringBoot 之中已经有了明确的讲解,那么本次为 了清 ...
- 6-1 建立客户端与zk服务端的连接
6-1 建立客户端与zk服务端的连接 zookeeper原生java api使用 会话连接与恢复; 节点的增删改查; watch与acl的相关操作; 导入jar包;
- android客户端app和服务端交互token的作用
Android客户端和服务端如何使用Token和Session niceheart关注1人评论34644人阅读2014-09-16 16:38:44 对于初学者来说,对Token和Session的 ...
随机推荐
- 在windows下安装Redis步骤(收集)
一.下载windows版本的Redis 去官网找了很久,发现原来在官网上可以下载的windows版本的,现在官网以及没有下载地址,只能在github上下载,官网只提供linux版本的下载 官网下载地址 ...
- 快速开发微信小程序
image.png 最近婷主在做微信小程序.自己的微信公众号也需要添加点料,乘着这次放假,把微信小程序研究了下.虽然没有做什么很强大的功能,不过好歹自己的公众号也有了微信小程序.够用即可. 1.需要先 ...
- sql语句中3表删除和3表查询
好久没来咱们博客园了,主要近期在忙一些七七八八的杂事,包括打羽毛球比赛的准备和自己在学jqgrid的迷茫.先不扯这些没用的了,希望大家能记得小弟,小弟在此谢过大家了. 回归正题:(以下的sql是本人在 ...
- html input size maxlength
最近做项目用到input的size和maxlength属性,以前只顾用没有用心去看看这2个标签的区别,今天周末baidu了一下,有所理解.特记录于此! <p>Name: <inp ...
- base 64
我们的图片大部分都是可以转换成base64编码的data:image. 这个在将canvas保存为img的时候尤其有用.虽然除ie外,大部分现代浏览器都已经支持原生的基于base64的encode和d ...
- 【python】pyqt练习
import sys from PyQt4.QtCore import * from PyQt4.QtGui import * import ui_price class PriceDlg(QDial ...
- (一)Spring容器相关操作
一.spring事件 spring的事件有如下两个成员. 1.ApplicationEvent,容器事件,由容器发布 2.ApplicationListener 监听器,可以由容器中的任何监听器Bea ...
- 你不知道的Console命令
一.显示信息的命令 1: <!DOCTYPE html> 2: <html> 3: <head> 4: <title>常用console命令</t ...
- IOS控件:计算文字长度(UITextField,UILabel对象 和 IBAction)
#import <UIKit/UIKit.h> // UIViewController类为程序提供了基本的视图管理模块 @interface NavControllerViewContro ...
- CNBlog客户端--第一阶段记录
开始 五一小长假由于没有出去玩,所以我就用来继续写我的 CNBlog Android 客户端!首先呢!先上图!让大家看看,我做到哪儿了!! 不知道大家看了是什么感觉哈!有意见请评论哦!! 完成度以及遇 ...