风行天下

JAVA太极
posts - 4, comments - 10, trackbacks - 0, articles - 55
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

appfuse1.6使用手册

Posted on 2005-08-11 15:19 风太少 阅读(224) 评论(0)  编辑  收藏

一、       开发环境设置

1、下载

1)        http://java.sun.com下载稳定版本的JDK

2)        http://java.sun.com下载稳定版本的J2EESDK

3)        http://ant.apache.org 下载1.6版本的ant工具。

4)        http://www.mysql.com 下载MySQL数据库。

2、安装

创建 Tools SDKs 目录在windows下如:c:\Tools  c:\SDKs*nix下,如:/opt/dev/tools  opt/dev/sdks

1)        创建环境变量 SDKS_HOME TOOLS_HOME

2)        安装tomcat Tools目录

3)        安装antTools目录

4)        安装MySQLTools目录

5)        创建Source目录,用来放置工程源码。如果在*nix系统下,则创建/dev到你的/home

一般如下图:

SDKs -
    - j2sdk-1.4.2_05
Tools - 
    - apache-ant-1.6.2
    - jakarta-tomcat-5.0.28
    - mysql
Source

 

3、配置

设置一下环境变量

l         HOME = c:\Source

l         SDKS_HOME = c:\SDKs

l         TOOLS_HOME = c:\Tools

l         JAVA_HOME = %SDKS_HOME%\j2sdk-1.4.2_05

l         ANT_HOME = %TOOLS_HOME%\apache-ant-1.6.2

l         CATALINA_HOME = %TOOLS_HOME%\jakarta-tomcat-5.0.28

l         MYSQL_HOME = %TOOLS_HOME%\mysql

l         PATH: %JAVA_HOME%\bin;%ANT_HOME%\bin;%CATALINA_HOME%\bin;%MYSQL_HOME%\bin

一、       开发流程

1、创建DAO和数据映射对象

主要任务:

[1] 创建一个新对象并且加入XDoclet标签

[2] 利用ant从该对象建立一个数据库表

[3] 创建一个DAOTest,运行JUnit来测试DAO

[4] 创建一个DAO,实现对该对象的CRUD(添加、删除、更新)操作

[5] Spring中配置Person object PersonDAO

[6] 运行DAOTest

首先我们需要创建一个Person对象。


package org.appfuse.model;

public class Person extends BaseObject {
  private Long id;
  private String firstName;
  private String lastName;

    /*
     Generate your getters and setters using your favorite IDE: 
     In Eclipse:
     Right-click -> Source -> Generate Getters and Setters
    */
}

这个类扩展基类BaseObject。基类具备equals(), hashCode() toString() 三个方法,hibernate组件需要使用这些方法。

创建以后,我们需要添加XDoclet标签来生成Hibernate Map FileHibernate map object – tables --    columns

增加@hibernate.class 到代码


/**
 * @hibernate.class table="person"
 */
public class Person extends BaseObject {

增加XDoclet标签来生成主键


    /**
     @return Returns the id.
     * @hibernate.id column="id"
     *  generator-class="increment" unsaved-value="null"
     */

    public Long getId() {
        return this.id;
    }

利用antobject建立数据库表

利用命令 ant setup-db来建立数据库表。这个命令可以建立Person.hbm.xml文件和数据库表Person

[schemaexport] create table person (
[schemaexport]    id bigint not null,
[schemaexport]    primary key (id)
[schemaexport] );

Person.hbm.xml文件在build/dao/gen/**/hibernate 目录下可以找到。你可以在那里发现该文件内容为:


<?xml version="1.0"?>

<!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.appfuse.model.Person"
        table="person"
        dynamic-update="false"
        dynamic-insert="false"
    >

        <id
            name="id"
            column="id"
            type="java.lang.Long"
            unsaved-value="null"
        >
            <generator class="increment">
            </generator>
        </id>

        <!--
            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>

现在我们加入@hibernate.property属性,来生成数据表的列。


    /**
     * @hibernate.property column="first_name" length="50"
     */
    public String getFirstName() {
        return this.firstName;
    }

