Maven 整合 SSH 框架

     前面的一系列文章中,我們總結了三大框架:Struts2,Hibernate,Spring 的基本知識。本篇就姑且嘗試着使用 Maven 這個項目構建工具來將這三個框架整合一起。說到這裏,如果有對 Maven 還不熟悉的同學,此處推薦下面兩個鏈接快速瞭解下,記得回來!

Maven 是什麼?
如何給小白說明 Maven 是什麼?

我對 Maven 的理解就是,它是一個工具能提供兩大主要功能,其一是依賴管理,其二是項目構建。

所謂的依賴管理就是指,我們對於框架中的 jar 包從此不需要手動的添加到項目中來,而是使用 Maven 的語法進行引用,當然在打包發佈的時候,這些包還是會被加入進來,但是在我們的源代碼中就不存在任何的 jar 包,整個項目輕量可移植性強。

而所謂的項目構建指的是,對項目進行編譯,測試,打包,發佈等。原先我們是通過 IDE 來完成這樣的工作,但是不同的 IDE 有不同的使用操作,但是如果你是 Maven 項目的話,無論你在哪種 IDE 中編碼,都可以使用相同的 Maven 命令進行上述的幾種操作,這其實在一定程度上減少了我們對 IDE 的依賴。

上述我們簡單介紹了 Maven 這個項目管理工具,具體深入的學習不是本篇的重點,本篇着重完成對 SSH 框架整合的一個操作,主要涉及以下內容:

  • 分別配置各個框架的運行環境
  • 瞭解整個 Web 項目配置文件的加載順序
  • Spring 整合 Struts2
  • Spring 整合 Hibernate
  • 創建Action,Service,Dao 模擬登錄過程
  • 項目的模塊分離與再聚合

一、分別配置各個框架的運行環境

首先,我們先將三個框架各自的運行環境都配置到我們的 web 項目中。

創建一個 Maven 的 web 工程,基本的目錄結構大致是這樣的:

web 項目的基本目錄結構

然後我們先來配置 struts2 的運行環境。
第一步,pom.xml 中依賴 struts2 的核心包:

<dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts2-core</artifactId>
   <version>2.3.32</version>
</dependency>

由於 Maven 會自動引入該核心包所依賴的其他 jar 包,所以我們無需在手動依賴其他任何 jar 包。

第二步,web.xml 中配置核心過濾器:

<!--配置Struts的核心過濾器-->
<filter>
  <filter-name>struts</filter-name>
  <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class></filter>

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

第三步,創建 struts.xml 用於配置控制器 Action。

至此,struts2 的運行環境已經配置完成,下面我們看 Hibernate 運行環境的配置。
第一步,依賴相關的 jar 包,我們看看 Hibernate 需要依賴哪些 jar 包?

//mysql 驅動的依賴
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>6.0.6</version>
</dependency>
//Hibernate 核心包依賴
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>4.3.11.Final</version>
</dependency>

同樣,hibernate 核心包需要依賴的其他 jar 包,Maven 會爲我們自動查詢並引入。

第二步,創建 Hibernate 核心配置文件 hibernate.cfg.xml 並完成基本信息的配置。

這裏寫圖片描述

需要說明一點的是,爲了簡單起見,這裏我們並沒有使用數據源進行數據庫的連接,等到與 Spring 整合的時候會使用數據源配置數據庫連接。

至此,Hibernate 的基本環境也已經配置完成,下面我們看 Spring 的環境配置。

第一步,引入 Spring 相關依賴:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.0.0.RELEASE</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>4.0.0.RELEASE</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-expression</artifactId>
  <version>4.0.0.RELEASE</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.0.0.RELEASE</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>4.0.0.RELEASE</version>
</dependency>

第二步,創建 Spring 核心配置文件 applicationContext.xml 。

第三步,web.xml 中創建 Spring 的配置文件加載 Listener,它的具體作用我們下一小節進行介紹。

<!--配置Spring監聽器-->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListene</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

這樣,三個框架各自的運行環境就已經創建完成了,但是顯然它們現在是不能整合共同工作的。整個項目的目錄結構如下:

這裏寫圖片描述

二、瞭解整個 Web 項目配置文件的加載順序

如果上述操作無誤的話,現在我們的 web.xml 配置文件中起碼應該是這樣的:

這裏寫圖片描述

當整個 web 應用啓動時,首先會去加載 web.xml ,其中會啓動 struts 的核心過濾器,然後我們的 Spring 監聽器監聽到 web 容器啓動後,會根據 ServletContext 中保存的我們的配置參數信息去加載 Spring 的配置文件。而一般來說,Spring 整合 Hibernate 之後,Spring 的配置文件中會指明去加載 Hibernate 的配置文件,更具體的我們下文會詳細介紹,此處只需要瞭解 Spring 配置文件中會去加載 Hibernate 的核心配置文件。

那麼,這樣的話,我們三個框架的核心配置文件已經能夠按順序加載了。下面我們兩兩整合框架,先進行 Spring 與 Struts2 的整合。

