使用 DWR(Direct Web Remoting)构建 AJAX 应用程序

Sang Shin, sang.shin@sun.com, Sun Microsystems, www.javapassion.cn



本动手实验室将指导您使用 DWR(Direct Web Remoting)开发基于 AJAX 的 Web 应用程序。本文档旨在帮助您尽快入门。

在本实验室中,您将了解:(1)循序渐进地构建基于 DWR 的 AJAX 应用程序(2)如何将 web 应用程序配置文件 web.xml 配置为对 DWR 适用的文件(3)如何使用和编写名为 dwr.xml 的 DWR 配置文件(4)如何使用一些 DWR 实用函数。


预计时间:90-120 分钟

前提条件

本教程假设您对以下技术有所了解或具有编程经验:

软件需求

开始之前,需要在您的计算机中安装以下软件。dwr.jar 文件已经包含在动手实验室的压缩文件中,您不必自己动手下载。


变更记录


将要做的事情

实验室练习


练习 1:构建和运行“Chat Demo”示例 DWR 应用程序

在本练习中,您将使用 NetBeans 构建和运行“Chat Demo”示例应用程序(dwr.examples.chat NetBeans 项目)。所需的全部代码和库文件已经给出为一个现成的 NetBeans 项目。

  1. 使用 NetBeans 打开、生成和运行“Chat-Demo”示例 DWR 应用程序
  2. 测试远程方法
  3. 深入了解 Chat-Demo 示例 DWR 应用程序
  4. 添加另一个方法来远程化到 Chat-Demo 示例应用程序
  5. 作为练习,请向 Chat-Demo 示例应用程序添加另一个方法

(1.1)使用 NetBeans 打开、生成和运行“Chat-Demo”示例 DWR 应用程序(dwr.examples.chat)

1. 打开 dwr.examples.chat NetBeans 项目。


图 1.10:打开 dwr.examples.chat NetBeans 项目

2. 解决引用问题


图 1.11:解决引用问题


图 1.12:解决


图 1.13:选择 dwr.jar 文件

图 1.14:解决了引用问题

3. 生成和运行项目


图 1.16:运行


图 1.17:使用 AJAX 运行数据验证


返回练习顶部

(1.2)测试远程方法

DWR 为远程方法提供了一个测试页面。您只需要将 /dwr 附加到该 URL 后面。

1. 在您的浏览器中,进入 http://localhost:8080/dwr.examples.chat/dwr。此页面是一个调试页面,您可以在其中和后端应用程序进行交互。
2. 单击 Chat。(如下图 1.13 所示)它将显示出所有由 DWR 远程化的方法。


图 1.13:调试页面

3. 现在您看到两个由 DWR 远程化的方法 —— addMessage("")getMessage(),这意味着可以通过匹配 JavaScript 对象对这两个方法进行调用。
4. 单击 getMessages() 方法的 Execute 按钮。(如下图 1.14 所示)


图 1.14:调试页面,单击 getMessages() 方法的 Execute 按钮

5. 您应看到下图 1.15。下图显示了调用 JavaScript 对象 Chat 的 getMessages() 方法而以 JSON 形式返回的数据。(注意:我们将在本课程的后面介绍 JSON。)


图 1.15:返回的数据

6.将任意字符串,本例中为 3rd message 键入 addMessage() 调用的灰色区域并单击 Execute 按钮。(如下图 1.16 所示)


图 1.16:调试页面,单击 addMessage() 方法的 Execute 按钮

7. 您应看到下图 1.17。下图显示了调用 JavaScript 对象 Chat 的 addMessage() 方法而返回的数据


图 1.17:返回的数据

返回练习顶部

(1.3)深入了解“Chat-Demo”示例 DWR 应用程序

在本步骤,您将通过了解组成 dwr.examples.chat 示例应用程序的部分来了解 DWR 的底层架构。

1. 首先,您的 web 应用程序中必须有 dwr.jar 文件。dwr.examples.chat 应用程序中有这个文件。可以通过展开 dwr.examples.chat 项目节点并选择 Libraries 来查看该文件。您应该看到 dwr.jar 文件。(如下图 1.30 所示)

