JAVA+AXIS客户端调用Asp.net Web Service过程中遇到的问题及解决方法

        背景:公司与某运营商合作,运营商提供了接口文档,在文档中规定了数据流是双向的,运营商和公司之间的通讯采用Web Service方式,双方互为客户端和服务器端。这次遇到的问题,就是运营商的客户端调用我公司服务端的Web Service时出现的情况。需要特别说明的是:运营商有几十家合作伙伴,所以客户端的代码是不能因为某一家合作伙伴而修改的,各合作伙伴的WEB SERVICE开发环境也不相同,大部分都是用JAVA语言开发,而我公司是用VS2005开发的。
        过程:
        涉及的接口文档部分如下:
用户数据同步(syncUserData):

Index

Parameter Name

Req

Type

Size

Description

1

Mobile

M

String

21

用户号码

2

SPID

M

String

21

合作方标识

3

Service

M

String

21

业务代码

4

Action

M

Integer

4

用户操作

5

Time

M

String

14

时间戳 YYYYMMDDhhmmss

6

Desc

M

String

255

原因描述

7

Terminal

M

String

4

终端类型

        运营商客户端采用:JAVA JDK 1.5+AXIS实现的Web Service客户端调用,并提供了具体的调试例子:
package  smp.webservice.client;

import  java.rmi.RemoteException;

import  javax.xml.namespace.QName;
import  javax.xml.rpc.ServiceException;

import  org.apache.axis.client.Call;
import  org.apache.axis.client.Service;

public   class  ServiceClient  {
    
public int syncUserData(String Mobile, String SPID, String Service, Integer Action, String Time, String Desc,    String terminal, String serviceEndPoint)
        
throws Exception {
        Object result
=null;
        
try {
            Call call 
= this.invokeFunction("syncUserData", serviceEndPoint);
            result
=call.invoke(new Object[] { Mobile, SPID, Service, Action, Time, Desc, terminal });
        }
 catch (Exception e) {
            
throw e;
        }

        
        
try{
            
return ((Integer)result).intValue();
        }
catch(Exception e){
            
return Integer.parseInt(((String)result));
        }

    }


    
public Call invokeFunction(String operationName, String serviceEndPoint)
        
throws ServiceException {
        Service service 
= ServiceInstance.getInstance();
        Call call 
= (Call) service.createCall();
        call.setTargetEndpointAddress(serviceEndPoint);
        call.setOperationName(
new QName(operationName));
        
return call;
    }


    
/**
     * test the client method
     
*/

    
public static void main(String[] args) {
        ServiceClient sc 
= new ServiceClient();
        String endPoint 
= "http://127.0.0.1/WebTest/Service.asmx";

        
try {
            
int i=sc.syncUserData("13312345678""3735127""834621"new Integer(8), "20080101120000""desc","9",endPoint);

            System.out.println(
"result: " + i);
        }
 catch (Exception e) {
            e.printStackTrace();
        }

    }

}

其中endPoint的值是用于调用我本地的.net开发的WEB服务地址。 
我用asp.net中的C#语言生成了WEBSERVICE,但JAVA客户端调用会报错,后用AXIS中自带的抓包工具Axis Tcp Monitor对客户端的调用(此时调用的是运营商供测试用的WEB SERVICE,JAVA语言的)进行了抓包,结果如下:
POST /axis/services/SPService HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.2
Host: 127.0.0.1:8081
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 1208

<? xml version="1.0" encoding="UTF-8" ?>
   
< soapenv:Envelope  xmlns:soapenv ="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:xsd ="http://www.w3.org/2001/XMLSchema"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" >
      
< soapenv:Body >
         
< syncUserData  soapenv:encodingStyle ="http://schemas.xmlsoap.org/soap/encoding/" >
            
< arg0  xsi:type ="soapenc:string"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/" > 13312345678 </ arg0 >
            
< arg1  xsi:type ="soapenc:string"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/" > 3735127 </ arg1 >
            
< arg2  xsi:type ="soapenc:string"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/" > 834621 </ arg2 >
            
< arg3  href ="#id0" />
            
< arg4  xsi:type ="soapenc:string"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/" > 20080101120000 </ arg4 >
            
< arg5  xsi:type ="soapenc:string"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/" > desc </ arg5 >
            
< arg6  xsi:type ="soapenc:string"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/" > 9 </ arg6 >
         
</ syncUserData >
         
< multiRef  id ="id0"  soapenc:root ="0"  soapenv:encodingStyle ="http://schemas.xmlsoap.org/soap/encoding/"  xsi:type ="soapenc:int"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/" > 8 </ multiRef >
      
</ soapenv:Body >
   
</ soapenv:Envelope >

发现参数名称都是arg0、arg1-arg6,而且int型参数arg3是通过href属性来实现的。查资料后得知AXIS客户端调用.Net是需要设置SoapDocumentService参数的。最后经过反复实验,终于用下面的C#代码成功处理了此客户端的请求:

using  System;
using  System.Web;
using  System.Web.Services;
using  System.Web.Services.Protocols;
using  System.Web.Services.Description;

[WebService(Namespace 
=   " www.microsoft.com " )]
[SoapDocumentService(RoutingStyle 
=  SoapServiceRoutingStyle.RequestElement)]
[WebServiceBinding(ConformsTo 
=  WsiProfiles.None)] 
public   class  Service : System.Web.Services.WebService
{
    
public Service () {

        
//Uncomment the following line if using designed components 
        
//InitializeComponent(); 
    }

 
    [SoapRpcMethod(Action 
= "syncUserData",RequestNamespace="")]
    
public int syncUserData([SoapElement("arg0")] string Mobile, [SoapElement("arg1")] string SPID,
    [SoapElement(
"arg2")] string Service, [SoapElement("arg3")] int Action, [SoapElement("arg4")] string Time,
    [SoapElement(
"arg5")] string Desc, [SoapElement("arg6")] string Terminal)
    
{
        
//处理过程省略……
        return 0;
    }

}

代码中:

SoapDocumentService属性:主要是用于JAVA+AXIS客户端调用.net服务端时使用的,具体的原因,可以网上查到。

WebServiceBinding(ConformsTo = WsiProfiles.None):因为上面SoapDocumentService属性的设置,所以此WEBSERVICE已经不符合微软默认的“‘WSI 基本概要’1.1 版”。

SoapRpcMethod属性:主要是因为客户端为了调用不同合作伙伴的WEB SERVICE,所以在JAVA语句call.setOperationName(new QName(operationName));中只设置了方法名称,而没有设置命名空间。.net 服务端为了处理这种情况下的请求,必须在本属性中设置RequestNamespace=""。这里的处理是非常重要的!

[SoapElement("arg0")] ……:是对请求进行XML序列化处理,把实际请求中的参数名称arg0映射到我自己定义的名称Mobile中。

        有人可能认为在WEB 服务开始阶段设置[WebService(Namespace = "")]不也可以让命名空间设为空吗?为什么要在SoapRpcMethod属性中设置。这是因为在这个案例中,必须用到SoapRpcMethod属性,而使用此属性后,就不能设置[WebService(Namespace = "")],不然调用时服务端就会报错。具体原因,我还不是十分了解,如果有高手能解释这个原因,我将拭目以待:)。

        还有一个情况就是,在调试过程中经常会发现,因为参数中有一个int型的数据(请参考抓包数据),所以往往string型的数据都能读出来了,这个int型的数据却总是为0 (读不出正确的值),所以上面的c#代码中的SoapRpcMethod属性就是解决这个问题的。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值