三、Spring 整合 Struts2

Spring 與 Struts2 整合的核心點在於,將 Struts2 的 Action 交由 Spring 的 IOC 容器來創建。我們先創建一個 Action,

//index.jsp
<body>
    <form action="login" method="post">
        姓名:<input type="text" name="name" /><br/>
        <input type="submit" value="提交" />
    </form>
</body>
public class LoginAction extends ActionSupport {

    private String name;
    //省略getter,setter方法
    public String execute(){
        if("single".equals(this.name)){
            return SUCCESS;
        }else{
            return ERROR;
        }
    }
}

Spring 中配置該 Action 的實例信息:

<bean id="login_action" class="Actions.LoginAction" scope="prototype">

</bean>

接下來在 struts.xml 中引用該 bean 即可。

<package name="myPackage" extends="struts-default">
    <action name="login" class="login_action">
        <result name="success">/welcom.jsp</result>
        <result name="error">/error.jsp</result>
    </action>
</package>

注意我們這裏 action 標籤中的 class 屬性已經不再指向具體的 Action 類了,它指向的是 Spring 中的實例 bean。

至此,對於 Struts2 和 Spring 的整合大致上結束了,爲什麼說大致呢?當你啓動 web 容器運行上述程序時,會報錯:

Unable to load configuration. - action .....

告訴你無法加載 struts.xml 配置文件,其實就是 action 的 class 屬性對應的類找不到的意思。解決辦法是,添加一個 Spring 插件依賴,該插件會讓容器在找不到對應的實體類的時候,去 Spring IOC 容器中找。具體依賴是:

<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-spring-plugin</artifactId>
  <version>2.3.15.1</version>
</dependency>

然後我們啓動 web 容器測試我們的整合效果。

這裏寫圖片描述
這裏寫圖片描述

整合成功! Struts2 與 Spring 的整合還算簡單,Spring 整合 Hibernate 則相對複雜一些。

四、Spring 整合 Hibernate

整合 Hibernate 的第一步依然是依賴相關 jar 包。

//MySQL 驅動包
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>6.0.6</version>
</dependency>
//c3p0 
<dependency>
  <groupId>com.mchange</groupId>
  <artifactId>c3p0</artifactId>
  <version>0.9.5</version>
</dependency>

第二步是配置數據源和 session 工廠。

<!--讀取屬性配置文件內容-->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置c3p0數據源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${diverClass}"/>
    <property name="jdbcUrl" value="${jdbcUrl}"/>
    <property name="user" value="${user}"/>
    <property name="password" value="${password}"/>
</bean>

創建一個屬性文件保存 jdbc 連接的基本信息,連接驅動,連接 url,用戶名,密碼等。然後我們在 Spring 配置文件中配置了一個單例的數據源,它負責創建於數據庫的連接。

接着配置一個 SessionFactory 實例:

<!--配置session工廠-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocations" value="classpath:hibernate.cfg.xml"/>
</bean>

創建 session 工廠的時候會去加載 Hibernate 的核心配置文件,這裏我們通過注入 configLocations 屬性的值告訴 Spring 該文件的位置。這裏還需要引入一個在 Spring 配置文件中支持 Hibernate 相關操作的一個插件:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>4.0.0.RELEASE</version>
</dependency>

Spring 對 Hibernate 的整合也基本結束,下面我們通過模擬一個登陸操作來初步體驗下整合後框架的整體運行過程。

五、模擬登錄過程

爲了項目之間各個模塊的耦合性低,我們通常會選擇將整個項目分分層,Action 控制器攔截請求,Service 處理業務,Dao 完成對數據的存取。

這裏寫圖片描述

MyDao 中封裝着我們對於數據庫的所有操作,MyService 中封裝着我們所有的業務邏輯。我們先在 Dao 層中添加一個方法用於根據用戶名返回給用於所有信息,也就是返回該用戶名所匹配的那條記錄。

public class MyDao {

    private SessionFactory sessionFactory;
    //省略getter,setter方法
    public UserInfo getByName(String name){
        Session session = this.sessionFactory.openSession();
        List list = session.createSQLQuery("SELECT * FROM logins WHERE NAME ='"+name+"'")
                .addEntity(UserInfo.class)
                .list();
        session.close();
        if(list != null && list.size() != 0){
            return (UserInfo) list.get(0);
        }else {
            return null;
        }
    }
}
//Spring IOC 容器中配置一個 MyDao 實例
<bean id="myDao" class="Dao.MyDao">
   <property name="sessionFactory" ref="sessionFactory"/>
</bean>

接着我們寫 Service 層:

public class MyService {

    private MyDao dao;
    //省略getter,setter方法
    public boolean sure(String name,String pwd){
        UserInfo userInfo = this.dao.getByName(name);
        if(userInfo == null){
            return false;
        }else {
            if(userInfo.getPwd().equals(pwd)) return true;
            else return false;
        }
    }
}
//Spring IOC 容器中配置一個 Service 實例
<bean id="myService" class="Service.MyService">
    <property name="dao" ref="myDao"/>