注意:dwr.jar 文件可从 DWR home site 下载。


图 1.30:dwr.jar

2. 必须将 DWR servlet 映射包含到 web 应用程序的 web.xml 中。每个 DWR 应用程序都必须包含它。调试参数可以被设为 false 或 absent。

<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

可以在 Web 页->WEB-INF 节点下看到 dwr.examples.chat 应用程序的 web.xml 文件。(如下图 1.33 所示)


图 1.33:web.xml 文件必须包含 DWR servlet 映射

3. 您还必须将名称为 dwr.xml 的 DWR 配置文件和 web.xml 文件存放到同一个目录下。在此文件中,您要指定哪些 Java 类及其方法进行“远程化”。可在 Web 页->WEB-INF 节点下查看 dwr.examples.chat 应用程序的 dwr.xml 文件。(如下图 1.34 所示)


图 1.34:dwr.xml 文件

在本例中,dwr.xml 表明 mypackage.Chat Java 类的所有公共方法都将被远程化为 Chat JavaScript 对象。现在,让我们来看看 mypackage.Chat Java 类以及如何从浏览器中调用该类的方法。

4. 右键单击 源包->mypackage 下的 Chat.java 将其在源代码编辑器窗口中打开。(如下图 1.35 所示)


图 1.35:mypackage.Chat.java

注意到有两个公共方法 —— addMessage(String text)getMessage()。这两个方法将被远程化。现在让我们看看这两个方法是如何从 JavaScript 中被调用的。

5. 在 Web 页 下双击 index.html 将其在源代码编辑器窗口中打开。(如下图 1.36 所示)


图 1.36:index.html

注意 Chat JavaScript 对象的 addMessage()getMessages() 方法是如何被调用的。

返回练习顶部

(1.4) 添加另一个方法来远程化到 Chat-Demo 示例应用程序


现在将向 mypackage.Chat Java 类添加另一个用于远程化的方法。新方法用于返回发布的消息数目。我们称其为 getNumberOfMessages()

1. 在 源包->mypackage 下双击 Chat.java 将其在源编辑器中打开。
2. 修改 Chat.java 文件,如下所示。需要添加的新代码段突出显示为 蓝色粗体

