使用ASP等客户端来访问Java的Web Service,取得复杂数据(DTO)

本文介绍了如何使用ASP.Net客户端调用Java编写的Web Service,并解决返回DTO(JavaBean)数据为空的问题。通过分析 Soap 传输机制,修改Wsdl中return接口定义,成功接收并解析返回值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文使用ASP.Net的客户端来访问Java写的Web Service。Web Service返回的结果是一个DTO(JavaBean)。

 

日前看到很多朋友说用ASP的客户端调用Java写的Web Service返回结果是Null,本文也提供了一些看法,希望对大家有点帮助。

 

首先说一下机制,这里只涉及最简单的。

首先,传输的协议是Soap,说白了就是使用一个规范的XML文本来进行传输。客户端和WS端都根据规范来解析XML文本,以获得需要的数据。

 

下面是正文。

下来建立Java的Web Service端。

首先建立一个动态网页工程。

 

接下来我们建立一个DTO(JavaBean)来充当传输的介质。

代码如下:

  1. package demo;
  2. public class EmployeeDTO {
  3.     String name;
  4.     String dept;
  5.     String age;
  6.     public String getName() {
  7.         return name;
  8.     }
  9.     public void setName(String name) {
  10.         this.name = name;
  11.     }
  12.     public String getDept() {
  13.         return dept;
  14.     }
  15.     public void setDept(String dept) {
  16.         this.dept = dept;
  17.     }
  18.     public String getAge() {
  19.         return age;
  20.     }
  21.     public void setAge(String age) {
  22.         this.age = age;
  23.     }
  24. }

好了,现在我们来建立一个Web Service程序

代码如下:

  1. package demo;
  2. /**
  3.  * Demo Web Service
  4.  * 
  5.  * @author redria
  6.  *
  7.  */
  8. public class EmployeeWS {
  9.     
  10.     /**
  11.      * Get Employee DTO Info
  12.      * 
  13.      * @return
  14.      */
  15.     public EmployeeDTO getInfo() {
  16.         //New DTO
  17.         EmployeeDTO dto = new EmployeeDTO();
  18.         dto.setName("Sol");
  19.         dto.setDept("GGXX");
  20.         dto.setAge("...?");
  21.         //Return Value
  22.         return dto;
  23.     }
  24. }

现在我们准备好了,可以发布Web Service程序了。使用插件可以很方便的发布服务。这里使用附带WTP的Eclipse附带的工具来发布。

 

 

当然,在这里点击下面的生成Client也可以自动帮你生成Client端。因为本文使用ASP来生成客户端,所以这里就不说明Java的了

 

好了,现在测试一下我们的结果:

 

可以看到,我们Web Service完全正常。(这里如果不正常,可能是你的环境有问题)

 

现在我们将其发布到tomcat中去。

访问我们刚才发布的Web Service的wsdl文件。你可以看到:

 

说明我们的服务已经发布成功了。

 

现在来建立一个ASP.Net的客户端。

打开Visual Studio

新建一个ASP.Net Web Site工程

 

首先我们添加一个 Web 参照,将我们刚才发布的地址加入,就可以看到了。

 

 

好了,现在我们来添加吧。

 

之后来写前台的Aspx文件和后台的cs文件

  1. <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" >
  4. <head runat="server">
  5.     <title>無題のページ</title>
  6. </head>
  7. <body>
  8.     <form id="form1" runat="server">
  9.     <div>
  10.         <asp:Button ID="BTN_GETINFO" runat="server" OnClick="BTN_GETINFO_Click" Text="获取信息" /><br />
  11.         <br />
  12.         <asp:Label ID="LB_NAME" runat="server" Text="Name:"></asp:Label>
  13.         <asp:Label ID="LB_NAMERESULT" runat="server"></asp:Label><br />
  14.         <asp:Label ID="LB_DEPT" runat="server" Text="Dept:"></asp:Label>
  15.         <asp:Label ID="LB_DEPTRESULT" runat="server"></asp:Label><br />
  16.         <asp:Label ID="LB_AGE" runat="server" Text="Age:"></asp:Label>
  17.         <asp:Label ID="LB_AGERESULT" runat="server"></asp:Label></div>
  18.     </form>
  19. </body>
  20. </html>

 

  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.Web;
  5. using System.Web.Security;
  6. using System.Web.UI;
  7. using System.Web.UI.WebControls;
  8. using System.Web.UI.WebControls.WebParts;
  9. using System.Web.UI.HtmlControls;
  10. public partial class _Default : System.Web.UI.Page 
  11. {
  12.     protected void Page_Load(object sender, EventArgs e)
  13.     {
  14.     }
  15.     protected void BTN_GETINFO_Click(object sender, EventArgs e)
  16.     {
  17.         //call Web Service
  18.         localhost.EmployeeWSService service = new localhost.EmployeeWSService();
  19.         localhost.EmployeeDTO dto = service.getInfo();
  20.         this.LB_NAMERESULT.Text = dto.name;
  21.         this.LB_DEPTRESULT.Text = dto.dept;
  22.         this.LB_AGERESULT.Text = dto.age;
  23.     }
  24. }

 

