分享
 
 
 

J2ME WEB服务入门教程

王朝java/jsp·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

作者:C. Enriq 文章来源:SUN中国技术社区

J2ME Web 服务 API( Web Services API,WSA)是作为 JSR 172 在 Java Community Process 中开发的,它拓展了 J2ME, 从而支持 Web 服务。API 的两个可选软件包对两个功能区域进行标准化,这两个功能区域对于 Web 服务的客户机来说是至关重要的:远程服务调用和 XML 解析。 本文将介绍这两个软件包,展示如何使用它们并描述在 J2ME 无线工具包(J2ME Wireless Toolkit)中对它们的支持。

要系统地学习更多关于无线应用程序开发的复杂内容,请参阅文章“The Complexity of Developing Mobile Networked Data Services, J2ME Wireless Connection Wizard For Sun Java System Studio”,该文章描述了移动联网应用程序的主要元素。

简介

WSA 设计用于与 J2ME 配置文件协同工作,J2ME 配置文件要么基于 Connected Device Configuration (CDC),要么基于 Connected Limited Device Configuration (CLDC 1.0 或 CLDC 1.1)。远程调用 API 基于 J2SE 的 Java API for XML-Based RPC (JAX-RPC 1.1) 的一个完整子集,它包含了一些远程方法调用(Remote Method Invocation,RMI)类,以满足 JAX-RPC 依赖。XML 解析 API 基于 Simple API for XML, v2 (SAX2)的一个完整子集。

WSA 的目标是把对 Web 服务调用和 XML 解析的基本支持集成到设备的运行时环境,这样开发人员就不必在每个应用程序中嵌入这样的功能了——在像移动电话和个人数字助理这样资源有限的设备中,这算是一个特别浪费资源的问题。

核心规范

Web Services Interoperability Organization (WS-I) 促进了定义 Web 服务的核心规范和应用层协议,并且它们受 World Wide Web Consortium (W3C) 和 Organization for the Advancement of Structured Information Standards (OASIS) 的指导。4 个关键标准规定了如何创建、部署、发现以及如何使用 Web 服务:

Web 服务标准描述Simple Object Access Protocol (SOAP) 1.1

定义了传输和数据编码

Web Services Definition Language (WSDL) 1.1

定义了如何描述远程服务

Universal Description, Discovery, & Integration (UDDI) 2.0

定义了如何发现远程服务

Extensible Markup Language (XML) 1.0XML Schema

定义了可扩展标记语言(Extensible Markup Language ,XML) 和 XML 模式(Schema)

这些主要规范往往非常广泛,而且 Web 服务开发人员已发现难以实现完全互操作性。为了解决标准解释中存在的差异,WS-I 已定义了一组称作 WS-I Basic Profile, version 1.0 的一致性规则。JSR 172 符合基本配置文件(Basic Profile)。

J2ME 平台上的 Web 服务

JSR 172 规定了标准化客户端技术,允许 J2ME 应用程序在典型 Web 服务架构上使用远程服务,如图 1 所示:

图 1 在典型 Web 服务架构上的 J2ME Web 服务

在高层,该 Web 服务架构具有三个元素:

驻留在支持 WSA 无线设备上的网络感知应用程序。该应用程序包括使用 JSR 172 运行库与网络进行通信的 JSR 172 存根。下文将会描述存根和运行库所扮演的角色。 无线网络和 Internet 以及对应的通信和数据编码协议,包括二进制协议、HTTP 以及 SOAP/XML. Web 服务器,扮演服务提供者的角色,通常在一个或多个防火墙和代理网关后面。Web 服务器通常提供对专用网络上后端应用程序和服务器的访问。 WSA 的第一个版本只解决了 Web 服务的使用,不支持服务端点的创建和开发;J2ME 设备可以是服务用户,但不可以是服务提供者。JSR 172 还没有规定使用 UDDI 的服务发现的 API。

了解 JSR 172

首先考查如何组织典型的基于 JSR 172 的应用程序,开始了解 J2ME Web Services 是如何运作的:

该应用程序本身是一个基于移动信息设备配置文件(Mobile Information Device Profile,MIDP)或个人基础配置文件(Personal Basis Profile,PBP))的智能客户机,具有特定于业务的逻辑、用户界面、持久性逻辑以及生命周期和应用程序状态管理。该应用程序可以使用 JAXP 子集 API 来处理 XML 文档。还可以使用 JAX-RPC 子集 API 来使用 Web 服务,从而使用 JSR 172 存根和运行库。