/*
* Chat.java
*
* Created on May 29, 2006, 8:03 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package mypackage;

import java.util.LinkedList;
import java.util.List;

public class Chat{

private static int numberOfMessages = 0;

public List addMessage(String text){
if (text != null && text.trim().length() > 0){
messages.addFirst(new Message(text));
while (messages.size() > 10){
messages.removeLast();
}
numberOfMessages++;
}
return messages;
}

public List getMessages(){
return messages;
}

public int getNumberOfMessages(){
return numberOfMessages;
}

private static LinkedList messages = new LinkedList();
}

3. 右键单击 dwr.examples.chat 项目节点并选择 运行。我们想要在此处进行测试的目的是要确保添加的新方法是远程化的。
4. 在浏览器中,进入 http://localhost:8080/dwr.examples.chat/dwr。这是一个调试页面,从中可以和后端应用程序进行交互。
5. 单击 Chat。(如下图 1.x 所示) 将显示由 DWR 远程化的所有方法。应包含 getNumberOfMessages()。也可以单击该方法的 Execute 按钮。将返回数目。(如下图 1.40 所示)


图 1.40:检验添加的新方法被正确远程化

现在您可以确定新方法已经由 DWR 正确远程化。现在让我们更改客户端。

6. 双击 Web 页 下的 index.html 将其在源编辑器中打开。
7. 修改 index.html 文件,如下所示。需要添加的新代码段突出显示为 蓝色粗体

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Chat-Demo</title>

<!-- You have to include these two JavaScript files -->
<script type='text/javascript' src='dwr/engine.js'></script>
<script type='text/javascript' src='dwr/util.js'></script>

<!-- This JavaScript file is generated specifically for your application -->
<script type='text/javascript' src='dwr/interface/Chat.js'></script>

<script type='text/javascript'>
function sendMessage(){
var text = DWRUtil.getValue("text");
DWRUtil.setValue("text", "");

// Invoke addMessage(text) method of the Chat class on
// the server. The gotMessages is a callback function.
Chat.addMessage(text, gotMessages);
}

function checkMessages(){
Chat.getMessages(gotMessages);

// This code will not work - you do not want to call the method
// synchronously.
var chatcount = Chat.getNumberOfMessages();
DWRUtil.setValue("chatcount", chatcount);
}

// Callback function
function gotMessages(messages){
var chatlog = "";
for (var data in messages){
chatlog = "<div>" + messages[data].text + "</div>" + chatlog;
}
DWRUtil.setValue("chatlog", chatlog);
setTimeout("checkMessages()", 1000);
}
</script>
</head>

<body onload="setTimeout('checkMessages()', 1000)">
<p>Messages:</p>
<div id="chatlog" style="border: 1px solid black;"></div>
<p>Number of messages:</p>
<div id="chatcount" style="border: 1px solid black;" ></div>
<p>
Your Message:
<input id="text" />
<input type="button" value="Send" onclick="sendMessage()" />
</p>
</body>
</html>

8. 右键单击 dwr.examples.chat 项目节点并选择 运行。 您将看到以下结果。(下图 1.43 所示)


图 1.43:消息字段的数目并未更新

注意到,以上运行情况和您的预期并不一样。chatcount 没有显示出来。这一定是有原因的。想一想这段代码为什么不能运行。

9. 修改 index.html 文件,如下所示。需要添加的新代码段突出显示为 蓝色粗体

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Chat-Demo</title>

<!-- You have to include these two JavaScript files -->
<script type='text/javascript' src='dwr/engine.js'></script>
<script type='text/javascript' src='dwr/util.js'></script>

<!-- This JavaScript file is generated specifically for your application -->
<script type='text/javascript' src='dwr/interface/Chat.js'></script>

<script type='text/javascript'>
function sendMessage(){
var text = DWRUtil.getValue("text");
DWRUtil.setValue("text", "");

// Invoke addMessage(text) method of the Chat class on
// the server. The gotMessages is a callback function.
Chat.addMessage(text, gotMessages);
}

function checkMessages(){
Chat.getMessages(gotMessages);
}

function checkChatCount(){
// The getNumberOfMessages() needs to be called in asynchronous fashion
Chat.getNumberOfMessages(gotChatCount);

}

// Callback function
function gotMessages(messages){
var chatlog = "";
for (var data in messages){
chatlog = "<div>" + messages[data].text + "</div>" + chatlog;
}
DWRUtil.setValue("chatlog", chatlog);
setTimeout("checkMessages()", 1000);

// The checkChatCount() function gets called in 1000 ms.
setTimeout("checkChatCount()", 1000);
}

// Callback function of the Chat.getNumberOfMessages(gotChatCount)
function gotChatCount(ChatCount){
DWRUtil.setValue("chatcount", ChatCount);
}

</script>
</head>

<body onload="setTimeout('checkMessages()', 1000)">
<p>Messages:</p>
<div id="chatlog" style="border: 1px solid black;"></div>
<p>Number of messages:</p>
<div id="chatcount" style="border: 1px solid black;" ></div>
<p>
Your Message:
<input id="text" />
<input type="button" value="Send" onclick="sendMessage()" />
</p>
</body>
</html>

10. 右键单击 dwr.examples.chat 项目节点并选择 清理并生成项目部署项目,然后以连续顺序 运行。您应看到以下结果(如下图 1.45 所示)


图 1.45:现在消息数被正确显示出来

返回练习顶部

(1.5)为远程化添加另一个方法

作为练习,向 Chat.java 添加另一个方法,如代码 1.46 所示,然后像对待 以上 1.4 步骤 中的 getNumberOfMessages() 方法一样,将其信息显示在浏览器中。

public String getLastMessage(){
if (messages.size()== 0) {
return "";
}
//getFirst will actually return the "last" message based on this data
//structure
Message m = (Message)messages.getFirst();
return (String)m.getText();

}
代码 1.46:修改您自己的练习

结束语

在本练习中,您构建并运行了一个简单的 DWR 示例应用程序。了解了 DWR 应用程序是如何构造的。也添加了另一个用于远程化的 Java 方法。

返回顶部




练习 2:构建和运行“Dynamic Form Editing”示例 DWR 应用程序 Build and run "Dynamic Form Editing" sample DWR application

在本练习中,您将构建和运行另一个 DWR 示例应用程序,名称为“Dynamic Form Editing”。此处您将练习如何将一个名称为 Person 的 JavaBean 对象作为参数传给一个远程化方法。(2.1)所需的所有代码和库文件都在一个现成的 NetBeans 项目中。在步骤(2.2)中,将按照本文档中的说明来更改代码。步骤(2.3)留做您自己的练习。


(2.1)使用 NetBeans 打开、生成和运行“Dynamic Form Editing”示例 DWR 应用程序

1. 打开 dwr.examples.form-editing NetBeans 项目

2. 效仿 以上练习 1,解决引用问题。

3. 生成和运行项目。


图 2.10:运行“Dynamic Form Editing”示例 DWR 应用程序的结果


图 2.11:编写表单

返回练习顶部

(2.2)将一个嵌套对象作为参数传递

在本步骤中,将把 Person 类的 name 字段由当前的 String 类型修改为 JavaBean 类。Person 类被认为是一个嵌套类,因为它包含另一个类。

1. 双击 dwr.examples.form-editing->源包->uk.ltd.getahead.testdwr 下的 Person.java 将其在 NetBeans 的源编辑器中打开。
2. 修改 Person.java,如下所示 —— 将 name 字段的 String 类型改为 Name 类。需要更改的代码段显示为 蓝色粗 体。在 Person.java 文件中, 有四处需要进行从 StringName 的更改。

package uk.ltd.getahead.testdwr;

public class Person {

private Name name;
private String address;
private int id;
private float salary;

// No arg constructor to make it a JavaBean
public Person(){
}

public Person(Name name, String address, int id, float salary){
this.name = name;
this.address = address;
this.salary = salary;
this.id = id;
}

public Name getName() {
return name;
}

public void setName(Name name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public float getSalary() {
return salary;
}

public void setSalary(float salary) {
this.salary = salary;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

}

3. 现在要创建 Name 类。右键单击 dwr.examples.form-editing->源包 下的 uk.ltd.getahead.testdwr 包节点并选择 新建->Java 类。(如下图 2.21 所示)


图 2.21:创建一个新的 Java 类

4. 在 名称和位置 窗格下的 类名: 字段处键入 Name。单击 完成。(如下图 2.22 所示)


图 2.22:Name 类

5. 修改由 IDE 生成的 Name.java 代码,如下所示。(如代码 2.23 所示)需要添加的代码段突出显示为 蓝色粗 体。请确保没有带参数的构造方法。否则,DWR 将在类转换中出现问题。

package uk.ltd.getahead.testdwr;

/**
*
* @author sang
*/
public class Name {

private String firstname;
private String middlename;
private String lastname;

// No arg constructor
public Name() {
}

public Name(String firstname, String middlename, String lastname) {
this.firstname = firstname;
this.middlename = middlename;
this.lastname = lastname;
}

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = firstname;
}

