科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道设计移动 Web 服务

设计移动 Web 服务

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

从何时选择移动 Web 服务到总体设计指导原则再到用于移动 Web 服务的值类型,本文提出了在设计用于移动设备的 Web 服务时需要考虑的许多设计事项。文中还介绍了许多设计移动 Web 服务方面的最佳实践。

作者:中国IT实验室 来源:中国IT实验室 2007年9月22日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共4页)

注意 float 和 double 类型的使用

首先需要注意的一点是,正如您所知,CLDC 1.0 (Connected Limited Device Configuration) 并没有出于性能的原因而提供 float 和 double 本机类型,即使 CLDC 1.1 和 CDC 都为其提供了支持。那么,如果您必须使用针对 CLDC 1.0 的 Web 服务,您该如何做呢?JSR-172 为您提供了部分答案。

为了在 CLDC 1.0 中缺省支持 xsd:float 和 xsd:double,实现必须 生成代码来将这些类型映射到 java.lang.String。为了支持为 float 和 double 提供本机支持的配置和平台(CLDC 1.1 和 CDC),存根生成器实现也必须 生成代码来将这些类型映射到适当的本机 Java 类型。(详细信息,请参阅参考资料,以获得指向 JSR-172: J2ME Web 服务规范的链接。)

我将演示一个添加两个 float 数的简单 Web 服务(清单 7)。



清单 7. 添加两个 float 数

public class TaskWs {
    public TaskWs() {

    }

    /** 
     * Adding two float numbers and return their sum
     * @param a First number to add,
     * @param b Second number to add
     * @return The sum of a and b.
     */
    public float addTwo(float a, float b) {
        return a + b;
    }

}
}

所生成的 WSDL 定义中的 XML 数据类型定义如清单 8 所示。



清单 8. 与清单 7 对应的 WSDL 定义

 <wsdl:types>
  <schema targetNamespace="http://ws.test.ibm.com" 
    xmlns="http://www.w3.org/2001/XMLSchema" 
  xmlns:impl="http://ws.test.ibm.com" xmlns:intf="http://ws.test.ibm.com" 
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <element name="addTwoResponse">
     <complexType>
      <sequence>
       <element name="addTwoReturn" type="xsd:float"/>
      </sequence>
     </complexType>
    </element>
    <element name="addTwo">
     <complexType>
      <sequence>
       <element name="a" type="xsd:float"/>
       <element name="b" type="xsd:float"/>
       <element name="b" type="xsd:float"/>
      </sequence>
     </complexType>
    </element>
  </schema>
  </wsdl:types>

对于针对 CLDC 1.0 的 Web 服务客户端,所生成的存根如清单 9 所示。



清单 9. 为 CLDC 1.0 生成的客户端存根

 public interface TaskWs extends java.rmi.Remote {
    public java.lang.String addTwo(java.lang.String _a, java.lang.String _b)
            throws java.rmi.RemoteException, javax.xml.rpc.JAXRPCException;
}

所以,当调用 CLDC 1.0 中的 Web 服务时,您必须使用 addTwo() 方法提供两个 String 参数,而对于针对平台 CLDC 1.1 的 Web 服务客户端,所生成的服务接口与清单 10 中所描述的类似:



清单 10. 为 CLDC 1.1 生成的客户端存根

public interface TaskWs extends java.rmi.Remote {
    public float addTwo(float _a, float _b) 
    throws java.rmi.RemoteException, javax.xml.rpc.JAXRPCException;
}

这将 xsd:float 映射到所生成的客户端存根中的 float 类型。看到 CLDC 1.0 和 CLDC 1.1 之间的不同之处了吗?

在为移动设备开发 Web 服务时,请注意 float 和 double 类型,因为 CLDC 1.0 虚拟机实现无法加载为 CLDC 1.1 生成的存根(使用到 float 和 double 的本机映射)。同时针对 CLDC 1.0 和 CLDC 1.1 的 Java 2 Platform Micro Edition (J2ME) 应用程序的开发人员应该使用到 java.lang.String 的缺省映射,以获得最好可重用性。

在处理输入和输出参数时注意可能出现的问题

JSR-172 指定了以副本的形式传送并以副本的形式创建返回值的所有参数。但是,当处理数据集合时,零数组 (返回零)和空数组 (返回其本身)需要密切关注。

我的建议是尽可能地避免使用空数组。当处理移动 Web 服务时,空数组可能是一个问题。

假定您需要返回任务对象数组。原始代码如清单 11 所示。



清单 11. 一个简单的值对象