在像手提电话这样的设备中,应用程序和 JSR 172 存根通常驻留在设备内存中,而所有 JSR 172 元素连同基础配置文件和配置一起嵌入到设备本身。

JSR 172 运行库和服务提供者接口

在 JSR 172 操作的中心是运行库,带有服务提供者接口,允许存根执行所有与调用 RPC 服务端点有关的任务:

设置特定于 RPC 调用的属性。 描述 RPC 调用输入和返回值。 编码输入值。 调用 RPC 服务端点。 对应用程序解码并为其返回服务端点所返回的全部值。 图 3 描绘出了客户机应用程序、存根以及运行库三者之间的关系:

图 3 JSR 172 运行库和 SPI

虽然 JSR 172 运行库隐藏了像连接管理和数据编码这样的复杂性,但 SPI 从运行库实现细节分离出了存根,从而允许存根在供应商实现之间的可移植性。

客户机应用程序不直接与运行库和 SPI 进行交互;而是使用存根。运行库和 SPI 主要为打算开发 JSR 172 运行库和自动化工具的第三方供应商所关心,比如开发人员用于生成存根的 WSDL 到 Java 映射工具。

由于应用程序开发人员不直接使用 SPI,因此本文不会较详尽地介绍运行库和 SPI。如果想了解关于它们的更多信息,可以查阅 JSR 172 规范。

JSR 172 JAX-RPC 子集 API

正如前面所提到的,JSR 172 Web 服务远程调用 API 基于 J2SE 的 JAX-RPC 1.1 API 的一个完整子集。以下列表在高层描述了该子集。要了解详细信息,请参阅 JSR 172 specification

符合 WS-I Basic Profile。 支持 SOAP 1.1。 支持所有传输,比如 HTTP 1.1,它可以传送 SOAP 消息,而且具有一个捆绑 SOAP 1.1 的已定义协议。 支持全套数据类型:逻辑型、字符型、短整型、整型、长整型、浮点型、双精度型、字符串型(String)、基本类型数组以及复杂类型(包括基本或复杂类型的结构)。

注意,真正的浮点支持只在基于 CDC 或基于 CLDC 1.1. On CLDC 1.0 的软件堆栈中出现,浮点型和双精度型映射为 String。还要注意,所支持的数据类型会约束所支持的 WSDL 数据类型。后面的部分将讨论 WSDL 到 Java 数据类型映射。

支持表示 RPC 调用或响应(使用 Document/Literal 消息传递模式的 WSDL 操作)的 SOAP 消息的 Literal 表示;不支持 Encoded 表示。 不支持带有附件的 SOAP 消息。 不支持 SOAP 消息处理程序。 不支持服务端点;即不允许设备是 Web 服务提供者。 不提供发现支持(UDDI). 要减少对网络带宽的需求——以及要节省用户的时间和每字节的开销,请不要在设备本身上强制使用 XML 编码。

注:实现可能会使用更高效的编码,比如设备与无线网关间的二进制协议,只要它对消费者和生产者来说都是透明的。

下表描述了 JSR 172 JAX-RPC 子集中的软件包:

Java\ 软件包

描述

javax.microedition.xml.rpc

定义了存根使用的 Type,它是合法简单类型的枚举:逻辑型、字节型、短整型、整型、长整型、浮点型、双精度型、 String

定义了存根使用的 ComplexType,它是表示 WSDL xsd:complextype 定义的特殊类型

定义了存根使用的 Element,它表示 WSDL xsd:element 定义

定义了存根使用的 Operation,它表示服务端点的 WSDL wsdl:operation

定义了 FaultDetailHandler,这是一个处理自定义故障的存根所实现的接口

定义了存根使用的 FaultDetailException,这是一个 Exception 类,表示运行时实现抛出的作为 JAXRPCException 结果的异常;为 service-specificDefines 返回存根异常详细值所使用的 QName(限定名)类,并将相关的 QName 返回给 Stub 实例

javax.xml.namespace

定义了存根所使用的 QName(限定名)类

javax.xml.rpc

定义了 Stub 接口,这是所有 JAX-RPC 存根的基本接口;还定义了 NamespaceConstants 以及与 JAXRPCException 有关的类

java.rmi

标准 java.rmi 软件包子集,包含它以满足 JAX-RPC 依赖性;只定义了 Remote 处理程序和三个异常类:MarshalException、 RemoteException 和 ServerException

除了像 RemoteException 这样的异常,存根还使用大多数上述 API;应用程序本身使用存根。

在应用程序中使用 JAX-RPC 子集