    /**
     * @hibernate.property column="last_name" length="50"
     */
    public String getLastName() {
        return this.lastName;
    }

运行 ant setup-db 命令来生成数据库

[schemaexport] create table person (
[schemaexport]    id bigint not null,
[schemaexport]    first_name varchar(50),
[schemaexport]    last_name varchar(50),
[schemaexport]    primary key (id)
[schemaexport] );

你可以通过修改property 的其他属性来订制列。

 

由于采用测试驱动开发方法,所有下面首先建立 DAOTest。该测试类建立在test/dao/**/dao目录下。我们采用Spring框架来组装DAO


package org.appfuse.dao;

import org.appfuse.model.Person;
import org.springframework.dao.DataAccessException;

public class PersonDAOTest extends BaseDAOTestCase {
    
    private Person person = null;
    private PersonDAO dao = null;

    protected void setUp() throws Exception {
        super.setUp();
        dao = (PersonDAO) ctx.getBean("personDAO");
    }

    protected void tearDown() throws Exception {
        super.tearDown();
        dao = null;
    }
}

该测试类扩展了BaseDAOTestCase类,具备了初始化方法。并且从SpringApplicationContext中得到类实例。

下面给这个测试类添加CRUDcreate, retrieve, update, delete)方法。代码如下:


    public void testGetPerson() throws Exception {
        person = new Person();
        person.setFirstName("Matt");
        person.setLastName("Raible");

        dao.savePerson(person);
        assertNotNull(person.getId());

        person = dao.getPerson(person.getId());
        assertEquals(person.getFirstName(), "Matt");
    }

    public void testSavePerson() throws Exception {
        person = dao.getPerson(new Long(1));
        person.setFirstName("Matt");

        person.setLastName("Last Name Updated");

        dao.savePerson(person);

        if (log.isDebugEnabled()) {
            log.debug("updated Person: " + person);
        }

        assertEquals(person.getLastName(), "Last Name Updated");
    }

    public void testAddAndRemovePerson() throws Exception {
        person = new Person();
        person.setFirstName("Bill");
        person.setLastName("Joy");

        dao.savePerson(person);

        assertEquals(person.getFirstName(), "Bill");
        assertNotNull(person.getId());

        if (log.isDebugEnabled()) {
            log.debug("removing person...");
        }

        dao.removePerson(person.getId());

        try {
            person = dao.getPerson(person.getId());
            fail("Person found in database");
        catch (DataAccessException dae) {
            log.debug("Expected exception: " + dae.getMessage());
            assertNotNull(dae);
        }
    }

在测试时,有时会需要一些初始数据,这些初始数据可以在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>
</table>

 

建立DAO接口


package org.appfuse.dao;

import org.appfuse.model.Person;

public interface PersonDAO extends DAO {
    public Person getPerson(Long personId);
    public void savePerson(Person person);
    public void removePerson(Long personId);
}

建立HibernateDAO实现类


package org.appfuse.dao.hibernate;

import org.appfuse.model.Person;
import org.appfuse.dao.PersonDAO;
import org.springframework.orm.ObjectRetrievalFailureException;

public class PersonDAOHibernate extends BaseDAOHibernate implements PersonDAO {

    public Person getPerson(Long id) {
        Person person = (Person) getHibernateTemplate().get(Person.class, id);

        if (person == null) {
            throw new ObjectRetrievalFailureException(Person.class, id);   
        }

        return person;
    }

    public void savePerson(Person person) {
        getHibernateTemplate().saveOrUpdate(person);
    }

    public void removePerson(Long id) {
        // object must be loaded before it can be deleted
        getHibernateTemplate().delete(getPerson(id));
    }
}

使用ant compile-dao来编译DAO类,使用ant test-dao –Dtestcase=PersonDAO来进行DAO的测试。DAO接口建立在src/dao目录下,DAOHibernate实现类建立在src/dao/hibernate目录下。

 

Spring框架中配置Person类和PersonDAO

src/dao/**/dao/hibernate/applicationContext-hibernate.xml文件中进行如下配置:


<property name="mappingResources"
    <list> 
        <value>org/appfuse/model/Person.hbm.xml</value> 
        <value>org/appfuse/model/Role.hbm.xml</value> 
        <value>org/appfuse/model/User.hbm.xml</value> 
        <value>org/appfuse/model/UserCookie.hbm.xml</value>  
    </list> 
</property> 

然后加入下列代码邦定Person.hbm.xmlPersonDAO对象。


<!-- PersonDAO: Hibernate implementation --> 
<bean id="personDAO" class="org.appfuse.dao.hibernate.PersonDAOHibernate"
    <property name="sessionFactory"><ref local="sessionFactory"/></property> 
</bean> 

如果为了简单你可以直接使用autowrie=”ByName”来直接生成xml文件中的内容。

 

现在运行测试可以得到正确的结果,那么你的DAOPerson对象创建成功!

2、创建服务

[1]创建一个新的ManagerTest

[2]创建一个新的Manager来调用DAO,处理业务逻辑

[3]Spring中配置服务和事物管理

[4]运行服务测试

 

在上面我们已经创建了PersonPersonDAO,现在我们需要在test/service/**/service目录下创建ManagerTestPersonManagerTest扩展BaseManagerTestCase类,在这个基类中实现了Spring配置文件的载入。

PersonManagerTest代码如下:


package org.appfuse.service;

import org.appfuse.model.Person;
import org.springframework.dao.DataAccessException;

public class PersonManagerTest extends BaseManagerTestCase {

    private Person person = null;
    private PersonManager mgr = null;

    protected void setUp() throws Exception {
        super.setUp();
        mgr = (PersonManager) ctx.getBean("personManager");
    }

    protected void tearDown() throws Exception {
        super.tearDown();
        mgr = null;
    }
}

然后加入具体的测试方法到PersonManagerTest类中:


    public void testGetPerson() throws Exception {
        person = mgr.getPerson("1");

        assertNotNull(person.getFirstName());
    }

    public void testSavePerson() throws Exception {
        person = mgr.getPerson("1");
        person.setFirstName("test");

        mgr.savePerson(person);
        assertEquals(person.getFirstName(), "test");
    }

    public void testAddAndRemovePerson() throws Exception {
        person = new Person();
        person = (Person) populate(person);

        mgr.savePerson(person);
        assertEquals(person.getFirstName(), "Bill");
        assertNotNull(person.getId());

        log.debug("removing person, personId: " + person.getId());

        mgr.removePerson(person.getId().toString());

        try {
            person = mgr.getPerson(person.getId().toString());
            fail("Person found in database");
        catch (DataAccessException dae) {
            log.debug("Expected exception: " + dae.getMessage());
            assertNotNull(dae);
        }
    }

下面创建一个PersonManager接口到src/service/**/service目录下。


package org.appfuse.service;

import org.appfuse.model.Person;

public interface PersonManager {
    public Person getPerson(String id);
    public void savePerson(Person person);
    public void removePerson(String id);
}

接着创建一个PersonManager的实现类PersonManagerImplsrc/service/**/service/impl目录下:


package org.appfuse.service.impl;

import org.appfuse.model.Person;
import org.appfuse.dao.PersonDAO;
import org.appfuse.service.PersonManager;

public class PersonManagerImpl extends BaseManager implements PersonManager {
    private PersonDAO dao;

    public void setPersonDAO(PersonDAO dao) {
        this.dao = dao;
    }

    public Person getPerson(String id) {
        return dao.getPerson(Long.valueOf(id));
    }

    public Person savePerson(Person person) {
        dao.savePerson(person);
    }

    public void removePerson(String id) {
        dao.removePerson(Long.valueOf(id));
    }
}

在上面代码中PersonDAO通过Spring框架中的配置来实例化。现在可以使用ant compile-service命令来编译服务对象。

 

Spring中配置服务和事务管理

src/service/**/service/applicationContext-service.xml文件中加入以下代码来注册服务:


    <bean id="personManager" parent="txProxyTemplate">
        <property name="target">
            <bean class="org.appfuse.service.impl.PersonManagerImpl" autowire="byName"/>
        </property>
    </bean>

Parent属性的定义参考TransactionProxyFactoryBean

3、创建ActionJSP页面

在这里我们使用Struts作为WEB框架,当然可以使用Spring MVC以及WebWork2来作为WEB层框架。

主要任务:

[1]XDoclet标签到Person类中,这样可以方便的生成PersonForm

[2]使用XDoclet来创建JSP页面的主要代码。

[3]创建Action的测试以及Action

[4]运行Action测试

[5]修改JSP页面,使其可以运行

 

我们现在通过在Person对象的代码中添加XDoclet来方便的生成PersonForm对象,以便在Struts当中使用。


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

在这里我们让PersonForm对象扩展BaseForm对象。

 

下面我们生成主要的JSP页面代码。

利用ant compile命令来编译Person类。这样就可以生成PersonForm类。

进入extras/viewgen目录下,运行命令 ant –Dform.name=PersonForm来生成主要的JSP代码。这是你可以在extras/viewgen/build目录下看到如下文件:

PersonForm.property(主要元素的Label)

PersonForm.jsp(表单页面)

PersonFormList.jsp(列表页面)

Copy PersonForm.propertyweb/WEB-INF/classes/ApplicationResources_zh.property文件中。

Copy PersonForm.jspPersonFormList.jspweb/pages/目录下。

 

创建Action测试类:

我们利用StrutsTestCase可以创建Action的测试类。


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();
    }
}

