站内搜索: 请输入搜索关键词

当前页面: 开发资料首页JSP 专题appfuse文档(五)--创建Action和JSP

appfuse文档(五)--创建Action和JSP

摘要: appfuse文档(五)--创建Action和JSP

创建ActionJSP<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

本章将向你展示怎样创建Action和JSP。

这部分内容依赖Part II: 创建Manager

关于本章

本章将向你展示怎样创建一个Struts的Action, 一个JUnit Test (使用StrutsTestCase<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /> ),和一个包含form的JSP。我们创建的Action将和在上一章中创建的PersonManager进行交互。

AppFuse使用Struts 作为它默认的Web框架。在1.6中,你还可以使用Spring 或者 WebWork 。在1.7和1.8中将会把Tapestry和JSF集成进来。

我们首先创建一个Struts Action和JSP。

内容

· [1] 为Person添加XDoclet Tags来产生PersonForm

· [2] 使用XDoclet 来创建JSP的skeleton(骨架)

· [3] 创建测试PersonAction 的PersonActionTest

· [4] 创建PersonAction

· [5] 运行PersonActionTest

· [6] 清理JSP,使它合乎要求 [make it presentable]

· [7] 创建测试Action的Canoo WebTest[可以像浏览器一样测试Action]

AppGen

AppGen是<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1.6.1的一部分,它是基于Lance Lavandowska Ben Gill 的工具产生的. 起初,我不想添加像这个B/S结构的程序产生的代码特征(表和POJO之间、DAO和Manager之间的一对一关系)。我的大部分的工程中,我使用的DAO和Manager要比POJO少得多。

默认情况下, AppGen将只产生Actions/Controllers, Action/Controller Tests, 测试数据, i18n key 和JSP.它也会为你配置好Action/Controller。它使用通用的BaseManager和BaseDAOHibernate 类(被配置为"manager"和"dao") 来减少产生的文件数。我也认识到有时候你可能需要产生所有的DAO 和Manager类及它们的测试类,所以我添加了一个可以达到这个目的的选项。

安装完框架后,如果你想使用AppGen工具,请按照下面的步骤进行:

1. 先安装框架,在model目录中创建你的POJO(ltf:该POJO的hibernate和Struts的标签都要添加,然后”ant setup”)

2. 然后配置applicationContext-hibernate.xml 配置映射文件

"mappingResources">

org/appfuse/model/Person.hbm.xml
org/appfuse/model/Role.hbm.xml
org/appfuse/model/User.hbm.xml
org/appfuse/model/UserCookie.hbm.xml

3. 进入到目录extras/appgen中,
然后运行"ant -Dmodel.name=Person -Dmodel.name.lowercase=person"。本例中,类Person应当已经存在你的"model"包里面了。这将为你产生所有你在这个手册里面创建的所有的文件。

4. 运行"ant install-detailed "来安装产生的文件(ltf:实际上就是将产生的文件复制到源代码树的相应位置)。你可以运行
"ant install-detailed -Dmodel.name=Person -Dmodel.name.lowercase=person"

5. 修改personForm.jsp,将“id”属性变为隐藏域(hidden)。

6. 进入cd ..\..”, 运行“ant setup”以产生新的struts-config.xml等文件。

7. 修改JSP文件,如果当前JSP中没有必须填的字段,则要将*Form页面最下部的html:javascript代码注释掉。

8. 运行“ant deploy

注意: 如果你不想产生所有的DAO/Manager/Test, 运行"ant install " 代替"ant install-detailed "。在安装文件之前,要保证所有文件已经被创建到了目录extras/appgen/build/gen中。如果你只是想测试这个工具,你可以进入这个目录,然后运行"ant test" 。

警告: 我建议你在做这些之前备份你的工程,我已经测试了这个工具,它工作的很好,但它会更改你的源文件的目录树结构。

使用"lowercase"参数的原因是使产生的JSP的文件名开头的字母为小写的。

这个工具将自动产生CRUD代码,这样可以使你将精力集中在业务逻辑和美化界面上。

Person添加XDoclet Tags来产生PersonForm

现在我们要生成供Web层使用的PersonForm对象。我们为Person.java需要添加Xdoclet标签来创建ActionForm。在Person.java 文件的JavaDoc中, 添加下面的@struts.form标签(可以参考 User.java):

<table class=MsoNormalTable style="BACKGROUND: white; WIDTH: 100%; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt; mso-cellspacing: 0cm" cellSpacing=0 cellPadding=0 width="100%" border=0> <tr style="HEIGHT: 22.6pt; mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes"> <td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #ece9d8; HEIGHT: 22.6pt; BACKGROUND-COLOR: transparent" vAlign=top noWrap>

