java调用.net写的webserver接口(.asmx后缀)

  之前项目上一直调用的是java代码写的接口,方法一直没有问题,这次调用.asmx后缀的.net接口的时候,原来的方法在创建连接的时候就已经出错,百度得到很多答案,在此整理一下。

一、使用axis1.x调用webservice方法 
Axis的最常用版本:1.4和2.0版本。以下为1.4版本 

1.所需jar包

maven仓库国内镜像地址:https://mvnrepository.com/

2.相关代码

核心代码: 
// webserviceURL 

// 指出service所在完整的URL
String url= "http://xxx/WebService.asmx"; 
Service service = new Service(); 
Call call = (Call) service.createCall(); 
call.setTargetEndpointAddress(new java.net.URL(url)); 

// 设置要调用的方法 

// http://tempuri.org/是wsdl中definitions根节点的targetNamespace属性值 
call.setOperationName(new QName("http://tempuri.org/","addProductRepStage")); 

// 该方法需要的参数 

call.addParameter("CustNo", org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN); 
call.addParameter("passwd", org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN); 
call.addParameter("Jobno", org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN); 

// 方法的返回值类型 

call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING); 
// call.setUseSOAPAction(true); 
// call.setSOAPActionURI("http://tempuri.org/addProductRepStage"); 
// 调用该方法, new Object[] { CustNo, passwd, Jobno}为参数列表 
String xmlStr = call.invoke(new Object[] { CustNo, passwd, Jobno}).toString(); 
} catch (Exception e) { 
e.printStackTrace(); 
}

JAVA用这种方式调用webservice,需要注意的地方: 
1. 服务器未能识别 HTTP 标头 SOAPAction 的值: 
症状一: 
Web Service + ASP.NET 应用程序部署到服务器默认目录中,在IE中用http://<服务器地址>/<程序目录名>/<默认启动页面名>发生“服务器未能识别 HTTP 标头 SOAPAction 的值”错误。 
症状二: 
在Java平台上调用.NET Web Service的服务时,出现"服务器未能识别 HTTP 标头 SOAPAction 的值"。 
症状三: 
在Java平台下调用.NET WEB Service,出现数据时有时无。 

解决对策: 

给.NET的WebService类(即.asmx文件下的类)添加属性[SoapDocumentService(RoutingStyle=SoapServiceRoutingStyle.RequestElement)] 
小知识: 
什么是SoapAction?它在WSDL中有何作用? 
SOAPAction HTTP request header被用来标识SOAP HTTP请求的目的地,其值是个URI地址。SOAP发送并不限制格式、URI特征或其必须可解析,那么在这种情况下,发送一个HTTP SOAP请求时,其HTTP客户端必须使用/指明SOAPAction HTTP request header。 

SOAPAction header的内容可以被用在服务端,诸如:防火墙适当的过滤基于HTTP的SOAP请求消息等场景。SOAPAction header的值为空串("")表示SOAP消息的目的地由HTTP请求的URI标识;无值则表示没有指定这条消息的目的地。 

补充说明: 
在.NET环境调用.NET WebService出现 “SOAPAction 值在 XML Web services 的所有方法中不唯一的错误”,也可以通过此法解决。 

2. 为了Java能够调用WebService的方法,所以.NET写的WebServiced的每个方法都要声明为Rpc方法,即添加"[SoapRpcMethod.....]". 
例如:[WebMethod] 
        [SoapRpcMethod(Use=SoapBindingUse.Literal,Action= http://tempuri.org/HelloWorld", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/")] 

3. 对返回值、参数的处理上: 
应尽量将webservice方法的返回值、参数都写成字符串(String)不要使用复杂对象类型,这样便于在网络上传输。避免了复杂对象类型的不易转换问题。。。对于返回类型是字符串数组型的,可以设置返回类型为org.apache.axis.encoding.XMLType.SOAP_VECTOR或java.lang.String[].class. 

二.利用xfire调用WebService 
XFire是新一代的Java Web服务引擎,XFire使得在JavaEE应用中发布Web服务变得轻而易举。和其他Web服务引擎相比,XFire的配置非常简单,可以非常容易地和Spring集成,它使得Java开发人员终于可以获得和.Net开发人员一样的开发效率。 

核心代码: 

Service service = new ObjectServiceFactory().create(IWebservice.class); 
XFireProxyFactory factory = new XFireProxyFactory(XFireFactory.newInstance().getXFire()); 
String url= "http://localhost:8080/webservices/services/webservices"; 
IWebservice iw = (IWebservice) factory.create(service, url); 
List list=iw.getTest();

完整示例代码:

package avicit.mms.common;

import javax.xml.namespace.QName;
import org.apache.axis.Constants;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;

public class Test {
    public static void main(String[] args) {
        Textaxis();
    }
    //通过axis方式调用webservice接口
    public static void Textaxis() {
        try {
            StringBuffer xml = new StringBuffer();
            xml.append("<?xml version="1.0" encoding="GB2312"?>
");
            xml.append("<stages>
");
            xml.append("...");
            xml.append("</stages>
");
            // 指出service所在完整的URL
            String url = "http://127.0.0.1:9080/xxx/WebService.asmx";
            //调用接口的targetNamespace
            //targetNamespace 就是你用浏览器打开url 路径加上?wsdl,即http://xxx/WebService.asmx?wsdl 中的targetNamespace属性值
            String targetNamespace = "http://tempuri.org/";
            //所调用接口的方法method
            String method = "addProductRepStage";
            // 创建一个服务(service)调用(call)
            Service service = new Service();
            Call call = (Call) service.createCall();// 通过service创建call对象
            // 设置service所在URL
            call.setTargetEndpointAddress(new java.net.URL(url));
            //设置要调用的方法
            call.setOperationName(new QName(targetNamespace, method));
            //设置要返回的数据类型
            call.setReturnType(new QName(targetNamespace, method), String.class);
            
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(targetNamespace+method);
            
            //变量最好只是用String类型,其他类型会报错,这里的proRepStageInfoXml是.net接口中需要的参数名
            call.addParameter(new QName(targetNamespace, "proRepStageInfoXml"),
                    Constants.XSD_STRING,
                    javax.xml.rpc.ParameterMode.IN);//设置参数名 proRepStageInfoXml  第二个参数表示String类型,第三个参数表示入参  
            
            //调用方法并传递参数
            String flag = (String) call.invoke(new Object[] {xml.toString()});//此处为数组,有几个变量传几个变量
            System.out.println(flag);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

  这两天发现一个问题,所以在此备注一下,Axis的jar包中的axis-wsdl4j-1.5.1和cxf调用接口中要用到的wsdl4j-1.6.2有冲突,版本多少其实不重要,就是两个jar包里面的类差不多,所以如果有高版本的wsdl4j的jar包,就不需要在引axis-wsdl4j-1.5.1的jar包了。

原文地址:https://www.cnblogs.com/1012hq/p/11393484.html