创建 JSR 172 JAX-RPC 客户机的一般步骤如下:

从描述远程 Web 服务的 WSDL XML 文档生成 JSR 172 JAX-RPC 存根类。 在自己的代码中创建生成存根的实例。 实例化之后,调用生成存根的方法。这些方法与 WSDL XML 文档中服务端点的 wsdl:操作相对应。 生成 JSR 172 JAX-RPC 存根

客户机应用程序通过存根和设备的 JSR 172 运行库与远程服务进行交互。该运行库隐藏了与连接、SOAP 以及数据编码管理相关的复杂性。

要与运行库进行交互,客户机通常使用存根生成器所生成的存根或者 WSDL 到 Java 的映射工具,它们用于在 WSDL 文档中输入远程服务接口定义,并生成使用 JAX-RPC 子集 API 和运行库 SPI 的存根类。虽然也能手工开发这些存根,但使用该生成器效果会更佳。下图概述了存根的生成:

生成 JSR 172 存根的一般步骤。

最后所得到的存根类实现了 Stub Interface 和服务的远程接口,并使用了支持类。

生成 JSR 172 JAX-RPC 存根的步骤类似于创建基于 RMI 的应用程序的步骤。在标准 RMI 中,RMI 编译器 (rmic) 从远程接口定义生成存根。如图 4 所示,创建 WSA 应用程序之后,WSDL 到 Java 的映射工具从 WSDL XML 文件生成存根。映射工具生成远程接口 Java 文件和支持类,它们由生成的存根本身所使用。然后将 JSR 172 存根编译为 Java 类,并同应用程序一起打包。

Sun 的 J2ME Wireless Toolkit V2.1 包含 JSR 172 JAX-RPC 存根生成器——本文稍后将讲述如何使用它。第三方供应商提供了自己的存根生成器。

使用 JSR 172 JAX-RPC 存根

存根一旦生成了,应用程序就可以使用它了。以下代码片段使用了称作 PubService 的服务,以便检索无线技术文章:

package j2medeveloper.pubwebservice

// MIDP

import javax.microedition.midlet.MIDlet;

import javax.microedition.lcdui.Display;

import javax.microedition.lcdui.Form;

...

// JAX-RPC

import java.rmi.RemoteException;

// JAX-RPC

String serviceURL = "www.j2medeveloper.com/pubwebservice";

String articleID = "IntroJSR172";

...

// Instantiate the service stub.

PubService_Stub service = new PubService_Stub();

// Set up the stub.

service._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, serviceURL);

service._setProperty(Stub.SESSION_MAINTAIN_PROPERTY, new Boolean(true));

...

try {

// Invoke the PubService method getArticleByID() to retrieve

// a specific article by ID. A WirelessArticle represents an

// article and has methods to get the article's author, date,

// title, summary, and body. PubService also has a method to

// get the PubService's RSS feed.

WirelessArticle article = service.getArticleByID(articleID);

// Create a Form to display the article.

javax.microedition.lcdui.Form form =

new Form(article.getShortTitle());

form.append(wrap(article.getSummary()));

...

...

display.setCurrent(form);

} catch (RemoteException e) {

// Handle RMI exception.

} catch (Exception e) {

// Handle exception.

}

...

使用存根会使远程服务调用变得非常容易。该代码用例子说明了 PubService_Stub,初始化了实例,并调用了它的其中一个方法 getArticleByID(),以便对文章本身进行检索。然后,应用程序使用了文章的访问方法来获取文章的标题、摘要等等。

注意,因为调用 PubService_Stub.getArticleByID() 是分块调用,因此在实际应用程序中,要用分离的线程来分派该调用。在 WSA 中,方法调用遵循常见的客户机/服务器交互的同步请求-响应模型:客户机向服务器发出请求,然后等待服务器的响应:

图 5 同步请求/响应模型

如何对方法及其参数进行编码、序列化和发送,以及如何接收、解码和反序列化响应,对应用程序来说是完全透明的。JSR 172 存根和运行库处理所有这些单调冗长的细节。

将 WSDL 数据类型映射到 Java

下面简要考察一下 JSR 172 的 JAX-RPC 子集 API 中的 WSDL 到 Java 的数据类型映射:

WSDL 数据类型

Java 数据类型

xsd:string

String

xsd:int

int 或 Integer

xsd:long

long 或 Long

xsd:short

short 或 Short

xsd:boolean

boolean 或 Boolean

xsd:byte

byte 或 Byte

xsd:float

String、float 或 Float

