Ada Li

星期三 九月 05, 2007

Java EE 5实现Web服务(Web Services)及多种客户端实例-小结

问题解决

在开发过程中,可能会遇到以下问题:

1.错误信息:

javax.xml.ws.WebServiceException: Failed to access the WSDL at: http://localhost:8080/StockQuoteWS/StockQuoteService?WSDL. It failed with:

Connection refused: connect.

at Connection refused: connect.

at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:136)

at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:122)

at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:226)

......

原因及解决方法:

Web服务需要部署在服务器上,上面的错误信息往往是因为没有启动应用服务器NetBeans "运行环境"tab中,"服务器"->"Sun Application Server 9" -> 启动


2. 错误信息

java.lang.LinkageError: JAXB 2.0 API is being loaded from the bootstrap classloader, but this RI (from jar:file:/C:/Java/netbeans-5.5.1/ide7/modules/ext/jaxws21/jaxb-impl.jar!/com/sun/xml/bind/v2/model/impl/ModelBuilder.class) needs 2.1 API. Use the endorsed directory mechanism to place jaxb-api.jar in the bootstrap classloader. (See http://java.sun.com/j2se/1.5.0/docs/guide/standards/)

at com.sun.xml.bind.v2.model.impl.ModelBuilder.<clinit>(ModelBuilder.java:136)

at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:406)

at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:270)

......


原因及解决方法:

这种错误通常发生在Java SE 6(JDK 6)平台上,因为Java SE 6(JDK 6)缺省自带的是 JAXB 2.0 JAX-WS 2.0.最简单的办法是把NetBeans 5.5.1 中自带的JAXB 2.1 JAX-WS 2.1 拷贝到Java SE 6(JDK 6)平台中去.具体做法如下,在Java 平台的JRElib目录下建立endorsed目录,比如"C:\Java\jdk1.6.0\jre\lib\endorsed",然后在NetBeans 5.5.1 中找到jaxb-api.jarjaxws-api.jar两个文件,比如在目录"C:\Java\netbeans-5.5.1\ide7\modules\ext\jaxws21\api"下.

把这两个jar文件从NetBeans 5.5.1中拷贝到 C:\Java\jdk1.6.0\jre\lib\endorsed 中.


Java Ee平台上实现Web服务及多种客户端实例结构图





结构图可以更清楚地了解前面实例中各个部件之间的关系。


JAVA EE 5平台上实现Web服务实例(模拟股票行情机)用蓝色表示。

瘦客户端(thin client)用黄色表示

胖客户端(rich client)用绿色表示

移动客户端(mobile client)用红色表示




参考:


http://uddi.org/


http://www.w3.org/TR/ws-arch/


http://zh.wikipedia.org/


http://www.netbeans.org/


http://www.java.net/



作者简介:

李力目前在Sun Microsystems任高级软件工程师,有近十年软件开发经验,曾就职于AIGCA等公司,任软件工程师及系统分析员等职位,在J2EE领域有丰富的实际开发经验。

Java EE 5实现Web服务(Web Services)及多种客户端实例-移动客户端

准备及安装软件

