struts2使用jpa[JPA(Java Persistence API)作为Java EE 5.0平台标准的ORM规范,将得到所有Java EE服务器的支持。]进行crud的一篇文章:

本文翻译自:http://cwiki.apache.org/S2WIKI/struts-2-spring-2-jpa-ajax.html

来 自Struts2 WiKi上的一篇文章,讲解如何在Eclipse + WTP中进行Spring2, Struts2, JPA的整合开发。很基础的说,希望对于想学习SSH的人能有一定的帮助。我在翻译的过程中,也尝试使用MyEclipse来进行整合开发。但由于水平有 限,翻译质量不敢恭维,有何错误地方,请尽量告知。谢谢!

晚上调试成功了,现在把几点需要注意的地方说一下!希望你也能顺利的通过调试,有什么问题欢迎大家一起讨论。

 

本指南演示了如何在Eclipse中配置Struts2,并让它与Spring2,Java Persistence API(使用Hibernate)和Struts2 Ajax 标签一起工作。

注意:按指南一步一步来需要Struts2.0.3或更高版本

 

Show me the code

你可以在 zipped Eclipse projectEclipse开发: Struts 2 + Spring 2 + JPA + AJAX_hibernate下载源代码,必需的依赖库在/WebContent/WEB-INF/lib目录下,需要导入到Eclipse中。


Prerequisites

 

Tomcat

首先要安装好Tomcat,如果在安装的时候遇到任何问题,请查看Tomcat的安装指南

 

MySql

安装并配置MySQL。创建一个名为“quickstart”的数据库,并运行下面脚本来创建“Person”表。后面在applicationContext.xml里,我们将使用"root"数据库用户名和密码,记得用你自己的数据库设置来替换它们。


CREATE
      
       
      
      TABLE
      
       
      
      '
      
      quickstart
      
      '
      
      .
      
      '
      
      Person
      
      '
      
       (
  
      
      '
      
      id
      
      '
      
       
      
      INTEGER
      
       UNSIGNED 
      
      NOT
      
       
      
      NULL
      
       AUTO_INCREMENT,
  
      
      '
      
      firstName
      
      '
      
       
      
      VARCHAR
      
      (
      
      45
      
      ) 
      
      NOT
      
       
      
      NULL
      
      ,
  
      
      '
      
      lastName
      
      '
      
       
      
      VARCHAR
      
      (
      
      45
      
      ) 
      
      NOT
      
       
      
      NULL
      
      ,
  
      
      PRIMARY
      
       
      
      KEY
      
      (
      
      '
      
      id
      
      '
      
      )
)
ENGINE 
      
      =
      
       InnoDB;


 注:上面的DDL需要保存在文件中,然后在MySQL中导入。我直接复制然后在查询分析器中执行失败

创建Eclipse项目

  1. 打开Eclipse,我是认真的,你必须打开Eclipse
  2. 点击File -> New -> Project. 选择"Dynamic Web Project"并点击下一步(注:如果使用MyEclipse,这里不太一样)
  3. 输入项目名,这里我使用"quickstart"。这个项目将要在Tomcat中运行,所以我们需要为它创建应用服务器配置
  1. 在"Target Runtime"下面点击"New",选择"Apache Tomcat5.5"并点击下一步
  2. 输入Tomcat的安装路径并选择一下已安装的JRE(需要1.5)
  1. 现在你应该回到了项目创建向导,并且Tomcat是你的Target Runtime。点击下一步,选择"Dynamic Web Module"和"Java"facets,最后点"finish"。

(上面讲的都是Eclipse WTP中的配置,如果使用MyEclipse请自行修正)

 

库依赖关系

你 的项目应该包含"src","build"和"WebContent"目录。我们把所有必需的jar文件放在"/WebContent/WEB- INF/lib"目录下。请复制它们到${workspace}/quickstart/WebContent/WEB-INF/lib目录。jar文件 名的版本号已经被去除了!

Jar

From

xwork.jar

Struts 2

struts2-api.jar

Struts 2

struts2-core.jar

Struts 2

struts2-Spring-plugin.jar

Struts 2

ognl.jar

Struts 2

freemarker-2.3.4.jar

Struts 2

mysql-connector-java.jar

MySql JDBC Driver

spring.jar

Sping 2.0

antlr.jar

Hibernate Core

asm.jar

Hibernate Core