public class SimpleTask {
    /**
     * The name of the task
     */
    private String name;

    /**
     * The default constructor
     *
     */
    public SimpleTask() {

    }

    /**
     * @return Returns the name of the task.
     */
    public String getName() {
        return name;
    }

    /**
     * @param name
     *            The name to set.
     */
    public void setName(String name) {
        this.name = name;
    }
}

Web 服务实现如清单 12 所示。



清单 12. 返回值对象的数组的方法

1  public SimpleTask[] getSimpleTasks(){
2       SimpleTask[] tasks = null;
3       /*
4        * Your code dealing with DB goes here
5        * ....
6        * tasks = ...
7        */
8       return tasks;
9	}

当生成 Web 服务存根和使用生成的存根测试 Web 服务时,本例中的每一个部分都将正常工作。但是,因为在结束一个阶段之前您需要使用 Jtest 进行完整的代码检查,所以当您对代码片段运行 Jtest 时,您将看到一条建议:“Return zero-length arrays instead of null”。在犹豫片刻之后后,您将赞同 Jtest 的建议。如果您返回零数组,该代码的客户端必须编写额外的代码来检查返回值是否为零(如清单 13 所示)。



清单13. 用于调用 Web 服务的客户端代码片段

   SimpleTask[] tasks = service.getSimpleTasks();
       if(tasks != null){
           int length = tasks.length;
           //do something here
       }

当您将 SimpleTask[] tasks = null;(清单 12 中的第 2 行)修改为 SimpleTask[] tasks = new SimpleTasks[0]; 时,您只需将清单 13 编写为:

   SimpleTask[] tasks = service.getSimpleTasks();
           int length = tasks.length;

在修改之后,您会认为代码逻辑没有更改,并再次运行客户端来调用 Web 服务,但是现在却引发了异常。到目前为止,您已经根据 Jtest 的建议做了许多小的修补――您忘记修改了什么――这可能导致需要花额外的时间来努力找到发生错误的原因。这个过程真的漫长而乏味。

那么,问题究竟出在什么地方呢?一般来说,对于零对象数组(如 SimpleTask),返回的 SOAP 消息如清单 14 所示。



清单 14. 返回零数组时的 SOAP 消息

<soapenv:Body>
<p147:getSimpleTasksResponse xmlns:p147="http://ws.test.ibm.com">
  <getSimpleTasksReturn xsi:nil="true" />
</p147:getSimpleTasksResponse>
</soapenv:Body>

对于空数组(如 SimpleTask[] tasks = new SimpleTask[0]),SOAP 消息如清单 15 所示。



清单 15. 返回空数组时的 SOAP 消息

<soapenv:Body>
<p147:getSimpleTasksResponse xmlns:p147="http://ws.test.ibm.com">
  <getSimpleTasksReturn />
 </p147:getSimpleTasksResponse>
 </soapenv:Body>

其不同之处在于 <getSimpleTasksReturn/> 和 <getSimpleTasksReturn xsi:nil = true> 之间。图 2 说明了空数组参数大部分时间是无效的。对于自定义的数据类型(包括另一个自定类型的数组),不要将类变量初始化为空数组――相反,要将其初始化为零数组,尽管所生成的空数组和零数组的 WSDL 定义是相同的。



图 2. 根据 JSR-172 编码零数组参数和空数组参数
根据 JSR-172 编码零数组参数和空数组参数 

结束语

在处理移动 Web 服务时,您需要更加谨慎,因为移动 Web 服务规范只支持部分 API。如果您计划开发移动 Web 服务,则当您处理值类型和集合类型时,我向您介绍了一些窍门。此外,我还提供了以下信息:

  • 设计前考虑事项,例如何时使用 Web 服务,以及如何分析使用 Web 服务、套接字或消息传递技术之间的利弊。
  • 在决定使用 Web 服务后需要考虑的设计事项,包括:
    1. 管理粒度
    2. 设计 Web 服务接口
    3. 使用 Document/literal 作为编码样式
    4. 为什么您应该使用 JavaBeans 组件而不是 EJB 技术作为您的服务提供程序
    5. 为什么您应该避免 XML 元素嵌套太深
    6. 嵌套和粒度之间的平衡
  • 在使用 JAX-RPC 值类型时需要考虑的移动 Web 服务设计事项,包括:
    1. 公共缺省构造器
    2. Setter 和 getter 方法
    3. 使用数组类型而不是 Java Collection 类型
    4. 确定首选数据类型
    5. 处理输入和输出参数

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件