我们添加PERSON_KEYsrc/dao/**/Constants.java中,这个常量用来匹配formStruts配置文件中的名称。


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

接下来,我们在src/web/**/action目录中创建Action


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");
        }
    }
}

在这里有时需要进行PersonPersonForm的转换,你可以使用ConvertUtil.convert() 或者 BeanUtils.copyProperties

现在我们在Action文件的头部加入XDoclet标签,这样可以自动的生成Struts配置文件。


/**
 * @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 {

在程序中可能还会需要在页面上显示其他的文字信息,那么这些信息应该加入到资源文件当中,例如:

person.added=Information for <strong>{0}</strong> has been added successfully.
person.deleted=Information for <strong>{0}</strong> has been deleted successfully.
person.updated=Information for <strong>{0}</strong> has been updated successfully.

 

现在可以运行Action的测试了。

 

如果Action测试运行成功,那么你可以修改JSP页面,使它符合你对界面的要求。

4、添加验证和列表页面

主要任务:

[1]添加验证标记到Person类中

[2]查看添加验证后的JSP页面,并且测试

[3]添加testGetPeople方法到DAOManager测试中

[4]添加testSerach方法到Action测试中

[5]Action中添加Serach方法

[6]创建personFormList.jsp页面

[7]在菜单中添加链接

 

Struts当中使用验证通常是将验证写到vaildtion.xml文件中,但是这样配置比较麻烦。我们现在使用XDoclet来自动生成这个验证配置文件。

Person对象当中需要验证的字段的GET方法前加入验证标签,如下:


    /**
     * @struts.validator type="required"
     * @hibernate.property column="first_name" length="50"
     */
    public String getFirstName() {
        return this.firstName;
    }

    /**
     * @struts.validator type="required" 
     * @hibernate.property column="last_name" length="50"
     */
    public String getLastName() {
        return this.lastName;
    }