* @struts.form include-all="true" extends="BaseForm"

</td></tr></table>

我们继承org.appfuse.webapp.form.BaseForm,因为它有toString()方法,它可以使我们调用log.debug(formName)来打印一个窗体对象的友好的视图.

如果你重命名 "org.appfuse" packages"com.company"或者其他的方式,那么你的默认包内没有model类,你要在@struts.form标签部分添加完整类名

(包括包名)[fully-qualify]来引用org.appfuse.webapp.form.BaseForm

使用XDoclet 来创建JSPskeleton(骨架)

这一步,我们将生成skeleton或者用于显示PersonForm信息的JSP. 我说生成的是skeleton是因为它只是<form>自己。它将包含表的数据和对应PersonForm.java中每个属性的Struts标签。我们使用的工具只是一个类(FormTagsHandler.java) 和2个XDoclet模板(FormKeys.xdtStrutsForm_jsp.xdt),所有这些文件位于目录extras/viewgen中。

警告: "viewgen" 在AppFuse1.6.1中已经是不建议使用的工具了,在1.7中将被删除。appgen 将提供同样的功能。

下面是一个生成JSP和窗体元素的Label的属性文件(properties file)的简单步骤:

· 执行ant compile – 根据Person.java产生PersonForm.java(build/web/gen/)

· 使用命令行”cmd”, 进入到目录"extras/viewgen"

· 执行ant -Dform.name=PersonForm将在extras/viewgen/build中产生3个文件:

· PersonForm.properties (form元素的label)

· PersonForm.jsp (用来查看一个Person的JSP的骨架程序)

· PersonFormList.jsp (或是PersonList,查看People列表的JSP的骨架程序)

· 复制PersonForm.properties的内容到 web/WEB-INF/classes/ApplicationResources_en.properties.
例:以下内容要加入到ApplicationResources_en.properties文件:

# -- person form --

personForm.firstName=First Name

personForm.id=Id

personForm.lastName=Last Name

· 复制PersonForm.jspweb/pages/personForm.jsp.
复制PersonFormList.jsp(PersonList.Jsp)web/pages/personList.jsp.
注意:每个新文件的名字第一个字符都是小写。

"pages"目录下的文件在部署时将会放入"WEB-INF/pages"目录中。这样可以使用容器提供的安全机制去保护WEB-INF中的文件。这只针对客户的请求,不会阻止Struts ActionServletforward。将JSP放入WEB-INF中,以确保他们只能通过Action被访问。这样安全的问题将被转移到Action中。这样可以更有效率,同时也是它从表现层中脱离出来。

AppFuse的Web程序的安全机制指定所有*.html模式的页面都应该被保护。 (除了/signup.html/passwordHint.html)。这样确保客户端必须通过Action才能跳转到在pages目录下的JSP。

如果你使用Eclipse, 你可能要"refresh"工程才能看到PersonForm。它位于目录build/web/gen中。这是在Eclipse中看到、导入PersonForm的唯一途径, 因为它被 XDoclet产生,并且不在你的常规的源代码的目录树中。你可以在这里找到它:build/web/gen/org/appfuse/webapp/form/PersonForm.java.

BaseAction 中,你可以注册其他的Converters (如: DateConverter )所以 BeanUtils.copyProperties知道怎样去convert Strings Objects.如果你有POJO的列表 (如:父子关系),你将需要使用convertLists(java.lang.Object)方法进行手工转换。

NOTE: 如果你想为一个特殊页指定CSS,你可以添加<body id="pageName"/> 到文件的顶部。这将被SiteMesh捕捉到并会被放如最终的页面中。这样你就可以像下面这样一页一页的定义你的CSS:

body#pageName element.class { background-color: blue }

· ApplicationResources_en.properties中添加JSP文件的 titleheadingKey

在生成的JSP中,有2个Key,用于title (浏览器窗口的顶部)和header (页头).
我们现在需要添加这2个key (personDetail.titlepersonDetail.heading) 到ApplicationResources_en.properties文件中.

打开web/WEB-INF/classes/ApplicationResources_en.properties
然后将下面的内容添加到文件底部:

# -- person detail page --

personDetail.title=Person Detail

personDetail.heading=Person Information

在上文中我们刚刚添加"personForm.*" key到这个文件,为什么我既使用personForm又使用personDetail? 最好的解释是它很好的分离了页面上的form labeltext。另一个原因是所有的*Form.*给我们一个很好的数据库所有字段的表示方法。

