`
peterwei
  • 浏览: 250279 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

cxf调用.net webservice之any元素

阅读更多
这两天工作之余帮前公司的小弟调一个比较恶心的Web Service问题。是CXF Java客户端调用.net Web Service的接口。接口返回类型是复杂类型,而且是<any> type,这个类型比较变态,cxf的wsdl2java不能很好的转换该类型。请看详请。

接口Wsdl主要内容展示:
<?xml version="1.0" encoding="utf-8" ?>
-
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
	xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://esf.soufun.com/"
	xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
	xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://esf.soufun.com/"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
	-
	<wsdl:types>
		-
		<s:schema elementFormDefault="qualified" targetNamespace="http://esf.soufun.com/">
//.net接口
			<s:element name="AgentInfo">
				-
				<s:complexType>
					-
					<s:sequence>
						<s:element minOccurs="0" maxOccurs="1" name="userName"
							type="s:string" />
						<s:element minOccurs="0" maxOccurs="1" name="pwd" type="s:string" />
					</s:sequence>
				</s:complexType>
			</s:element>
			-
//.net 接口返回类型。
			<s:element name="AgentInfoResponse">
				-
				<s:complexType>
					-
					<s:sequence>
						-
						<s:element minOccurs="0" maxOccurs="1" name="AgentInfoResult">
							-
							<s:complexType mixed="true">
								-
								<s:sequence>
									<s:any />
								</s:sequence>
							</s:complexType>
						</s:element>
					</s:sequence>
				</s:complexType>
			</s:element>
			-
			//省略N多字
	<wsdl:service name="Service">
		-
		<wsdl:port name="ServiceSoap" binding="tns:ServiceSoap">
			<soap:address
				location="http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx" />
		</wsdl:port>
		-
		<wsdl:port name="ServiceSoap12" binding="tns:ServiceSoap12">
			<soap12:address
				location="http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx" />
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>


关于<any>类型
<any> 元素
<any> 元素使我们有能力通过未被 schema 规定的元素来拓展 XML 文档!
下面这个例子是从名为 "family.xsd" 的 XML schema 中引用的片段。它展示了一个针对 "person" 元素的声明。通过使用 <any> 元素,我们可以通过任何元素(在
<lastname> 之后)扩展 "person" 的内容:
<xs:element name="person">

  <xs:complexType>

    <xs:sequence>

      <xs:element name="firstname" type="xs:string"/>

      <xs:element name="lastname" type="xs:string"/>

      <xs:any minOccurs="0"/>

    </xs:sequence>

  </xs:complexType>

</xs:element>
现在,我们希望使用 "children" 元素来扩展 "person" 元素。这此种情况下我们就可以这么做,即使以上这个 schema 的作者没有声明任何 "children" 元素。
请看这个 schema 文件,名为 "children.xsd":
<?xml version="1.0" encoding="ISO-8859-1"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://www.devwb.com"

xmlns="http://www.devwb.com"

elementFormDefault="qualified">



<xs:element name="children">

  <xs:complexType>

    <xs:sequence>

      <xs:element name="childname" type="xs:string"

      maxOccurs="unbounded"/>

    </xs:sequence>

  </xs:complexType>

</xs:element>



</xs:schema>

下面这个 XML 文件(名为 "Myfamily.xml"),使用了来自两个不同的 schema 中的成分,"family.xsd" 和 "children.xsd":
<?xml version="1.0" encoding="ISO-8859-1"?>



<persons xmlns="http://www.microsoft.com"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:SchemaLocation="http://www.microsoft.com family.xsd

http://www.devwb.com children.xsd">



<person>

<firstname>David</firstname>

<lastname>Smith</lastname>

<children>

  <childname>mike</childname>

</children>

</person>



<person>

<firstname>Tony</firstname>

<lastname>Smith</lastname>

</person>



</persons>

上面这个 XML 文件是有效的,这是由于 schema "family.xsd" 允许我们通过在 "lastname" 元素后的可选元素来扩展 "person" 元素。
<any> 和 <anyAttribute> 均可用于制作可扩展的文档!它们使文档有能力包含未在主 XML schema 中声明过的附加元素。

以上是网上介绍any的一个例子,一句话总结就是any可以是任意的复杂类型。并且是扩展的方法,不固定。

生成Java client stub
wsdl2java -p com.soufun.esf -d src -all
http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx?wsdl


简要说明:
-p:生成类的包路径
-d:生成的类放在哪
-all:生成所有东西


生成的接收文件片断,可以看到any类型转换成List<Object>.
@XmlAccessorType(XmlAccessType.FIELD)
	@XmlType(name = "", propOrder = { "content" })
	public static class AgentInfoResult {

		@XmlMixed
		@XmlAnyElement(lax = true)
		protected List<Object> content;


错误的调用代码:
	public static void test() throws MalformedURLException {
		URL wsdlURL = new URL(
				"http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx?wsdl");
		Service ss = new Service(wsdlURL, SERVICE_NAME);
		ServiceSoap port = ss.getServiceSoap12();
		AgentInfoResult resp = port.agentInfo("ljxxx", "ljxxxx");
		System.out.println("agentInfo.result=" + resp.getContent());

}
下面是.net应该返回的any格式
<agent account='abc' name='aa' ....

List里面应该有对象Agent对象才对,但是没有,agent为null.
也就是说wsdl2java无法正常转换any type类型到java相关对象。

正确的调用方法:
用xerces-2.6.2.jar包解析any返回内容
	/**
	 * 获取.net webservice any类型的数据。
	 */
	public static void test2() {
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

		factory.getInInterceptors().add(new LoggingInInterceptor());
		factory.getOutInterceptors().add(new LoggingOutInterceptor());
		factory.setServiceClass(ServiceSoap.class);
		factory.setAddress("http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx?wsdl");
		ServiceSoap service = (ServiceSoap) factory.create();
		com.soufun.esf.AgentInfoResponse.AgentInfoResult result = service
				.agentInfo("ljxxx", "ljxxxx");
		// javax.xml.soap.SOAPElement e=(SOAPElement)
		// result.getContent().get(0);
		for (int i = 0; i < result.getContent().size(); i++) {
			org.apache.xerces.dom.ElementNSImpl element = (ElementNSImpl) result
					.getContent().get(i);
			System.out.println(element.getAttributes().getNamedItem("account"));
			System.out.println(element.getAttributes().getNamedItem("name")
					.getNodeValue());
			System.out.println(element.getAttributes().getNamedItem("level"));
			System.out.println(element.getAttributes().getNamedItem("score"));
			System.out.println(element.getAttributes().getNamedItem("mobile"));
			System.out.println(element.getAttributes().getNamedItem("email"));
			System.out.println(element.getAttributes().getNamedItem("mobile"));
			System.out.println(element.getAttributes().getNamedItem(
					"expiredDate"));
		}
	}


这个里面result.getContent()里面的agent依旧为null,只好直接用org.apache.xerces.dom.ElementNSImpl接收相应any转换的元素,然后解析。

成功,结果如下:
信息: Outbound Message
---------------------------
ID: 1
Address: http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx?wsdl
Encoding: UTF-8
Content-Type: text/xml
Headers: {SOAPAction=["http://esf.soufun.com/AgentInfo"], Accept=[*/*]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><AgentInfo xmlns="http://esf.soufun.com/"><userName>ljcs2</userName><pwd>lj123456</pwd></AgentInfo></soap:Body></soap:Envelope>
--------------------------------------
2011-4-13 0:33:18 org.apache.cxf.interceptor.LoggingInInterceptor logging
信息: Inbound Message
----------------------------
ID: 1
Encoding: UTF-8
Content-Type: text/xml; charset=utf-8
Headers: {content-type=[text/xml; charset=utf-8], X-AspNet-Version=[2.0.50727], connection=[keep-alive], Vary=[Accept-Encoding], Date=[Tue, 12 Apr 2011 16:34:04 GMT], Content-Length=[716], X-UA-Compatible=[IE=EmulateIE7], X-Powered-By=[ASP.NET], Server=[nginx], Cache-Control=[private, max-age=0]}
Payload: <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AgentInfoResponse xmlns="http://esf.soufun.com/"><AgentInfoResult><agent account="ljcs2" name="杜佳霖" level="三级" score="2500" mobile="01059107070" email="zhangguoqi@soufun.com" right="" expiredDate="2011-3-24 0:00:00" xmlns=""><branch name="链家导入测试" phone="" /><post all="10" store="0" uesd="0" /><tags><tag name="十万火急" remain="0" uesd="0" /><tag name="新推房源" remain="0" uesd="0" /></tags></agent></AgentInfoResult></AgentInfoResponse></soap:Body></soap:Envelope>
--------------------------------------
account="ljcs2"
杜XX
level="三级"
score="2500"
mobile="01059107070"
email="zhangguoqi@soufun.com"
mobile="01059107070"
expiredDate="2011-3-24 0:00:00"


总结

Cxf不能很好的处理.net web service中的any 元素,只好借助变态的解析方法。.net应该返回标准元素,如string等,这样的web service各语言调用起来才方便。Java也可以接收xml string后再解析。

相信此文能给那些想从cxf java客户端调用.net web service any元素的人带来方便。我在遇到此问题时,google了国内外的网站,没有提到cxf调用any类型的办法,所以总结写下此文,给后来者提供方便。

如果大家以前用cxf处理过.net any类型,有更好的办法,也希望能说说。
分享到:
评论
3 楼 zdq19891104 2013-09-24  
soufun这个webService太坑爹。。
2 楼 yanglinone1 2013-05-28  
太棒了,找半天问题了
1 楼 chrissie 2012-07-25  
遇到同样的问题!你的文章帮忙解决了~灰常感谢!支持一下!

相关推荐

    JAVA 用 Apache CXF 调用 .NET 服务端 WebService 代码

    JAVA 用 Apache CXF 调用 .NET 服务端 WebService 代码 整个JAVA工程的压缩,导入到myeclipse可直接运行,如果只想浏览下,请访问:http://blog.csdn.net/wqmain/article/details/8216331

    java调用.net发布的webservice(asmx)

    本文将详细讲解如何使用Java调用.NET发布的Web Service(ASMX),并解决在此过程中可能出现的SOAPAction报错和“Server not identified”错误。 首先,我们需要了解ASMX。ASMX是.NET Framework早期版本中用于创建...

    使用CXF和camel-cxf调用webservice

    本篇文章将详细介绍如何使用CXF和camel-cxf调用Web服务,以及这两个工具的核心功能和使用场景。 Apache CXF是一个全面的服务开发框架,它支持多种Web服务标准,如SOAP、WS-*协议栈、RESTful服务等。CXF提供了丰富的...

    cxf实现webservice详细文档

    cxf实现webservice详细文档 cxf调用.net webservice 技术详解

    java调用.NET的webservice源码

    Java调用.NET的Web服务(WebService)是一种跨平台、跨语言的通信方式,它允许不同技术栈的应用程序之间共享功能和服务。在这个场景中,Java应用作为客户端,通过HTTP协议调用由.NET框架构建的Web服务。本文将详细...

    camel-cxf调用和发布webservice例子

    用camel-cxf调用webservice和发布一个webservice接口例子,首先启动QueryServiceMain主函数启动webservice接口,然后启动测试类TestWebservice。例子主要是实现java代码实现camel调用webservice接口

    用java调用.net接口的方法

    标签中的".net webservice 接口 源代码"表明,压缩包可能包含了示例代码,供学习者参考和实践。你可以根据提供的源代码,分析其工作原理,了解具体实现细节,包括请求构造、数据封装、错误处理等。 总的来说,调用...

    webService(基于cxf)的完整例子

    在这个基于CXF的Web服务完整例子中,我们将深入探讨CXF的核心概念、配置、以及如何创建和调用Web服务。 1. **CXF框架介绍**:CXF,全称为"Code first eXtended Framework",最初由XFire项目发展而来,后与Apache ...

    C#动态调用CXF WEBSERVICE框架的共通类

    C#动态调用CXF WEBSERVICE框架共通类。

    java程序调用.net/c#的webservice

    Java程序调用.NET/C#的Web服务是一种跨平台的交互方式,主要依赖于SOAP(Simple Object Access Protocol)协议,使得不同编程语言开发的应用程序能够相互通信。在本场景中,用户已经提供了一个.NET的Web服务,而我们...

    cxf客户端调用webservice所需jar包

    当我们需要在客户端调用Web服务时,CXF扮演着关键角色。本篇将详细讲解如何利用CXF客户端来调用Web服务以及所需的jar包。 首先,让我们了解CXF的基本概念。CXF是一个用于构建和服务导向架构(SOA)应用程序的开源...

    cxf做的webservice对外提供接口调用

    【标题】:“cxf做的webservice对外提供接口调用” 【描述】中提到的“webservice对外发布接口全部源码拿起来就能用”,这表明这是一个关于使用Apache CXF框架创建和发布的Web服务项目。Apache CXF是一个开源的Java...

    java调用.net的WebService.pdf

    【Java调用.NET WebService详解】 在跨平台的软件开发中,Java与.NET之间的互操作性是一个重要的话题。本文将详细介绍如何使用Java调用.NET构建的Web服务,以获取天气预报为例,展示具体步骤和代码实现。 首先,...

    java调用.net的webservice传字符串参数

    本主题主要探讨如何在Java环境中调用.NET的Web服务,特别是传递字符串参数。我们将深入讲解两种主流的方法:Axis和XFire。 **一、 Axis** 1. **Axis简介**: Axis是Apache软件基金会的一个开源项目,它提供了一套...

    cxf调用c#的webservice

    本教程将详细讲解如何使用Apache CXF框架在Java环境中调用C#编写的Web服务。 **CXF简介** Apache CXF是一个开源的Java框架,用于构建和服务导向架构(SOA)。它支持多种Web服务标准,如SOAP、RESTful API等,同时也...

    使用CXF调用发布webservice

    【精品文档】基于cxf webservice传递List及bean.pdf CXF学习笔记.doc 使用Apache CXF开发Web Service.pdf 如何使用myeclipse开发 webservice

    springboot整合CXF发布webservice和客户端调用

    - 对于客户端调用,可以使用CXF的`JaxWsProxyFactoryBean`创建服务代理对象,然后调用其方法进行服务调用。 4. **项目结构** - `.classpath`和`.project`是Eclipse IDE的项目配置文件。 - `pom.xml`是Maven的...

    spring+CXF实现WebService(http+https)

    2. **创建WebService**: 使用CXF,首先需要定义服务接口,通常是一个Java接口,然后提供其实现。Spring会自动扫描并注册这些服务。在Spring配置文件中,可以通过`&lt;jaxws:endpoint&gt;`标签来声明一个CXF Web服务,...

    CXF作为客户端调用webService的demo

    用CXF作为客户端调用webService的demo:本人亲测可用,eclipse工程项目包含完整代码和完整jar包, 只要用eclipse导入项目即可,运行控制台显示success或者false字符串,说明OK。

    CXF 调用ASP服务器端通过用户名密码验证

    java CXF客户端请求ERP SAP webservice通过用户名和密码验证功能!

Global site tag (gtag.js) - Google Analytics