Struts2,spring&JPA(Hibernate)的集成

 

12月26日

Struts2,spring&JPA(Hibernate)的集成

  Struts2,Spring和Hibernate都是大家很熟悉的框架了。三个框架各有所长,并且在各自擅长的领域都是比较优秀的。而将三者集成应用到web开发中,则是强强联合,极高的提高了软件开发生产率。

   Struts2,如其名所解,用于搭建基本的MVC2 web框架。它有两个比较大的好处,一是迫使开发人员遵循MVC这样的先进模式,使web application有一个清晰的架构。如下图所示(摘录至struts2 in action);

image

二是封装了servelt api, 从而自动化一些比较繁琐的工作,方便了开发人员,比如请求参数的类型转换等工作。如下图所示,

image

spring是一个比较大而全的框架,它也提供了MVC框架等丰富的功能。但是我们这里仅仅利用它的一个核心功能:dependency injection(即IOC,控制反转)

Hibernate是一个持久层框架,实现了ORM,即对象关系的映射。我们没用采用native hibernate api,而是遵循java规范,使用了Hibernate实现的JPA。这种做法虽然不能使用某些native hibernante的高级功能,但是提高了DAO层的移植性,即使采用其他的ORM框架,也可以快速配置。

三者的集成还是有点麻烦,让初学者有点畏惧。所以现在就把个人的一点集成经验总结一下。struts2的配置当然还是主体,当某些地方用到依赖注入,以及设计持久层时,我们还需要配置其它的两个框架。

注意点1:在WEB-INF/lib中加入正确的jar包。这些包若未正确加载,在后续启动服务器运行web application时就会在console中看见许多ClassNotFoundException,

image

注意点2:web.xml文件,其实只要用servlet来做web application,都要配置这个文件的,大家一定不会陌生。但是在集成这些框架时,要稍微修改一些地方。(在xml文件中我们用红色标注)

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

<!-- The web.xml, also known as the deployment descriptor, defines a Java Servlet web application.
         This document is a mandatory element of any web application and must reside within WEB-INF.  The
         deployment descriptor defines all the servlets and servlet filters that belong to this web
         application. -->

<web-app 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>S2 HelloWorld (XML Based)</display-name> 

<!--配置Spring框架,实质是配置了一个监听器-->  

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

<!--这里配置了一个特殊的过滤器,解决了Lazy Loading中才出现的一个烦人的问题,即EntityManager要及时关闭,但是关闭后就不能正常访问还未加载的对象实例了。--> 

    <filter>
        <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter> 

        <!-- Declaration of the Struts 2 filter.  Since our entire web application will be a Struts 2
                    application, we will not have any other servlets or filters.  Of course, real Struts 2
                    applications may also have other servlets or filters, but since we are doing only Struts 2
                    stuff in this example, we need only define the Struts 2 filter.  -->
 
  
          
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
   </filter>
 
    <filter-mapping>
        <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

<!-- The Struts 2 filter should be mapped to ALL requests coming into the web application.  As a filter,
                 it can let the non-struts requests pass through and they will arrive at which ever servlets to which
                 they may be mapped.  Of course, this sample app has no other servlets, so we expect the filter to catch
                 everything.  When the filter recognizes a Struts 2 request, typically by the .action extension, the
                 normal filter chaining of a web application is aborted and the request is completely handled by
                 the Struts 2 system. -->
       
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

注意点3:在WEB-INF中不光要配置web.xml,还需要配置使用Spring的一个重要xml文件:applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">

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

<bean id="userService" class="apress.lulu.service.UserServiceImpl" ></bean>

<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://127.0.0.1:3306/apress" />
    <property name="username" value="root" />
    <property name="password" value="198482" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

 

package apress.lulu.service;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Transactional;
import apress.lulu.model.User;

/*
* with the help of Hibernate3.2 , we can implement user service to query user info and
*  and to persist user info
*  user spring to manage EntityManager instance
*/

/*

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

*我们直接用@Transactional 就可以实现事务管理了,不用下面那么多代码了(绿色代码部分)

*/

@Transactional
public class UserServiceImpl implements UserService {
   // private EntityManagerFactory emf;
    private EntityManager em;

   // public UserServiceImpl() {
        //emf = Persistence.createEntityManagerFactory("s2app");
   // }

    public User findByEmail(String email) {
       // EntityManager entityMgr = emf.createEntityManager();
        return em.find(User.class,email);
    }

    public void persist(User user,String emailId) {

       // EntityManager entityMgr = emf.createEntityManager();
      //  EntityTransaction tx = null;
       // try {
         //   tx = entityMgr.getTransaction();
         //   tx.begin();

            if( "".equals(emailId) ) {
                em.persist(user);
            } else {
                em.merge(user);
            }

         //   tx.commit();
       // } catch (Exception e) {
       //     if ( tx != null && tx.isActive() )
       //         tx.rollback();
       //     throw (RuntimeException)e.getCause();
       // }

    }
   

//<bean

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

//正是有了这个bean的帮助,我们可以利用Spring来注入EntityManager instance
    @PersistenceContext 

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

注意点4 persistence.xml文件来配置JPA中的相关信息。

/WEB-INF/classes/META-INF/persistence.xml.下面的xml文件就是一个persisentce.xml文件,它配置了JPA的信息,但是由于引入了Spring框架类管理bean,所以我们的这个配置文件很少,许多持久化配置信息反映在applicationContext.xml中。但是这个文件又不能不写,若不写在启动tomcat服务器时会报错误,因此我们这里就简单的写一下。

<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="struts2InAction">
       <properties>

          <property name="hibernate.show_sql" value="true" />
          <property name="hibernate.hbm2ddl.auto" value="create"/>
       </properties>
   </persistence-unit>
</persistence>

特别注意这个属性

<properties>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>

其实这个参数(hibernate.hbm2ddl.auto)的作用主要用于:自动创建|更新|验证数据库表结构。如果不是此方面的需求建议设置 value="none".

其它几个参数的作用:

validate               加载hibernate时,验证创建数据库表结构
create                 每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因。一次看hibernate视频教程,授课老师就在这个地方出问题了,每次他一加载hibernate就会重新创建数据库表结构,数据库相关的数据就丢失了,搞得他很郁闷,大家要不注意,也会同样郁闷
create-drop         加载hibernate时创建,退出是删除表结构
update                加载hibernate自动更新数据库结构

完成这些XML文件的配置后根据需求设计action,POJO,DAO以及JSP后就完成了一个web application

 

发布了19 篇原创文章 · 获赞 4 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章