最近,我有一个客户,他希望数据库中的所有字段都应该是可以查询的。这很好实现。我只在ApplicationResources.properties文件中搜寻包含"Form."Key,然后把它们放到下拉列表中。用户能够输入查询值,然后选择一个他希望搜索的列。我很高兴我将FormDetail区分开了!

创建测试PersonAction PersonActionTest

为测试PersonAction, 我们创建一个StrutsTestCase,我们在test/web/**/action 目录中创建PersonActionTest.java.

实际上, 我常常复制另存为一个已经有的ActionTest (i.e. UserActionTest). [P]erson覆盖 [Uu]se

如果你的确复制了UserActionTest,确保已经改变UserFormExPersonForm UserFormEx 是一个 UserForm的扩展,它有用于 Rolessetter,返回String[] 因为 UserForm已经产生,User.java对象中这样做不是很可行的。

<table class=MsoNormalTable style="BACKGROUND: white; WIDTH: 100%; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt; mso-cellspacing: 0cm" cellSpacing=0 cellPadding=0 width="100%" border=0> <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes"> <td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent" vAlign=top noWrap>

package org.appfuse.webapp.action;

import org.appfuse.Constants;
import org.appfuse.webapp.form.PersonForm;

public class PersonActionTest extends BaseStrutsTestCase {

public PersonActionTest(String name) {
super(name);
}

public void testEdit() throws Exception {
setRequestPathInfo("/editPerson");
addRequestParameter("method", "Edit");
addRequestParameter("id", "1");
actionPerform();

verifyForward("edit");
assertTrue(request.getAttribute(Constants.PERSON_KEY) != null);
verifyNoActionErrors();
}

public void testSave() throws Exception {
setRequestPathInfo("/editPerson");
addRequestParameter("method", "Edit");
addRequestParameter("id", "1");

actionPerform();

PersonForm personForm =
(PersonForm) request.getAttribute(Constants.PERSON_KEY);
assertTrue(personForm != null);

setRequestPathInfo("/savePerson");
addRequestParameter("method", "Save");

// update the form from the edit and add it back to the request
personForm.setLastName("Feltz");
request.setAttribute(Constants.PERSON_KEY, personForm);

actionPerform();

verifyForward("edit");
verifyNoActionErrors();
}

public void testRemove() throws Exception {
setRequestPathInfo("/editPerson");
addRequestParameter("method", "Delete");
addRequestParameter("id", "2");
actionPerform();

verifyForward("mainMenu");
verifyNoActionErrors();
}
}

</td></tr></table>

你要往src/dao/**/Constants.java中添加一个变量PERSON_KEY.
名字"personForm"要和struts-config.xml中配置的form名字一样.

<table class=MsoNormalTable style="BACKGROUND: white; WIDTH: 100%; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt; mso-cellspacing: 0cm" cellSpacing=0 cellPadding=0 width="100%" border=0> <tr style="HEIGHT: 70.5pt; mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes"> <td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #ece9d8; HEIGHT: 70.5pt; BACKGROUND-COLOR: transparent" vAlign=top noWrap>

/**
* The request scope attribute that holds the person form.
*/
public static final String PERSON_KEY = "personForm";

</td></tr></table>

如果你试着运行这个测试, 你将得到很多NoSuchMethodErrors错误
所以我们要在PersonAction类中定义edit, save, 和delete方法

创建PersonAction

src/web/**/action, 创建PersonAction.java。内容如下:

<table class=MsoNormalTable style="BACKGROUND: white; WIDTH: 100%; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt; mso-cellspacing: 0cm" cellSpacing=0 cellPadding=0 width="100%" border=0> <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes"> <td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent" vAlign=top noWrap>

package org.appfuse.webapp.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import org.appfuse.model.Person;
import org.appfuse.service.PersonManager;
import org.appfuse.webapp.form.PersonForm;

/**
* @struts.action name="personForm" path="/editPerson" scope="request"
* validate="false" parameter="method" input="mainMenu"
*/
public final class PersonAction extends BaseAction {

public ActionForward cancel(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
return mapping.findForward("mainMenu");
}

public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (log.isDebugEnabled()) {
log.debug("Entering 'delete' method");
}

ActionMessages messages = new ActionMessages();
PersonForm personForm = (PersonForm) form;

// Exceptions are caught by ActionExceptionHandler
PersonManager mgr = (PersonManager) getBean("personManager");
mgr.removePerson(personForm.getId());

messages.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("person.deleted",
personForm.getFirstName() + ' ' +
personForm.getLastName()));

