Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences


Referenced by
Articles
Articles_cn
Articles_pt
Articles_zh
CreateManager_zh
ValidationAndList_zh




JSPWiki v2.2.33

[RSS]


Hide Menu

CreateActions_zh


Difference between version 3 and version 2:

At line 152 added 321 lines.
你需要为src/dao/**/Constants.java添加__PERSON_KEY__变量,这个"personForm"与struts-config.xml中的名称相对应。
[{Java2HtmlPlugin
/**
* The request scope attribute that holds the person form.
*/
public static final String PERSON_KEY = "personForm";
}]
如果你尝试运行测试,你会得到几个NoSuchMethodErrors,所以,让我们定义PersonAction的edit、save和delete方法。
!!创建PersonAction [#4]
在src/web/**/action,创建PersonAction.java,有下面的内容:
[{Java2HtmlPlugin
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");
}
}
}
}]
你会注意到以上的代码有许多对''convert''的调用来转化PersonForm到Person,这个转化''convert''方法在BaseAction.java(调用ConvertUtil.convert())中,并且使用[BeanUtils.copyProperties|http://jakarta.apache.org/commons/beanutils/api/org/apache/commons/beanutils/BeanUtils.html#copyProperties(java.lang.Object,%20java.lang.Object)] 来实现POJOs → ActionForms和ActionForms → POJOs的转化。
;:''如果你运行Eclipse,你需要对project运行"refresh"来显示PersonForm,它在build/web/gen目录中,这个目录必须是project的源目录之一,这是Eclipse看到和导入PersonForm的唯一方式,因为它是通过XDoclet产生并且不在通常的源目录中,你可以在build/web/gen/org/appfuse/webapp/form/PersonForm.java找到它。''
;:''在[BaseAction|http://raibledesigns.com/downloads/apptracker/api/org/appfuse/webapp/action/BaseAction.java.html]里你可以定义自己的转换器(例如 [DateConverter|http://raibledesigns.com/downloads/apptracker/api/org/apptracker/util/DateConverter.java.html]),因此BeanUtils.copyProperties能够知道Strings → Objects的转化。如果你的POJOs存在Lists(例如 父子关系),你需要使用{{convertLists(java.lang.Object)}}方法手工完成这个转化。''
现在你需要添加''edit'' forward和''savePerson'' action-mapping,这两个早就在PersonActionTest中提到,为此,可以在PersonAction.java添加一些额外的XDoclet标签,在类的声明前面加入这些注释,你一定已经有了''editPerson'' action-mapping的XDoclet标签,我在这里展示你会在类中看到的所有的XDoclet标签。
[{Java2HtmlPlugin
/**
* @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 {
}]
action-mappings中''editPerson''和''savePerson''主要区别是''savePerson''的XDoclet标签的validation标记是true(见validation="true"),注意"input"属性必须指向到一个forward,而不是个路径(例如/editPerson.html),如果你希望edit同save一样是是用用save的路径也是可以的,只要确保validate="false",然后在你的"save"方法中,你可以执行form.validate()来处理错误。
你一定注意到了这里是用PersonManager的方式与PersonManagerTest中的一样,PersonAction和PersonManagerTest都是PersonManagerImpl的''客户'',这很有意义。
本教程几乎所有的事情都搞定了,让我们来运行这些测试!
!!运行PersonActionTest [#5]
如果你查看PersonActionTest,你会发现所有的测试依赖于数据库中一条id=1的记录(testRemove依赖于id=2),所以要添加那些样本数据(metadata/sql/sample-data.xml),我会添加到底部,顺序并不重要(目前),因为它们互相并不存在依赖关系。
{{{
<table name='person'>
<column>id</column>
<column>first_name</column>
<column>last_name</column>
<row>
<value>1</value>
<value>Matt</value>
<value>Raible</value>
</row>
<row>
<value>2</value>
<value>James</value>
<value>Davidson</value>
</row>
</table>
}}}
DBUnit&#20250;&#22312;&#25191;&#34892;&#27979;&#35797;&#21069;&#21152;&#36733;&#36825;&#20123;&#25968;&#25454;&#65292;&#25152;&#20197;&#36825;&#20123;&#35760;&#24405;PersonActionTest&#21487;&#20197;&#24471;&#21040;&#12290;
&#22914;&#26524;&#29616;&#22312;&#20320;&#25191;&#34892;__ant test-web -Dtestcase=PersonAction__ - &#25152;&#26377;&#20107;&#24773;&#20250;&#25353;&#35745;&#21010;&#25191;&#34892;&#65292;&#22312;&#20316;&#23581;&#35797;&#21069;&#35831;&#30830;&#23450;Tomcat&#24050;&#32463;&#36816;&#34892;&#12290;
%%(color:green)BUILD SUCCESSFUL\\
Total time: 1 minute 21 seconds%%
!!&#28165;&#29702;JSP&#26469;&#20351;&#23427;&#26356;&#22909;&#30475; [#6]
&#35753;&#25105;&#20204;&#24320;&#22987;&#28165;&#29702;personForm.jsp&#65292;&#20462;&#25913;&lt;html:form&gt;&#30340;''action''&#20026;"savePerson"&#65292;&#36825;&#20445;&#35777;&#39564;&#35777;&#36215;&#20316;&#29992;&#65292;&#21516;&#26102;&#20462;&#25913;''focus''&#23646;&#24615;&#65292;&#20174;focus=""&#25913;&#20026;focus="firstName"&#65292;&#36825;&#26679;&#22312;&#39029;&#38754;&#25171;&#24320;&#21518;&#20809;&#26631;&#20250;&#33853;&#21040;firstName&#23383;&#27573;(&#20351;&#29992;JavaScript)&#12290;
&#29616;&#22312;&#20320;&#22914;&#26524;&#25191;&#34892;__ant db-load deploy__&#65292;&#21551;&#21160;Tomcat&#65292;&#28982;&#21518;&#22312;&#20320;&#30340;&#27983;&#35272;&#22120;&#36755;&#20837;[http://localhost:8080/appfuse/editPerson.html?id=1]&#65292;&#20320;&#20250;&#30475;&#21040;&#22914;&#19979;&#20449;&#24687;&#65306;
%%(border: 1px solid black; margin: 0 auto; height: 166px; width: 337px)
[personForm-final.png]
%%
%%note __&#27880;&#24847;:&#22914;&#26524;&#20320;&#20462;&#25913;&#20102;''web''&#20013;&#30340;&#20219;&#20309;&#25991;&#20214;&#65292;&#35831;&#20351;&#29992;__deploy-web__&#65292;&#21542;&#21017;&#65292;&#20351;&#29992;__deploy__&#26469;&#32534;&#35793;&#21644;&#37096;&#32626;&#12290;%%
&#26368;&#21518;&#65292;&#20026;&#20102;&#20351;&#39029;&#38754;&#26356;&#21152;&#30340;&#29992;&#25143;&#21451;&#22909;&#65292;&#20320;&#20063;&#35768;&#24076;&#26395;&#20026;&#29992;&#25143;&#22312;form&#19978;&#38754;&#28155;&#21152;&#19968;&#27573;&#20449;&#24687;&#65292;&#21482;&#38656;&#22312;personForm.jsp&#39029;&#30340;&#39030;&#31471;&#28155;&#21152;(&#20351;&#29992; &lt;fmt:message&gt;)&#12290;
!![[&#21487;&#36873;&#30340;] &#21019;&#24314;Canoo WebTests&#26469;&#27979;&#35797;&#27169;&#25311;&#27983;&#35272;&#22120;&#30340;actions [#7]
&#26412;&#25945;&#31243;&#26368;&#21518;&#30340;&#27493;&#39588;(&#21487;&#36873;&#30340;)&#26159;&#21019;&#24314;[Canoo WebTest|http://webtest.canoo.com]&#26469;&#27979;&#35797;JSPs&#12290;
;:''&#25105;&#35828;&#26159;&#21487;&#36873;&#30340;&#65292;&#26159;&#22240;&#20026;&#20320;&#21487;&#20197;&#36890;&#36807;&#27983;&#35272;&#22120;&#36816;&#34892;&#21516;&#26679;&#30340;&#27979;&#35797;&#12290;''
&#20320;&#21487;&#20197;&#20351;&#29992;&#22914;&#19979;&#30340;URLs&#26469;&#27979;&#35797;&#19981;&#21516;actions&#30340;adding&#12289;editing&#21644;saving&#12290;
* Add - [http://localhost:8080/appfuse/editPerson.html].
* Edit - [http://localhost:8080/appfuse/editPerson.html?id=1] (make sure and run __ant db-load__ first).
* Delete - [http://localhost:8080/appfuse/editPerson.html?method=Delete&amp;id=1] (or edit and click on the Delete button).
* Save - Click [edit|http://localhost:8080/appfuse/editPerson.html?id=1] and then click the Save button.
Canoo&#27979;&#35797;&#38750;&#24120;&#30340;&#28789;&#27963;&#65292;&#21482;&#38656;&#35201;&#37197;&#32622;XML&#25991;&#20214;&#65292;&#20026;&#20102;&#27979;&#35797;add&#12289;edit&#12289;save&#21644;delete&#65292;&#25171;&#24320;test/web/web-tests.xml&#28155;&#21152;&#22914;&#19979;&#30340;XML&#65292;&#20320;&#19968;&#23450;&#27880;&#24847;&#21040;&#36825;&#20123;&#29255;&#26029;&#30340;target&#21517;&#31216;&#26159;''PersonTests''&#65292;&#20250;&#36816;&#34892;&#25152;&#26377;&#30456;&#20851;&#30340;&#27979;&#35797;&#12290;
;:''&#25105;&#20351;&#29992;CamelCase&#30340;target&#21629;&#21517;&#26041;&#24335;(vs. &#20256;&#32479;&#30340;&#23567;&#20889;&#65292;&#19979;&#21010;&#32447;&#20998;&#21106;&#30340;&#26041;&#24335;)&#26159;&#22240;&#20026;&#24403;&#25340;&#20889;''-Dtestcase=Name''&#26102;&#65292;&#25105;&#20250;&#32463;&#24120;&#20064;&#24815;&#20110;&#20351;&#29992;CamelCase&#26041;&#24335;&#26469;&#21629;&#21517;&#25105;&#30340;JUnit Tests&#12290;''
[{Java2HtmlPlugin
<!-- runs person-related tests -->
<target name="PersonTests"
depends="EditPerson,SavePerson,AddPerson,DeletePerson"
description="Call and executes all person test cases (targets)">
<echo>Successfully ran all Person JSP tests!</echo>
</target>
<!-- Verify the edit person screen displays without errors -->
<target name="EditPerson"
description="Tests editing an existing Person's information">
<webtest name="editPerson">
&config;
<steps>
&login;
<invoke description="click Edit Person link" url="/editPerson.html?id=1"/>
<verifytitle description="we should see the personDetail title"
text=".*${personDetail.title}.*" regex="true"/>
</steps>
</webtest>
</target>
<!-- Edit a person and then save -->
<target name="SavePerson"
description="Tests editing and saving a user">
<webtest name="savePerson">
&config;
<steps>
&login;
<invoke description="click Edit Person link" url="/editPerson.html?id=1"/>
<verifytitle description="we should see the personDetail title"
text=".*${personDetail.title}.*" regex="true"/>
<setinputfield description="set lastName" name="lastName" value="Canoo"/>
<clickbutton label="Save" description="Click Save"/>
<verifytitle description="Page re-appears if save successful"
text=".*${personDetail.title}.*" regex="true"/>
</steps>
</webtest>
</target>
<!-- Add a new Person -->
<target name="AddPerson"
description="Adds a new Person">
<webtest name="addPerson">
&config;
<steps>
&login;
<invoke description="click Add Button" url="/editPerson.html"/>
<verifytitle description="we should see the personDetail title"
text=".*${personDetail.title}.*" regex="true"/>
<setinputfield description="set firstName" name="firstName" value="Abbie"/>
<setinputfield description="set lastName" name="lastName" value="Raible"/>
<clickbutton label="${button.save}" description="Click button 'Save'"/>
<verifytitle description="Main Menu appears if save successful"
text=".*${mainMenu.title}.*" regex="true"/>
<verifytext description="verify success message"
text="Information for &lt;strong&gt;Abbie Raible&lt;/strong&gt; has been added successfully."/>
</steps>
</webtest>
</target>
<!-- Delete existing person -->
<target name="DeletePerson"
description="Deletes existing Person">
<webtest name="deletePerson">
&config;
<steps>
&login;
<invoke description="click Edit Person link" url="/editPerson.html?id=1"/>
<clickbutton label="${button.delete}" description="Click button 'Delete'"/>
<verifytitle description="display Main Menu" text=".*${mainMenu.title}.*" regex="true"/>
<verifytext description="verify success message"
text="Information for &lt;strong&gt;Matt Canoo&lt;/strong&gt; has been deleted successfully."/>
</steps>
</webtest>
</target>
}]
&#23436;&#25104;&#28155;&#21152;&#21518;&#65292;&#20320;&#19968;&#23450;&#21487;&#20197;&#22312;Tomcat&#36816;&#34892;&#26102;&#36816;&#34892;__ant test-canoo -Dtestcase=PersonTests__&#65292;&#25110;&#32773;&#20351;&#29992;__ant test-jsp -Dtestcase=PersonTests__&#35753;Ant&#20026;&#20320;&#21551;&#21160;/&#20851;&#38381;Tomcat&#65292;&#20026;&#20102;&#22312;&#25152;&#26377;&#30340;Canoo&#27979;&#35797;&#20013;&#21253;&#25324;PersonTests&#65292;&#25226;&#23427;&#20316;&#20026;"run-all-tests"&#30340;&#20381;&#36182;target&#12290;
&#20320;&#24517;&#39035;&#27880;&#24847;&#21040;Canoo&#27809;&#26377;&#23458;&#25143;&#31471;&#30340;&#26085;&#24535;&#65292;&#22914;&#26524;&#20320;&#26399;&#26395;&#30475;&#21040;&#19968;&#20123;&#20449;&#24687;&#65292;&#20320;&#21487;&#20197;&#22312;&#27599;&#19968;&#20010;target&#30340;&lt;/canoo&gt;&#21644;&lt;/target&gt;&#20043;&#38388;&#28155;&#21152;&#22914;&#19979;&#20195;&#30721;&#12290;
{{{<loadfile property="web-tests.result"
srcFile="${test.dir}/data/web-tests-result.xml"/>
<echo>${web-tests.result}</echo>}}}
%%(color:green)BUILD SUCCESSFUL\\
Total time: 11 seconds%%
----
''Next Up:'' __Part IV:__ [&#28155;&#21152;&#39564;&#35777;&#21644;&#21015;&#34920;&#39029;&#38754;|ValidationAndList] - &#32473;personForm&#30340;firstName&#21644;lastName&#23383;&#27573;&#28155;&#21152;&#24517;&#28155;&#30340;&#39564;&#35777;&#36923;&#36753;&#21644;&#26174;&#31034;person&#25152;&#26377;&#35760;&#24405;&#30340;&#39029;&#38754;&#12290;

Back to CreateActions_zh, or to the Page History.