好了,现在来运行看看结果。

 

好了,看起来,我们已经完全成功了。

 

接下来我们把Web Service放到Axis2中间来看看。

首先,由于发布的路径不一样我们需要相应的修改Web Service的wsdl文件。

 

修改address地址如下

  1. <wsdlsoap:address location="http://localhost:8080/axis2/services/EmployeeWSService"/>

好了,现在打包发布吧。使用Axis2官方提供的插件可以很方便发布,这里就不多说了,不懂可以参照我关于ESB(ServiceMix)的那片文章中有提到,或者自己在网上搜搜,相关说明很多。

 

发布后我们可以在Axis2的Service列表中看到

 

 

接下来修改我们再来新建一个Asp的客户端,来看看有什么区别。

 

我们新建一个Aspx页面。

 

现在我们将Axis2的服务添加到Web 参照中去。

 

 

为了不和前一个Web Service冲突,我们将名字改掉

 

下面来完成页面

  1. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml">
  4. <head runat="server">
  5.     <title>無題のページ</title>
  6. </head>
  7. <body>
  8.     <form id="form1" runat="server">
  9.         <div>
  10.             <h1>使用Axis2的Web Service</h1>
  11.             <asp:Button ID="BTN_GETINFO" runat="server" OnClick="BTN_GETINFO_Click" Text="获取信息" /><br />
  12.             <br />
  13.             <asp:Label ID="LB_NAME" runat="server" Text="Name:"></asp:Label>
  14.             <asp:Label ID="LB_NAMERESULT" runat="server"></asp:Label><br />
  15.             <asp:Label ID="LB_DEPT" runat="server" Text="Dept:"></asp:Label>
  16.             <asp:Label ID="LB_DEPTRESULT" runat="server"></asp:Label><br />
  17.             <asp:Label ID="LB_AGE" runat="server" Text="Age:"></asp:Label>
  18.             <asp:Label ID="LB_AGERESULT" runat="server"></asp:Label>
  19.         </div>
  20.     </form>
  21. </body>
  22. </html>

 

  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.Collections;
  5. using System.Web;
  6. using System.Web.Security;
  7. using System.Web.UI;
  8. using System.Web.UI.WebControls;
  9. using System.Web.UI.WebControls.WebParts;
  10. using System.Web.UI.HtmlControls;
  11. public partial class Default2 : System.Web.UI.Page
  12. {
  13.     protected void Page_Load(object sender, EventArgs e)
  14.     {
  15.     }
  16.     protected void BTN_GETINFO_Click(object sender, EventArgs e)
  17.     {
  18.         //call Web Service
  19.         Axis2.EmployeeWSService service = new Axis2.EmployeeWSService();
  20.         Axis2.EmployeeDTO dto = service.getInfo();
  21.         this.LB_NAMERESULT.Text = dto.name;
  22.         this.LB_DEPTRESULT.Text = dto.dept;
  23.         this.LB_AGERESULT.Text = dto.age;
  24.     }
  25. }

 

好了,我们可以看到和前一个没有什么区别,那我们来尝试一下。

结果是,一点访问WebService,我们的程序就出错了,因为WebService的返回结果是null。(相信很多朋友在调用Java发布在各种服务上的WS,都或多或少发生了类似返回为null的问题)

 

可是我们同样的代码,为什么会有不同的结果?难道问题处在了Axis2上面?

 

我们可以确信,我们的代码没有错误,因为放在Axis2之前,我们的程序很正常。

然而看看WebService端,好像也没有出错,如果打log,会发现我们其实是成功调用了Web Service,Web Service也正确返回值了,为什么我们在客户端收到的是一个Null值?

 

要解决这个问题,我们可以尝试分析一下我们到底传输了什么soap。

我们使用一些包截取工具来截取我们传输的信息。

 

这里本文使用的是 Microsoft SOAP Toolkit Version 3 ,当然是用其它工具也行。

 

现在我们来分别截取一下我们两次调用返回的结果吧,看看有什么不同。(这里也可以使用我在关于ESB(ServiceMix)的那片文章中最后测试用的html,那个html就是把发送的soap和返回的soap都显示的网页)

 

