使用structs2開發的一個java項目小慄子,請勿用作不合適的地方!!! ...
1 概述
File Space系統適用於團體,主要提供的是團隊文件分享以及個人文件的存儲管理服務。分為個人文件存儲管理平臺和團隊文件共用平臺。
個人文件存儲平臺主要為個人提供相關的文件分類存儲服務:該部分在用戶登錄後,可以選擇添加新的文件,創建新的分類,修改原有的文件,查看相關的文件,以及對個人信息的管理等。
團隊space主要是將個人部分添加的資料進行共用性的展示。
個人用戶可以瀏覽團隊共用的內容,然後在已登錄的情況下,可以將瀏覽到的自己喜歡的資料添加到自己的收藏。
項目針對半封閉的團隊管理方式,因此用戶添加方式採用管理員添加方式。
詳細的系統功能請看下圖(圖1-1)所示:
圖:1-1
2 需求分析
2.1 系統需求概述
當今的時代推崇共用,工作團隊中也需要共用。此系統為團隊提供文件方面共用,通過為用戶提供一個文件的存儲管理平臺,吸引用戶進行文件上傳,然後對上傳的文件進行共用。
2.2 用例分析
該系統包括普通用戶以及管理員兩種活動者,此外,可以有游客,但是游客只能查看共用的概要信息。系統中,管理員用戶是繼承自普通用戶,在普通用戶的基礎上多了對系統用戶的管理功能。普通用戶主要有系統的登陸登出,對於個人信息的管理,對於個人文件的管理,對於文件分類的管理以及對於收藏的管理,此外,下載文件功能單獨列出,是基於用戶既可以下載自己的文件,也可以下載共用區的文件。詳細的用例情況請參考(圖2-1)。
圖:2-1
3 系統設計
3.1 技術路線
整體使用基於Model-View-Controller (MVC)模型的Struts2 web應用框架,使用JSP作為視圖顯示,實現前後端的分離,數據存儲採用JDBC進行持久化存儲。系統選用MYSQL資料庫來存儲數據,使用Tomcat7.0作為系統伺服器。在頁面表示方面綜合應用了HTML5標準,JQuery等增加頁面效果。此外,系統採用Tomcat自帶的Tomcat JDBC Pool 增加數據訪問的性能。
3.2 系統總體架構設計
總體基於MVC模式的B/S web系統,考慮擴展方便設計了4層架構:頁面表示層(JSP)、請求處理轉發層(Action)、業務邏輯層(Service)和持久化存儲層(DAO)。
下圖(圖:3-1)是大部分B/S系統的架構圖。
圖:3-1
3.3 資料庫設計
資料庫根據系統的需要設計了用戶表、文件表、文件類型表、收藏表,各個表中標示了實體的基本的必要屬性,圖中連線標示外鍵關係。用戶與文件、文件類型、收藏都是1對多的關係,文件與收藏也是1對多的關係,同一個文件可以被不同的用戶進行收藏,但每個用戶只能單獨收藏。此外,文件表與類型表是多對1的關係。圖3-2中的連線標示外鍵關係。
圖:3-2
3.4 系統詳細設計
A.頁面佈局結構如下圖3-3:
圖:3-3
B.單頁面內的操作採用調用Jquery方法,傳遞JSON數據的方式進行局部刷新。
C.進入首頁需要執行action獲取相關的文件數據,採用先進入一個頁面,在該頁面直接進行調用的方式實現。
D.密碼使用MD5進行加密
E.使用攔截器在執行相關Action前進行登錄狀態的攔截。
F.使用資料庫連接池提高系統性能。
G.使用存儲過程,封裝資料庫操作。
H.使用Log4j記錄DAO層的操作以及出錯處理。
I.具體的Action方法實現邏輯參考功能實現。
4 系統實現
4.1 分頁功能的實現
分頁功能針對系統中顯示的數據的數據非常多的時候採用的技術,目的是為了讓系統按照頁碼展示相對應的數據記錄,減少數據傳遞的數量,增加頁面訪問速度,提高用戶體驗。
分頁實現採用定義分頁類(圖:4-1),然後需要使用分頁的方法填寫分頁類的屬性值,完成分頁。
圖:4-1 圖:4-2
分頁類定義了5個屬性:當前頁(currPage)、每一頁顯示的記錄數目(ItemOfPage)、
總共的記錄條數(totalItem)、總共的頁數(totalPage)、對應頁面的記錄集合(items)。
其中當前頁需要傳遞的前臺數據,如果前臺沒有傳遞當前需要獲取的是第幾頁則預設為第一頁;每一頁顯示的記錄數目採用的預設顯示10條的方式,用戶無法修改;總共的記錄條數需要讀取資料庫中的數目,採用分頁的需要首先在DAO層定義讀取資料庫所有數據數目的方法,然後在service層進行調用,然後填寫到Pager對象中;總共的頁數需要通過總共的記錄條數以及每頁顯示的條數進行計算,然後將結果填入;最後根據該Pager對象的屬性獲取相應的資料庫記錄填寫到Items列表中,傳遞到前臺進行顯示。
計算總共頁數的方法:
totalItem%pager.getItemOfPage()==0?(totalItem/pager.getItemOfPage()):(totalItem/pager.getItemOfPage()+1)
4.2 日誌功能的實現
日誌採用Log4j的方式,首先導入如圖(圖4-2)的日誌包,然後配置log4j.properties文件(圖4-3)。然後在需要添加日誌的頁面通過log4j包中的方法獲取日誌對象,填寫相應的日誌信息。
private static Logger logger = Logger.getLogger(UserDaoImpl.class);
圖:4-3
4.3 MD5加密(密碼)的實現
首先定義加密類MD5以及加密的靜態方法toMD5(),然後在需要加密的地方通過MD5調用靜態方法進行加密。
toMD5()方法採用網上的博客教程,實現如下:
1 public final static String toMD5(String s) { 2 3 char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 4 5 try { 6 7 byte[] btInput = s.getBytes(); 8 9 // 獲得MD5摘要演算法的 MessageDigest 對象 10 11 MessageDigest mdInst = MessageDigest.getInstance("MD5"); 12 13 // 使用指定的位元組更新摘要 14 15 mdInst.update(btInput); 16 17 // 獲得密文 18 19 byte[] md = mdInst.digest(); 20 21 // 把密文轉換成十六進位的字元串形式 22 23 int j = md.length; 24 25 char str[] = new char[j * 2]; 26 27 int k = 0; 28 29 for (int i = 0; i < j; i++) { 30 31 byte byte0 = md[i]; 32 33 str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 34 35 str[k++] = hexDigits[byte0 & 0xf]; 36 37 } 38 39 return new String(str); 40 41 } catch (Exception e) { 42 43 e.printStackTrace(); 44 45 return null; 46 47 } 48 49 }View Code
4.4 登錄許可權控制的實現
系統的許可權控制是通過攔截器實現。
首先定義該攔截器,在執行相關的Action前進行攔截,該攔截器的實現通過繼承
MethodFilterInterceptor並重寫doIntercept方法實現。
關鍵代碼如下:
1 HttpServletRequest request = ServletActionContext.getRequest(); 2 3 User user = (User) request.getSession(false).getAttribute("user"); 4 5 if(user == null){ 6 7 //logger.info("用戶沒有登錄!"); 8 9 return "re"; 10 11 } else { 12 13 //logger.info("用戶登錄成功!"); 14 15 return invoker.invoke(); 16 17 }View Code
4.5 資料庫連接池的實現
資料庫連接池能夠有效的提高訪問資料庫的速度,因此採用。
該項目使用Tomcat7.0 自帶的Tomcat JDBC Pool,通過在項目中添加context.xml中配置數據源,然後通過獲取context中的數據源獲取資料庫的連接。
4.6 文件上傳功能的實現
文件上傳前臺使用類型為file的input,因為中文文件名在下載時出現問題,難以傳輸,因此在這裡限制上傳的文件名必須是英文名。
後臺上傳實現直接就通過
ServletActionContext.getServletContext().getRealPath("/upload");
獲取文件上傳的地址(項目下麵的upload文件夾),然後將文件通過文件的輸入輸出流寫入到伺服器。
最後將文件的相關的存儲信息寫入到資料庫,以便下載。
4.7 文件下載功能的實現
首先根據前臺傳遞過來的文件的id值,獲取該文件的相關信息,然後定義一個文件輸出流以及相關的getter與setter方法,確定fileName以及contentType,最後配置輸出的result
<result name="download" type="stream">
<param name="inputName">fileDown</param>
<param name="contentDisposition">attachment;filename="${fileFileName}"</param>
<param name="contentType">fileContentType;charset=utf-8</param>
</result>
4.8 查看文件列表功能的實現
文件列表分為區分用戶與不區分用戶的列表兩種,分別對應首頁的共用的文件展示與個人文件的展示,首頁的文件展示因為文件數量巨大,因此採用的是分頁的方式進行展示,個人文件裡面的文件列表因為每一次展示都需要涉及文件的分類,因此數量不是很大,沒有採用分頁。
首頁文件的共用展示,採用的分頁方式過程請參考分頁的實現
個人文件的展示通過session裡面的用戶對象以及前臺傳過來的文件類型的id值獲取相關的文件對象列表進行實現。
4.9 資料庫設計(用戶區分,文件級聯刪除,存儲過程)
資料庫的具體設計見系統設計中的資料庫設計。
用戶區分採用的是在用戶的屬性中添加判斷該用戶是否是管理員的欄位,根據該欄位的值進行判斷該用戶是管理員還是普通用戶。
文件刪除功能,項目中沒有提供單個文件的刪除功能。
在用戶刪除某個文件類型的時候,根據外鍵關係,級聯刪除這些文件信息,在管理員刪除該用戶時,該用戶下麵的文件也會被刪除。
項目的數據訪問都採用的是存儲過程。
採用Navicat直接在資料庫定義存儲過程,然後在DAO層中通過
prepareCall(“call XXX”);調用該存儲過程獲得數據。
4.10 麵包屑導航功能的實現
麵包屑導航的作用是告訴訪問者他們目前在網站中的位置以及如何返回,當網站中出現典型的單線3層以上的層次使用麵包屑導航可以有效的提高用戶的體驗。
本次項目中因為要實現文件分類的無限級別的分類,因此採用麵包屑導航。
項目中的頁面部分展示通過後臺傳遞的Map集合直接讀取顯示。
Map裡面存放的當前分類的所有的父類的id值(鍵)以及對應的類別名稱(值)。
因為考慮到需要按照一定的順序存放,Map採用的是LinkedHashMap。
Map裡面鍵的集合裡面的值通過資料庫裡面定義的函數實現。
該函數通過傳遞的當前的類別的id值獲取該類別的所有的父類並且按照一定的順序,形成字元串輸出。
該函數如下:
1 BEGIN 2 3 DECLARE sParentList varchar(1000); 4 5 DECLARE sParentTemp varchar(1000); 6 7 SET sParentTemp =cast(rootId as CHAR); 8 9 WHILE sParentTemp is not null DO 10 11 IF (sParentList is not null) THEN 12 13 SET sParentList = concat(sParentTemp,',',sParentList); 14 15 ELSE 16 17 SET sParentList = concat(sParentTemp); 18 19 END IF; 20 21 SELECT group_concat(parentid) INTO sParentTemp FROM tab_type where FIND_IN_SET(tid,sParentTemp)>0; 22 23 END WHILE; 24 25 RETURN sParentList; 26 27 ENDView Code
源碼地址:https://github.com/husky00/Java/tree/master/Java/FileSpace01
sql地址:http://files.cnblogs.com/files/husky/FileSpace.zip 用的mysql 資料庫,sql 使用navicat自動導出的!