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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章