public String getMiddlename() {
return middlename;
}

public void setMiddlename(String middlename) {
this.middlename = middlename;
}

public String getLastname() {
return lastname;
}

public void setLastname(String lastname) {
this.lastname = lastname;
}

}
代码 2.23:Name.java

5. 修改 Demo.javacreatePeople() 方法,如下所示。(如代码 2.24 所示)做此更改是要使用 Name 对象实例创建 Person 对象实例。

private void createPeople() {
Person fred = new Person(new Name("Fred", "Middle", "Shin"), "1 Red Street",
2, 100000.0f);
Person jim = new Person(new Name("Jim", "M", "Clinton"), "42 Brown Lane", 3, 20000.0f);
Person shiela = new Person(new Name("Shiela", "Mi", "Hutcherson"), "12 Yellow Road",
4, 3000000.0f);

people.put(new Integer(fred.getId()), fred);
people.put(new Integer(jim.getId()), jim);
people.put(new Integer(shiela.getId()), shiela);
}

private static final String SESSION_CLICKS = "sessionClicks";

private static final String CONTEXT_CLICKS = "contextClicks";

private static int nextId = 10;

private final Map people = new HashMap();

private Person person = new Person(new Name("John Doe", "Mid", "Thompson"),
new Date().toString(), 1, 100000.0F);
}
代码 2.24:经过修改的 Demo.java