1JAVA SE 5 (JDK 1.5)及以上版本(http://java.sun.com/javase/downloads/index.jsp )

2NetBeans 5.5.1 (http://zh-cn.netbeans.org/index_zh_CN.html )

3NetBeans Mobility Pack for CLDC(http://zh-cn.netbeans.org/products/mobility/index_zh_CN.html )


建立移动客户端(mobile client)调用Web服务


1. NetBeans菜单“文件”->“新建项目“。 “新建项目”窗口中,“类别“选择“Mobile”, "项目“选择“Mobile应用程序”. 点击“下一步”



2. “名称和位置”窗口中,输入“项目名称” “MobileClient”. 取消“创建HelloMIDlet”.




3.“选择缺省平台”窗口中,如下配置

仿真平台:Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC

设备:DefaultColorPhone

设备配置:CLDC-1.1

设备配置文件:MIDP-2.0

点击“完成“按钮





4. NetBeans中生成“MobileClient”项目。鼠标右键点击“MobileClient”项目,选择“新建”->“文件/文件夹”。“新建文件”窗口中,“类别“选择“MIDP”, 文件类型选择“J2ME Web服务客户端”. 点击“下一步”



5. “新建J2ME Web服务客户端”窗口中,在WSDL URL栏中,输入“J2ME Web服务客户端http://localhost:8080/StockQuoteWS/StockQuoteService?WSDL ”。 点击“检索WSDL”按钮,在“客户端名称”中自动出现“StockQuoteService”,表示检索成功。修改"包"名为"com.sun.sdn.demo.ws.client. 点击"完成"按钮.


在点击“检索WSDL”按钮之前, 请用”设置代理”按钮, 确认已经设置了适和的代理服务器。关于WSDL URL,请参考<<JAVA EE 5平台上实现Web服务实例(模拟股票行情机)>>



6. NetBeans mobileClient项目中自动生成了Web服务的调用类,以及MIDlet.






7. Sun手机仿真器中,运行结果如下:







8.当询问是否使用网络通话时,选择"是".最后的运行结果







创建移动客户端访问Web 服务的过程看起来非常简单,比瘦客户端和胖客户端的步骤都要少.但是这种客户端如果部署在真正的手机上,需要手机支持JSR 172规范。目前这种手机并不多, 目前有诺基亚 E62, N75, N77, 索尼爱立信 W600,S600,P990, 摩托罗拉A1200 .

Java EE 5实现Web服务(Web Services)及多种客户端实例-胖客户端

胖客户端,相对于瘦客户端来说,有着界面丰富,操作速度快,功能强大等优点. 目前国内比较流行的炒股软件,比如钱龙,大智慧, 同花顺,都属于胖客户端类. 而胖客户端的缺点在于升级成本高等.

准备及安装软件

1JAVA SE 5 (JDK 1.5)及以上版本(http://java.sun.com/javase/downloads/index.jsp )

2NetBeans 5.5.1 (http://zh-cn.netbeans.org/index_zh_CN.html )

建立胖客户端调用Web服务


1。打开NetBeans 5.5.1, 菜单“文件”中选择“新建项目”

2。“新建项目”窗口中,“类别”栏中选择“常规”,“项目“栏中选择“ Java应用程序”,点击“下一步”按钮。



3。“新建Java应用程序 ”窗口中,在“项目名称”栏中输入“RichClient”

取消”创建主类”. 点击”完成”























4. 接下来要创建GUI窗体. 鼠标右键点击”RichClient”项目. 选择"新建"->"文件/文件夹". "新建文件"窗口中, “类别”选择”Java GUI窗体”, “文件类型”选择”JFrame窗体”





5. "新建JFrame窗体”中, 输入如下

类名: StockQuoteJFrame

: com.sun.sdn.demo.ws.client

点击”完成”按钮






6. 空白窗体"StockQuoteJFrame"出现在设计窗口中. NetBeans中的GUI采用托拽”组件面板”部件到窗体的方式来布局, 打开"组件面板"窗口,可以通过菜单"窗口"->"组件面板". 完成后的StockQuoteJFrame.java 窗体如下:



7. 建立完GUI窗体, 接下来需要建立Web服务的客户端. 需要先导入相关的Web服务库. 选择”RichClient"项目下的库。鼠标右键点击”库", 选择”添加库...”"添加库"窗口中,选择”JAX-WS 2.1”. 点击”添加库”按钮.


8。鼠标右键点击”RichClient”项目, 选择“新建”->“文件/文件夹”. ”新建文件”窗口中,“类别”选择“Web服务”,“文件类型”选择“Web服务客户端”。点击“下一步”。


9.“新建Web服务客户端”窗口中,输入如下:

WSDL URL: http://localhost:8080/StockQuoteWS/StockQuoteService?WSDL

包名:com.sun.sdn.demo.ws.client 

点击”完成”

关于WSDL URL,请参考<<JAVA EE 5平台上实现Web服务实例(模拟股票行情机)>>





另外, 点击”设置代理”按钮, 确认已经设置了适和的代理服务器.




10. 出现如下提示窗口,询问"已在外部修改了文件E:\mymodules\RichClient\catalog.xml, 是否重新装入它?", 点击”是”



11. NetBeans 自动在客户端生成Web服务的调用类.在”文件"Tab, 可以在”ThinClient”->"build"->"generated"->"wsimport",查看com.sun.sdn.demo.ws包中自动生成的调用类,

GetQuote.class

GetQuoteResponse.class

ObjectFactory.class

StockQuote.class

StockQuoteService.class

package-info.class



12. stockQuoteJFrame.java的源窗口中, 加入下面一个方法

public String getQuote(String stockCode){

return null;

}


13. getQuote()方法体中, 鼠标右键点击任一位置.选择”Web服务客户端资源”->"调用Web服务操作"



14. 自动生成的代码(黑体)如下

public String getQuote(String stockCode){

try { // Call Web Service Operation

com.sun.sdn.demo.ws.client.StockQuoteService service = new com.sun.sdn.demo.ws.client.StockQuoteService();

com.sun.sdn.demo.ws.client.StockQuote port = service.getStockQuotePort();

// TODO initialize WS operation arguments here

java.lang.String arg0 = "";

// TODO process result here

java.lang.String result = port.getQuote(arg0);

System.out.println("Result = "+result);

} catch (Exception ex) {

// TODO handle custom exceptions here

}

return null;

}

15. stockQuoteJFrame.java的设计页面, 右键点击”get quote”按钮, 选择”事件”->"Action"->"actionPerformed". 添加如下代码:

private void jButtonGetQuoteActionPerformed(java.awt.event.ActionEvent evt) {

String stockCode = jTextFieldStockCode.getText();

String quote = "Stock " + stockCode + " quote is " + this.getQuote(stockCode);

jLabelResult.setText(quote);

}


15. 修改后的stockQuoteJFrame.java的部分代码如下:

private void jButtonGetQuoteActionPerformed(java.awt.event.ActionEvent evt) {

String stockCode = jTextFieldStockCode.getText();

String quote = "Stock " + stockCode + " quote is " + this.getQuote(stockCode);

jLabelResult.setText(quote);

}

....

String getQuote(String stockCode){

String result = "";

try { // Call Web Service Operation

com.sun.sdn.demo.ws.client.StockQuoteService service = new com.sun.sdn.demo.ws.client.StockQuoteService();

com.sun.sdn.demo.ws.client.StockQuote port = service.getStockQuotePort();

result = port.getQuote(stockCode);

} catch (Exception ex) {

ex.printStackTrace();

}

return result;

}


16.鼠标右键点击“RichClient”, 选择“运行项目”。运行结果如下:











在胖客户端的建立过程中,有一个环节是导入JAX-WS库。而建立瘦客户端中没有这一步,是因为瘦客户端部署在Sun Application Server 9 上,Java EE 5平台中带有JAX-WS. 部署胖客户端的Java SE 5则没有JAX-WS包。不过从Java SE 6 开始,已经把JAX-WS包中加了进去。

Java EE 5实现Web服务(Web Services)及多种客户端实例-瘦客户端

瘦客户端指采用浏览器作客户端, 而代码实现通常采用Web应用程序.


准备及安装软件


1JAVA SE 5 (JDK 1.5)及以上版本(http://java.sun.com/javase/downloads/index.jsp )

2NetBeans 5.5.1 (http://zh-cn.netbeans.org/index_zh_CN.html )

3Sun Application Server 9 (https://glassfish.dev.java.net/): 可以直接下载带Sun Application Server 9NetBeans (http://www.netbeans.info/downloads/index.php )


建立瘦客户端调用Web服务


1。打开NetBeans 5.5.1, 菜单“文件”中选择“新建项目”

2。“新建项目”窗口中,“类别”栏中选择“Web”,“项目“栏中选择“Web应用程序”,点击“下一步”按钮。

3。“新建Web应用程序 ”窗口中,在“项目名称”栏中输入“ThinClient”

“服务器”中选择“Sun Application Server 9”

Java Ee版本”中选择“Java EE 5”

4。接下来在“ThinClient”项目中建立Web Serv ices Client . 鼠标右键点击“”项目,选择“新建”->“文件/文件夹”

5。“新建文件”窗口中,“类别”选择“Web服务”,“文件类型”选择“Web服务客户端”。点击“下一步”。




5。“新建Web服务客户端”窗口中,输入如下:

WSDL URL: http://localhost:8080/StockQuoteWS/StockQuoteService?WSDL

包名:com.sun.sdn.demo.ws.client 


关于WSDL URL,请参考<<JAVA EE 5平台上实现Web服务实例(模拟股票行情机)>>


6.出现如下提示窗口:




7.选择"是"之后,NetBeans 自动在客户端生成Web服务的调用类.在”文件"Tab, 可以在”ThinClient”->"build"->"generated"->"wsimport",查看自动生成的调用类




8.接下来,在JSP文件中调用Web 服务.在ThinClientindex.jsp源代码窗口中,鼠标右键点击任何一位置,在菜单中选择”Web服务客户端资源”->"调用Web服务操作"





9. 在"选择要调用的操作"窗口中,选择"getQuote"方法.




10. index.jsp中自动生成的调用代码如下:

<%-- start web service invocation --%><hr/>

<%

try {

com.sun.sdn.demo.ws.client.StockQuoteService service = new com.sun.sdn.demo.ws.client.StockQuoteService();

com.sun.sdn.demo.ws.client.StockQuote port = service.getStockQuotePort();

// TODO initialize WS operation arguments here

java.lang.String arg0 = "";

// TODO process result here

java.lang.String result = port.getQuote(arg0);

out.println("Result = "+result);

} catch (Exception ex) {

// TODO handle custom exceptions here

}

%>

<%-- end web service invocation --%><hr/>

11. 为了顺利运行index.jsp, 要在jsp中加入输入框,来接收股票代码信息.修改后的index.jsp代码如下



12. 鼠标右键点击"ThinClient,选择"运行项目",运行结果如下图.



Java EE 5实现Web服务(Web Services)及多种客户端实例-实现Web服务

JAVA EE 5平台上的JAX-WS


J2EE 1.4平台上实现Web Services的是JAX-RPC, 而到了JAVA EE 5, 重新命名为JAX-WS.


JAX-RPCJAX-WS最大的不同是编程模式的差别。 JAVA EE 5采用了JAVA SE 5 Java语言新特性,在JAX-WS使用了大量的标注(annotation, 因而减少了Web Services的代码量与部署工作,自然也简化了开发。


实现Web服务(模拟股票行情机)


这个例子中采用自低向上的开发方式,即先实现一个模拟的股票行情机,再把这个应用程序发布为Web服务,即最终产生WSDL


JAVA EE 5 平台上可以最终发布为Web服务的模块有三种, Servlet, EJB以及POJO (plain old Java Object).


下面以POJO为例,来建立模拟的股票报价Web服务


准备及安装软件

  1. JAVA SE 5 (JDK 1.5)及以上版本(http://java.sun.com/javase/downloads/index.jsp )

  2. NetBeans 5.5.1 (http://zh-cn.netbeans.org/index_zh_CN.html )

  3. Sun Application Server 9 (https://glassfish.dev.java.net/): 可以直接下载带Sun Application Server 9NetBeans (http://www.netbeans.info/downloads/index.php )


建立模拟的股票报价Web服务


1。打开NetBeans 5.5.1, 菜单“文件”中选择“新建项目”

2。“新建项目”窗口中,“类别”栏中选择“Web”,“项目“栏中选择“Web应用程序”,点击“下一步”按钮。

3。“新建Web应用程序 ”窗口中,在“项目名称”栏中输入“StockQuoteWS”

“服务器”中选择“Sun Application Server 9”, 这是Web Services 部署和运行的平台

Java Ee版本”中选择“Java EE 5”, 这样可以使用JAX-WS来开发Web Services




4。点击“完成”按钮后,在NetBeans IDE中生成StockQuoteWS项目。接下来建立一个StockQuotePOJO类。鼠标右键点击“StockQuoteWS项目”,选择“新建”->“Java类”。

5。“新建Java类 ”窗口中,输入类名和包名,比如

类名:StockQuote

包名:com.sun.sdn.demo.ws








6。为StockQuote类添加一个getQuote()的方法. 方法实现如下:

public String getQuote(String stockCode){

String quote = "";

if (ht.containsKey(stockCode))

quote = (String)ht.get(stockCode);

return quote;

}

7。把POJO发布为Web Services,在JAX-WS中非常简单,仅仅需要在类前面加上@WebService() 。而POJO类中所有的公共方法也都会转换为Web Services 的方法.

/*

* StockQuote.java

*

* Created on 2007820, 下午11:25

*

* To change this template, choose Tools | Template Manager

* and open the template in the editor.

*/


package com.sun.sdn.demo.ws;

import javax.jws.WebService;

/**

* @author Ada Li

*/

@WebService()

public class StockQuote {

/** Creates a new instance of StockQuote */

public StockQuote() {

init();

}

java.util.Hashtable ht = new java.util.Hashtable();

void init(){

ht.put("601988.ss", "5.90");

ht.put("000002.sz", "30.11");

}

public String getQuote(String stockCode){

String quote = "";

if (ht.containsKey(stockCode))

quote = (String)ht.get(stockCode);

return quote;

}

}

StockQuote类添加@WebService()标注(annotation)之后,就可以在NetBeansStockQuoteWS项目中看到新生成“Web服务”目录,目录下列出了”StockQuote”以及方法“getQuote”






8。到这一步已经完成了StockQuoteWeb服务开发,接下来要部署以及测试这个Web服务。

9。鼠标右键点击“StockQuoteWS”项目,选择“部署项目”。部署完成后,可以在NetBeans “运行环境”->"服务器"->“Sun Application Server 9”->"应用程序"->“Web应用程序”下看到“StockQuoteWS”, 表示Web服务成功部署在了Sun Application Server 上。





10NetBeans IDE 提供了Web服务的测试工具。鼠标右键点击“StockQuoteWS”项目->"Web服务"-〉“StockQuote”,选择“测试Web服务”,浏览器会打开“StockQuoteService Web Service Test”窗口。在文本框中输入“601988.ss”,点击“getQuote”按钮。




输出结果如下图:



11。在这个Java EE 5 平台上实现的Web服务,可以通过Web服务的测试工具察看WSDL以及SOAP的信息。而UDDI,测试工具使用的是NetBeans自带的Web Services Registry


StockQuoteWS部署完成后,最重要的记住WSDL的位置,即http://localhost:8080/StockQuoteWS/StockQuoteService?WSDL接下来创建Web服务客户端时候,需要这个URL.



Java EE 5实现Web服务(Web Services)及多种客户端实例-原理

文章分六部分


()Java EE 5实现Web服务(Web Services)及多种客户端实例-原理

通过一个实时的股票报价的Web服务来解释Web服务(Web Services)原理.


()Java EE 5实现Web服务(Web Services)及多种客户端实例-实现Web服务

JAVA EE 5平台上实现Web服务实例, 一个模拟的股票行情机Web服务.


()Java EE 5实现Web服务(Web Services)及多种客户端实例-瘦客户端

JSP实现一个瘦客户端(thin client)调用Web服务


()Java EE 5实现Web服务(Web Services)及多种客户端实例-胖客户端

采用GUI界面,实现胖客户端(rich client)调用Web服务


()Java EE 5实现Web服务(Web Services)及多种客户端实例-移动客户端

采用Java ME建立移动客户端(mobile client)调用Web服务


()Java Ee平台上实现Web服务及多种客户端实例-小结

给出了前面实例几部分的结构图,以及一些错误的解决方法.



()Web服务(Web Services)原理


一个 实时的股票报价的Web服务


在讲Web服务之前,先看一个实时的股票报价的Web服务。

http://www.webservicex.net/stockquote.asmx?op=GetQuote


symbol栏中输入中国工商银行的股票代码“601988.SS”(中国沪市的后缀是SS, 比如中国银行601988.SS,深市后缀是SZ, 比如万科A000002.SZ)。



得到的结果是XML格式的文档。

<?xml version="1.0" encoding="utf-8" ?>

<string xmlns="http://www.webserviceX.NET/">

<StockQuotes>

<Stock>

<Symbol>601988.SS</Symbol>

<Last>5.90</Last>

<Date>8/20/2007</Date>

<Time>9:37pm</Time>

<Change>+0.14</Change>

<Open>5.90</Open>

<High>5.95</High>

<Low>5.85</Low>

<Volume>17503092</Volume>

<MktCap>N/A</MktCap>

<PreviousClose>5.76</PreviousClose>

<PercentageChange>+2.43%</PercentageChange>

<AnnRange>3.23 - 6.35</AnnRange>

<Earns>0.00</Earns>

<P-E>N/A</P-E>

<Name>"</Name>

</Stock>

</StockQuotes>

</string>


可以看到中国工商银行股票在8/20/2007 9:37pm 时(采用的是GMT -5时区的时间,与北京时间差13个小时)的股票价格是5.90 元,返回的信息中还包括股票当天的最高价,最低价,昨日收盘价等信息。这个股票报价的Web服务是免费的,但是有大约50分钟的延迟。


Web服务(Web Services )原理


Web服务是一种面向服务的架构的技术,通过标准的Web协议提供服务,目的是保证不同平台的应用服务可以互操作。

根据W3C的定义, Web服务(Web service)应当是一个软件系统,用以支持网络间不同机器的互动操作。网络服务通常是一组应用程序接口(API),它们部署在网络系统(如国际互联网)的远程服务器端,客户提交特定的请求来访问这些接口,使程序执行。







在上图Web Services的体系结构图中,有三种角色和三种技术。以前面的股票报价Web服务来解释这些名词:


三种角色



  1. 服务提供者(Service Provider):股票报价Web服务是由Symbol公司开发的,那么Symbol公司就是Web服务的提供者。

  2. 服务中介(Service Broker): Web服务需要被人查找到, 才能被用户使用, 因此需要一个地方来注册并发布Web服务.http://www.webservicex.net/就提供了这么一个地方.这个网站被称为 Service Broker

  3. 服务请求者(Service Requeter): 任何使用这个Web服务的人员或者组织.



三种技术: WSDL, SOAP 以及UDDI


1WSDL(Web Services Description Language )

一个XML格式文档,用以描述服务端口访问方式和使用协议的细节。通常用来辅助生成服务器和客户端代码及配置信息。


在浏览器中输入“http://www.webservicex.net/stockquote.asmx?WSDL,可以看到WSDL文档的详细内容。



股票报价Web 服务的WSDL中定义了名为”StockQuote”Web服务,以及使用SOAP文档作为参数的方法"GetQuote". 这个WSDL还定义了基于HttpGetHttpPost的方法,但这不在本文讨论范围之内.



<wsdl:binding name="StockQuoteSoap" type="tns:StockQuoteSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="GetQuote">
<soap:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

......

<wsdl:service name="StockQuote">
<wsdl:port name="StockQuoteSoap" binding="tns:StockQuoteSoap">
<soap:address location="http://www.webservicex.net/stockquote.asmx"/>
</wsdl:port>
</wsdl:service>


2SOAP(Simple Object Access Protocol, )


一个基于XML的可扩展消息信封格式,需同时绑定一个传输用协议。这个协议通常是HTTP HTTPS,但也可能是SMTP XMPP


Web服务使用者, 调用Web服务的方法, 使用的是SOAP格式的参数. 在前面的例子中, 发送请求的SOAP内容如下:


SOAP request

POST /stockquote.asmx HTTP/1.1
Host: www.webservicex.net
Content-Type: text/xml; charset=utf-8
Content-Length: unknown
SOAPAction: "http://www.webserviceX.NET/GetQuote"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol>601988.SS</symbol>
    </GetQuote>
  </soap:Body>
</soap:Envelope>



web服务返回的相应SOAP内容如下:


SOAP response

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: unknown

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetQuoteResponse xmlns="http://www.webserviceX.NET/">
      <GetQuoteResult><string xmlns="http://www.webserviceX.NET/"><StockQuotes><Stock><Symbol>601988.SS</Symbol><Last>5.90</Last><Date>8/20/2007</Date><Time>9:37pm</Time><Change>+0.14</Change><Open>5.90</Open><High>5.95</High><Low>5.85</Low><Volume>17503092</Volume><MktCap>N/A</MktCap><PreviousClose>5.76</PreviousClose><PercentageChange>+2.43%</PercentageChange><AnnRange>3.23 - 6.35</AnnRange><Earns>0.00</Earns><P-E>N/A</P-E><Name>"</Name></Stock></StockQuotes></string>
</GetQuoteResult>
    </GetQuoteResponse>
  </soap:Body>
</soap:Envelope>



3UDDIUniversal Description, Discovery, and Integration


一个用来发布和搜索WEB服务的协议,应用程序可藉由此协议在设计或运行时找到目标WEB服务。


UDDI的作用类似于常见的电话本,Web服务要在某个地方注册,登记之后,才能被其它组织或个人查找到并使用Web服务的种种功能。例如提供股票报价的Web服务的网站(http://www.webservicex.net)就提供Web服务存放及查找。


2000年九月发布了UDDI之后, IBM, Microsoft SAP等公司提供了免费的UDDI注册服务器,用户可以在申请用户名及密码之后,在服务器上提交自己的Web服务。但是在2005UDDI 3.0正式成为 OASIS的标准之后, IBM, Microsoft SAP宣布自200612月之后,不再提供公用的UDDI注册服务。


目前, 有关UDDI注册服务则由相关的产品实现,比如

Sun Microsystems 公司的The Java Web Services Developer Pack

IBM公司的WebSphere UDDI Registry

Microsoft 公司的Microsoft® Windows Server 2003 Enterprise UDDI Services


使用这些Web服务产品,企业可以搭建内部的或者外部的UDDI服务器。Sun Microsystems 公司的The Java Web Services Developer Pack (JWSDP)1.6 , 即支持UDDI 3.0, 也支持 ebXML (Electronic Business using XML).


实时的股票报价的Web服务已经被用在了很多教程中,也可以针对这个Web服务开发实际的应用,比如建立客户端来调用Web服务StockQuote。这就需要对返回的XML格式的字符串进行解析,可以采用JAXPJava API for XML processing)包。JAVA SE 5 中已经包含JAXP, 不需要单独下载。


本文的目的主要是为了阐述JAVA EE 5 平台上实现Web服务的过程,因此在建立一个类似的股票报价的Web服务时,简化了股票报价的逻辑。在Web服务的返回信息中,仅包含静态的股票价格。


以下分几个部分讲述JAVA EE 5平台上实现一个模拟的股票行情Web服务,并且采用不同的客户端来调用这个Web服务。客户端包括:瘦客户端,胖客户端以及移动客户端。


  1. JAVA EE 5平台上实现Web服务实例(模拟股票行情机)

  2. 瘦客户端(thin client)调用Web服务

  3. 胖客户端(rich client)调用Web服务

  4. 移动客户端(mobile client)调用Web服务

Java游戏部署在Palm Os平台仿真器

由于Palm OSAccess公司收购,因此Palm OS 也被另命名为Garnet OS。但在这一小节的介绍中,依然采用Palm Os的称呼。


准备软件:

Access网站(http://www.access-company.com/developers/downloads/index.html)上下载

  1. "Garnet OS Development Suite, Version 1.2""

  2. Java Technology for Garnet OS (Java Technology for Garnet OS Toolkit (WEME Release 5.7.1)


安装软件:

1。运行 Garnet OS Development Suite, Version 1.2 安装文件Garnet_OS_Development_Suite_1_2_Installer.zip,安装在c:\Program Files目录下, 安装完成后,可以看到C:\Program Files\ACCESS\Garnet OS Development Suite目录。

2。解压缩Java Technology for Garnet Os文件Java_Tech_for_Garnet_WEME57.zip到目录C:\Java\PalmOS

3。准备Java程序包,打开NetBeans IDE, 找到项目VariousGames. (如何生成VarousGames项目,参考前面《()NetBeans IDE上的手机游戏例子》


4。鼠标右键点击VarousGames, 选择"生成项目",可以在输出窗口中,看到生成了两个文件,(VariousGames.jar, VariousGames.jad)Palm Os上的运行文件后缀名是prc. 下面需要将这两个文件转换为Palm Os上的prc文件


5。打开目录C:\Java\PalmOS\Tools\lib。把jclFoundation10目录和charconv.zip一起拷贝到JDKlib目录下,比如C:\Java\jdk1.6.0\lib


6。运行C:\Java\PalmOS\Tools\bin目录下的jartoprc_w.exe,在“JAD File or URL”中输入VariousGames.jad及路径,比如“E:\mymodules\VariousGames\dist\VariousGames.jad”, 点击“Generate PRC”按钮,可以在窗口下方看到如下结果“Done. Result is: E:\mymodules\VariousGames\dist\games.prc“



接下来为Palm OS Simulator 准备JVM环境。在C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\目录下新建立Autoload录。拷贝下列文件到目标目录

源文件

目标文件

C:\Java\PalmOS\JVM\Simulator\J9JavaVMMidp20.dll

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\J9JavaVMMidp20.dll

C:\Java\PalmOS\JVM\Simulator\ams.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\ams.prc

C:\Java\PalmOS\JVM\Simulator\J9JavaVMMidp20.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\J9JavaVMMidp20.prc

C:\Java\PalmOS\JVM\Simulator\J9JavaVMMidp20_es.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\J9JavaVMMidp20_es.prc

C:\Java\PalmOS\JVM\Simulator\J9JavaVMMidp20_zh_CN.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\J9JavaVMMidp20_zh_CN.prc

C:\Java\PalmOS\JVM\Simulator\j9keystore.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\j9keystore.prc

C:\Java\PalmOS\JVM\Simulator\J9Launcher.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\J9Launcher.prc

C:\Java\PalmOS\JVM\Simulator\j9pref.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\j9pref.prc

C:\Java\PalmOS\JVM\Simulator\j9secpol.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\j9secpol.prc

C:\Java\PalmOS\JVM\Simulator\PalmMidp20_22.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\PalmMidp20_22.prc

C:\Java\PalmOS\JVM\Simulator\pref.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\pref.prc

E:\mymodules\VariousGames\dist\games.prc

C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release\Autoload\games.prc



Java游戏部署在Palm OS Simulator


1。运行”Garnet OS Simulator”, 选择“ACCESS”->"Garnet SDK Tools" -> "Garnet OS Simulator", 或者双击运行C:\Program Files\ACCESS\Garnet OS Development Suite\sdk-5r4\tools\Palm_OS_54_Simulator\release目录下的PalmSim_54_rel.exe




2。Palm中的games图标就是之前编译的games.prc. 鼠标点击运行games, 可以看到如下结果:





3。很不幸地是,继续在Palm OS Simulator上运行这两个Java游戏,会遇到下面的错误."SystemMgr.c, Line:6244, SysLikerStub(): Failed to load the shared library"




Java游戏部署在BREW平台仿真器上

准备软件:

1。Samsung Java SDK (http://developer.samsungmobile.com/Developer/resources/board_list.jsp)


安装软件:

1。将samsungSDK_1.0.2.zip解压缩后,可以看到SamsungSDK_20070725.exe文件.执行这个文件,在安装过程中,选择”NetBeans Plug-in”



2。之后还会遇到提示, 需要开发者选择NetBeans IDE 安装的目录. 最后Samusng Java SDK安装在例如C:\Java\SamsungSDK目录下.

3。重新启动NetBeans IDE, 选择菜单”工具”->"Java平台管理器"

4。在"Java平台管理器" 窗口中,选择"Java Micro Edition 平台仿真器"

5。在下一步出现的窗口中,点击"查找更多Java Me平台文件夹",找到 Samsung Java SDK 后的目录,比如C:\Java\SamungSDK. 只选择”c:\Java\SumsungSDK”添加后的平台如下:




Java游戏部署在Samsung SGH-U700


1。打开NetBeans IDE, 找到项目VariousGames. (如何生成VarousGames项目,参考前面《()NetBeans IDE上的手机游戏例子


2。鼠标右键点击VariousGames, 选择“属性”,出现VariousGames属性窗口,改变以下设置:

仿真器平台: SamsungSDK 1.0

设备:SGH-U700

设备配置:CLDC 1.1

设备配置文件:MIDP 2.0





3。回到NetBeans IDE , 运行VariousGames结果如下:



Java游戏部署在Windows Mobile平台仿真器

前面几种平台,都可以集成到NetBeans IDE开发环境中. 很遗憾的是, 目前NetBeans还没办法集成Windows Mobile平台的仿真器. 可以采用不同于前面平台的方式,把Java程序部署在Windows Mobile平台的仿真器上.



准备软件:


下载"Windows Mobile 6 Localized Emulator Images

"(http://www.microsoft.com/downloads/details.aspx?familyid=38C46AA8-1DD7-426F-A913-4F370A65A582&displaylang=en),选择其中的0409\Windows Mobile 6 Standard Images USA).msi 73.3 MB"下载

简体中文版,请下载"0804\Windows Mobile 6 Standard Images (CHS).msi 83.2 MB


下载"WebSphere Everyplace Micro Environment

"中的 Windows, Windows CE, Windows Pocket PC, Windows XP: WebSphere Everyplace Micro Environment 部分. 在进一步的下载选项中,选择”CLDC 1.1/MIDP 2.0 for Windows Mobile 5.0 Smartphone Edition/ARM ”


(http://www14.software.ibm.com/download/data/web/en_US/trialprograms/N882497S32820G44.html?S_TACT=104CBW71&st=1&sp=20).


需要注意的是,WebSphere Everyplace Micro Environment不是免费的,试用版有使用限制


安装软件:


1。执行Windows Mobile 6 Standard Images (USA).msi, 安装目录, 例如在: C:\Program Files\Microsoft Device Emulator

2。执行ibm-weme-wm50-arm-midp20_6.1.1.20061110-161633.exe文件例如将这个文件安装到C:\Java”目录后,可以在”C:\Java\IBM\WEME\runtimes\61\wm50-arm-sp-midp20”目录下看到”weme-wm50-sp-arm-midp20_6.1.1.20061110-161633.zip”. 解压缩zip文件到temp目录下备用, 目录结构如下





部署 Java程序到Windows Mobile 仿真器上


1。准备Java程序包,打开NetBeans IDE, 找到项目VariousGames. (如何生成VarousGames项目,参考前面《()NetBeans IDE上的手机游戏例子


2。找到VarousGames生成的两个文件。

VariousGames.jar

VariousGames.jad


3。打开"Windows Mobile 6 Standard "仿真器,路径是”Windows Mobile 6 SDK” -> "Standard Emulator Images" -> "US English" -> "Standard", 出现如下仿真器:



4。接下来要为这个仿真器建立一个虚拟的存储卡,用来放置Java 程序文件,以及运行Java程序所需要的 JVM。选择仿真器上的菜单“File”->"Configure...", 出现“Emulator Properties”窗口,在“Shared Folder”栏中,选择或者输入目录,作为一个虚拟的存储卡. 例如”C:\Java\Emulator\wm_card”





5。在 C:\Java\Emulator\wm_card 目录下,创建目录\j9\midp20, 拷贝 weme-wm50-sp-arm-midp20_6.1.1.20061110-161633.zip 解压缩后的bin lib目录到\j9\midp20目录下, C:\Java\Emulator\wm_card 目录下,放入两个文件

    VariousGames.jad

    VariousGames.jar

C:\Java\Emulator\wm_card的目录结构如下



6。在Windows Mobile 仿真器上安装JVM环境, 在仿真器上找到"File Explorer, 在"My Device" 中选择"Storage Card, 可以看到如下内容:







7。在仿真器里,运行 \Storage Card\j9\midp20\bin下的emulator






8。按下” Install”按钮, URL 文本框中,输入:"file:///Storage Card/VariousGame.jad"







9。再经过几个提示信息窗口后,会出现以下的MIDlet列表.



10。运行PushPuzzle的结果如下:



Java游戏部署在BlackBerry仿真器上(RIM)

准备软件:

.

下载 BlackBerry Java Development Environment v4.2.1 (http://na.blackberry.com/eng/developers/downloads/jde.jsp) 


安装软件:

运行BlackBerry_JDE_4.2.1.exe,安装目录,例如:C:\Program Files\Research In Motion\BlackBerry JDE 4..

2。NetBeans,选择菜单”工具"->"Java 平台管理器", 点击”添加平台”,在”添加平台”窗口中, 选择:"定制Java Micro Edition 平台管理器"


3。在下一个窗口"常规信息"中,输入如下信息:

平台Home 目录:C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1

平台名称:BlackBerry JDE 4.2.1

设备名称:8800

预校验命令:"{platformhome}{/}bin{/}preverify" {classpath|-classpath "{classpath}"} -d "{destdir}" "{srcdir}"

执行命令:cmd /C "cd /D {platformhome}{/}simulator&{device}"

调试器命令:cmd /C "cd /D {platformhome}{/}bin&jdwp"



点击下一步.




4。在出现的"引导库"窗口中,有一系列的jar文件,只需要保留一个net_rim_api.jar,而删除其余的jar 文件,点击"完成"。如下所示:






部署Java程序到BlackBerry 8800仿真器上


1。在NetBeans IDE 中,选择菜单"文件"-> "新建项目",在在出现的"新建项目"窗口中,"类别"框中选择"移动"下的"MIDP2.0样例",右边“项目”中选择“MIDP2.0的各种游戏”。




2。在下一个窗口中,输入项目名称:VariousGamesBlackBerry, 点击下一步

3。在下一个窗口"选择缺省平台中"中,选项如下

仿真器平台:BlackBerry JDE 4.2.1

设备:8800




4。在netBeans IDE中,运行VariousGamesBlackBerry. 结果如下:




5。在blackBerry仿真器的"Application"类别下,可以看到已经有两个Java程序的图标.WordGamePushPuzzle.


Java游戏部署在Symbian平台仿真器上

准备软件:

.

下载 Series 80 Platform SDKs (http://forum.nokia.com/main/resources/tools_and_sdks/index.html#java), 这个SDK包括两部分,我们只需要下载MIDP部分"Series 80 Developers Platform 2.0 SDK for Symbian OS, for MIDP (59MB)


安装软件:


1。安装NetBeans Mobility Pack for CDC .

2。解压缩S80_DP2_0_MIDP_SDK.zip, 例如放在c:\java\Nokia目录下

3。打开NetBeans, 选择菜单”工具”->"Java平台管理器"

4。在"Java平台管理器" 窗口中,选择"Java Micro Edition 平台仿真器"

5。在下一步出现的窗口中,点击"查找更多Java ME平台文件夹",找到Nokia S80_DP2_0_MIDP_SDK.zip解压缩后的目录,比如C:\Java\Nokia\Devices\S80_DP2_0_MIDP_SDK

6。下一步添加了平台”Series 80 Developer Platform 2.0 SDK for Symbian OS, For J2ME MIDP”



部署Java游戏到Nokia 仿真器中


1。打开NetBeans IDE, 找到项目VariousGames. (如何生成VarousGames项目,参考前面《()NetBeans IDE上的手机游戏例子

2。鼠标右键点击VariousGames, 选择“属性”,出现VariousGames属性窗口,改变以下设置:

仿真器平台: Series 80 Developer Platform 2.0 SDK for Symbian OS, For J2ME MIDP

设备:S80_DP2_0_MIDP_SDK

    点击“确定“按钮。


3。回到 NetBeans IDE 中,运行VariousGams,看到如下的结果。



4。选择”PushPuzzle”, 出现Nokia的仿真器,以及PushPuzzle游戏的界面









Java游戏部署在Linux平台仿真器上(Motorola)

准备软件:

1。下载 Motorola Java ME SDK v6.4 for Linux OS Products (http://developer.motorola.com/docstools/sdks/linux64/)


安装软件:

1。解压缩linux_64_SDK.zip, 例如,解压缩后的文件放在c:\java\Motorola目录下

2。打开NetBeans, 选择菜单”工具”->"Java平台管理器",在出现的”Java平台管理器”窗口中,点击”添加Java平台”,出现以下窗口.


3。选择"Java Micro Edition平台仿真器”,点击下一步,在"平台文件夹"中选中"EmulatorM.3. Motorola A780仿真器就在这个包中.最后出现的窗口如下:




4。点击完成,可以看到”Java 平台管理器”已经出现了Motorola A780的仿真器。




部署Java游戏到Motorola A780仿真器中


1。打开NetBeans IDE, 找到项目VariousGames. (如何生成VarousGames项目,参考前面《()NetBeans IDE上的手机游戏例子

2。鼠标右键点击VariousGames, 选择“属性”,出现VariousGames属性窗口,改变以下设置:

仿真器平台:Motorala Java(TM) ME SDK v6.4 for Linux Products – Emulator M.3

设备:A780

点击“确定“按钮。



3。回到 NetBeans IDE 中,运行VariousGams,看到如下的结果。



NetBeans IDE上的Java手机游戏例子

手持终端设备,包括手机,智能手机,掌上电脑等等。手持终端设备平台类似于计算机中的操作系统,目前比较广泛见到的有以下几种


1Linux

2Symbian

3BlackBerry

4Windows Mobile

5BREW:

6Palm OS


不同平台上的游戏程序,存在着不兼容的问题。而Java语言的跨平台特性,在手持终端设备得到很好的体现和应用。



很多平台供应商,比如微软,高通,和手机制造商,如摩托罗拉,诺基亚等都开发了针对自己产品的仿真器.Java手机游戏如果要真正地运行在手机上,开发完成后往往需要以下几个测试环节.

1.运行在具体的手机仿真器上.

2.运行在真正的手机上,

3.如果是需要下载的游戏,还需要通过移动运营商的平台测试,如中国移动的百宝箱,中国联通的神奇宝典.


NetBeans IDE集成各种平台的仿真器,让手机上JAVA程序的开发和测试变得十分方便。现在以NetBeans IDE开发环境中自带的一个手机游戏程序为例,看Java游戏程序如何部署在以上不同的手持终端平台的模拟器上. 对不同的手机平台,选某个代表厂商或者公司开发的仿真器。



这个系列分为以下几个部分

()NetBeans IDE上的Java手机游戏例子

()Java游戏部署在Linux平台仿真器上(Motorola

()Java游戏部署在Symbian平台仿真器上(Nokia)

()Java游戏部署在BlackBerry仿真器上(RIM)

()Java游戏部署在Windows Mobile平台仿真器(Microsoft)

()Java游戏部署在BREW平台仿真器上(Samsung)

()Java游戏部署在Palm Os平台仿真器(Access)

()NetBeans IDE上的Java手机游戏例子


准备软件:

1。下载Java SE 5.0或以上版本(http://java.sun.com/javase/downloads/index_jdk5.jsp )

2。下载NetBeans IDE 5.5.1 (http://www.netbeans.info/downloads/index.php?rs=22 )

3。下载NetBeans Mobility Pack for CLDC (http://www.netbeans.info/downloads/index.php?p=4)


安装软件:

按照以下顺序安装软件:

  1. 安装Java SE 5.0

  2. 安装NetBeans IDE 5.5.1

  3. 安装NetBeans Mobility Pack for CLDC


生成Java游戏例子

1。安装完成后,打开NetBeans IDE , 选择菜单"文件"->"新建项目"。在出现的"新建项目"窗口中,"类别"框中选择"移动"下的"MIDP2.0样例",右边“项目”中选择“MIDP2.0的各种游戏”。



2。在下一个窗口中,选项如下

仿真器平台:Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC

设备配置:CLDC-1.1

设备配置文件:MIDP-2.0


Sun Java(TM) Wireless Toolkit 2.5.1 for CLDCSun提供的缺省仿真器。




完成后,在NetBeans中看到VarousGames项目,


3。鼠标右键点击VarousGames, 选择"生成项目",可以在输出窗口中,看到生成了两个文件,VariousGames.jarVariousGames.jad. 这两个文件作为部署文件,在之后的章节中会使用到。




4。鼠标右键点击VarousGames项目,选择“运行项目”,可以看到如下结果:











包括两个游戏:贪吃蛇(WormGame)和推箱子(PushPuzzle)



贪吃蛇



推箱子


项目中有完整的源代码,这篇文章里不谈如何进行手机游戏的编码,而是着重介绍这两款游戏如何部署在不同平台的仿真器上.

星期三 八月 29, 2007

AJAX与JSF实现带进度条的批量上传文件实例

一。NetBeans 5.5.1 中的样例:


NetBeans 5.5.1中自带了一个“文件上载“的例子,使用这个例子,请先下载并安装以下软件:

  1. JAVA SE 5 (JDK 1.5) 及以上版本http://java.sun.com/javase/downloads/index.jsp

  2. NetBeans 5.5.1http://zh-cn.netbeans.org/index_zh_CN.html

  3. Sun Application Server 9.0https://glassfish.dev.java.net/

2+3可以下载“NetBeans IDE 5.5.1 with Java EE Application Server 9.0 U1 Patch 1 bundle ”http://www.netbeans.info/downloads/index.php?rs=22&p=3


NetBeans中,选择菜单“新建项目”-〉“类别”中选择“样例”-〉“Java BluePrint Solution” ->AJAX编程模型。项目中选择“文件上载”。项目名缺省为“fileupload”


运行项目“fileupload”, 并且选择几个上传文件,文件类型可以多种多样,比如pdf, jar, ra, zip, jpeg, gif等等。可以看到如下界面。


传输完毕,可以看到如下结果。



显示了上传文件开始,结束的的时间,上传文件总的字节数目等等。


项目“fileupload”/web/docs/下有一个fileupload.html 的文档,解释了这个上传文件的参数及使用(English)。文件上载是一个JSF控件,开发者需要了解的除了如何在服务器端处理请求中的参数,如何在客户端显示响应信息外,所需要了解的仅仅是一些参数的设置。如这个例子中的代码所示:

<ui:fileUploadTag id="TestFileuploadForm0" retFunction="testRetFunction" retMimeType="text/xml"

postProcessingMethod="#{FileUploadCustomBean.postProcessingMethod}"

progressBarDivId="progress1x" progressBarSubmitId="submit1x" progressBarSize="40">

<input type="file" size="40" name="fileToUpload0" id="fileToUpload0Id"/><br/>

<input type="file" size="40" name="fileToUpload1" id="fileToUpload1Id"/><br/>

<input type="file" size="40" name="fileToUpload2" id="fileToUpload2Id"/><br/>

<input type="submit" id="submit1x" name="submit1x" value="Submit"/><br/>

<div id="progress1x"></div><br/>

</ui:fileUploadTag>


参数如下:

id

文件上载JSF控件的标识

serverLocationDir

文件上载的目标目录。在示范例子中未给出这个参数的应用。缺省的情况下,文件会上载到Sun application Server domains/domain1/lib/upload目录下。

retFunction

JavaScript 的回调函数,用于客户端出来服务器返回的响应信息。

retMimeType

服务器端返回响应信息的类型,缺省的是“text/xml ”

postProcessingMethod

服务器端用来处理请求信息的方法。

progressBarDivId

进度条的Id

progressBarSubmitId

和进度条关联的触发文件上载的id。示范例子中是“submit”按钮

progressBarSize

进度条的大小



二。使用FileUpload控件建立实例PhotoAlbum


下面给出另外一个使用这个上传文件的小例子PhotoAlbum,最主要是为了说明如何提取上传后的文件名,以及如何用AJAX技术来部分刷新上传页面。另外想借这个例子用 NetBeans开发JSF程序的一般流程。


1NetBeans中选择菜单“新建项目”。“类别“中选择“Web”, 项目中选择“Web应用程序”。

2。“新建Web应用程序”窗口中,输入及选择以下内容:

项目名称:PhotoAlbum

源代码结构:Java BluePrints

服务器:Sun Java System Application Server 9

Java EE 版本:Java EE 5




注意:如果服务器选择中没有出现“Sun Java System Application Server 9”。请在NetBeans中,选择菜单” 窗口”->“ 运行时”. 在”运行环境”窗口中,鼠标右键选择”服务器”, 点击”添加服务器”。在”平台文件夹位置”中选择安装”Sun Java System Application Server 9”的目录。在下一个窗口中,输入服务器的管理用户名和密码(缺省管理用户名和密码是“ admin/adminadmin”)。 

3。下一个窗口中,选择“Java Server Faces”框架。点击“完成”






4。选择项目“PhotoAlbum”中的库,右键选择“添加jar/文件夹”,加入文件上载所需要的几个jar文件。在NetBeans安装目录下,例如C:\Java\netbeans-5.5.1\enterprise3\modules\ext\blueprints,加入以下五个jar文件

    shale-remoting.jar

    bp-ui-5.jar

    commons-logging-1.1.jar

    commons-io-1.2.jar

    commons-fileupload-1.1.1.jar

需要注意的是: 为了完成下面的例子,有两个jar文件需要比较新的版本,并且需要加入库rome-0.8.jar. 为方便起见,本文给出下载的jar文件,


最后的库文件为六个:

    shale-remoting-1.0.4.jar

    bp-ui-5-0.8.jar

    commons-logging-1.1.jar

    commons-io-1.2.jar

    commons-fileupload-1.1.1.jar

    rome-0.8.jar



5。在项目“PhotoAlbum”中的Web目录下,手工创建一个目录images. 如果PhotoAlbum的工作目录是e:\mymodules\PhotoAlbum, 那么这个目录的绝对路径是:E:\mymodules\PhotoAlbum\web\images.


6。创建JSF Bean, 鼠标右键点击项目“PhotoAlbum”中,选择“新建文件/文件夹”。在类别中选择“Web”, 在“文件类型”中选择“JSF受管Bean”





7。“新建JSF受管Bean”窗口中,输入:

类名:PhotoAlbum

包:com.sun.sdn.demo.jsf




这步创建完之后,可以查看项目“PhotoAlbum”中“配置文件“下的“faces-config.xml”, 可以看到刚创建的“FileUploadBackBean”已经自动加入到配置文件中。


        <managed-bean>
<managed-bean-name>FileUploadBackBean</managed-bean-name>
<managed-bean-class>com.sun.sdn.demo.jsf.FileUploadBackBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>



8。在 FileUploadBackBean 加入如下代码:

/*
* FileUploadBackBean.java
*
* Created on 2007827, 下午2:48
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package com.sun.sdn.demo.jsf;
import java.util.Enumeration;
import java.util.Hashtable;
import java.io.IOException;

import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.servlet.ServletContext;
import org.apache.shale.remoting.faces.ResponseFactory;

import com.sun.javaee.blueprints.components.ui.fileupload.FileUploadStatus;
/**
*
* @author Ada Li
*/
public class FileUploadBackBean {
/**
*
Factory for response writers that we can use to construct the
* outgoing response.
*/
private static ResponseFactory factory = new ResponseFactory();
private String serverLocationDir = "E:/mymodules/PhotoAlbum/build/web/images";
String imageRootUrl = "../images";

/** Creates a new instance of FileUploadBackBean */
public FileUploadBackBean() {
}
public void postProcessingMethod(FacesContext context, Hashtable htUpload, FileUploadStatus status) {
// set custom return enabled so Phaselistener knows not to send default response
status.enableCustomReturn();
// Acquire a response containing these results
ResponseWriter writer = factory.getResponseWriter(context, "text/xml");
try {
writer.startElement("response", null);

String imageFileLocation = "";
for (Enumeration e = htUpload.keys() ; e.hasMoreElements() ;) {
String key = (String)e.nextElement();
//System.out.println(key.substring(0, 13));
if (key.substring(0, 13).equals("fileLocation_")){
imageFileLocation = (String)htUpload.get(key);
String fileName = imageFileLocation.replaceFirst(getServerLocationDir(), "");
String imageFileUrl = imageRootUrl + fileName;
writer.startElement("imageFileUrl", null);
writer.write(imageFileUrl);
writer.endElement("imageFileUrl");
}
}
writer.endElement("response");
writer.flush();
} catch (IOException iox) {
System.out.println("FileUploadPhaseListener error writting AJAX response : " + iox);
}
}
public String getServerLocationDir() {
return serverLocationDir;
}
public void setServerLocationDir(String serverLocationDir) {
this.serverLocationDir = serverLocationDir;
}
}

FileUploadBackBean中有两个参数需要根据情况设定,即 serverLocationDir imageRootUrl 。因为PhotoAlbum缺省部署完成后,项目在应用服务器中的部署位置就是/build目录。在这个例子中,文件上载到/build/images目录下,因此还需要手工在PhotoAlbumweb目录下建立一个images目录,PhotoAlbum部署完成后,在/build/目录下自动会建立images目录。


上载后的文件放在/build/images目录下,通过浏览器访问的话,URLhttp://localhost:8080/PhotoAlbum/images/XXXX.jpg, 因此,获得上传的文件名之后,之前要加上相对路径“../images”.


文件中方法 postProcessingMethod 的主要作用是提取上传文件名,并生成xml格式的响应信息。信息的格式如下:

<response>
<imageFileUrl>../images/Bike.jpg</imageFileUrl>
<imageFileUrl>../images/Bungee.jpg</imageFileUrl>
<imageFileUrl>../images/Duke.in.City.jpg</imageFileUrl>
<imageFileUrl>../images/Pointing.jpg</imageFileUrl>
<imageFileUrl>../images/Thiniing.jpg</imageFileUrl>
</response>



9。现在开始写JSP页面。在PhotoAlbum项目中,加入JSF框架之后,项目中自动加入了一个WelcomJSF.jsp页面。修改后的WelcomJSF.jsp代码如下:


<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@taglib uri="http://java.sun.com/blueprints/ui" prefix="ui" %>
<html>
<head>
<title>AJAXJSF实现带进度条的批量文件上载</title>
<script>

function props(namex) {
var listx="";
var ob=dojo.byId(namex);
for(xx in ob) {
listx += xx + " = " + ob[xx] + "<br/>"
}
//document.write(listx);
alert(listx);
}

function testRetFunction(type, data, evt){
// handle successful response here
var photoAlbum = document.getElementById("photo_album");
var resultx = data.getElementsByTagName("response")[0];
if(resultx) {
var photoAlbum = document.getElementById("photo_album");

var tb = document.createElement("table");
tb.setAttribute("border", 1);
var tbody = document.createElement("tbody");
var tr = document.createElement("tr");
tb.insertBefore(tbody, null);
tbody.insertBefore(tr, null);
photoAlbum.insertBefore(tb, null);

var imageUrls = resultx.getElementsByTagName("imageFileUrl");
for (var i=0; i<imageUrls.length; i++){
var td = document.createElement("td");
td.setAttribute("width", "20%");
td.setAttribute("valigh", "top");

var url = imageUrls[i].childNodes[0].nodeValue;
var image = document.createElement("img");
image.setAttribute("src", url);
image.setAttribute("width", "100");

td.insertBefore(image, null);
tr.insertBefore(td, null);
}
}
}

</script>
</head>
<body>
<h1>AJAXJSF实现带进度条的批量文件上载</h1>

<f:view>

<table border="1" colspacing="5" colpadding="5">
<tr>
<td>
<br/>
<ui:fileUploadTag id="TestFileuploadForm0"
serverLocationDir="#{FileUploadBackBean.serverLocationDir}"
retFunction="testRetFunction" retMimeType="text/xml"
postProcessingMethod="#{FileUploadBackBean.postProcessingMethod}"
progressBarDivId="progress1x" progressBarSubmitId="submit1x" progressBarSize="40">
<input type="file" size="40" name="fileToUpload0" id="fileToUpload0Id"/><br/>
<input type="file" size="40" name="fileToUpload1" id="fileToUpload1Id"/><br/>
<input type="file" size="40" name="fileToUpload2" id="fileToUpload2Id"/><br/>
<input type="file" size="40" name="fileToUpload3" id="fileToUpload3Id"/><br/>
<input type="file" size="40" name="fileToUpload4" id="fileToUpload4Id"/><br/>
<input type="submit" id="submit1x" name="submit1x" value="Submit"/><br/>
<div id="progress1x"></div><br/>
</ui:fileUploadTag>
</td>
</tr>
</table>
<br><br>
<div id="photo_album"></div>
</f:view>
</body>
</html>


welcomeJSF.jsp页面中,重点就是JavaScript函数 testRetFunction(), 它作为AJAX中客户端的回调函数, 接受来自服务器端的响应信息后,通过DOM技术, 在原有页面上,动态地创建了tableimg 对象,来显示上传的图像.


FileUploadBackBean 声明了属性 serverLocationDir ,并且有对这个属性的setget方法,那么在JSF中,对这个属性的调用可以直接是#{FileUploadBackBean.serverLocationDir}


10。运行的结果如下



三。小结


JSF(JavaServer Faces)主要的目的是把表示和动作分开。在通常的JSP开发中, Http请求映射到事件处理器,在服务器端操作页面控件,都不是很方便。而JSF技术分离了动作和表示,可以让开发者更专注于自己的领域,而把一些映射的工作或者底层的工作交给框架来实现。


JSF提供了大量的tab library, 前面的文件上载的控件就是其中之一。在使用这个控件的时候,可以注意到,编写Bean时,并不需要直接从HttpRequest中读取参数值,并且在返回响应信息时候,也并没有在代码中直接指定具体的页面。AJAXJSF的应用中,体现在增加了JavaScript回调函数的接口,就是WelcomJSF.jsp中的函数testRetFunction()


PhotoAlbum作为一个示例,代码中缺少一些必要的环节,比如对文件类型的判断,比如返回出错信息给客户端。这些留给读者来完成吧。AJAX应用在JSF上感兴趣的朋友,可以参考开源软件Java[TM] BluePrints Solutions Catalog for Java EE 5 https://blueprints.dev.java.net/bpcatalog/ee5/index.html

Calendar

Feeds

Search

Links

Navigation

Referrers