asm-attrs.jar

Hibernate Core

cglib.jar

Hibernate Core

dom4j.jar

Hibernate Core

jdbc2_0-stdext.jar

Hibernate Core

ehcache.jar

Hibernate Core

hibernate3.jar

Hibernate Core

xml-apis.jar

Hibernate Core

commons-collections.jar

Hibernate Core

ejb3-persistence.jar

Hibernate Annotations

jta.jar

Hibernate Annotations

hibernate-annotations.jar

Hibernate Annotations

hibernate-entitymanager.jar

Hibernate Entity Manager

javassist.jar

Hibernate Entity Manager

jboss-archive-browsing.jar

Hibernate Entity Manager

右击项目点“刷新”,通知Eclipse我们加入了很多的jar文件。

我 使用Struts2.0.6, Spring2.0.3, Hibernate3.2。struts2-api.jar找不到,没有也可以运行成功;Hibernate Annotations和Hibernate Entity Manager需要在Hibernate的主页上下载,不包括在Core里面;另外jta.jar和javassist.jar在Hibernate Tools里面,同样要下载;最后,上面列表并缺少一个包,因为Hibernate3.2对此有一点小小的修改,你需要把Hibernate Annotations里面的hibernate-commons-annotations.jar拷贝进来。

 

领域模型

我们的领域模型只有一个简单的"Person"类,它包含少量的实例变量。

  1. 创建一个新类并命名为"Person",然后输入"quickstart.model"作为包名。
  2. 添加"id"(int), "firstName"(String)和"lastName"(String)三个实例变量,并为它们加上setter/getter方法。
  3. 为你的类加上"@Entity"annotation,给"id" 加上 "@Id"和"@GeneratedValue" 注解

你的类如下:


Person.java



package
      
       quickstart.model;


      
      import
      
       javax.persistence.Entity;

      
      import
      
       javax.persistence.GeneratedValue;

      
      import
      
       javax.persistence.Id;