5. 修改 dwr.examples.form-editing->Web Pages 下的 index.html。(以下代码 2.25 所示)代码 2.25 是 index.html 的完整文档。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>DWR Examples from DWR website</title>

<script type='text/javascript' src='dwr/engine.js'></script>
<script type='text/javascript' src='dwr/interface/Demo.js'></script>
<script type='text/javascript' src='dwr/util.js'></script>

<script type='text/javascript'>
// This function gets called when window is loaded.
// The fillForm is a callback function to be called asynchronously.
function readPerson() {
Demo.getExamplePerson(fillForm);
}

function writePerson() {
DWRUtil.getValues(person);
DWRUtil.getValues(person.name);
DWRUtil.getValues(person.address);
Demo.setExamplePerson(null, person);
}

function clearPerson() {
//person = { id:"", name:"", address:"", salary:"" };
person = { id:"", firstname:"", middlename:"", lastname:"", address:"", salary:"" };
DWRUtil.setValues(person);
}

var person;
var name;

// Callback function
function fillForm(aperson) {
// Add some alert messages to display the data that is received from the server
alert(DWRUtil.toDescriptiveString(aperson));
alert(DWRUtil.toDescriptiveString(aperson.name));
person = aperson;
DWRUtil.setValues(person);
// Note the easy syntax for accessing the Name child object from Person parent object
name = aperson.name;
DWRUtil.setValues(name);
}

// Initialization that is called when window is loaded
function init() {
DWRUtil.useLoadingMessage();
readPerson();
}

// Call init function when window is loaded
window.onload = init;

</script>
</head>

<body>

<h1>Dynamic Form Editing</h1>

<p>This is a very simple demonstration of form editing using DWR.</a>

<h2>Demo</h2>
<table>
<tr>

<td>First Name:</td>
<td><input id="firstname" type="text"/></td>
<td>Middle Name:</td>
<td><input id="middlename" type="text"/></td>
<td>Last Name:</td>
<td><input id="lastname" type="text"/></td>

</tr>
<tr>

<td>Salary:</td>
<td><input id="salary" type="text"/></td>

</tr>
<tr>

<td>ID:</td>

<td><input id="id" type="text"/></td>

</tr>
<tr>

<td>Address:</td>
<td><input type="text" id="address"/></td>

</tr>
<tr>

<td colspan="2" align="right">
<input type="button" value="Clear" onclick="clearPerson()"/>
<input type="button" value="Read" onclick="readPerson()"/>
<input type="button" value="Write" onclick="writePerson()"/>
</td>

</tr>
</table>
</body>
</html>
代码 2.25:经过修改的 index.html

6. 修改 dwr.examples.form-editing->Web 页->WEB-INF 下的 dwr.xml 文件(以下代码 2.26 所示) 您正在指导 DWR 完成 Name JavaBean 类的转换。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>

<allow>

<create creator="new" javascript="Demo" scope="session">
<param name="class" value="uk.ltd.getahead.testdwr.Demo"/>
</create>

<create creator="new" javascript="Chat">
<param name="class" value="uk.ltd.getahead.testdwr.Chat"/>
</create>

<create creator="new" javascript="UrlValidator">
<param name="class"
value="org.apache.commons.validator.UrlValidator"/>
</create>

<create creator="new" javascript="CreditCardValidator">
<param name="class"
value="org.apache.commons.validator.CreditCardValidator"/>
</create>

<create creator="script" javascript="EmailValidator"
scope="application">
<param name="language" value="beanshell"/>
<param name="script">
import org.apache.commons.validator.EmailValidator;
return EmailValidator.getInstance();
</param>
</create>