xsd:double

String、double 或 Double

xsd:QName

javax.xml.namespace.QName

xsd:base64Binary

byte[]

xsd:hexBinary

byte[]

Arrays

取决于 XML 数组的模式

xsd:complexType

基本和类类型的序列

别忘了,因为 CLDC 1.0 不支持浮点类型,因此一定要将浮点型和双精度型映射为 String 型。当目标既包含 CLDC 1.0 又包含 CLDC 1.1 平台时,开发人员应使用该默认映射。

要了解关于 WSDL 的更多信息,请参阅 JSR 172 specificationW3C's WSDL specification

在应用程序中使用 JAXP 子集

现在将注意力转移到 JAXP 子集——其他 JSR 172 API。记得 JAXP 和 JAX-RPC 都是可选软件包;它们彼此独立地存在。

JAXP XML 解析 API 基于 Simple API for XML v2(SAX2)的一个完整子集。虽然标准 SAX2 API 中的大多数类没被包含在该子集中,但保留有所有必要的核心功能。

以下列表在高层描述了 JAXP 子集。要了解更多信息,请参阅 JSR 172 specification

基于 SAX 2.0 的一个完整子集

不支持 SAX 1.0,因为 SAX 2.0 已将它取代了。

支持 XML 命名空间 既支持 UTF-8 又支持 UTF-16 字符编码。 要么不支持文档对象模型(Document Object Model (DOM))的 Level 1.0 ,要么不支持 DOM 的 Level 2.0 ,因为考虑到它太笨重。 不支持可扩展样式表语言转换(Extensible Stylesheet Language Transformations,XSLT)。 支持文档类型定义(Document Type Definition,DTD)。

解析器可以根据 XML 文档类型的指定内部或外部定义来对这些文档进行验证。 JSR 172 规定,文档验证是可选的,因为该操作开销极大,一个文档在限制较高的基于 CLDC 的环境不适合,但可能会在更高端的基于 CDC 的平台上获得成功。如果跳过 DTD 处理,DefaultHandler.skippedEntity() 方法就会通知应用程序。该逻辑符合 XML 1.0 规范。

下表描述了 JSR 172 JAXP 子集中的软件包:

Java 软件包

描述

javax.xml.parsers

定义了 SAXParser,这是一个表示简单的基于 SAX 的解析器的 API。

定义了 SAXParserFactory,这是一个获得和配置基于 SAX 的解析器的工厂。

定义了 ParserConfigurationException,抛出时指示配置错误。

定义了 FactoryConfigurationError,抛出时指示解析器工厂的问题。

org.xml.sax

定义了 Attributes,这是一个通过以下形式提供对属性列表进行访问的接口: 属性索引 限定命名空间的名称 限定(前缀)名称

定义了 Locator,这是一个用于将 SAX 事件与文档位置相关联的接口。通过使用 Locator(该 Locator 通过调用 DefaultHandler 对象的 setDocumentLocator() 方法而指定)的实例,该应用程序可以获取解析事件位置信息,比如事件行号、列号以及公共和系统标识符。 Locator 提供了获取当前文档事件结束位置的行号、列号的方法以及获取当前文档事件的公共和系统标识符的方法。

定义了 InputSource,它封装输入源。它提供了获取或设置字节流、字符集、编码以及公共和系统标识符的方法。

定义了通用 SAX 异常类、SAXException 以及三个子类: SAXNotRecognizedException、SAXNotSupportedException 和 SAXParseException

org.xml.sax.helpers

定义了 DefaultHandler,这是 SAX2 事件处理程序的基类。它提供了要扩展的应用程序的事件处理行为的缺省实现。应用程序开发人员只需覆盖相关的方法,就可以设计解析行为。 在读取 XML 流的时候,当解析器与 XML 元素或属性发生冲突时,它就通过调用其中一个 DefaultHandler 方法来通知确定事件的应用程序;例如:

startDocument() 和 endDocument(),在 XML 文档的开头和末尾 startElement() 和 endElement(),在 XML 元素的开头和末尾 characters(),当在元素内部发现字符数据时 skippedEntity(),当跳过一个实体时 JSR 172 specification 描述了 DefaultHandler 方法的其余部分。

以下方法定义显示了如何使用 JAXP 来解析从 PubService 检索的 RSS 提要:

/**

* Invoke the service and parse the RSS feed.

*/