当然,你还可以加入很多自定义的验证规则,或者使用msgkey


@struts.validator type="required" msgkey="errors.required"

现在,你可以保存Person.java文件,然后运行 ant clean webdoclet命令来生成验证文件。

生成后的验证文件如下:


      <form name="personForm">
              <field property="firstName"
                     depends="required">

                  <arg0 key="personForm.firstName"/>
              </field>
              <field property="lastName"
                     depends="required">

                  <arg0 key="personForm.lastName"/>
              </field>
      </form>

而在jsp文件中,你可以看到如下的客户端验证代码:

<html:javascript formName="personForm" cdata="false"
    dynamicJavascript="true" staticJavascript="false"/>
<script type="text/javascript" 
    src="<html:rewrite page="/scripts/validator.jsp"/>"></script>

如果你希望使用服务器端验证方法,那么可以将上面的代码删除掉。

使用客户端验证的效果:

使用服务器端验证的效果:

testGetPeople方法到PersonDAOPersonManager测试方法当中。

打开PersonDAOTest.java文件,加入以下代码:


    public void testGetPeople() {
        person = new Person();
        List results = dao.getPeople(person);
        assertTrue(results.size() > 0);
    }

打开PersonManagerTest.java文件,加入以下代码:


    public void testGetPeople() {
        List results = mgr.getPeople(new Person());
        assertTrue(results.size() > 0);
    }

 

现在需要在DAO当中实现这样的方法:


    public List getPeople(Person person);

 

PersonManager中实现这样的方法:


    public List getPeople(Person person) {
        return getHibernateTemplate().find("from Person");
    }