@Entity

      
      public
      
       
      
      class
      
       Person {
    @Id
    @GeneratedValue
    
      
      private
      
       Integer id;
    
      
      private
      
       String lastName;
    
      
      private
      
       String firstName;

    
      
      public
      
       String getFirstName() {
        
      
      return
      
       firstName;
    }

    
      
      public
      
       
      
      void
      
       setFirstName(String firstName) {
        
      
      this
      
      .firstName 
      
      =
      
       firstName;
    }

    
      
      public
      
       String getLastName() {
        
      
      return
      
       lastName;
    }

    
      
      public
      
       
      
      void
      
       setLastName(String lastName) {
        
      
      this
      
      .lastName 
      
      =
      
       lastName;
    }

    
      
      public
      
       Integer getId() {
        
      
      return
      
       id;
    }

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


@Entity让JPA服务Provider知道这个类可以被持久化。@Id标识"id"域为这个类的主键,@GeneratedValue使id域被提供者(Hibernate)自动生成。类和实例变量默认都被映射到同名的表和列上,详细情况请查看JPA文档。

 

Person service.

我们现在来写对"Person"对象进行CRUD操作的类。

  1. 创建一个接口,命名为"PersonService",包名为"quickstart.service"

PersonService.java



package
      
       quickstart.service;


      
      import
      
       java.util.List;


      
      import
      
       quickstart.model.Person;


      
      public
      
       
      
      interface
      
       PersonService {
    
      
      public
      
       List
      
      <
      
      Person
      
      >
      
       findAll();

    
      
      public
      
       
      
      void
      
       save(Person person);

    
      
      public
      
       
      
      void
      
       remove(
      
      int
      
       id);

    
      
      public
      
       Person find(
      
      int
      
       id);
}


    

     2.  创建一个类,命名为"PersonServiceImpl",包名为"quickstart.service"


PersonServiceImpl.java


package 
    quickstart.service;

 
   import 
    java.util.List;

 
   import 
    javax.persistence.EntityManager;
 
   import 
    javax.persistence.PersistenceContext;
 
   import 
    javax.persistence.Query;

 
   import 
    org.springframework.transaction.annotation.Transactional;

 
   import 
    quickstart.model.Person;

@Transactional
 
   public 
     
   class 
    PersonServiceImpl  
   implements 
    PersonService {
     
   private 
    EntityManager em;

    @PersistenceContext
     
   public 
     
   void 
    setEntityManager(EntityManager em) {
         
   this 
   .em  
   = 
    em;
    }

    @SuppressWarnings( 
   " 
   unchecked 
   " 
   )
     
   public 
    List 
   < 
   Person 
   > 
    findAll() {
        Query query  
   = 
    getEntityManager().createQuery( 
   " 
   select p FROM Person p 
   " 
   );
         
   return 
    query.getResultList();
    }

     
   public 
     
   void 
    save(Person person) {
         
   if 
    (person.getId()  
   == 
     
   null 
   ) {
             
   // 
    new 
   
 
               em.persist(person);
        }  
   else 
    {
             
   // 
    update 
   
 
               em.merge(person);
        }
    }

     
   public 
     
   void 
    remove( 
   int 
    id) {
        Person person  
   = 
    find(id);
         
   if 
    (person  
   != 
     
   null 
   ) {
            em.remove(person);
        }
    }

     
   private 
    EntityManager getEntityManager() {
         
   return 
    em;
    }

     
   public 
    Person find( 
   int 
    id) {
         
   return 
    em.find(Person. 
   class 
   , id);
    }

}

@PersistenceContext 会让Spring在实例化的时候给服务注入一个EntityManager。@PersistenceContext注解可以放在实例变量,或者 setter方法前面。如果一个类被注解为@Transactional,Spring将会确保类的方法在运行在一个事务中。


JPA 配置

  1. 在"src"目录下创建一个"META-INF"目录
  2. 在"META-INF"目录下创建一个名为"persistence.xml"的文件。

persistence.xml



<
      
      persistence 
      
      xmlns
      
      ="http://java.sun.com/xml/ns/persistence"
      
      
    xmlns:xsi
      
      ="http://www.w3.org/2001/XMLSchema-instance"
      
      
    xsi:schemaLocation
      
      ="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
      
      
    version
      
      ="1.0"
      
      >
      
      
    
      
      <
      
      persistence-unit 
      
      name
      
      ="punit"
      
      >
      
      
    
      
      </
      
      persistence-unit
      
      >
      
      

      
      </
      
      persistence
      
      >


JPA configuration can be set on this file. On this example it will be empty because the datasource configuration will be on the Spring configuration file. JPA的配置信息可以在这个文件中设置。本例中该文件为空,因为数据源(datasource)配置放在Spring的配置文件中。

 

Spring

  1. 更新/WebContent/WEB-INF/web.xml文件为以下内容:

web.xml


 
 
 
  
    
<? 
    xml version="1.0" encoding="UTF-8" 
    ?> 
    
 
    < 
    web-app  
    id 
    ="person" 
     version 
    ="2.4" 
     xmlns 
    ="http://java.sun.com/xml/ns/j2ee" 
    
    xmlns:xsi 
    ="http://www.w3.org/2001/XMLSchema-instance" 
    
    xsi:schemaLocation 
    ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
    > 
    
     
    < 
    display-name 
    > 
    person 
    </ 
    display-name 
    > 
    
     
    < 
    filter 
    > 
    
         
    < 
    filter-name 
    > 
    struts2 
    </ 
    filter-name 
    > 
    
         
    < 
    filter-class 
    > 
    
            org.apache.struts2.dispatcher.FilterDispatcher
         
    </ 
    filter-class 
    > 
    
     
    </ 
    filter 
    > 
    

     
    < 
    filter-mapping 
    > 
    
         
    < 
    filter-name 
    > 
    struts2 
    </ 
    filter-name 
    > 
    
         
    < 
    url-pattern 
    > 
    /* 
    </ 
    url-pattern 
    > 
    
     
    </ 
    filter-mapping 
    > 
    


     
    < 
    welcome-file-list 
    > 
    
         
    < 
    welcome-file 
    > 
    index.jsp 
    </ 
    welcome-file 
    > 
    
     
    </ 
    welcome-file-list 
    > 
    

     
    < 
    listener 
    > 
    
         
    < 
    listener-class 
    > 
    
            org.springframework.web.context.ContextLoaderListener
         
    </ 
    listener-class 
    > 
    
     
    </ 
    listener 
    > 
    
 
    </ 
    web-app 
    >  

   这会使容器将所有请求转发给Struts的"FilterDispatcher"类。"index.jsp"被设为主页,Spring的"ContextLoaderListener"被配置为listener(监听器) 
 
 
1. 在/WebContent/WEB-INF目录下创建一个名为"applicationContext.xml"的文件,内容如下: 
   applicationContext.xml  
       
<?     xml versinotallow="1.0" encoding="UTF-8" 
    ?> 
    
     < 
    beans  
    xmlns 
    ="http://www.springframework.org/schema/beans" 
    
    xmlns:xsi     ="http://www.w3.org/2001/XMLSchema-instance" 
    
    xmlns:aop     ="http://www.springframework.org/schema/aop" 
    
    xmlns:tx     ="http://www.springframework.org/schema/tx" 
    
    xsi:schemaLocation     ="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"     > 
    

         < 
    bean
             class 
    ="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" 
      
    /> 
    

         < 
    bean  
    id 
    ="personService" 
     class 
    ="quickstart.service.PersonServiceImpl" 
      
    /> 
    

         < 
    bean  
    id 
    ="entityManagerFactory" 
    
        class     ="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
    > 
    
             < 
    property  
    name 
    ="dataSource" 
     ref 
    ="dataSource" 
      
    /> 
    
             < 
    property  
    name 
    ="jpaVendorAdapter" 
    > 
    
                 < 
    bean
                     class 
    ="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" 
    > 
    
                     < 
    property  
    name 
    ="database" 
     value 
    ="MYSQL" 
      
    /> 
    
                     < 
    property  
    name 
    ="showSql" 
     value 
    ="true" 
      
    /> 
    
                 </ 
    bean 
    > 
    
             </ 
    property 
    > 
    
         </ 
    bean 
    > 
    

         < 
    bean  
    id 
    ="dataSource" 
    
        class     ="org.springframework.jdbc.datasource.DriverManagerDataSource" 
    > 
    
             < 
    property  
    name 
    ="driverClassName" 
     value 
    ="com.mysql.jdbc.Driver" 
      
    /> 
    
             < 
    property  
    name 
    ="url" 
     value 
    ="jdbc:mysql://localhost/test" 
      
    /> 
    
             < 
    property  
    name 
    ="username" 
     value 
    ="root" 
      
    /> 
    
             < 
    property  
    name 
    ="password" 
     value 
    ="root" 
      
    /> 
    
         </ 
    bean 
    > 
    

         < 
    bean  
    id 
    ="transactionManager" 
    
        class     ="org.springframework.orm.jpa.JpaTransactionManager" 
    > 
    
             < 
    property  
    name 
    ="entityManagerFactory" 
     ref 
    ="entityManagerFactory" 
      
    /> 
    
         </ 
    bean 
    > 
    

         < 
    tx:annotation-driven  
    transaction-manager 
    ="transactionManager" 
      
    /> 
    

         < 
    bean  
    id 
    ="personAction" 
     scope 
    ="prototype" 
    
        class     ="quickstart.action.PersonAction" 
    > 
    
             < 
    constructor-arg  
    ref 
    ="personService" 
      
    /> 
    
         </ 
    bean 
    > 
    
     </ 
    beans 
    >

注 意"personAction"bean的"class"属性被设为Action类的名字,并且"personService"bean会作为参数传递到 action的构造器中。改变"dataSource"Bean的"url", "username"和"passwrod"属性为你数据库的值。更多beans设置的细节,请参看Spring的文档。"scope"是Spring2 新增的属性,它意味着Spring会在该类型的对象被请求时创建一个新的PersonAction对象。在Struts2里,一个新的action对象被 创建,用来为每个请求服务,这就是我们为什么需要scope="prototype"。


Struts

 现在我们需要创建一个简单的Struts action,它封装了PersonServices的方法。并且我们配置Struts使用Spring作为对象工厂。

  1. 打开新建类对话框,输入"PersonAction"作为类名,包名为"quickstart.action",内容如下:

PersonAction.java


package
      
       quickstart.action;


      
      import
      
       java.util.List;


      
      import
      
       quickstart.model.Person;

      
      import
      
       quickstart.service.PersonService;


      
      import
      
       com.opensymphony.xwork2.Action;

      
      import
      
       com.opensymphony.xwork2.Preparable;


      
      public
      
       
      
      class
      
       PersonAction 
      
      implements
      
       Preparable {
    
      
      private
      
       PersonService service;
    
      
      private
      
       List
      
      <
      
      Person
      
      >
      
       persons;
    
      
      private
      
       Person person;
    
      
      private
      
       Integer id;

    
      
      public
      
       PersonAction(PersonService service) {
        
      
      this
      
      .service 
      
      =
      
       service;
    }

    
      
      public
      
       String execute() {
        
      
      this
      
      .persons 
      
      =
      
       service.findAll();
        
      
      return
      
       Action.SUCCESS;
    }

    
      
      public
      
       String save() {
        
      
      this
      
      .service.save(person);
        
      
      this
      
      .person 
      
      =
      
       
      
      new
      
       Person();
        
      
      return
      
       execute();
    }

    
      
      public
      
       String remove() {
        service.remove(id);
        
      
      return
      
       execute();
    }

    
      
      public
      
       List
      
      <
      
      Person
      
      >
      
       getPersons() {
        
      
      return
      
       persons;
    }

    
      
      public
      
       Integer getId() {
        
      
      return
      
       id;
    }

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

    
      
      public
      
       
      
      void
      
       prepare() 
      
      throws
      
       Exception {
        
      
      if
      
       (id 
      
      !=
      
       
      
      null
      
      )
            person 
      
      =
      
       service.find(id);
    }

    
      
      public
      
       Person getPerson() {
        
      
      return
      
       person;
    }

    
      
      public
      
       
      
      void
      
       setPerson(Person person) {
        
      
      this
      
      .person 
      
      =
      
       person;
    }
}


看,我的action是一个简单的POJO!

"Preparable" 接口指示Struts去调用"prepare"方法,如果"PrepareInterceptor"被应用在action上(默认就是这样子的)。 action的构造器有一个"PersonService"参数,在action被实例化的时候Spring会负责注入。

 

  1. 在"src"目录下创建一个名为"struts.xml"的文件,内容如下:

struts.xml


<?
      
      xml version="1.0" encoding="UTF-8" 
      
      ?>
      
      

      
      <!
      
      DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd"
      
      >
      
      

      
      <
      
      struts
      
      >
      
      
    
      
      <
      
      constant 
      
      name
      
      ="struts.objectFactory"
      
       value
      
      ="spring"
      
       
      
      />
      
      
    
      
      <
      
      constant 
      
      name
      
      ="struts.devMode"
      
       value
      
      ="true"
      
       
      
      />
      
      

    
      
      <
      
      package 
      
      name
      
      ="person"
      
       extends
      
      ="struts-default"
      
      >
      
      

        
      
      <
      
      action 
      
      name
      
      ="list"
      
       method
      
      ="execute"
      
       class
      
      ="personAction"
      
      >
      
      
            
      
      <
      
      result
      
      >
      
      pages/list.jsp
      
      </
      
      result
      
      >
      
      
            
      
      <
      
      result 
      
      name
      
      ="input"
      
      >
      
      pages/list.jsp
      
      </
      
      result
      
      >
      
      
        
      
      </
      
      action
      
      >
      
      

        
      
      <
      
      action 
      
      name
      
      ="remove"
      
       class
      
      ="personAction"
      
       method
      
      ="remove"
      
      >
      
      
            
      
      <
      
      result
      
      >
      
      pages/list.jsp
      
      </
      
      result
      
      >
      
      
            
      
      <
      
      result 
      
      name
      
      ="input"
      
      >
      
      pages/list.jsp
      
      </
      
      result
      
      >
      
      
        
      
      </
      
      action
      
      >
      
      

        
      
      <
      
      action 
      
      name
      
      ="save"
      
       class
      
      ="personAction"
      
       method
      
      ="save"
      
      >
      
      
            
      
      <
      
      result
      
      >
      
      pages/list.jsp
      
      </
      
      result
      
      >
      
      
            
      
      <
      
      result 
      
      name
      
      ="input"
      
      >
      
      pages/list.jsp
      
      </
      
      result
      
      >
      
      
        
      
      </
      
      action
      
      >
      
      
    
      
      </
      
      package
      
      >
      
      


      
      </
      
      struts
      
      >


设 置"struts.objectFactory"为"spring"会强制Struts使用Spring来实例化action,并注入所有定义在 applicationContext.xml中的依赖关系。每个action别名的"class"属性被设置为"personAction",这也就是 我们在applicationContext.xml中定义的PersonAction bean。要让Struts与Spring一起工作,我们仅仅需要做上面这点事情。

 

页面设计

我们只有两个页面,"index.jsp"和"list.jsp"。"list.jsp"返回数据库中所有person的列表。我们把这个列表放到一个不同的页面上,是因为我们将要添加一点ajax来改进它。

  1.  在/WebContent/pages目录下创建一个名为"list.jsp" 的新文件,它的内容如下:

list.jsp


<%     @ taglib prefix     = 
    " 
    s 
    " 
     uri 
    = 
    " 
    /struts-tags 
    " 
    %> 
    

     <     p 
    > 
    Persons 
    </ 
    p 
    > 
    
     <     s:if  
    test 
    ="persons.size > 0" 
    > 
    
         <     table 
    > 
    
             <     s:iterator  
    value 
    ="persons" 
    > 
    
                 <     tr  
    id 
    ="row_<s:property value=" 
    id" 
    /> 
    ">
                     <     td 
    > 
    
                         <     s:property  
    value 
    ="firstName" 
      
    /> 
    
                     </     td 
    > 
    
                     <     td 
    > 
    
                         <     s:property  
    value 
    ="lastName" 
      
    /> 
    
                     </     td 
    > 
    
                     <     td 
    > 
    
                         <     s:url  
    id 
    ="removeUrl" 
     action 
    ="remove" 
    > 
    
                             <     s:param  
    name 
    ="id" 
     value 
    ="id" 
      
    /> 
    
                         </     s:url 
    > 
    
                         <     s:a  
    href 
    ="%{removeUrl}" 
     theme 
    ="ajax" 
     targets 
    ="persons" 
    > 
    Remove 
    </ 
    s:a 
    > 
    
                         <     s:a  
    id 
    ="a_%{id}" 
     theme 
    ="ajax" 
     notifyTopics 
    ="/edit" 
    > 
    Edit 
    </ 
    s:a 
    > 
    
                     </     td 
    > 
    
                 </     tr 
    > 
    
             </     s:iterator 
    > 
    
         </     table 
    > 
    
     </     s:if 
    >


上 面代码呈现了一个表格,每行代表一个Person,包含first name,last name,以及一个链接用来删除person,一个链接用来编辑person。删除链接有一个"targets"属性,设置为"persons",表示当 用户点击它时,一个异步的请求会被传递给"remove" action(struts.xml配置"remove"指向PersonAction的 remove方法),传递person  id作为参数。


注意list.jsp是在pages目录下,如果你放在其它目录,则需要相应修改struts.xml文件


当编辑链接被点击时,它会打开/edit主题,这将触发一个javascript函数来组装各个域。

  1. 在/WebContent目录下创建一个新文件"index.jsp",它的内容如下:

index.jsp

  
 
<%   @ taglib prefix   = 
  " 
  s 
  " 
   uri 
  = 
  " 
  /struts-tags 
  " 
  %> 
  
   <   html 
  > 
  
       <   head 
  > 
  
           <   s:head  
  theme 
  ="ajax" 
   debug 
  ="true" 
  /> 
  
           <   script  
  type 
  ="text/javascript" 
  > 
  
            dojo.event.topic.subscribe(   "   /save 
  " 
  ,  
  function 
  (data, type, request) {
                   if   (type  
  == 
    
  " 
  load 
  " 
  ) {
                    dojo.byId(   "   id 
  " 
  ).value  
  = 
    
  "" 
  ;
                    dojo.byId(   "   firstName 
  " 
  ).value  
  = 
    
  "" 
  ;
                    dojo.byId(   "   lastName 
  " 
  ).value  
  = 
    
  "" 
  ;
                }
            });

            dojo.event.topic.subscribe(   "   /edit 
  " 
  ,  
  function 
  (data, type, request) {
                   if   (type  
  == 
    
  " 
  before 
  " 
  ) {
                       var    id  
  = 
   data.split( 
  " 
  _ 
  " 
  )[ 
  1 
  ];

                       var    tr  
  = 
   dojo.byId( 
  " 
  row_ 
  " 
  + 
  id);
                       var    tds  
  = 
   tr.getElementsByTagName( 
  " 
  td 
  " 
  );

                    dojo.byId(   "   id 
  " 
  ).value  
  = 
   id;
                    dojo.byId(   "   firstName 
  " 
  ).value  
  = 
   dojo.string.trim(dojo.dom.textContent(tds[ 
  0 
  ]));
                    dojo.byId(   "   lastName 
  " 
  ).value  
  = 
   dojo.string.trim(dojo.dom.textContent(tds[ 
  1 
  ]));
                }
            });
           </   script 
  > 
  
       </   head 
  > 
  
       <   body 
  > 
  
           <   s:url  
  action 
  ="list" 
   id 
  ="descrsUrl" 
  /> 
  

           <   div  
  style 
  ="width: 300px;border-style: solid" 
  > 
  
               <   div  
  style 
  ="text-align: right;" 
  > 
  
                   <   s:a  
  theme 
  ="ajax" 
   notifyTopics 
  ="/refresh" 
  > 
  Refresh 
  </ 
  s:a 
  > 
  
               </   div 
  > 
  
               <   s:div  
  id 
  ="persons" 
   theme 
  ="ajax" 
   href 
  ="%{descrsUrl}" 
   loadingText 
  ="Loading..." 
   listenTopics 
  ="/refresh" 
  /> 
  
           </   div 
  > 
  

           <   br 
  /> 
  

           <   div  
  style 
  ="width: 300px;border-style: solid" 
  > 
  
               <   p 
  > 
  Person Data 
  </ 
  p 
  > 
  
               <   s:form  
  action 
  ="save" 
   validate 
  ="true" 
  > 
  
                   <   s:textfield  
  id 
  ="id" 
   name 
  ="person.id" 
   cssStyle 
  ="display:none" 
  /> 
  
                   <   s:textfield  
  id 
  ="firstName" 
   label 
  ="First Name" 
   name 
  ="person.firstName" 
  /> 
  
                   <   s:textfield  
  id 
  ="lastName" 
   label 
  ="Last Name" 
   name 
  ="person.lastName" 
  /> 
  
                   <   s:submit  
  theme 
  ="ajax" 
   targets 
  ="persons" 
   notifyTopics 
  ="/save" 
  /> 
  
               </   s:form 
  > 
  
           </   div 
  > 
  
       </   body 
  > 
  
   </   html 
  >

看,并没有页面刷新!

"personx" div会异步地装载它的内容,当请求被处理时显示"Loading..."提示(你可以使用"indicator"属性得到更佳的进度反馈),你可以通过 点击"Refresh"链接来强制页面进行刷新。"submit"按钮,向action "save"提交一个异步的请求(PersonAction的"save"方法)

 

Validation验证

我 们并不想我们的数据库存在任何的无名氏,所以我们给Form增加一点基本的客户端验证。在Struts2中,验证可以被放在xml文件里,命名模式为: ActionName-validation.xml,放在与action相同的包路径下。要给action的特定别名添加验证(比如方法), validation文件的命名必须为:ActionName-alias-validation.xml,这里的"alias"就是你的action的 别名(这里也就是方法名,如"save")。在src/quickstart/action目录下添加一个名为"PersonAction-save- validation.xml"文件,它的内容如下:


<!   DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
       "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"   >   
   <   validators 
  > 
  
       <   field  
  name 
  ="person.firstName" 
  > 
  
           <   field-validator  
  type 
  ="requiredstring" 
  > 
  
               <   message 
  > 
  First name is required! 
  </ 
  message 
  > 
  
           </   field-validator 
  > 
  
       </   field 
  > 
  
       <   field  
  name 
  ="person.lastName" 
  > 
  
           <   field-validator  
  type 
  ="requiredstring" 
  > 
  
               <   message 
  > 
  Last name is required! 
  </ 
  message 
  > 
  
           </   field-validator 
  > 
  
       </   field 
  > 
  
   </   validators 
  >


关于现有的validator,以及如何编写和插入你自己的validator,请查看Struts文档

要 运行项目,右击你的项目并选择Run AS -> Run on Server。你也可以通过相同的办法来调试它,右击项目 Debug As -> Debug on Server。下载并安装Struts 2的 showcase演示项目来查看更多的例子。

参考资料

StrutsEclipse开发: Struts 2 + Spring 2 + JPA + AJAX_hibernate

Spring JPA DocEclipse开发: Struts 2 + Spring 2 + JPA + AJAX_hibernate

JPA and Spring TutorialEclipse开发: Struts 2 + Spring 2 + JPA + AJAX_hibernate

Eclipse DaliEclipse开发: Struts 2 + Spring 2 + JPA + AJAX_hibernate