<create creator="new" javascript="XOM">
<param name="class"
value="uk.ltd.getahead.testdwr.XOMDemo"/>
</create>
<create creator="new" javascript="JDOM">
<param name="class"
value="uk.ltd.getahead.testdwr.JDOMDemo"/>
</create>
<create creator="new" javascript="DOM4J">
<param name="class"
value="uk.ltd.getahead.testdwr.DOM4JDemo"/>
</create>
<create creator="new" javascript="DOM">
<param name="class"
value="uk.ltd.getahead.testdwr.DOMDemo"/>
</create>

<convert converter="bean"
match="uk.ltd.getahead.testdwr.Person"/>
<convert converter="bean"
match="uk.ltd.getahead.testdwr.Message"/>
<convert converter="bean"
match="uk.ltd.getahead.testdwr.Name"/>
<convert converter="bean" match="$Proxy*"/>

</allow>

</dwr>
代码 2.26:经过修改的 dwr.xml

7. 右键单击 dwr.examples.form-editing 项目并选择 运行。您应看到一条显示出的内容为返回数据的 alert 消息。(如下图 2.27 所示)


图 2.27:回调函数中第一条 alert 消息

8. 单击 alert 消息的 OK。您会看到第二条 alert 消息,其中显示 Name 对象的内容。
9. 单击第二条 alert 消息的 OK。(如下图 2.28 所示)


图 2.28:回调函数中的第二条 alert 消息

10. 您会看到下图中的结果。(如下图 2.29 所示)


图 2.29:显示默认人物

11. 改变这些值并单击 Write 按钮。
12. 如果显示出改变的值请单击 Read 按钮。


故障排除:如果看到以下错误对话框,意味着 DWR 在 Person Java 对象和 Person JavaScript 对象的转换中出现了问题。问题可能源自(1)Person Java 类不是 JavaBean —— 也许它不含有不带参数的构造方法(2)dwr.xml 文件的 <convert> 元素未被指定或未被正确指定。




解决方案:本练习的解决方案是一个现成的 NetBeans 项目 <LAB_UNZIPPED_DIRECTORY>/ajaxdwrintro/solutions/dwr.examples.form-editing-solution。您可以打开并运行它。



返回练习顶部

(2.3)用一个 Java 类作 Address 字段作为练习

作为练习,将一个 JavaBean 类作为 Address 字段(代替 String 类型)。按照以下代码 2.30 编写 Address.java。如以上 步骤(2.2),对 Demo.javaindex.htmldwr.xml 文件作出修改。重新生成并测试该应用程序。

package uk.ltd.getahead.testdwr;

/**
*
* @author sang
*/
public class Address{

private String street;
private String state;
private String zipcode;

/** Creates a new instance of Address*/
public Address() {
}

public Address(String street, String state, String zipcode) {
this.street = street;
this.state = state;
this.zipcode = zipcode;
}

public String getstreet() {
return street;
}

public void setstreet(String street) {
this.street = street;
}

public String getstate() {
return state;
}

public void setstate(String state) {
this.state = state;
}

public String getzipcode() {
return zipcode;
}

public void setzipcode(String zipcode) {
this.zipcode = zipcode;
}

}


返回练习顶部

结束语

在本练习中,您了解了如何将 Java 对象作为远程方法的参数传递。也了解了如何将嵌套 Java 对象作为参数传递。

返回顶部



练习 3:构建并运行“Dynamic Table Editing”(dwr.examples.table-editing)示例 DWR 应用程序

在本练习中,您将构建并运行另一个名称为“Dynamic Table Editing”的 DWR 示例应用程序(dwr.examples.table-editing project)。您将了解如何使用 DWRUtil.addRows()DWRUtil.removeAllRows() 实用函数来操纵表格。

在进行此练习前,请通过阅读 DWR 网站的 Generating Tables tutorial 来熟悉这两个实用函数。步骤(3.1)中所需的所有代码和库文件已经提供在一个现成的 NetBeans 项目中。

    1. 使用 NetBeans 打开、生成和运行“Dynamic Table Editing”示例 DWR 应用程序
    2. 向表格中添加另一个字段 Hobby
    3. 向表格中再添加一个您自己的字段作为练习