在这里你可以看到区别。如果直接使用Hibernate的话,那么实现这样的一个功能至少需要有以下的代码:


    Example example = Example.create(person)
                             .excludeZeroes()    // exclude zero valued properties
                             .ignoreCase();      // perform case insensitive string comparisons
    try {
        return getSession().createCriteria(Person.class)
                           .add(example)
                           .list();
    catch (Exception e) {
        throw new DataAccessException(e.getMessage());
    }
    return new ArrayList();

而现在代码的数量减少了很多。只有下面的一句就可以。


    public List getPeople(Person person) {
        return dao.getPeople(person);
    }

在完成上述操作之后,我们可以运行下面的语言来进行编译和测试:

*       ant test-dao -Dtestcase=PersonDAO

*       ant test-service -Dtestcase=PersonManager

 

添加testSerach方法到Action的测试类中。

打开personActionTest.java加入下列代码:


    public void testSearch() {
        setRequestPathInfo("/editPerson");
        addRequestParameter("method""Search");
        actionPerform();



        verifyForward("list");

        assertNotNull(getRequest().getAttribute(Constants.PERSON_LIST));
        verifyNoActionErrors();
    }

现在这个类还无法被编译,因为你没有将PERSON_LIST加入到Constants.java文件中。


    /**
     * The request scope attribute that holds the person list
     */
    public static final String PERSON_LIST = "personList";

下面在Action中加入Serach方法。


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

        PersonManager mgr = (PersonManager) getBean("personManager");
        List people = mgr.getPeople(null);
        request.setAttribute(Constants.PERSON_LIST, people);

        // return a forward to the person list definition
        return mapping.findForward("list");
    }

然后运行命令ant test-web -Dtestcase=PersonAction来进行测试。

 

建立列表页面。

将原来已经生成的PersonFormList.jsp拷贝到web/pages/目录下,修改其中的代码以便使其适合你的要求。

现在需要在metadata/web/global-forwards.xml文件中注册一个全局转向,以便能找到你的Action


        <forward name="editPerson" path="/editPerson.html"/>
        <forward name="viewPeople" path="/editPerson.html?action=Search"/>

 

完成以后,我们将这个功能加到菜单链接里面。

打开web/pages/mainMenu.jsp文件,加入下列代码:


    <li>
        <html:link forward="viewPeople">
            <fmt:message key="menu.viewPeople"/>
        </html:link>
    </li>

在上面代码中的menu.viewPeople是菜单项的名称,你需要在资源文件中加入这个名称的本地语言。

menu.viewPeople=查看人员

然后打开web/WEB-INF/menu-config.xml文件,加入这个菜单的配置。


<Menu name="PeopleMenu" title="menu.viewPeople" forward="viewPeople"/>

在页面上加入这个新的菜单。打开web/pages/menu.jsp


<%@ include file="/common/taglibs.jsp"%>

<div id="menu">
<menu:useMenuDisplayer name="ListMenu" permissions="rolesAdapter">
    <menu:displayMenu name="AdminMenu"/>
    <menu:displayMenu name="UserMenu"/>
    <menu:displayMenu name="PeopleMenu"/>
    <menu:displayMenu name="FileUpload"/>
    <menu:displayMenu name="FlushCache"/>
    <menu:displayMenu name="Clickstream"/>
</menu:useMenuDisplayer>
</div>

 

 

现在你可以通过运行ant clean deploy命令启动tomcat并且部署应用程序,这样你可以运行该程序。

4、添加验证和列表页面

主要任务:

[1]添加验证标记到Person类中

[2]查看添加验证后的JSP页面,并且测试

[3]添加testGetPeople方法到DAOManager测试中

[4]添加testSerach方法到Action测试中

[5]Action中添加Serach方法

[6]创建personFormList.jsp页面

[7]在菜单中添加链接

 

Struts当中使用验证通常是将验证写到vaildtion.xml文件中,但是这样配置比较麻烦。我们现在使用XDoclet来自动生成这个验证配置文件。

Person对象当中需要验证的字段的GET方法前加入验证标签,如下:


    /**
     * @struts.validator type="required"
     * @hibernate.property column="first_name" length="50"
     */
    public String getFirstName() {
        return this.firstName;
    }

    /**
     * @struts.validator type="required" 
     * @hibernate.property column="last_name" length="50"
     */
    public String getLastName() {
        return this.lastName;
    }

当然,你还可以加入很多自定义的验证规则,或者使用msgkey


@struts.validator type="required" msgkey="errors.required"

现在,你可以保存Person.java文件,然后运行 ant clean webdoclet命令来生成验证文件。

生成后的验证文件如下:


      <form name="personForm">
              <field property="firstName"
                     depends="required">

                  <arg0 key="personForm.firstName"/>
              </field>
              <field property="lastName"
                     depends="required">

                  <arg0 key="personForm.lastName"/>
              </field>
      </form>

而在jsp文件中,你可以看到如下的客户端验证代码:

<html:javascript formName="personForm" cdata="false"
    dynamicJavascript="true" staticJavascript="false"/>