// save messages in session, so they'll survive the redirect
saveMessages(request.getSession(), messages);

return mapping.findForward("mainMenu");
}

public ActionForward edit(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (log.isDebugEnabled()) {
log.debug("Entering 'edit' method");
}

PersonForm personForm = (PersonForm) form;

// if an id is passed in, look up the user - otherwise
// don't do anything - user is doing an add
if (personForm.getId() != null) {
PersonManager mgr = (PersonManager) getBean("personManager");
Person person = mgr.getPerson(personForm.getId());
personForm = (PersonForm) convert(person);
updateFormBean(mapping, request, personForm);
}

return mapping.findForward("edit");
}

public ActionForward save(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (log.isDebugEnabled()) {
log.debug("Entering 'save' method");
}

// Extract attributes and parameters we will need
ActionMessages messages = new ActionMessages();
PersonForm personForm = (PersonForm) form;
boolean isNew = ("".equals(personForm.getId()));

if (log.isDebugEnabled()) {
log.debug("saving person: " + personForm);
}

PersonManager mgr = (PersonManager) getBean("personManager");
Person person = (Person) convert(personForm);
mgr.savePerson(person);

// add success messages
if (isNew) {
messages.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("person.added",
personForm.getFirstName() + " " +
personForm.getLastName()));

// save messages in session to survive a redirect
saveMessages(request.getSession(), messages);

return mapping.findForward("mainMenu");
} else {
messages.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("person.updated",
personForm.getFirstName() + " " +
personForm.getLastName()));
saveMessages(request, messages);

return mapping.findForward("edit");
}
}
}

</td></tr></table>

从上面的代码你可以注意到: 有很多调用convert 一个PersonForm或者Person对象。这个convert BaseAction.java中的一个方法,它内部调用ConvertUtil.convert()方法,并使用BeanUtils.copyProperties 将进行如下转换:POJO → ActionForm,将ActionForm → POJO。

现在,你要添加edit forward和savePerson action-mapping, PersonActionTest中将引用它们。 为了达到这个目的, 我们要添加Xdoclet标签到 PersonAction.java的顶部. 如果你在上面的类声明中所有的都正确,你应该已经有用于editPerson action-mapping的XDoclet标签了,但我仍然要把它列在这里,以便你能够看到这个类顶部的所有的XDoclet标签。

<table class=MsoNormalTable style="BACKGROUND: white; WIDTH: 100%; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt; mso-cellspacing: 0cm" cellSpacing=0 cellPadding=0 width="100%" border=0> <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes"> <td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent" vAlign=top noWrap>