(3.1)使用 NetBeans 打开、生成和运行“Table Editing”示例 DWR 应用程序


1. 打开 dwr.examples.table-editing NetBeans 项目。
2. 如 以上练习 1 中所示 解决引用问题。
3. 生成和运行项目。

图 3.10:编辑 Shiela 的信息


图 3.11:编辑 Shiela 的地址


图 3.12:再添加一行



图 3.13:添加了新行

返回练习顶部

(3.2)向表格中再添加一个字段“Hobby”


在本步骤中,您将向表格中再添加一个字段,名称为 Hobby,并重新生成该应用程序。

1. 修改 Person.java。需要添加的代码段突出显示为 蓝色粗 体。(如代码 3.20 所示)

package uk.ltd.getahead.testdwr;

public class Person {

/* Getters and setters go here */
private String name;
private String address;
private int id;
private float salary;
private String hobby;

// No arg constructor to make it a JavaBean
public Person(){
}

public Person(String name, String address, int id, float salary, String hobby){
this.name = name;
this.address = address;
this.salary = salary;
this.id = id;
this.hobby = hobby;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public float getSalary() {
return salary;
}

public void setSalary(float salary) {
this.salary = salary;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getHobby() {
return hobby;
}

public void setHobby(String hobby) {
this.hobby= hobby;
}
}
代码 3.20:经过修改的 Person.java

2. 修改 Demo.java 以反映 Person 类的 hobby 属性。(以下代码 3.21 所示)

/**
* Setup the list of people.
*/
private void createPeople() {
Person fred = new Person("Fred", "1 Red Street",
2, 100000.0f, "Swimming");
Person jim = new Person("Jim", "42 Brown Lane", 3, 20000.0f, "Golfing");
Person shiela = new Person("Shiela", "12 Yellow Road",
4, 3000000.0f, "Dancing");

people.put(new Integer(fred.getId()), fred);
people.put(new Integer(jim.getId()), jim);
people.put(new Integer(shiela.getId()), shiela);
}

private static final String SESSION_CLICKS = "sessionClicks";

private static final String CONTEXT_CLICKS = "contextClicks";

private static int nextId = 10;

private final Map people = new HashMap();

private Person person = new Person("John Doe",
new Date().toString(), 1, 100000.0F, "Walking");
代码 3.21:经过修改的 Demo.java

3. 修改 index.html 中的 JavaScript 代码。(以下代码 3.22 所示)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>DWR Examples from DWR website</title>

<script type='text/javascript' src='dwr/engine.js'></script>
<script type='text/javascript' src='dwr/interface/Demo.js'></script>
<script type='text/javascript' src='dwr/util.js'></script>

<script type='text/javascript'>
// Callback function for Delete method
function update() {
Demo.getAllPeople(fillTable);
}

// Functions to be passed to DWRUtil.addRows
var getName = function(person) { return person.name };
var getDoB = function(person) { return person.address }; // if we return to using dates, add .toLocaleDateString()
var getSalary = function(person) { return person.salary };
var getHobby = function(person) { return person.hobby};
var getEdit = function(person) {
return '<input type="button" value="Edit" onclick="readPerson('+person.id+')"/>';
};
var getDelete = function(person) {
return '<input type="button" value="Delete" onclick="deletePerson('+person.id+', \''+person.name+'\')"/>';
};

// Callback function for getAllPeople method
// The table is reconstructed
function fillTable(people) {
DWRUtil.removeAllRows("peoplebody");
DWRUtil.addRows("peoplebody", people, [ getName, getDoB, getSalary, getHobby, getEdit, getDelete ])
}

// Event handler to be called when Edit button is clicked
function readPerson(id) {
Demo.getPerson(fillForm, id);
}

// Event handler to be called when Delete button is clicked
function deletePerson(personid, name) {
if (confirm("Are you sure you want to delete " + name + "?")) {
Demo.deletePerson(update, { id:personid });
}
}

// Event handler to be called when Save button is clicked
function writePerson() {
DWRUtil.getValues(person);
Demo.addPerson(update, person);
}

var person = { id:-1, name:null, address:null, salary:null, hobby:null };

// Event handler to be called when Clear button is clicked
function clearPerson() {
person = { id:-1, name:null, address:null, salary:null, hobby:null };
DWRUtil.setValues(person);
}

// Callback function for readPerson method
function fillForm(aperson) {
person = aperson;
DWRUtil.setValues(person);
}

// Function that will be called when page is loaded
function init() {
DWRUtil.useLoadingMessage();
update();
}

// Set init function to be called when page is loaded
window.onload = init;
</script>
</head>

<body>

<h1>Dynamically Editing a Table</h1>

<p>This demo stores the list of people in your session, so the editing relies on <b>Cookies</b>. DWR can use application, session and request scope to store beans</p>

<h2>Demo</h2>

<table border="1" class="rowed">

<thead>
<tr>

<th>Name</th>
<th>Address</th>
<th>Salary</th>
<th>Hobby</th>
<th colspan="2">Actions</th>

</tr>
</thead>
<tbody id="peoplebody">
</tbody>

</table>

<h4>Edit Person</h4>

<table>
<tr>

<td>ID:</td>
<td><span id="id">-1</span></td>

</tr>
<tr>

<td>Name:</td>

<td><input id="name" type="text"/></td>

</tr>
<tr>

<td>Salary:</td>
<td><input id="salary" type="text"/></td>

</tr>
<tr>

<td>Address:</td>
<td><input type="text" id="address"/></td>

</tr>
<tr>

<td>Hobby:</td>
<td><input type="text" id="hobby"/></td>

</tr>
<tr>

<td colspan="2" align="right">
<input type="button" value="Save" onclick="writePerson()"/>
<input type="button" value="Clear" onclick="clearPerson()"/>
</td>

</tr>
</table>
</body>
</html>
代码 3.22:经过修改的 index.html

4. 右键单击 dwr.examples.table-editing 项目节点并选择 运行。您应看到下图。(如图 3.33 所示)


图 3.33:添加了 Hobby 字段

5. 再添加一个人,观察应用程序是否预期运行。.

返回练习顶部

(3.3)向表格中再添加一个您自己的字段作为练习


作为练习,向表格中再添加一个您选择的字段。像在以上 步骤(3.2) 中一样,对 Person.java、Demo.java index.html 文件作出修改。重新生成并测试该应用程序。作为选择性练习,请效仿以上 步骤(2.2),将一个 JavaBean 类作为 Address 字段。

结束语


在本练习中,您构建并运行了一个名称为“Dynamic Table Editing”(dwr.examples.table-editing)的 DWR 示例应用程序。您也了解了如何使用 DWRUtil.addRows()DWRUtil.removeAllRows() 实用函数来操纵表格。

返回顶部



练习 4:构建并运行“Dynamically Populating a Selection List”示例 DWR 应用程序


在本练习中,您将构建并运行另一个 DWR 示例应用程序,名称为“Dynamically Populating a Selection List”。


(4.1) 使用 NetBeans 打开、生成和运行“Dynamically Populating a Selection List”示例 DWR 应用程序


1. 打开 dwr.examples.populating-selectionlist NetBeans 项目。
2. 效仿 以上练习 1,解决引用问题。

3. 生成和运行项目。


图 4.10:应用程序的运行结果

图 4.11:Pick a Number 选项被改变


返回顶部





课外练习(针对 Sang Shin“AJAX 在线课程”的学习者)


1. 课外练习是要按以下要求修改您在练习 3 中构建的 dwr.examples.table-editing 项目。(可以通过复制 dwr.examples.table-editing 项目来创建一个新项目。)您可以将新项目命名为任意名称,但此处我将称其为 dwr.examples.table-editing-homework
2. 将以下文件以 AJAXHomework-ajaxdwrintro 作为 发送主题 发送到 ajaxhomework@sun.com


原文链接: http://www.javapassion.com/handsonlabs/ajaxdwrintro/