private void parseRSSfeed() {

try {

// Create a RSS parser handler

parser = new RSSParserHandler();

try {

SAXParserFactory factory = SAXParserFactory.newInstance();

saxParser = factory.newSAXParser();

} catch (Exception e) {

// Handle exception...

return;

}

// Invoke the remote service method getRSSFeed to

// retrieve the RSS feed for the Pub service

// web site.

String rssFeed = service.getRSSFeed();

// Parse the RSS feed.

byte[] rssFeedByteArray = rssFeed.getBytes("UTF-8");

ByteArrayInputStream rssFeedByteArrayInputStream =

new ByteArrayInputStream(rssFeedByteArray);

saxParser.parse(rssFeedByteArrayInputStream, parser);

} catch (RemoteException e) {

// Handle RMI exception.

} catch (Exception e) {

// Handle exception.

}

}

parseRSSfeed() 方法使用 PubService_Stub.getRSSFeed() 远程服务来检索 PubService 的 RSS Content XML 文档,然后将其传递到 JAXP RSS-feed XML 解析器。以下类定义显示了如何实现负责解析 RSS 提要的处理程序:

/**

* RSS Parser handler class to parse the RSS feed from the

* server.

*/

class RSSParserHandler extends DefaultHandler {

// Stack to keep track of document parsing.

Stack stack;

// Current document element.

Object current;

/** Start of document processing. */

public void startDocument() {

rssParsingComplete = false;

title = link = description = null;

stack = new Stack();

}

/** Process the new element. */

public void startElement(

String uri, String localName, String qName,

Attributes attributes) throws SAXException {

if ("item".equals(qName)) {

title = link = description = null;

}

stack.push(qName);

}

/** Process the character data for current tag. */

public void characters(

char[] ch, int start, int length) {

Object current = stack.peek();

if ("title".equals(qName)) {

title = new String(ch, start, length));

} else if ("link".equals(qName)) {

link = new String(ch, start, length));

} else if ("description".equals(qName)) {

description = new String(ch, start, length));

}

}

/** Process the end element tag. */

public void endElement(

String uri, String localName, String qName) {

stack.pop();

if ("rss".equals(qName)) {

rssParsingComplete = true;

} else {

// Do something with title, link, description, such

// as displaying it to the user.

}

}

}

注意,startDocument()、startElement()、stopElement() 以及 characters() 方法的定义提供了 SAX2 XML 解析所需的最低功能。

支持 Web 服务的 J2ME 无线工具包

J2ME Wireless Toolkit v2.1 包含开发充分利用 J2ME Web Service 的 MIDlet 所需的库。该工具包还包含 JAX-RPC 存根生成器,可以从命令行或 KToolbar 菜单运行它,如下图所示:

图 6 J2ME 无线工具包 2.1 实用程序和存根生成器

在 Utilities 屏幕上选择 Stub Generator。在出现的对话框中,输入描述要使用服务的输入 WSDL 文档的 URL、生成文件的输出路径以及用于已生成存根文件的软件包名。相应地选择 CLDC 1.0 或 1.1。

J2ME 无线工具包的 v2.1 还包含一个示例应用程序 JSR172Demo。

结束语

J2ME Web 服务规范(J2ME Web Services Specification)使 J2ME 平台上的 Web 服务和 XML 解析编程接口标准化了。随着 JAX-RPC 子集 API 的出现,开发人员可以使用 Java 编程语言和熟悉的 JAX-RPC API 来创建使用基于 XML 的远程服务的应用程序。而不必处理 HTTP、SOAP 和数据转换的底层细节。而且随着 JAXP 子集 API 的引入,XML 解析目前已是 J2ME 平台本身不可分割的一部分。J2ME Web Services API 消除了开发人员在每个应用程序中包含用于远程调用和 XML 解析代码的需要。

这些功能强大的 API 允许移动应用程序更容易地访问基于 Web 的服务,但是开发人员千万别忘了 J2ME 设备提供的受限制的应用程序环境。仅仅移植现有的基于 XML 的桌面或企业应用程序不是开发 J2ME 平台的 Web 服务客户机的适当方法。对设备处理能力、电池寿命、网络带宽以及安全性的适当考虑也是不可缺少的。

更多信息

JSR 172: J2ME Web Services Specification Web Services Interoperability Organization (WS-I) World Wide Web Consortium (W3C) Organization for the Advancement of Structured Information Standards (OASIS) The Complexity of Developing Mobile Networked Data Services, J2ME Wireless Connection Wizard For Sun Java System Studio W3C WSDL website 致谢

非常感谢 JSR 172 规范负责人 Jon Ellis 和 Mark Young 对本文的反馈。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有