使用SSH框架來完成CRM系統流程總結
今天是國慶節的第四天,也是中間一天。沒有捨得出去玩,因為我覺得像這樣的大塊時間來的不容易,不用去上課,沒有人干擾,用來學習自己喜歡的東西挺幸福的。我用將近一個星期的時間學習別人的CRM系統。自己也是剛學完SSH框架,用SSH框架來實現CRM系統。過程中犯下過許多錯誤。我把一些常遇到的錯誤已經發過部落格。今天,我不想再再往下走,去學新的東西。我想停下來吸收吸收SSH中的東西。
關於的自己的CRM系統,我這次先不放程式碼,我需要完善一下。這次先來總結專案流程。
話說SSH:前邊已經提到過使用的框架就是SSH(spring+struts2+hibernate),順帶著稍微總結一下這三個框架吧,框架本來就是軟體的半成品,初學者需要先掌握使用方法,其實最多的是配置的問題(配置有使用xml檔案的形式,也可以採用註解開發的模式,各有好處,xml便於維護,註解用起來速度更快。一定不要把兩個搞混了)。我覺得學習框架就像學習開車,一上來應該先學會開車,因為先學會開車了才能夠給自己帶來方便,至於車的構造,不應該是初學者去搞的(這裡指框架的底層,更深層的是原始碼,但是具體流程還是要掌握一下的,只有掌握具體的流程,在調錯的時候才能一針見血),等能夠使用熟練了以後,就應該挖挖底層了,因為不想造車的司機不是好司機,如果作為初學者,不懂底層可以原諒,如果使用很長時間還不瞭解底層,就有點說不過去了。就像開了十年車,不知道車的構造,車出了問題,不知道哪裡出的問題,這顯得多麼荒謬...
分說:struts2,就是基於mvc設計模式的web應用框架,web層的框架,一般都是基於前端控制器模型來設計的。
分說:hibernate,就是一個持久層的ORM框架。(ORM)(Object relational Mapping)物件關係對映。目的就是用來建立實體類和資料庫中表的對映關係。達到操作物件就能操作資料庫的目的。(這裡都稍微總結一下吧,有點小跑題,不要慌,麵包會有的..)
分說:spring,EE開發的一站式框架。也正是spring將三個框架連線在一起,一起在專案中發力。spring的好處有:輕量,控制反轉,面向切面,可以很方便的對程式進行擴充套件,方便解耦,AOP的程式設計支援,宣告式事務支援,方便程式的測試,方便整合各種優秀的框架,降低javaEE開發API的難度。解耦合的思想很重要,後期方便維護和擴充套件。框架各管一層,spring又將框架連線起來。
總結完了三個框架,下邊來麵包吧:
不管是用什麼框架,建立專案搭建必須的環境是第一步,我們需要引入jar包,這是為的專案能跑起來需需要的所有的jar包
antlr-2.7.7.jar asm-3.3.jar asm-commons-3.3.jar asm-tree-3.3.jar c3p0-0.9.2.1.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.apache.commons.logging-1.1.1.jar com.springsource.org.apache.log4j-1.2.15.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar commons-beanutils-1.8.3.jar commons-collections-3.2.1.jar commons-fileupload-1.3.1.jar commons-io-2.2.jar commons-lang-2.5.jar commons-lang3-3.2.jar commons-logging-1.1.1.jar dom4j-1.6.1.jar ezmorph-1.0.6.jar freemarker-2.3.22.jar geronimo-jta_1.1_spec-1.1.1.jar hibernate-c3p0-5.0.7.Final.jar hibernate-commons-annotations-5.0.1.Final.jar hibernate-core-5.0.7.Final.jar hibernate-jpa-2.1-api-1.0.0.Final.jar jandex-2.0.0.Final.jar javassist-3.18.1-GA.jar jboss-logging-3.3.0.Final.jar json-lib-2.4-jdk15.jar jstl.jar log4j-1.2.16.jar log4j-api-2.2.jar log4j-core-2.2.jar mchange-commons-java-0.2.3.4.jar mysql-connector-java-5.1.7-bin.jar ognl-3.0.6.jar slf4j-api-1.6.1.jar slf4j-log4j12-1.7.2.jar spring-aop-4.2.4.RELEASE.jar spring-aspects-4.2.4.RELEASE.jar spring-beans-4.2.4.RELEASE.jar spring-context-4.2.4.RELEASE.jar spring-core-4.2.4.RELEASE.jar spring-expression-4.2.4.RELEASE.jar spring-jdbc-4.2.4.RELEASE.jar spring-orm-4.2.4.RELEASE.jar spring-test-4.2.4.RELEASE.jar spring-tx-4.2.4.RELEASE.jar spring-web-4.2.4.RELEASE.jar standard.jar struts2-core-2.3.24.jar struts2-spring-plugin-2.3.24.jar xwork-core-2.3.24.jar
匯入完了jar包以後,還需要引入配置檔案,
- 建立專案,環境的搭建:匯入jar包
- 引入配置檔案
- Struts2的框架需要修改的是:
- Web.xml
- Struts2的框架需要修改的是:
<!-- struts2的核心過濾器 -->
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.Strut sPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-
-
- Struts.xml
- spring的框架
- Jdbc.properties
- log4j.properties
- applicationContext.xml
- web.xml
- Hibernate的框架
- Hibernate.cfg.xml ---現在交給spring去管理了
-
- 建立相關的包結構
關於包的結構,與類的建立有需要注意的點,我們最好是採用介面+實現類的方式,這樣也方便事務的管理。
如果做功能比較齊全一點的專案,就像我做的CRM管理系統,
這裡說一下封裝繼承的用法,和優點 (體現在dao層)
有幾個模組的程式碼有大量的重複,比方說客戶管理模組,聯絡人管理模組,拜訪管理模組,都需要分頁,都需要進行URCD操作,在dao層有很大一部分程式碼是重複的,就是你有我也有的地方,對於這個地方,我們就可以使用泛型,抽取出來公共的程式碼
實現步驟就是寫一個公共的接口出來,其他模組的介面可以來繼承這個介面,由於繼承的優點所在,各個模組相同的部分給父親,然後每個模組又繼承父親,父親有的孩子都可以共享,這樣就可以實現抽取程式碼,簡化程式碼的目的。
比如我crm專案的抽取出來的通用介面
package com.xing.crm.dao;
import java.io.Serializable; import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
/** * 通用的Dao介面 * @author DELL * */ public interface BaseDao<T> { //儲存的方法 public void save(T t); //更新的方法 public void update(T t); //刪除的方法 public void delete(T t); //查詢一個的方法 public T findById(Serializable id); //查詢所有的方法 public List<T> findAll(); //統計個數的方法 public Integer findCount(DetachedCriteria detachedCriteria); //分頁查詢的方法 public List<T> findByPage(DetachedCriteria detachedCriteria,Integer begin, Integer pageSize); }
BaseDao介面的實現類:(注意我的實現類繼承了hibernate的模板)
package com.xing.crm.dao.impl;
import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List;
import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Projections; import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.xing.crm.dao.BaseDao;
/** * 通用的Dao的實現類 * * @author DELL * */ public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {
// 提供構造方法,在構造方法中傳入具體型別的class private Class clazz;
/** * 不想讓子類中有帶引數的構造方法,就必須在父類中提供無參構造,在無參構造中獲取具體型別的Class 具體型別的Class是引數型別中的實際型別引數。 * * @param clazz */ public BaseDaoImpl() { // 反射:第一步獲得class Class clazz = this.getClass();// 獲取正在被呼叫的類的Class // 獲取引數化型別 Type type = clazz.getGenericSuperclass();// 如果是CustomerImpl繼承的BaseDaoImpl就獲得BaseDaoImpl<Customer> // 將type強轉換成引數化型別: ParameterizedType pType=(ParameterizedType) type; //通過引數化型別的方法獲得實際型別的引數 Type[] types= pType.getActualTypeArguments();//獲得的引數陣列 //因為我們只有一個引數,所以只需要獲得第一個引數即可 this.clazz=(Class) types[0];//最後一步獲得到實際型別引數Customer }
@Override public void save(T t) { this.getHibernateTemplate().save(t); }
@Override public void update(T t) { this.getHibernateTemplate().update(t); }
@Override public void delete(T t) { this.getHibernateTemplate().delete(t); }
@Override public T findById(Serializable id) { return (T) this.getHibernateTemplate().get(clazz, id); }
// 查詢所有的方法 @Override public List<T> findAll() { return (List<T>) this.getHibernateTemplate().find("from " + clazz.getSimpleName()); }
// 統計個數的方法 @Override public Integer findCount(DetachedCriteria detachedCriteria) { // 設定統計個數的條件 detachedCriteria.setProjection(Projections.rowCount()); List<Long> list = (List<Long>) this.getHibernateTemplate().findByCriteria(detachedCriteria); if (list.size() > 0) { return list.get(0).intValue(); } return null; }
// 分頁查詢的方法 @Override public List<T> findByPage(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize) { detachedCriteria.setProjection(null); return (List<T>) this.getHibernateTemplate().findByCriteria(detachedCriteria, begin, pageSize); }
}
接下來再寫模組的dao層介面的時候,介面需要繼承一下BaseDao介面。
接下來再寫模組的dao層的實現類,注意仍然是繼承BaseDaoImpl,就是繼承通用介面的實現類
這樣一來,好處就體現出來了,因為在我的模組實現類中一行程式碼都不需要寫了。如果不這樣寫的話,有十個模組,同樣的程式碼就需要寫十遍,因為每一個模組的dao層的實現類都要這樣來寫。程式碼量直接就體現出來了。這正是體現封裝和繼承的優點。
需要注意的是,我抽取出來的是模組共同的程式碼,並不是說這樣一來,dao層的實現類就真的一行程式碼都不需要了,如果某個模組有特殊的需求,那麼就需要在dao層的實現類中單獨來寫了。
接下來模組的service正常建立就可以
但是action類要繼承ActionSupport 並且實現ModelDriven介面