</bean>

創建 Service 實例的同時並將 MyDao 實例注入到其中,邏輯上實現了 Service 調 Dao,組件調用。下面寫控制器:

public class LoginAction extends ActionSupport {

    private String name;
    private String pwd;
    private MyService service;
    //省略getter,setter方法
    public void setName(String name) {
        this.name = name;
    }

    public String execute(){
       boolean flag = this.service.sure(name,pwd);
       if(flag) return SUCCESS;
       else return ERROR;
    }
}
//Spring IOC 容器中配置 Action 實例
<bean id="login_Action" class="Actions.LoginAction" scope="prototype">
    <property name="service" ref="myService"/>
</bean>
//struts.xml 中使 Action 生效
<package name="myPackage" extends="struts-default">
    <action name="login" class="login_Action">
        <result name="success">/welcom.jsp</result>
        <result name="error">/error.jsp</result>
    </action>
</package>

好了,我們來測試一下!

這裏寫圖片描述
這裏寫圖片描述

這裏寫圖片描述
這裏寫圖片描述

上述我們使用整合後的框架做了一個小案例,由於代碼量較小還不能體現框架分層處理的優勢,但是我們還要對其進行更深層次的解耦。

六、項目的模塊分離與再聚合

上述的項目中,我們的 Dao,Service,Action 等層次的代碼都處於同一個項目中,項目的模塊化就是將這些層分離出去,然後再以熱插拔的形式聚合回原項目,這樣的話,項目中的各個組件都是一個一個的子模塊,那麼任意一個模塊出現問題後,可以立即用一個新模塊接上。這種模塊化的思想已經越來越成爲一種主流的思想。

下面我們來介紹下,如何拆分出這些模塊。

首先我們要新建一個工程作爲父工程,這些 Dao,Service,Action 都是它下面的子模塊。打個比方來說,父工程就相當於電腦主板,Dao,Service,Action 都是熱插拔在上面的內存條、硬盤等部件,主板上的資源在各個部件上都是可見的。所以我們的父工程只需要做一件事,依賴子模塊所需要的所有的 jar 包。

這裏寫圖片描述

這個父工程什麼都不要有,只需要有一個 pom.xml 文件用於依賴所有需要的 jar 包即可。然後我們將上一個項目中所有需要依賴的 jar 包都添加到父工程的 pom.xml 中進行引用。

然後我們選中項目創建第一個子模塊 Dao,

這裏寫圖片描述

將屬於 Dao 的所有相關文件全部移植到 Dao 模塊中來。

這裏寫圖片描述

除了這些,還有一些配置在 Spring 中的代碼,我們也要拷貝過來。

這裏寫圖片描述

拷貝原先的 Spring 的配置文件並刪除和我們 Dao 層無關的所有配置代碼。這就完成了對 Dao 模塊的分離,下面我們分離 Service 模塊。

第一步是一樣的,先創建一個子模塊然後移植過來原先項目中和 Service 相關的所有代碼文件。

這裏寫圖片描述

相關的文件拷貝後的 Service 目錄結構如上圖所示,但是整個 Service 模塊是報錯的,原因很簡單,Service 現在是獨立於 Dao 的,但是它又是依賴 Dao 的,所以我們只需要將 Dao 模塊打包發佈到本地倉庫,然後 Service 通過 Maven 依賴即可。

<dependency>
    <groupId>top.walkeryam</groupId>
    <artifactId>Dao</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

依賴 Dao 包之後就會發現項目不再報錯了,最後我們分離 Action。

第一步依然是創建子模塊並移植過來相關的所有代碼,

這裏寫圖片描述

這裏的報錯和上述的原因是一樣的,Action 要依賴 Service ,所以我們只要爲其添加 Service 的引用即可。

<dependency>
   <groupId>top.walkeryam</groupId>
   <artifactId>Service</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>

但是還沒完,這麼多 Spring 配置文件,web 容器怎麼知道加載哪個?
修改 web.xml 中有關 Spring 配置文件位置的代碼:

這裏寫圖片描述

使用通配符告訴容器加載所有類路徑下符合指定規則的配置文件,這樣我們各個模塊中的 Spring 的配置都可以被加載了。

下面我們將 Action 打成 war 包,並存放到 web 容器的項目目錄下,單獨運行 Action,由於 Dao 和 Service 都已經以熱插拔的形式接入到 Action 中了,所以直接運行 Action 是沒有問題的。

這裏寫圖片描述

啓動本地 Tomcat ,瀏覽器中進行測試。

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

測試成功!那至此我們也完成了 Maven 項目的模塊化拆分與聚合的操作,項目之間的各個組件耦合度降低,每個組件又都是可熱插拔的,一旦哪天項目中的某個組件崩潰導致整個項目掛了,可隨機替換出錯的組件。

模塊化的思想已經越來越成熟了,不知道本篇上述的所有內容闡述的是否到位,但依然建議你深入理解整個解耦模塊化的思想。總結不到之處,望指出!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章