<script type="text/javascript" 
    src="<html:rewrite page="/scripts/validator.jsp"/>"></script>

如果你希望使用服务器端验证方法,那么可以将上面的代码删除掉。

使用客户端验证的效果:

使用服务器端验证的效果:

testGetPeople方法到PersonDAOPersonManager测试方法当中。

打开PersonDAOTest.java文件,加入以下代码:


    public void testGetPeople() {
        person = new Person();
        List results = dao.getPeople(person);
        assertTrue(results.size() > 0);
    }

打开PersonManagerTest.java文件,加入以下代码:


    public void testGetPeople() {
        List results = mgr.getPeople(new Person());
        assertTrue(results.size() > 0);
    }

 

现在需要在DAO当中实现这样的方法:


    public List getPeople(Person person);

 

PersonManager中实现这样的方法:


    public List getPeople(Person person) {
        return getHibernateTemplate().find("from Person");
    }

在这里你可以看到区别。如果直接使用Hibernate的话,那么实现这样的一个功能至少需要有以下的代码:


    Example example = Example.create(person)
                             .excludeZeroes()    // exclude zero valued properties
                             .ignoreCase();      // perform case insensitive string comparisons
    try {
        return getSession().createCriteria(Person.class)
                           .add(example)
                           .list();
    catch (Exception e) {
        throw new DataAccessException(e.getMessage());
    }
    return new ArrayList();

而现在代码的数量减少了很多。只有下面的一句就可以。


    public List getPeople(Person person) {
        return dao.getPeople(person);
    }

在完成上述操作之后,我们可以运行下面的语言来进行编译和测试:

*       ant test-dao -Dtestcase=PersonDAO

*       ant test-service -Dtestcase=PersonManager

 

添加testSerach方法到Action的测试类中。

打开personActionTest.java加入下列代码:


    public void testSearch() {
        setRequestPathInfo("/editPerson");
        addRequestParameter("method""Search");
        actionPerform();



        verifyForward("list");

        assertNotNull(getRequest().getAttribute(Constants.PERSON_LIST));
        verifyNoActionErrors();
    }

现在这个类还无法被编译,因为你没有将PERSON_LIST加入到Constants.java文件中。


    /**
     * The request scope attribute that holds the person list
     */
    public static final String PERSON_LIST = "personList";

下面在Action中加入Serach方法。


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

        PersonManager mgr = (PersonManager) getBean("personManager");
        List people = mgr.getPeople(null);
        request.setAttribute(Constants.PERSON_LIST, people);

        // return a forward to the person list definition
        return mapping.findForward("list");
    }

然后运行命令ant test-web -Dtestcase=PersonAction来进行测试。

 

建立列表页面。

将原来已经生成的PersonFormList.jsp拷贝到web/pages/目录下,修改其中的代码以便使其适合你的要求。

现在需要在metadata/web/global-forwards.xml文件中注册一个全局转向,以便能找到你的Action


        <forward name="editPerson" path="/editPerson.html"/>
        <forward name="viewPeople" path="/editPerson.html?action=Search"/>

 

完成以后,我们将这个功能加到菜单链接里面。

打开web/pages/mainMenu.jsp文件,加入下列代码:


    <li>
        <html:link forward="viewPeople">
            <fmt:message key="menu.viewPeople"/>
        </html:link>
    </li>

在上面代码中的menu.viewPeople是菜单项的名称,你需要在资源文件中加入这个名称的本地语言。

menu.viewPeople=查看人员

然后打开web/WEB-INF/menu-config.xml文件,加入这个菜单的配置。


<Menu name="PeopleMenu" title="menu.viewPeople" forward="viewPeople"/>

在页面上加入这个新的菜单。打开web/pages/menu.jsp


<%@ include file="/common/taglibs.jsp"%>

<div id="menu">
<menu:useMenuDisplayer name="ListMenu" permissions="rolesAdapter">
    <menu:displayMenu name="AdminMenu"/>
    <menu:displayMenu name="UserMenu"/>
    <menu:displayMenu name="PeopleMenu"/>
    <menu:displayMenu name="FileUpload"/>
    <menu:displayMenu name="FlushCache"/>
    <menu:displayMenu name="Clickstream"/>
</menu:useMenuDisplayer>
</div>

 

 

现在你可以通过运行ant clean deploy命令启动tomcat并且部署应用程序,这样你可以运行该程序。


只有注册用户登录后才能发表评论。


网站导航: