杰瑞科技汇

net如何调用Java的webservice?

下面我将为你提供一个详尽的指南,涵盖从最简单的方法到处理复杂情况的技巧。

net如何调用Java的webservice?-图1
(图片来源网络,侵删)

核心方法

主要有两种主流方法:

  1. 添加服务引用 (Add Service Reference):这是 Visual Studio 提供的图形化工具,最简单直观,适用于绝大多数标准的、基于 WSDL 的 WebService。
  2. 使用 svcutil.exe 命令行工具:功能与“添加服务引用”类似,但提供了更多自定义选项,适合在构建服务器或需要脚本化时使用。

我们主要介绍第一种方法,因为它最常用。


详细步骤:使用 Visual Studio 添加服务引用

假设我们有一个 Java WebService,其 WSDL 地址是 http://java-server.com/MyService?wsdl

步骤 1:获取 WSDL 地址

你需要确保可以访问到 Java WebService 的 WSDL 文件,在浏览器中输入 WSDL 地址,你应该能看到一个 XML 文件,里面定义了服务的所有操作、消息类型和端口类型。

net如何调用Java的webservice?-图2
(图片来源网络,侵删)

步骤 2:创建或打开 .NET 项目

在 Visual Studio 中创建一个新的 C# 项目(控制台应用程序、ASP.NET Core 应用等)。

步骤 3:添加服务引用

  1. 解决方案资源管理器 中,右键点击你的项目。

  2. 选择 添加 -> 服务引用...

  3. 在弹出的对话框中:

    net如何调用Java的webservice?-图3
    (图片来源网络,侵删)
    • 地址 框中,输入 Java WebService 的 WSDL 地址。
    • 点击 前往,Visual Studio 会下载并解析 WSDL 文件。
    • 解析成功后,会显示服务中的所有可用操作。
    • 命名空间 框中,为你将要生成的客户端代理类指定一个命名空间(MyJavaServiceReference)。
    • 点击 确定
  4. Visual Studio 会自动生成一系列文件,包括:

    • 一个客户端代理类(MyServiceClient),它封装了所有对 WebService 的调用。
    • 用于序列化和反序列化消息的类(对应 WSDL 中定义的复杂类型)。

这些文件通常位于 Service ReferencesConnected Services 文件夹下。

步骤 4:编写调用代码

现在你可以在你的 C# 代码中使用生成的客户端了。

using System;
using MyJavaServiceReference; // 使用你在步骤3中指定的命名空间
namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // 1. 创建客户端代理类的实例
                // 这个类名是根据 WSDL 中的服务名生成的,通常叫 [服务名]Client
                var client = new MyServiceClient();
                // 2. 准备输入参数
                // 参数类型是根据 WSDL 中的操作定义生成的
                var request = new MyRequestType
                {
                    // 假设 WSDL 中定义了一个名为 "inputParam" 的字符串参数
                    InputParam = "Hello from .NET!"
                };
                // 3. 调用 WebService 的方法
                // 方法名是根据 WSDL 中的操作名生成的
                Console.WriteLine("正在调用 Java WebService...");
                var response = client.MyOperation(request);
                // 4. 处理返回结果
                // 返回类型也是根据 WSDL 生成的
                if (response != null)
                {
                    Console.WriteLine("调用成功!");
                    Console.WriteLine($"返回结果: {response.OutputResult}");
                }
                else
                {
                    Console.WriteLine("调用成功,但返回结果为空。");
                }
            }
            catch (Exception ex)
            {
                // 捕获并处理可能发生的异常
                Console.WriteLine($"调用失败: {ex.Message}");
                // 如果是 SOAP 错误,通常可以从 InnerException 中获取更详细的信息
                if (ex.InnerException != null)
                {
                    Console.WriteLine($"内部错误: {ex.InnerException.Message}");
                }
            }
        }
    }
}

常见问题与解决方案

在调用 Java WebService 时,你很可能会遇到以下问题。