我们第一次成功的返回soap是

  1. <?xml version='1.0' encoding='UTF-8'?>
  2. <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">
  3.     <soapenv:Body>
  4.         <getInfoResponse xmlns:ns="http://demo">
  5.             <getInfoReturn>
  6.                 <age>...?</age>
  7.                 <dept>GGXX</dept>
  8.                 <name>Sol</name>
  9.             </getInfoReturn>
  10.         </getInfoResponse>
  11.     </soapenv:Body>
  12. </soapenv:Envelope>

 

而我们第二次使用Axis2返回的soap是

  1. <?xml version='1.0' encoding='UTF-8'?>
  2. <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  3.     <soapenv:Body>
  4.         <ns:getInfoResponse xmlns:ns="http://demo">
  5.             <ns:return type="demo.EmployeeDTO">
  6.                 <ns:age>...?</ns:age>
  7.                 <ns:dept>GGXX</ns:dept>
  8.                 <ns:name>Sol</ns:name>
  9.             </ns:return>
  10.         </ns:getInfoResponse>
  11.     </soapenv:Body>
  12. </soapenv:Envelope>

 

这两个的区别在哪里呢?

<ns:return type="demo.EmployeeDTO">和<getInfoReturn>是区别。

 

Axis2中的return值不在像以前一样直接写明,而是使用名字为return的量,使用type来定义它的类型。

所以这里我们的接口不一样,就像我们去A码头接人,人却从B码头来了,我们自然什么都没有接到。

 

找到问题的所在,接下来我们只要修改wsdl中的return接口定义,就可以接到值了。

修改发布到Axis2的WS的wsdl文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <wsdl:definitions targetNamespace="http://demo" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://demo" xmlns:intf="http://demo" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  3. <!--WSDLはApache Axis version: 1.4
  4. Built on Apr 22, 2006 (06:55:48 PDT)によって生成されました / [en]-(WSDL created by Apache Axis version: 1.4
  5. Built on Apr 22, 2006 (06:55:48 PDT))-->
  6.  <wsdl:types>
  7.   <schema elementFormDefault="qualified" targetNamespace="http://demo" xmlns="http://www.w3.org/2001/XMLSchema">
  8.    <element name="getInfo">
  9.     <complexType/>
  10.    </element>
  11.    <element name="getInfoResponse">
  12.     <complexType>
  13.      <sequence>
  14.       <element name="return" type="impl:EmployeeDTO"/>
  15.      </sequence>
  16.     </complexType>
  17.    </element>
  18.    <complexType name="EmployeeDTO">
  19.     <sequence>
  20.      <element name="age" nillable="true" type="xsd:string"/>
  21.      <element name="dept" nillable="true" type="xsd:string"/>
  22.      <element name="name" nillable="true" type="xsd:string"/>
  23.     </sequence>
  24.    </complexType>
  25.   </schema>
  26.  </wsdl:types>
  27.    <wsdl:message name="getInfoRequest">
  28.       <wsdl:part element="impl:getInfo" name="parameters"/>
  29.    </wsdl:message>
  30.    <wsdl:message name="getInfoResponse">
  31.       <wsdl:part element="impl:getInfoResponse" name="parameters"/>
  32.    </wsdl:message>
  33.    <wsdl:portType name="EmployeeWS">
  34.       <wsdl:operation name="getInfo">
  35.          <wsdl:input message="impl:getInfoRequest" name="getInfoRequest"/>
  36.          <wsdl:output message="impl:getInfoResponse" name="getInfoResponse"/>
  37.       </wsdl:operation>
  38.    </wsdl:portType>
  39.    <wsdl:binding name="EmployeeWSSoapBinding" type="impl:EmployeeWS">
  40.       <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
  41.       <wsdl:operation name="getInfo">
  42.          <wsdlsoap:operation soapAction=""/>
  43.          <wsdl:input name="getInfoRequest">
  44.             <wsdlsoap:body use="literal"/>
  45.          </wsdl:input>
  46.          <wsdl:output name="getInfoResponse">
  47.             <wsdlsoap:body use="literal"/>
  48.          </wsdl:output>
  49.       </wsdl:operation>
  50.    </wsdl:binding>
  51.    <wsdl:service name="EmployeeWSService">
  52.       <wsdl:port binding="impl:EmployeeWSSoapBinding" name="EmployeeWS">
  53.          <wsdlsoap:address location="http://localhost:8080/axis2/services/EmployeeWSService"/>
  54.       </wsdl:port>
  55.    </wsdl:service>
  56. </wsdl:definitions>

 

重新发布一下,再来测试我们的第二个客户端,果然成功的取到了值,问题圆满解决了。

 

注:Java客户端其实和Asp一样会遇到这种问题,问题的本质是一样的。

 

总结:现在功能强大的工具软件是我们的工作变得非常简单,遇到了这种问题,我们可以从它到底在传输什么着手,做些分析就可以找到问题的所在。尤其像Soap这样的东西,自己动手,丰衣足食么……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值