今日開始進行 OA 項目了, OA 是一個大型的辦公自動化管理系統。湯老師使用 6 天的時間帶領我們做這個項目,顯然是不可能全部完成的,我們要做其中重點的幾個模塊。這個項目將對我們之前學習的 struts1 、 hibernate3 、 jbpm3 、 jstl1.1 、 junit4 進行綜合性的系統練習。
?
在跟著老師學習新技術時,課堂上我們能很好的理解各知識點。但放到一起,在實際項目中應用時還時感覺有點陌生。不過還好,以前的工作經驗和每天整理學習日志讓這個項目的開端并未對我構成多大挑戰。但這對一個新人來說,是需要反復揣摩的,也正是這種實踐性的練習才讓我們掌握和混用理論性的知識。
?
做為一個應用級別的開發人員不僅要熟練掌握編程技術,而且也要對各業務流程有一定的了解。這在日后的開發工作中將起到重要的作用。說的直白些,就是熟練、穩健的使用編程技術將業務流程搭建起來。所以在這種實踐性項目中,我不僅要摸清各項技術的應用,也要熟悉業務流程,更要學好項目的架構。但是這個項目多少有些讓我失望,因為它的重點是讓同學們將之前學習的知識做個綜合練習,所以沒有從詳細的需求分析、編程文檔 ... 一一到來。
?
早上湯兄只是簡單的詳解了 OA 各大模塊,然后選出了其中的幾個小模塊做練習。下面我來總結一下。
?
一、 OA 辦公自動化系統
?
利用網絡通訊基礎及先進的網絡應用平臺,建設一個安全、可靠、開放、高效的信息網絡和辦公自動化、信息管理電子化系統,為管理部門提供現代化的日常辦公條件及豐富的綜合信息服務,實現檔案管理自動化和辦公事務處理自動化,以提高辦公效率和管理水平,實現企業各部門日常業務工作的規范化、電子化、標準化,增強檔案部門文書檔案、人事檔案、科技檔案、 財務檔案等檔案的可管理性,實現信息的在線查詢、借閱,最終實現 " 無紙 " 辦公。
?
其詳細資料可以查詢互聯網 ... 。
?
二、環境搭建
1. 開發環境 MyEclipse
2. 創建一個 WEB 工程 ????????
3. 在工程下添加資源目錄:
process : jbpm 使用的目錄
config : hibernate 、 jbpm 等工程使用的配置文件
test :單元測試類存放的目錄
4. 在 WebRoot 目錄下添加:
script :腳本文件存放目錄
style : CSS 樣式文件存放目錄
5. 在 WEB-INF 目錄下添加:
pages :頁面存放目錄
pages/department :與部門相關的頁面
pages/employee :與職員相關的頁面
pages/role :與角色相關的頁面,角色是一種權限分配的方法。經理、人事、秘書 ... 這就是角色,角色具有相應的權限組。比如經理具有審核員工、要員調動等權限。
6. 向工程中導入 jar 文件:
struts1 、 hibernate 、 mysql 、 jbpm 、 junit4 相應該的 jar 文件。
可以在工程上右鍵 -->"MyEclipse"-->"..." ,添加相應的框架 jar 文件。
7. 向工程中添加配置文件:
Struts1 和 hibernater 的配置文件。
?
三、基礎功能
1.DAO :
將 WEB 應用分三層架構,這樣使得程序更加易于編寫與維護。三層架構并不總適合于各 WEB 應用,在某些 WEB 應用中業務邏輯簡單,這樣使用三層就沒必要了。所以將 service 與 dao 層合并到一起。湯兄說先搞成三層的,然后我們再看有沒有必要這樣搞。然后再搞成二層的。
?
我們的層與層之間使用接口連接,這樣是為了可以方便的更換其中某一層的實現。比如數據訪問層,我們將數據庫更換為 XML 文件。但不需要修改 service 的代碼。這個早就說過了,只不過今日再次提出讓大家體會更深刻些。
?
湯老師使用 staruml 工具畫圖,接口與類的關系。我也用這個工具畫一下,感覺老好了:
?
按照上邊的關系,編寫接口與實現類,這個非常簡單。我們使用 hibernate 訪問數據庫,所以在 DaoBaseImpl 類的方法中使用 hibernate 的 Session 進行數據庫訪問。
?
2. 事務管理:
在一個請求中,我們如何保證這個請求的所有操作使用的是一個 Session ?比如,一個請求同時調用了 save 和 delete 操作。我們需要增強代碼的重用,如何使得這兩次調用只打開和關閉一次 Session ?
?
我們有什么好方法?編寫一個過濾器,在調用 doFilter 之前打開一個 Session ,在調用 doFilter 返回后關閉這個 Session 。我們這個過濾器過濾一“ *.do ”的請求。但這樣會導致,不需要 Session 操作數據庫的請求也會創建和關閉一個 Session ,這是完全浪費資源的。但我們有一好的解決辦法,看下面的實現。
?
我需要需要編寫一個 HibernateSessionUtils 類,用于管理 hibernate 的 Session :
package cn.itcast.oa.utils; ? import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; ? public class HibernateSessionUtils { ??? // Session 工廠 ??? private static SessionFactory sessionFactory = null ; ??? static { ??? ??? sessionFactory = new Configuration().configure().buildSessionFactory(); ??? } ??? // 一個請求對應一個線程,為了使一個請求統一使用一個 session 。 ??? // 所以在這里的使用 ThreadLocal , ThreadLocal<Session> 是 Map<Thread, Session> 的簡化形式。 ??? private static ThreadLocal<Session> sessionMap = new ThreadLocal<Session>(); ? ??? /** ??? ? * 取當前線程的 session ??? ? * 即使使用了過濾器,但沒有使用 Session 的請求是不會調用 getCurrentSession(true) 的。 ??? ? * @param creat ??? ? * ??????????? true 且當 session 為 null 時自動創建 session ,否則返回 null 。 ??? ? * @return ??? ? */ ??? public static Session getCurrentSession( boolean creat) { ??? ??? Session session = sessionMap .get(); ??? ??? if (creat && session == null ) { ??? ??? ??? session = sessionFactory .openSession(); ??? ??? ??? // 任何地方當初次使用 Session 時便開戶事務 ??? ??? ??? session.beginTransaction(); ??? ??? ??? sessionMap .set(session); ??? ??? } ??? ??? return session; ??? } ? ??? /** ??? ? * 關閉和刪除 session ??? ? */ ??? public static void closeAndRemoveSession() { ??? ??? Session session = sessionMap .get(); ??? ??? if (session != null ) { ??? ??? ??? session.close(); ??? ??? ??? sessionMap .remove(); ??? ??? } ??? } } |
?
在一個請求中,我們如何保證 Session 事務的正確處理?比如,經典的銀行轉賬示例。 Ok ,看了上邊的代碼,我們在初次使用 Session 時便開戶事務,那何時提交或回滾事務呢?我們在過濾器中實現:
package cn.itcast.oa.web.filter; ? import java.io.IOException; import javax.servlet.*; import org.hibernate.Session; import cn.itcast.oa.utils.HibernateSessionUtils; ? /** ? * 過濾 *.do 的請求 ? * @author Administrator ? * ? */ public class HibernateSessionFilter implements Filter { ? ??? public void destroy() { ??? } ? ??? public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ??? ??? ??? ServletException { ??? ??? ??? ??? try { ??? ??? ??? // 繼續調用 Action ??? ??? ??? chain.doFilter(request, response); ??? ??? ??? // 獲取當前請求的 Session ,返回 null 表示當前請求沒有使用 session ??? ??? ??? Session session = HibernateSessionUtils. getCurrentSession ( false ); ??? ??? ??? if (session != null ) ??? ??? ??? ??? // 如果當前請求使用了 seesion ,則提交事務。 ??? ??? ??? ??? session.getTransaction().commit(); ? ??? ??? } catch (Exception e) { ??? ??? ??? // 獲取當前請求的 Session ,返回 null 表示當前請求沒有使用 session ??? ??? ??? Session session = HibernateSessionUtils. getCurrentSession ( false ); ??? ??? ??? if (session != null ) ??? ??? ??? ??? // 如果當前請求使用了 seesion ,則回滾事務。 ??? ??? ??? ??? session.getTransaction().rollback(); ??? ??? ??? throw new ServletException(e); ??? ??? } finally { ??? ??? ??? // 關閉和刪除 session ??? ??? ??? HibernateSessionUtils. closeAndRemoveSession (); ??? ??? } ??? } ? ??? public void init(FilterConfig arg0) throws ServletException { ??? } } |
?
使用過濾器進行 session 管理還不算是一個好的方法。因為我們還沒有實現 service 層,所以在這里我們使用了 Filter 。管理 session 更好一些的方式是在 service 層中。因為 service 層中的一個方法處理一個業務邏輯請求。
?
四、 BEAN 對象管理
我們每編寫一個實現類的功能時,需要進行單元測試在這里就不多說了。
?
我們在單元測試或 service 層中需要創建 Dao 的接口對象,來完成對數據的訪問。如果我們直接 new DaoImpl ,這樣并未實現層與層之間的分離。此時經典的工廠模式派上了用場,這個模式從 JAVA 基礎增強、 JAVAWEB 到現在都有應用過。
?
我們通過工廠獲取需要的接口實現類對象,但如果整個系統中共需要 100 個或者更多的不同接口實現類,難道我們需要在工廠類中添加相應數量的 getxxx 方法?湯老師經驗豐富且十分有才,他使用了一個方法就可以解決獲取任意接口實現類的對象:
package cn.itcast.oa.utils; ? import java.io.*; import java.util.Properties; ? public class BeanFactory { ? ??? /** ??? ? * 獲取指定簡單接口名對應的實現類 ??? ? * <sp |
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
