● AppFuse的AppGen工具为我们自动生成了大量的代码,现在对关键业务代码做以回顾
和总结
Ø 描述:
i) 表单提交后,struts将转动相应的action类。AppFuse中的Action执行方法选择是通过Struts的LookupDispatchAction实现的,虽然这样可以实现一个Action根据url参数处理多种方法,但可扩展型比较差,调试麻烦,实现复杂,有待改进的地方。
ii) 客户程序通过具体的PersonManager类访问业务信息,PersonManager类通过
Spring的依赖注入方法取得具体PersonManager实现类,在PersonManager实
现类中对输入参数进行一定的处理后,PersonManager类将具体的业务信息访
问方法委托给PersonDAOHibernate完成,PersonDAOHibernate也是利用Spring
的依赖注入方法根据特点接口取得的。在PersonDAOHibernate中利用
Hibernate具体的操作业务数据。
iii) Hibernate在进行基本的业务处理时,会需要POJO作为参数,如savePerson(final Person person),AppFuse提供了很好的工具ConvertUtil类,他提供的convert(Object o)方法可以方便的实现Struts FormBean到POJO或反向的转换。
Ø 基础代码 POJO :Person.java
/**
* @struts.form include-all="true" extends"BaseForm"
* @hibernate.class table="person"
*/
public class Person extends BaseObject
{
private Long id;
private String firstName;
private String lastName;
/**
* @hibernate.id column="id"
* generator-class="increment" unsaved-value="null"
*/
public Long getId() {
return id;
}
/**
* @struts.validator type="required"
* @hibernate.property column="first_name" length="50" not-null="true"
*/
public String getFirstName() {
return firstName;
}
/**
* @struts.validator type="required"
* @hibernate.property column="last_name" length="50" not-null="true"
*/
public String getLastName() {
return lastName;
}
public void setId(Long l) {
id = l;
}
public void setFirstName(String string) {
firstName = string;
}
public void setLastName(String string) {
lastName = string;
}
public boolean equals(Object o) {
return false;
}
public int hashCode() {
return 0;
}
public String toString() {
return null;
}
}
Ø 通过ant gen-forms自动生成的的struts form bean
/**
* Generated by XDoclet/actionform. This class can be further processed with XDoclet/webdoclet/strutsconfigxml and XDoclet/webdoclet/strutsvalidationxml.
*
* @struts.form name="personForm"
*/
public class PersonForm
extends org.apache.struts.action.ActionForm
implements java.io.Serializable
{
protected String id;
protected String firstName;
protected String lastName;
/** Default empty constructor. */
public PersonForm() {}
public String getId()
{
return this.id;
}
public void setId( String id )
{
this.id = id;
}
public String getFirstName()
{
return this.firstName;
}
/**
* @struts.validator type="required"
*/
public void setFirstName( String firstName )
{
this.firstName = firstName;
}
public String getLastName()
{
return this.lastName;
}
/**
* @struts.validator type="required"
*/
public void setLastName( String lastName )
{
this.lastName = lastName;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
}
}
Ø 自动生成的映射文件Person.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping
>
<class
name="org.dudu.model.Person"
table="person"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
optimistic-lock="version"
>
<id
name="id"
column="id"
type="java.lang.Long"
unsaved-value="null"
>
<generator class="increment">
<!--
To add non XDoclet generator parameters, create a file named
hibernate-generator-params-Person.xml
containing the additional parameters and place it in your merge dir.
-->
</generator>
</id>
<property
name="firstName"
type="java.lang.String"
update="true"
insert="true"
access="property"
column="first_name"
length="50"
not-null="true"
/>
<property
name="lastName"
type="java.lang.String"
update="true"
insert="true"
access="property"
column="last_name"
length="50"
not-null="true"
/>
<!--
To add non XDoclet property mappings, create a file named
hibernate-properties-Person.xml
containing the additional properties and place it in your merge dir.
-->
</class>
</hibernate-mapping>
Ø 自动生成的PersonDAO
public interface PersonDAO extends DAO {
public List getPersons(Person person);
public Person getPerson(final Long id);
public void savePerson(Person person);
public void removePerson(final Long id);
}
Ø 自动生成的PersonDAOHibernate
public class PersonDAOHibernate extends BaseDAOHibernate implements PersonDAO {
public List getPersons(Person person) {
return getHibernateTemplate().find("from Person");
}
public Person getPerson(final Long id) {
Person person = (Person) getHibernateTemplate().get(Person.class, id);
if (person == null) {
log.warn("uh oh, person with id '" + id + "' not found...");
throw new ObjectRetrievalFailureException(Person.class, id);
}
return person;
}
public void savePerson(final Person person) {
getHibernateTemplate().saveOrUpdate(person);
}
public void removePerson(final Long id) {
getHibernateTemplate().delete(getPerson(id));
}
}
Ø 自动生成PersonManager
public interface PersonManager extends Manager {
public void setPersonDAO(PersonDAO personDAO);
public List getPersons(Person person);
public Person getPerson(final String id);
public void savePerson(Person person);
public void removePerson(final String id);
}
Ø 自动生成PersonManagerImpl
public class PersonManagerImpl extends BaseManager implements PersonManager {
private PersonDAO dao;
//使用代理模式,传入PersonDAOHibernate,最后处理还是由PersonDAOHibernate完成
// 不过是在处理前进行参数加工.
public void setPersonDAO(PersonDAO dao) {
this.dao = dao;
}
public List getPersons(final Person person) {
return dao.getPersons(person);
}
public Person getPerson(final String id) {
return dao.getPerson(new Long(id));
}
public void savePerson(final Person person) {
dao.savePerson(person);
}
public void removePerson(final String id) {
dao.removePerson(new Long(id));
}
}
Ø 自动生成Struts PersonAction
/**
* Action class to handle CRUD on a Person object
*
* @struts.action name="personForm" path="/persons" scope="request"
* validate="false" parameter="method" input="mainMenu"
* @struts.action name="personForm" path="/editPerson" scope="request"
* validate="false" parameter="method" input="list"
* @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"
* @struts.action-forward name="list" path="/WEB-INF/pages/personList.jsp"
*/
public final class PersonAction extends BaseAction {
public ActionForward cancel(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
return search(mapping, form, request, response);
}
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
ActionMessages messages = new ActionMessages();
PersonForm personForm = (PersonForm) form;
PersonManager mgr = (PersonManager) getBean("personManager");
mgr.removePerson(personForm.getId());
messages.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("person.deleted"));
saveMessages(request.getSession(), messages);
return search(mapping, form, request, response);
}
public ActionForward edit(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
PersonForm personForm = (PersonForm) form;
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 {
ActionMessages messages = new ActionMessages();
PersonForm personForm = (PersonForm) form;
boolean isNew = ("".equals(personForm.getId()) || personForm.getId() == null);
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"));
// save messages in session to survive a redirect
saveMessages(request.getSession(), messages);
return search(mapping, form, request, response);
} else {
messages.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("person.updated"));
saveMessages(request, messages);
return mapping.findForward("edit");
}
}
public ActionForward search(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
PersonManager mgr = (PersonManager) getBean("personManager");
request.setAttribute(Constants.PERSON_LIST, mgr.getPersons(null));
return mapping.findForward("list");
}
public ActionForward unspecified(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
return search(mapping, form, request, response);
}
}
Ø 自动生成的PersonForm.jsp
<%@ include file="/common/taglibs.jsp"%>
<title><fmt:message key="personDetail.title"/></title>
<content tag="heading"><fmt:message key="personDetail.heading"/></content>
<html:form action="editPerson" method="post" styleId="personForm"
focus="" onsubmit="return validatePersonForm(this)">
<table class="detail">
<html:hidden property="id"/>
<tr>
<th>
<dudu:label key="personForm.firstName"/>
</th>
<td>
<html:text property="firstName" styleId="firstName"/>
<html:errors property="firstName"/>
</td>
</tr>
<tr>
<th>
<dudu:label key="personForm.lastName"/>
</th>
<td>
<html:text property="lastName" styleId="lastName"/>
<html:errors property="lastName"/>
</td>
</tr>
<tr>
<td></td>
<td class="buttonBar">
<html:submit styleClass="button" property="method" onclick="bCancel=false">
<fmt:message key="button.save"/>
</html:submit>
<html:submit styleClass="button" property="method"
onclick="bCancel=true; return confirmDelete('Person')">
<fmt:message key="button.delete"/>
</html:submit>
<html:cancel styleClass="button" property="method" onclick="bCancel=true">
<fmt:message key="button.cancel"/>
</html:cancel>
</td>
</tr>
</table>
</html:form>
<html:javascript formName="personForm" cdata="false"
dynamicJavascript="true" staticJavascript="false"/>
<script type="text/javascript"
src="<html:rewrite page="/scripts/validator.jsp"/>"></script>
Ø 自动生成的PersonList.jsp
<%@ include file="/common/taglibs.jsp"%>
<title><fmt:message key="personList.title"/></title>
<content tag="heading"><fmt:message key="personList.heading"/></content>
<c:set var="buttons">
<button type="button" style="margin-right: 5px"
onclick="location.href='<c:url value="/editPerson.html"/>'">
<fmt:message key="button.add"/>
</button>
<button type="button" onclick="location.href='<html:rewrite forward="mainMenu"/>'">
<fmt:message key="button.cancel"/>
</button>
</c:set>
<c:out value="${buttons}" escapeXml="false"/>
<display:table name="${personList}" cellspacing="0" cellpadding="0"
id="personList" pagesize="25" styleClass="list"
export="true" requestURI="">
<display:column property="id" sort="true" headerClass="sortable"
url="/editPerson.html" paramId="id" paramProperty="id"
titleKey="personForm.id"/>
<display:column property="firstName" sort="true" headerClass="sortable"
titleKey="personForm.firstName"/>
<display:column property="lastName" sort="true" headerClass="sortable"
titleKey="personForm.lastName"/>
<display:setProperty name="paging.banner.item_name" value="person"/>
<display:setProperty name="paging.banner.items_name" value="persons"/>
</display:table>
<c:out value="${buttons}" escapeXml="false"/>
<script type="text/javascript">
<!--
highlightTableRows("personList");
//-->
</script>
Ø 自动生成的对应的struts配置
<struts-config>
<form-beans>
<form-bean
name="personForm"
type="org.dudu.webapp.form.PersonForm"
/>
</form-beans>
<action-mappings>
<action
path="/persons"
type="org.dudu.webapp.action.PersonAction"
name="personForm"
scope="request"
input="mainMenu"
parameter="method"
unknown="false"
validate="false"
>
<forward
name="edit"
path="/WEB-INF/pages/personForm.jsp"
redirect="false"
/>
<forward
name="list"
path="/WEB-INF/pages/personList.jsp"
redirect="false"
/>
</action>
<action
path="/editPerson"
type="org.dudu.webapp.action.PersonAction"
name="personForm"
scope="request"
input="list"
parameter="method"
unknown="false"
validate="false"
>
<forward
name="edit"
path="/WEB-INF/pages/personForm.jsp"
redirect="false"
/>
<forward
name="list"
path="/WEB-INF/pages/personList.jsp"
redirect="false"
/>
</action>
<action
path="/savePerson"
type="org.dudu.webapp.action.PersonAction"
name="personForm"
scope="request"
input="edit"
parameter="method"
unknown="false"
validate="true"
>
<forward
name="edit"
path="/WEB-INF/pages/personForm.jsp"
redirect="false"
/>
<forward
name="list"
path="/WEB-INF/pages/personList.jsp"
redirect="false"
/>
</action>
</action-mappings>
</struts-config>
Ø AppFuse struts action的基类BaseAction
public class BaseAction extends LookupDispatchAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (isCancelled(request)) {
ActionForward af = cancelled(mapping, form, request, response);
if (af != null) {
return af;
}
}
MessageResources resources = getResources(request);
// Identify the localized message for the cancel button
String edit = resources.getMessage(Locale.ENGLISH,
"button.edit").toLowerCase();
String save = resources.getMessage(Locale.ENGLISH,
"button.save").toLowerCase();
String search = resources.getMessage(Locale.ENGLISH,
"button.search").toLowerCase();
String view = resources.getMessage(Locale.ENGLISH,
"button.view").toLowerCase();
String[] rules = {edit, save, search, view};
String parameter = mapping.getParameter();
String keyName = null;
if (parameter != null) {
keyName = request.getParameter(parameter);
}
String path="";
//选择具体执行的方法名称
//如果url没有参数,默认执行Action中的edit方法
if ((keyName == null) || (keyName.length() == 0)) {
for (int i = 0; i < rules.length; i++) {
if (request.getServletPath().indexOf(rules[i]) > -1) {
path = request.getServletPath();
return dispatchMethod(mapping, form, request, response, rules[i]);
}
}
return this.unspecified(mapping, form, request, response);
}
String methodName =
getMethodName(mapping, form, request, response, parameter);
return dispatchMethod(mapping, form, request, response, methodName);
}
… …
}