/**
* @struts.action name="personForm" path="/editPerson" scope="request"
* validate="false" parameter="method" input="mainMenu"
*
* @struts.action name="personForm" path="/savePerson" scope="request"
* validate="true" parameter="method" input="edit"
*
* @struts.action-forward name="edit" path="/WEB-INF/pages/PersonForm.jsp"
*/
public final class PersonAction extends BaseAction {

</td></tr></table>

EditPersonsavePerson action-mapping的主要区别是savePerson的校验已经打开(看 validation="true") 。注意:"input"必须是一个forward, 而不能是一个path (如: /editPerson.html)。如果你想让edit和save都使用save path (ltf:path?),也可以的。只要确保两者的 validate="false",再在你的"save"方法中调用form.validate() ,然后适当的处理错误。

这里有几个用来显示操作成功消息的key,你要添加到目录web/WEB-INF/classes下的ApplicationResources_en.properties文件里。打开这个文件,添加如下

我通常添加到# -- success messages –-“注释下面.

person.added=Information for {0} has been added successfully.

person.deleted=Information for {0} has been deleted successfully.

person.updated=Information for {0} has been updated successfully.

你应该使用一般的added, deletedupdated messages,无论你怎么工作,它都可以避免因为每改变一个实体就要将消息改变。

你可能注意到你用来调用PersonManager的代码和用在PersonManagerTest中的是一样。PersonAction和PersonManagerTest都是PersonManagerImpl的“客户端”, 这样感觉很完美。

所有一切几乎都完成了,让我们运行测试吧!

运行PersonActionTest

如果你在看PersonActionTest, 所有的测试都依赖一条记录id=1的数据库记录(testRemove依赖id=2的记录), 所以要添加示例数据文件(metadata/sql/sample-data.xml). 我已经把它们添加到下面了 – 表的顺序并不重要,因为它目前没有和任何其他的表关联。
(ltf:如果这个表和其他的表用外键/触发器关联,则必须注意表创建的顺序和数据添加的顺序)。

<table name='person'>

id

first_name

last_name

1

Matt

Raible

2

James

Davidson

</table>

在我们的所有测试被执行之前,DBUnit会首先装载这个文件, 所以这个记录可以被PersonActionTest使用。

现在你执行ant test-web -Dtestcase=PersonAction – 一切都应该按照计划进行.
在你执行这个命令前,要确保Tomcat没有运行。

BUILD SUCCESSFUL
Total time: 1 minute 21 seconds

清理JSP,使JSP符合规格(presentable)

现在我们开始清理personForm.jsp,我们要使"id"变成一个”hidden”. 从web/pages/personForm.jsp中删除下面的代码块:

<table class=MsoNormalTable style="BACKGROUND: white; WIDTH: 100%; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt; mso-cellspacing: 0cm" cellSpacing=0 cellPadding=0 width="100%" border=0> <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes"> <td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent" vAlign=top noWrap>

<tr>
<th>

</th>
<td>


</td>
</tr>

</td></tr></table>

<table>标记之前添加下面的

<table class=MsoNormalTable style="BACKGROUND: white; WIDTH: 100%; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt; mso-cellspacing: 0cm" cellSpacing=0 cellPadding=0 width="100%" border=0> <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes"> <td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent" vAlign=top noWrap>

</td></tr></table>

你应该改变action为"savePerson",这样当你保存数据时,校验将被打开,同样, 改变focus属性,从focus=""到focus="firstName",这样页面打开后,光标停留在firstName字段(这是使用JavaScript实现的).

现在执行ant db-load deploy, 然后启动Tomcat,最后打开浏览器,输入 http://localhost:8080/appfuse/editPerson.html?id=1 , 你应该看到如下界面:

注意:如果你改变了web目录下的任何文件,要使用deploy-web target.
否则,使用deploy 编译并部署

最后,为了使这个页面更加友好,你可能想在form顶部向你的用户显示提示消息,这个很容易实现。
personForm.jsp顶部使用就可以了。
[可选] 创建测试ActionCanoo WebTest

这个指南最后一步使创建一个Canoo WebTest 用来测试JSP.

我之所以说这一步是可选的,是因为你可以使用浏览器达到同样目的。

你可以使用下面的URL来测试已经添加的不同的action, 编辑和保存一个用户。

· 添加 - http://localhost:8080/appfuse/editPerson.html

· 修改 - http://localhost:8080/appfuse/editPerson.html?id=1 (确信你已经首先运行了ant db-load)。

· 删除 - http://localhost:8080/appfuse/editPerson.html?method=Delete&id=1 (or edit and click on the Delete button)。

· 保存 – 单击 edit ,然后单击Save按钮。

Canoo测试相当平滑,配置它们在XML文件中十分简单。我们现在要为add, edit, save和delete添加测试用例,打开test/web/web-tests.xml,然后添加下面的XML。你将会注意到这个片断有一个叫PersonTests的任务,它运行所有相关的测试。

I use CamelCase target names (vs. the traditional lowercase, dash-separated) because when you're typing -Dtestcase=Name, I've found that I'm used to doing CamelCase for my JUnit Tests.

<table class=MsoNormalTable style="BACKGROUND: white; WIDTH: 100%; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt; mso-cellspacing: 0cm" cellSpacing=0 cellPadding=0 width="100%" border=0> <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes"> <td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent" vAlign=top noWrap>

添加完这些后,当Tomcat运行时,你应该可以运行ant test-canoo -Dtestcase=PersonTests,或者,如果你想start/stop Tomcat,执行ant test-jsp -Dtestcase=PersonTests当所有Canoo tests被运行(包括PersonTests),添加它作为"run-all-tests"任务的一个必需的依赖。

你应该注意到如果使用Canoo,客户端没有日志,如果你想知道正在干什么,你可以添加下面的文字到每个任务的末端的之间。

srcFile="${test.dir}/data/web-tests-result.xml"/>

${web-tests.result}

BUILD SUCCESSFUL
Total time: 11 seconds


下一步: Part IV: 添加校验和菜单 – 为 personForm添加校验逻辑,使firstName和lastName是必填字段,并且添加一个屏幕列表数据库中所有人的记录.

↑返回目录
前一篇: 经过百般努力,终于用JSP写出FileUpload上传小程序
后一篇: jsp+mysql制作简单的留言板(1)