问题 1:WSDL 无法解析或“请求被中止”

  • 症状:点击“前往”后,长时间无响应或提示“请求被中止”、“基础连接已关闭”等错误。
  • 原因:通常是由于 Java 服务器和 .NET 客户端之间关于 SOAP 协议版本的协商不一致,Java 服务器可能默认使用 SOAP 1.1,而 .NET 客户端可能尝试使用 SOAP 1.2,导致兼容性问题。
  • 解决方案:强制 .NET 客户端使用 SOAP 1.1。

在创建客户端实例后,设置其绑定属性。

var client = new MyServiceClient();
// 强制使用 SOAP 1.1
// "MyService" 是你在 WSDL 中看到的 <port> 元素的 name 属性值
var binding = client.Endpoint.Binding as BasicHttpBinding;
if (binding != null)
{
    binding.MessageVersion = MessageVersion.Soap11;
}

问题 2:用户名和密码认证(SOAP Header)

Java WebService 常常通过 SOAP Header 传递用户名和密码进行认证。

  • 症状:调用失败,提示“未授权”或“认证失败”。
  • 解决方案:在调用前,创建一个 MessageHeader 并添加到请求中。
var client = new MyServiceClient();
// 创建用户名和密码
var username = "your_username";
var password = "your_password";
// 创建 SOAP Header
var authHeader = new MyJavaServiceReference.UsernameToken
{
    Username = username,
    Password = password
};
// 将 Header 附加到客户端操作上下文
// MyOperation 是你要调用的方法名
using (new OperationContextScope(client.InnerChannel))
{
    // 创建消息头并添加到出站消息头集合中
    MessageHeader header = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", authHeader, false);
    OperationContext.Current.OutgoingMessageHeaders.Add(header);
    // 现在可以正常调用方法了
    var request = new MyRequestType { InputParam = "test" };
    var response = client.MyOperation(request);
    Console.WriteLine($"Result: {response.OutputResult}");
}

注意UsernameToken 这个类名和命名空间 http://... 需要根据 Java 服务端定义的 WSDL 中的 <xsd:element name="UsernameToken"> 来确定,你通常需要用工具(如 SoapUI)或直接查看 WSDL 来找到正确的结构。

问题 3:日期/时间格式不匹配

  • 症状:Java 服务端接收到的日期是 0001/01/01,或者抛出格式异常。
  • 原因:Java 和 .NET 处理日期时间的方式不同,Java 常用 java.util.Datejava.xml.datatype.XMLGregorianCalendar,而 .NET 使用 DateTime,它们的序列化格式可能有细微差别。
  • 解决方案:在调用前,将 .NET 的 DateTime 转换为 Java 期望的格式字符串。
// .NET 的 DateTime
var netDateTime = DateTime.Now;
// 转换为 ISO 8601 格式字符串,这是最通用的格式
var javaCompatibleDateString = netDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
// 然后将这个字符串作为参数传递给 WebService
var request = new MyRequestType
{
    // 假设参数是字符串类型
    DateParam = javaCompatibleDateString
};

如果服务端期望的是 XMLGregorianCalendar 类型,.NET 生成的代理类通常会有一个对应的属性,你可以直接赋值 DateTime,代理类会自动处理转换。

问题 4:复杂类型映射问题

  • 症状:某个复杂类型的字段在 .NET 客户端中为 null,或者类型不匹配。
  • 原因:Java 和 .NET 的数据类型不完全对应,Java 的 List<String> 可能会映射到 .NET 的 string[]List<string>
  • 解决方案
    1. 检查生成的代码:查看自动生成的 Reference.cs 文件,了解 WSDL 中的类型是如何被映射到 .NET 类型的。
    2. 使用共享类型:如果可能,让 Java 团队和 .NET 团队就数据结构达成一致,并使用 XSD (XML Schema Definition) 作为“事实标准”,双方都基于同一个 XSD 文件来生成客户端/服务端代码,可以最大程度地避免类型不匹配问题。

调试技巧

分享:
扫描分享到社交APP
上一篇
下一篇