|
本原則是本人結合項目的實施開發編寫代碼情況,對多年以來帶領項目實施奮戰在開發一線經驗的提煉與概括。這十條開發指導原則,最基本的思想是“高效,高質量的寫出滿足業務功能目標的代碼。”每人可以結合當前項目的實際情況應用,可以補充,修訂刪改進一步總結提煉。
1.先開發簡單明確的功能模塊,后開發復雜的功能模塊。
2.先做簡單的子功能,再做稍微復雜的子功能,后開發有難度邏輯復雜的子功能。
3.以滿足業務功能要求為主要目標,不保留無用的垃圾代碼。寫出高質量滿足功能要求的代碼,是建立在對業務需求理解,明確業務目標,邏輯思路清晰的結果。有時往往需要反復多次修改精益求精才能最后實現客戶滿意的功能。
4.每開發一個功能模塊,都要頭腦清晰。(功能目的,界面表現,程序邏輯思路,各層函數調用關系,數據存儲),全面系統考慮,力求每個細節都思考一遍,不使疏漏。在一般情況下比葫蘆畫瓢,充分借鑒一般常用的邏輯代碼,業界常用的一般方法,已有類庫函數。能夠迅速高效寫出高質量的一般性代碼,以便騰出精力解決關鍵問題。力求避免功能函數重復開發,代碼隨意復制,邏輯思路混亂,代碼隨意修改,瞎寫代碼。保證所寫的每一個函數,每行代碼,都有意義,都有目的,堅決刪除無用的垃圾代碼。這樣就保證了,我們寫出的代碼是簡潔的,思路明確的。隨著時間的推移,我們寫的代碼越來越多,就會積累出跟本項目相關的很多通用的類庫,函數。通過對比,更能深入的理解業務,抽象出公用的方法,邏輯規范。進而提高整個團隊的工作效率。通過循環迭代的思路,不斷地擴大成功經驗。
5.我們開發程序過程中,總有一些公用的函數類庫,可以調用。每次都不是從零開始,不是每行代碼都一行一行的手工輸入。要充分的利用工具,靈活應用學過的方法。
6.發揚團隊協作精神,提高整體測試交叉測試意識,積極總結開發一般性類庫函數,提供給大家調用。分享成功經驗。避免一個人孤軍開發,愁眉苦臉的編寫程序。共同攻克業務技術難題,苦中有樂。
7.力求高質量高效的完成開發模塊,不要鉆牛角尖,經常交流,不懂就問。注意不要把問題復雜化,想當然,自己跟自己制造困難。如果問題越來越復雜,越開發代碼越沒頭緒就立即停止編寫,回到問題的原點重新考慮或跟大家交流聽聽別人的意見。
8,在解決技術問題上,如果是關鍵問題,堅決研究,要徹底搞明白。與項目相關不影響全局的問題,可以根據實際情況優先級放低一級。針對難點業務復雜的問題,先做外圍知識技術準備,找出關鍵點,先易后難分步驟逐漸深入的去解決。最后將其貫穿成一個整體。
9.經常查看別人代碼,吸取別人的經驗,充實自己。我們的知識積累主要來自別人,主要在當前項目。取之于別人,受益于自己。受益于項目。
10.善于利用零星時間,比較已經做過的功能模塊。不斷的整理,優化已經開發過的代碼。發現Bug及時修正,精益求精。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/zhaoyu_1979/archive/2011/03/16/6254021.aspx
一相關下載(1) java JDK下載:
進入該網頁: http://java.sun.com/javase/downloads/index.jsp (或者直接點擊下載)如下圖:
選擇 Download JDK 只下載JDK,無需下載jre.
(2)eclipse下載
進入該網頁: http://www.eclipse.org/downloads/ (或者直接點擊下載:BT下載 HTTP下載) 如下圖:
我們選擇第一個(即eclipse IDE for java EE Developers)
(3)下載Android SDK
說明: Android SDK兩種下載版本,一種是包含具體版本的SDK的,一種是只有升級工具,而不包含具體的SDK版本,后一種大概20多M,前一種70多M。
完全版下載 (android sdk 2.1 r01) 升級版下載 (建議使用這個,本例子就是使用這個這里面不包含具體版本,想要什么版本在Eclipse里面升級就行)
二 軟件安裝
(1)安裝jdk 6u19 安裝完成即可,無需配置環境變量
(2)解壓eclipse eclipse無需安裝,解壓后,直接打開就行
(3)解壓android sdk 這個也無需安裝,解壓后供后面使用
(4)最終有三個文件夾,如下圖:
三 Eclipse配置
1 安裝android 開發插件
(1)打開Eclipse, 在菜單欄上選擇 help->Install New SoftWare 出現如下界面:
點擊 Add按鈕,出現如下界面
輸入網址: https://dl-ssl.google.com/android/eclipse/ (如果出錯,請將https改成http)
名稱: Android (這里可以自定義)
點擊OK,將出現如下界面
點擊 Next按鈕 ,出現如下界面:
點擊Next按鈕,出現如下界面:
選擇 I accept the terms of the license agreements 點擊Next,進入安裝插件界面
安裝完成后,出現如下界面
點擊Yes按鈕,重啟Eclipse
2 配置android sdk
(1)點擊菜單window->preferences,進入如下界面
選擇你的android SDK解壓后的目錄,選錯了就會報錯,這個是升級工具,目前還沒有一個版本的SDK
(2)升級SDK版本,選擇菜單 window->Android sdk and avd manager 出現如下界面
選擇update all按鈕,出現如下界面
選擇左邊的某一項,點擊accept表示安裝,點擊reject表示不安裝,我這里只選了SDK 2.1 和samples for api 7 , 自己可以任意自定義,確定后,選擇install按鈕,進入安裝界面如下:
安裝完成如下:
(3)新建AVD(android vitural device) 和上面一樣,進入android sdk and avd manager,選中Vitural Devices 在點擊New按鈕
點擊New按鈕后,進入如下界面:
名稱可以隨便取,target選擇你需要的SDK版本,SD卡大小自定義,點擊 Create AVD,得到如下結果
如上顯示創建AVD完畢
3 新建Android項目
(1)選擇菜單file->new->other 進入如下界面:
選擇新建Android Project項目,點擊Next按鈕,進入如下界面
名稱自定義,應用程序名自定義,報名必須包含一個點以上,min SDK version里面必須輸入整數
點擊Next出現如下界面:
注: 若有錯誤如: Project ... is missing required source folder: 'gen' ,則將gen->Android.Test->R.java這個文件刪掉,Eclipse會為我們重新生成這個文件,并且不會報錯。
(3)配置運行
右鍵項目->Run as -> Run Configuration 進入如下界面:
該界面,點擊Browse 按鈕,選擇你要運行的項目
選擇Target切換到以下界面
該界面選擇運行的AVD,將AVD前面的方框設置為選擇狀態。
(4)測試項目運行
右鍵項目名稱->run as ->Android Application 即可啟動運行該Android程序,如下所示:
正在進入
測試程序運行結果
四 結束語
至此,android開發環境搭建完畢,有問題請留言。在這里要注意,我這里只是下載了android sdk r4升級工具,沒有下載具體的SDK,而是通過在Eclipse里面的Android Sdk管理工具升級的,你也可以直接下載具體的SDK版本,如: Android sdk 2.1 r1 上面有這個的下載鏈接,但我任務用升級工具更好。
建立一個Silverlight項目,添加一個子窗口ChildWindow1.xaml.string testString;
public string TestString
{
get { return testString; }
set { testString = value; }
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
if (OkClicked != null)
{
TestString = txtUserInfor.Text;
OkClicked(this,new EventArgs());
}
this.DialogResult = true;
}
public FatherControl()
{
InitializeComponent();
childWindowDemo.OkClicked += new EventHandler(childWindowDemo_OkClicked);
}
void childWindowDemo_OkClicked(object sender, EventArgs e)
{
tbInfo.Text = childWindowDemo.TestString;
}
private ChildWindow1 childWindowDemo = new ChildWindow1();
private void Button_Click(object sender, RoutedEventArgs e)
{
childWindowDemo.Show();
}
完畢。
運行,點擊父窗體按鈕,彈出子窗體。在子窗體的輸入框中輸入內容,點擊確認后關閉子窗體,同時子窗體的數據更新到父窗體的輸入框中。
一. 好的編程習慣
1. 寫程序前打個草稿可以在心里,最好在紙上:目的要從整體上考慮程序的實現。
如果公司采用建模的方式,有建模工具(rose ,visio )那是最好不過的了。
2. 注意休息,不要浪費自已的休息時間,用去了自已的時間不但會寫出的代碼因為注意力不集中而會常常出現代碼的質量有問題,邏輯常出錯
3. 要善于收集相關的專業開發上的資料,以便以后能更快更好的解決問題目。提倡公司能提供內部知識勾通的工具(如知識論壇,內部即時聊天器);提倡公司內部有技術資料的共享庫,提高解決問題的能力.
4. 提高對所寫的模塊的相關全局把握能力,在寫程序中要最好先詳細設計后再發布.
5. 要學會與他人溝通如非工程師,學會溝通的不同方式,提高溝通的效率。
二. 不同的目標不同的知識重點
(一) 目標:程序員
職責:根據詳細設計文檔,或根據高級程序員的設計進行相關的開發。
1. 要學會看相關的需求文檔及詳細設計文檔。
注意:你必須要通過閱讀這些文檔把握住其中的重點,關鍵點,相關易漏點
2. 如果公司里會用UML來相互的溝通,這時你必須要深刻理解UML 的相關知識,一定要注意千萬不要對UML圖一知半解的情況下,就著寫代碼,那樣會錯的很慘。
3. 學好對應的計算機語言的基礎知識,如:程序的語法,關鍵點,易錯點,對應的出錯如何出理,如何才能把對就的程序寫的鍵壯一些
4. 如果用到數據庫的內容,在學會sql的前提下,盡量學會數據庫原理中的相關sql內容, 當然為了提高查詢的能力也可以增加一點
5. 如果用到面向對像的語言那最好學點相關的設計模式,這樣的可以增加代碼的擴展性,及可維護性等,能夠理解詳細設計中的模塊間的設計原則這個也可以提高對模塊的內容編寫的正確性.
6. 你一定要學會公司內部的通用的編碼規范。
7. 學習如何做單元測試比較好.必須要熟悉相關的單元測試工具.
8. 要不斷的對相關知識進行總結,同時也要必須把相關的資料進行整理和學習,在學習過后的資料中你可以在遇到問題時更快的找到問題的答題。
9. 在開發你必須記錄下大家常出錯的地方及大家的解決方法,這個對你以后錯誤的避免有很大的作用.
10. 在寫代碼中時必須把上面寫過代碼記在心里,這樣就可以養成習慣,提高代碼的速度
11. 對數據庫操作時,要盡量共用Connection,并小用以減少Connection的數量
(二) 目標:高級程序員
職責:對需求文檔進行系統相關模塊的詳細設計,并負責對程序員的支持及指導和相關核心模塊的編寫
所以不但要學會相關程序員要的知識,同時還要學會難度比較大的知識。
1. 程序員的知識,如設計模式你一定要不是簡單的看要懂,你還要應用設計模式對相應的模塊進行相關的詳細設計。
2. 要學好相關詳細設計的工具做的有的放矢,這樣可以更好提高對自已的設計的表達
3. 為了提高系統的運行效率會運用到
a. 數據庫的表結構如何建才能使應用的要查詢sql 更快。這時可要認真認真的學習一樣數據庫原理,千萬不要以為采用數據庫的范式越高系統的運行效率會越好,有時候適當的表冗余可以大幅度的提高系統的查詢效率. 同時適當的建索引,視圖,存儲過程也是提高系統對數據庫的查詢的效率之一。
b. 學習多線程的編程,不過千萬不要以為線程數越多運行的速度會越快,一般線程的數量超過一定的數量后,系統的運行速度反而會變慢。為了應用好多線程,操作系統這本書也要關于同步及相關進程和線程的知識必不可少。
c. 設計好的一程序的好的算法,可要比起解一道同一復雜的數學題,要難的多,所以要在學好的相關數學的知識上(如線性代數,離散數學,概率論,數理統計)。更要深入計算方法,及數據結構,讓數學問題用計算機來解決。
4.為了讓系統設計的更加的可擴展性,穩定性,設計模式和軟件工程可是不能少的東西。所以必須把設計模式用于模式級的設計.
5. 如果公司采用的是Rose (UML)進行設計的話,你對于UML 的理解一定要非常的準確,同時你要跟小組中的程序之間進行充分的UML概念上及對應用例圖,類型圖,對象圖,協作圖的意思多寫一些注釋加深大家對你的設計上的理解。
(三) 目標:系統分析員
職責:做好與客戶之間的關系,同時對客戶的需求要正確的理解,要選擇合適的開發技術,同時做好與客戶間溝通交流,學會說服對方。
1. 學會對客戶的溝通:要正確理解客戶的需求同時要保證相互之間的溝通順暢。
2. 對了解來的需求要能用筆正確的描述下來,并能很好的傳敘給其他人。這時要學會用如ROSE 等的軟件建模的工具。和powerdesign等的數據庫建模工具。和相關的UML,數據流程圖及相關的內容的知識。
3. 不但要全面的了解客戶的需求而且還要對需求進行未來的可能的改變要有相當多的了解。
4. 全面的了解客戶的需求后,要選擇合適的相關技術用于開發,:
這時要學習各種知識
a. 先擇數據庫:db2,infomix ,oracle ,sql server,mysql 的優缺點,可以從中選擇最適合的數據庫及理由。
b. 設計數據庫:要扎實在數據庫的理論(數據庫原理,數據庫系統設計)及相關數據庫設計經驗,要盡量多的分析過去數據庫設計,分析這么設計數據庫的好處。這時可能要用到 powerdesign等工具。
c. 寫需求說明文檔和概要設計文檔,同時要學會要分析相關需求說明文檔的需要的內容的相關知識,如人員工時的計算方法, 一般會用 project 來分析相關的項目的內容。
d. 選擇合適的程序語言及相關的架構,一般主流的架構是 J2EE和.net的相應的優點及它們之間的結合,如采用soap xml進行相關的結合,或用java-com 橋 進行相關的功能的調用。和它們之間的相關語言優缺點
e. 還要根據b/s,c/s 結構對開發的網絡影響的相關內容采取選擇。
5. 學會說服對方,畢竟客戶都不是個個是軟件專家,他們的選擇有時未必是正確的所以學會說服對方,是系統分析員必備的能力條件.
三. 訓練的方法:
1. 計劃行事:
(1 設定你的未來的學習目標
a. 未來要成為什么樣的人(主要是工作角色,如程序員,高級程序員,系統分析員)
b. 你近期要成為什么樣的人(當前的工作職責是什么,如果只寫代碼是程序員等)
c. 要完成近期的工作所必須要知識(如java 程序員,要學習java 基礎知識,等),關鍵的知識(如java中關鍵要用到的知識有,面向對象等),易錯的知識(比較原來的已有知識進行合對)
(2 設定你的學習目標后,并要有針對性的對應目標設定學習時間的按排及學習路線。并直觀的記錄在案,以便以后隨時核對,
(3 常常抽出一定的時間認真核對計劃的完成情況,如果沒有按時完成計劃的內容。分析原因,盡量想法趕上計劃內容如果存認是計劃有誤,要認真總結計劃失敗出錯的原因,對你的未來有很大的幫助。
注意:不要對計劃的按排過于樂觀 要盡量的考慮實現中的各種情況,同時適當按排一些緩沖時間,以便真正能按照計劃行事,以提高按計劃行事信心,同時這能有效避免出現計劃中途成沒有意義的東西。
2. 針對工作角色對自已的能力進行培養和知識進行學習。
關鍵的能力:
(1. 記憶能力:要學會把自已的寫的代碼和改的代碼記的清清楚楚。要能提高效率。
(2. 邏輯思維能力:要多多的看別人的復雜邏輯的代碼,分析復雜邏輯的運算。
(3.全局能力: 不要再范改了東,卻西出錯。(構造軟件這個很重要)
(4.學習能力: 并不是每個項目都你是所熟悉的項目的,并不是每個項目中的知識你都知道,要掌握最新的技術和最有用的知識,是最關鍵的。要學會,提高能力,這個東西是永遠對自己有好處的。
(5. 溝通能力; 學會幽默,學會講故事,學會交朋友,學會禮節。
(6.自制能力:如果一個人不能自制那這個人以后,不會有很大成果,即使很大機會發展起了,可是因為沒有自制能力很容易被人利用,或自己明明知道怎么做,可是就是不能控制自己的欲望.而常做下無法挽回在錯誤.
四. 例:java 程序員的知識結構及學習流程:
(一) 學習相關工作必須的知識
1.Java 語言的基礎(推薦書:《 java 編程思想》)
關鍵:
(1. java 面向對象及對應的程序現實
(2. java 多線程
(3. java 網絡 socket
(4. 應用界面
2.學會用智能集成開發工具jbuilder,eclipse等一種,根據資料里的內容,自已寫與例程類似的代碼,但注意不要直接抄它,一定要自已寫。同時最好寫到一個工程中以便對比。
3.如果用b/s結構要學習jsp的知識(推薦書:《 JSP 2.0技術手冊 》)
關鍵:
(1. 界面處理:
a . HTML——超文本標志語言:用于顯示頁面如:超文本鏈接, 表格,各種標志等。
b. CSS———層疊樣式表:控制正文外觀的一組格式.用于美化HTML頁面。
c. javaScript—嵌入HTML頁面瀏覽器來執行的腳本語言:讓頁面可以根據用戶的操作或事先設置等在客戶端進行動態變化,而且不需傳回服務器。比如: 對表單輸入的正確性做客戶端驗證.
(2.jsp元素:如java代碼寫法,對應標志---jsp:include,jsp:useBean,jsp:setProperty,
jsp:getProperty等.jsp的幾大對
(3. javaBean及其在jsp 中的調用和相關應用.
(4. 其他技術:
a. 如何操作數據庫—用jdbc(可能要補充一些數據庫的知識,如oracle ,sql server,
包括如何寫高效率的查詢sql,存儲過程等) ,
b. 如何發送email—用javaMail,
c. 如何學習如何用實現文件的上傳下載,如果操作文件,
d. 如何操作xml --用jdom 及 jaxp(這時有必要學習一下xml 的語法如 dtd等)
e. 如何遠程方法調用—用 rmi
f. 如何進行消息服務 ---用 jms
5.再有些公司會用到 J2EE 的架構如 EJB 作為業務邏輯.
(1.EJB中要分清
(2. struts MVC
(3. Hibernate 操作數據庫
6.最好學習一下UML
學用Rose建模
五 忠告:
1. 不要以為自已很差,要明白每個人都是這樣一步一個腳印的走過來的。(我們要有信心)
告訴自已:比爾蓋次,也是同我們一樣,出生時也是巴掌大.
我們只有多學,多練才可能有出路.
2. 不要以為自已學的多就很強,世界上的高手多的是,問問自己,你每小時可以寫幾行代碼,代碼一次寫下來有多少錯誤,如果你一次寫下沒有錯誤,一小時可以寫1000代碼,那才是真正的高手.
3 . 不要以為自已沒有項目做就會落后于他人,人家是參加了很多項目,可是人家只是項目中的一個小角色,如果我們在空時能都寫一些開源的項目,或自己開發和設計一些有用的開源的項目,水平及能力很快就上來了.
4. 不要以為自己做過很多的項目就很了不起了。你能說你做的項目中,你能體會整個項目為什么要這樣設計,為什么要這樣開發嗎?相信絕大多數是否定的回答。那還不如多學習一些已做的項目,了解他們為什么要這么做,為什么這么開發,多看一下它們的項目的文檔,我們能明白很多,這樣把他們的經驗放于你未來可能要接手的項目,這樣不是更好嗎?
5. 不要以為自己的學習能力很牛,你能快速閱讀一本書又能快速掌握它的內容嗎
那么, 能不能夠在進入方法前就調用一些安全檢測? 其實Spring AOP就是這個思想, 那么又如何實現安全檢測呢? Spring Acegi Security 框架就是做這個事情. 本文主要是討論下在已有的SSH系統中, 如何使用Acegi作為安全框架實現基于角色的權限控制(Role Based Access Control RBAC) 本文的主要參考資料: <Spring 2.0 核心技術與最佳實踐> 第10章 (Spring Acegi 安全框架) <精通Spring 2.X -- 企業應用開發詳解> 第17章 (使用Acegi 實施應用系統安全) acegi-security-1.0.6 官方文檔 說明: 本文介紹的是RBAC, 在官方文檔的基礎上有所擴展或改動, 以更適合WEB應用系統. 其實我覺得大多數的網站基于角色已經足夠了, 一般都沒必要基于權限. 文章開始: 一. 下載所要的軟件或JAR包: 我的相關配置是: Java 5, Tomcat 5.5.26, Struts 2.0.11, Spring 2.5.1, Hibernate 3.2, Acegi 1.0.6 二. 建立相關的數據庫: 數據表: 用戶信息表User: id, enable, user_name, user_pass, email_box 角色信息表RoleInfo: id, role_name, role_title, descp 用戶與角色關聯表(用戶與角色是多對多關系)UserRole: user_id, user_name, role_id, role_name 并在這三個表中插入相關的數據, 我是定義了兩種角色(role_name): ROLE_USER, ROLE_ADMIN 和三個用戶, 一個用戶角色為: ROLE_USER, ROLE_ADMIN 另一個用戶角色為: ROLE_USER 第三個沒有角色. 二. 修改配置文件: 其實對Acegi框架的應用難點就在配置文件, 所以要特別注意了: 在 src 建立Acegi的配置文件: acegi-security.xml acegi-security.xml 其內容如下: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans xsi:schemaLocation="http://www.springframework.org/schema/beans <!-- ================= <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> <property name="providers"> <list> <ref bean="daoAuthenticationProvider" /> <ref bean="rememberMeAuthenticationProvider" /> </list> </property> </bean> <!-- 基于DAO驗證的AuthenticationProvider --> <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="userDetailsService" /> </bean> <bean id="userDetailsService" class="org.ymcn.security.AcegiUserDeitailsService"> <property name="userDao" ref="userDao" /> <property name="userRoleDao" ref="userRoleDao" /> </bean> <bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider"> <property name="key" value="obullxl@163.com </bean> <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices"> <property name="userDetailsService" ref="userDetailsService" /> <property name="parameter" value="j_remember_me <property name="key" value="obullxl@163.com <property name="tokenValiditySeconds" value="31536000" /> </bean> <!-- ================= <bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased"> <property name="decisionVoters"> <list> <ref bean="roleVoter" /> </list> </property> <!-- 是否全部棄權就通過 --> <property name="allowIfAllAbstainDecisions" value="false" /> </bean> <bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter"> <property name="rolePrefix" value="ROLE_" /> </bean> <!-- ================= <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeFilter,exceptionFilter,securityInterceptor </value> </property> </bean> <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" /> <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter"> <!-- 登錄退出后的URL --> <constructor-arg value="/" /> <list> <ref bean="rememberMeServices" /> <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" /> </list> </constructor-arg> <!-- 登錄退出的URL --> <property name="filterProcessesUrl" value="/j_logout.j" /> <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <property name="authenticationManager" ref="authenticationManager" /> <!-- 登錄失敗后的URL --> <property name="authenticationFailureUrl" value="/login.jsp?msg=%E6%97%A0%E6%95%88%E7%9A%84%E7%94%A8%E6%88%B7%E5%90%8D%E6%88%96%E5%8F%A3%E4%BB%A4" /> <!-- 登錄成功后的URL --> <property name="defaultTargetUrl" value="/user/cmd.jsp" /> <!-- 登錄的URL --> <property name="filterProcessesUrl" value="/j_login.j" /> <property name="rememberMeServices" ref="rememberMeServices" /> </bean> <bean id="rememberMeFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter"> <property name="authenticationManager" ref="authenticationManager" /> <property name="rememberMeServices" ref="rememberMeServices" /> </bean> <bean id="exceptionFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"> <!-- 出現AuthenticationException時的登錄入口 --> <property name="authenticationEntryPoint"> <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl" value="/login.jsp" /> <property name="forceHttps" value="false" /> </bean> </property> <!-- 出現AccessDeniedException時的Handler --> <property name="accessDeniedHandler"> <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl"> <property name="errorPage" value="/denied.jsp" /> </bean> </property> </bean> <bean id="securityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager" /> <property name="accessDecisionManager" ref="accessDecisionManager" /> <property name="objectDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /admin/**=ROLE_ADMIN /user/**=ROLE_USER /cart/previeworder*=ROLE_USER </value> </property> </bean> </beans> 在上面的配置文件中, 紅色 <bean id="userDetailsService" class="org.ymcn.security.AcegiUserDeitailsService <property name="userDao" ref="userDao" /> <property name="userRoleDao" ref="userRoleDao" /> </bean> 在整個應用的安全控制中, 我們唯一要編寫代碼的類就是: org.ymcn.security.AcegiUserDeitailsService 就連登錄和登出的代碼也不要了. ![]() 三. 修改 web.xml <filter> <filter-name>acegiFilterChain</filter-name> <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> <init-param> <param-name>targetClass</param-name> <param-value>org.acegisecurity.util.FilterChainProxy</param-value> </init-param> </filter> <filter-mapping> <filter-name>acegiFilterChain</filter-name> <url-pattern>*.j</url-pattern> </filter-mapping> 注意: 四. 在 applicationContext.xml <!-- Acegi安全控制攔截器 --> <bean id="serviceSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"> <property name="validateConfigAttributes" value="true" /> <property name="authenticationManager" ref="authenticationManager" /> <property name="accessDecisionManager" ref="accessDecisionManager" /> <property name="objectDefinitionSource"> <bean class="org.acegisecurity.intercept.method.MethodDefinitionAttributes"> <property name="attributes"> <bean class="org.acegisecurity.annotation.SecurityAnnotationAttributes" /> </property> </bean> </property> </bean> <!-- 利用Spring的自動代理功能實現AOP代理 --> <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> <value>serviceSecurityInterceptor</value> </list> </property> <property name="beanNames"> <list> <value>userService</value> <value>mailService</value> </list> </property> </bean> 五. 編寫在利用Acegi框架唯一要我們編寫的類 AcegiUserDeitailsService.java package org.ymcn.security; import java.util.List; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.dao.DataAccessException; import org.ymcn.dao.UserDao; import org.ymcn.dao.UserRoleDao; import org.ymcn.model.User; import org.ymcn.model.UserRole; public class AcegiUserDeitailsService implements UserDetailsService { private final Log LOG = LogFactory.getLog(AcegiUserDeitailsService.class); /* 依賴注入 */ private UserDao userDao; private UserRoleDao userRoleDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void setUserRoleDao(UserRoleDao userRoleDao) { this.userRoleDao = userRoleDao; } /* 用戶所有的權限 */ //private final List<GrantedAuthority> grantedAuthList = new ArrayList<GrantedAuthority>(6); private GrantedAuthority[] grantedAuthArray; public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException { if(LOG.isDebugEnabled()) { LOG.debug("Loading UserDetails of userName: " + userName); } /* 取得用戶 */ User user = userDao.getUserByName(userName); if(user == null) { LOG.warn("UserDetails load failed: No such UserRole with userName: " + userName); throw new UsernameNotFoundException("User name is not found."); } /* 取得所有用戶權限 */ List<UserRole> userRoleList = userRoleDao.getUserRoleByUserName(userName); if(userRoleList == null || userRoleList.size() == 0) { LOG.warn("UserRole load failed: No such UserRole with userName: " + userName); throw new UsernameNotFoundException("UserRole is not found."); } /* 取得用戶的所有角色 */ int size = userRoleList.size(); grantedAuthArray = new GrantedAuthority[size]; int j = 0; for(int i = 0; i < size; i++) { UserRole userRole = userRoleList.get(i); if(userRole != null) { this.grantedAuthArray[j++] = new GrantedAuthorityImpl(userRole.getRoleName().toUpperCase()); } } LOG.info("UserName: " + userName + " loaded successfully."); return new org.acegisecurity.userdetails.User(userName, user.getUserPass(), true, true, true, true, this.grantedAuthArray); } } 六. 在業務邏輯代碼中利用Java 5注釋 @Secured({"ROLE_USER"}) void sendSimpleMail(Long userId); @Secured({"ROLE_ADMIN"}) void sendAttachmentMail() throws Exception; 其實就是在需要安全控制的方法前加上: @Secured({"角色名"}) 七. 整個工作完成 Acegi框架完全是一種可插拔式的, 完全可以在原有的系統中加個一個配置文件 上面的 AcegiUserDeitailsService.java true |
上個世紀90年代中期,為了推進我國企業管理信息化,尋求更大的企業發展空間,一批具有一定規模的財務軟件公司紛紛轉向企業管理軟件,大量冠名為某某管理的軟件產品迅速涌現,同時國際管理軟件巨頭紛紛搶灘國內市場,在這些軟件企業的大力推動下,我國企業界開始廣泛了解管理軟禁先進性,2004年-2005年,管理軟件開始成為市場迅速增長的需求,國內眾多公司開始使用管理軟件成為一種趨勢。
一、安裝篇
jspSmartUpload是由www.jspsmart.com網站開發的一個可免費使用的全功能的文件上傳下載組件,適于嵌入執行上傳下載操作的JSP文件中。該組件有以下幾個特點:
1、使用簡單。在JSP文件中僅僅書寫三五行JAVA代碼就可以搞定文件的上傳或下載,方便。
2、能全程控制上傳。利用jspSmartUpload組件提供的對象及其操作方法,可以獲得全部上傳文件的信息(包括文件名,大小,類型,擴展名,文件數據等),方便存取。
3、能對上傳的文件在大小、類型等方面做出限制。如此可以濾掉不符合要求的文件。
4、下載靈活。僅寫兩行代碼,就能把Web服務器變成文件服務器。不管文件在Web服務器的目錄下或在其它任何目錄下,都可以利用jspSmartUpload進行下載。
5、能將文件上傳到數據庫中,也能將數據庫中的數據下載下來。這種功能針對的是MYSQL數據庫,因為不具有通用性,所以本文不準備舉例介紹這種用法。
jspSmartUpload組件可以從www.jspsmart.com網站上自由下載,壓縮包的名字是jspSmartUpload.zip。下載后,用WinZip或WinRAR將其解壓到Tomcat的webapps目錄下(本文以Tomcat服務器為例進行介紹)。解壓后,將webapps/jspsmartupload目錄下的子目錄Web-inf名字改為全大寫的WEB-INF,這樣一改jspSmartUpload類才能使用。因為Tomcat對文件名大小寫敏感,它要求Web應用程序相關的類所在目錄為WEB-INF,且必須是大寫。接著重新啟動Tomcat,這樣就可以在JSP文件中使用jspSmartUpload組件了。
注意,按上述方法安裝后,只有webapps/jspsmartupload目錄下的程序可以使用jspSmartUpload組件,如果想讓Tomcat服務器的所有Web應用程序都能用它,必須做如下工作:
1.進入命令行狀態,將目錄切換到Tomcat的webapps/jspsmartupload/WEB-INF目錄下。
2.運行JAR打包命令:jar cvf jspSmartUpload.jar com
(也可以打開資源管理器,切換到當前目錄,用WinZip將com目錄下的所有文件壓縮成jspSmartUpload.zip,然后將jspSmartUpload.zip換名為jspSmartUpload.jar文件即可。)
3.將jspSmartUpload.jar拷貝到Tomcat的shared/lib目錄下。
二、相關類說明篇
㈠ File類
這個類包裝了一個上傳文件的所有信息。通過它,可以得到上傳文件的文件名、文件大小、擴展名、文件數據等信息。
File類主要提供以下方法:
1、saveAs作用:將文件換名另存。
原型:
public void saveAs(java.lang.String destFilePathName)
或
public void saveAs(java.lang.String destFilePathName, int optionSaveAs)
其中,destFilePathName是另存的文件名,optionSaveAs是另存的選項,該選項有三個值,分別是SAVEAS_PHYSICAL,SAVEAS_VIRTUAL,SAVEAS_AUTO。SAVEAS_PHYSICAL表明以操作系統的根目錄為文件根目錄另存文件,SAVEAS_VIRTUAL表明以Web應用程序的根目錄為文件根目錄另存文件,SAVEAS_AUTO則表示讓組件決定,當Web應用程序的根目錄存在另存文件的目錄時,它會選擇SAVEAS_VIRTUAL,否則會選擇SAVEAS_PHYSICAL。
例如,saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)執行后若Web服務器安裝在C盤,則另存的文件名實際是c:\upload\sample.zip。而saveAs("/upload/sample.zip",SAVEAS_VIRTUAL)執行后若Web應用程序的根目錄是webapps/jspsmartupload,則另存的文件名實際是webapps/jspsmartupload/upload/sample.zip。saveAs("/upload/sample.zip",SAVEAS_AUTO)執行時若Web應用程序根目錄下存在upload目錄,則其效果同saveAs("/upload/sample.zip",SAVEAS_VIRTUAL),否則同saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)。
建議:對于Web程序的開發來說,最好使用SAVEAS_VIRTUAL,以便移植。
2、isMissing
作用:這個方法用于判斷用戶是否選擇了文件,也即對應的表單項是否有值。選擇了文件時,它返回false。未選文件時,它返回true。
原型:public boolean isMissing()
3、getFieldName
作用:取HTML表單中對應于此上傳文件的表單項的名字。
原型:public String getFieldName()
4、getFileName
作用:取文件名(不含目錄信息)
原型:public String getFileName()
5、getFilePathName
作用:取文件全名(帶目錄)
原型:public String getFilePathName
6、getFileExt
作用:取文件擴展名(后綴)
原型:public String getFileExt()
7、getSize
作用:取文件長度(以字節計)
原型:public int getSize()
8、getBinaryData
作用:取文件數據中指定位移處的一個字節,用于檢測文件等處理。
原型:public byte getBinaryData(int index)。其中,index表示位移,其值在0到getSize()-1之間。
㈡ Files類
這個類表示所有上傳文件的集合,通過它可以得到上傳文件的數目、大小等信息。有以下方法:
1、getCount
作用:取得上傳文件的數目。
原型:public int getCount()
2、getFile
作用:取得指定位移處的文件對象File(這是com.jspsmart.upload.File,不是java.io.File,注意區分)。
原型:public File getFile(int index)。其中,index為指定位移,其值在0到getCount()-1之間。
3、getSize
作用:取得上傳文件的總長度,可用于限制一次性上傳的數據量大小。
原型:public long getSize()
4、getCollection
作用:將所有上傳文件對象以Collection的形式返回,以便其它應用程序引用,瀏覽上傳文件信息。
原型:public Collection getCollection()
5、getEnumeration
作用:將所有上傳文件對象以Enumeration(枚舉)的形式返回,以便其它應用程序瀏覽上傳文件信息。
原型:public Enumeration getEnumeration()
㈢ Request類
這個類的功能等同于JSP內置的對象request。只所以提供這個類,是因為對于文件上傳表單,通過request對象無法獲得表單項的值,必須通過jspSmartUpload組件提供的Request對象來獲取。該類提供如下方法:
1、getParameter
作用:獲取指定參數之值。當參數不存在時,返回值為null。
原型:public String getParameter(String name)。其中,name為參數的名字。
2、getParameterValues
作用:當一個參數可以有多個值時,用此方法來取其值。它返回的是一個字符串數組。當參數不存在時,返回值為null。
原型:public String[] getParameterValues(String name)。其中,name為參數的名字。
3、getParameterNames
作用:取得Request對象中所有參數的名字,用于遍歷所有參數。它返回的是一個枚舉型的對象。
原型:public Enumeration getParameterNames()
㈣ SmartUpload類這個類完成上傳下載工作。
A.上傳與下載共用的方法:
只有一個:initialize。
作用:執行上傳下載的初始化工作,必須第一個執行。
原型:有多個,主要使用下面這個:
public final void initialize(javax.servlet.jsp.PageContext pageContext)
其中,pageContext為JSP頁面內置對象(頁面上下文)。
B.上傳文件使用的方法:
1、upload
作用:上傳文件數據。對于上傳操作,第一步執行initialize方法,第二步就要執行這個方法。
原型:public void upload()
2、save
作用:將全部上傳文件保存到指定目錄下,并返回保存的文件個數。
原型:public int save(String destPathName)
和public int save(String destPathName,int option)
其中,destPathName為文件保存目錄,option為保存選項,它有三個值,分別是SAVE_PHYSICAL,SAVE_VIRTUAL和SAVE_AUTO。(同File類的saveAs方法的選項之值類似)SAVE_PHYSICAL指示組件將文件保存到以操作系統根目錄為文件根目錄的目錄下,SAVE_VIRTUAL指示組件將文件保存到以Web應用程序根目錄為文件根目錄的目錄下,而SAVE_AUTO則表示由組件自動選擇。
注:save(destPathName)作用等同于save(destPathName,SAVE_AUTO)。
3、getSize
作用:取上傳文件數據的總長度
原型:public int getSize()
4、getFiles
作用:取全部上傳文件,以Files對象形式返回,可以利用Files類的操作方法來獲得上傳文件的數目等信息。
原型:public Files getFiles()
5、getRequest
作用:取得Request對象,以便由此對象獲得上傳表單參數之值。
原型:public Request getRequest()
6、setAllowedFilesList
作用:設定允許上傳帶有指定擴展名的文件,當上傳過程中有文件名不允許時,組件將拋出異常。
原型:public void setAllowedFilesList(String allowedFilesList)
其中,allowedFilesList為允許上傳的文件擴展名列表,各個擴展名之間以逗號分隔。如果想允許上傳那些沒有擴展名的文件,可以用兩個逗號表示。例如:setAllowedFilesList("doc,txt,,")將允許上傳帶doc和txt擴展名的文件以及沒有擴展名的文件。
7、setDeniedFilesList
作用:用于限制上傳那些帶有指定擴展名的文件。若有文件擴展名被限制,則上傳時組件將拋出異常。
原型:public void setDeniedFilesList(String deniedFilesList)
其中,deniedFilesList為禁止上傳的文件擴展名列表,各個擴展名之間以逗號分隔。如果想禁止上傳那些沒有擴展名的文件,可以用兩個逗號來表示。例如:setDeniedFilesList("exe,bat,,")將禁止上傳帶exe和bat擴展名的文件以及沒有擴展名的文件。
8、setMaxFileSize
作用:設定每個文件允許上傳的最大長度。
原型:public void setMaxFileSize(long maxFileSize)
其中,maxFileSize為為每個文件允許上傳的最大長度,當文件超出此長度時,將不被上傳。
9、setTotalMaxFileSize
作用:設定允許上傳的文件的總長度,用于限制一次性上傳的數據量大小。
原型:public void setTotalMaxFileSize(long totalMaxFileSize)
其中,totalMaxFileSize為允許上傳的文件的總長度。
C.下載文件常用的方法
1、setContentDisposition
作用:將數據追加到MIME文件頭的CONTENT-DISPOSITION域。jspSmartUpload組件會在返回下載的信息時自動填寫MIME文件頭的CONTENT-DISPOSITION域,如果用戶需要添加額外信息,請用此方法。
原型:public void setContentDisposition(String contentDisposition)
其中,contentDisposition為要添加的數據。如果contentDisposition為null,則組件將自動添加"attachment;",以表明將下載的文件作為附件,結果是IE瀏覽器將會提示另存文件,而不是自動打開這個文件(IE瀏覽器一般根據下載的文件擴展名決定執行什么操作,擴展名為doc的將用word程序打開,擴展名為pdf的將用acrobat程序打開,等等)。
2、downloadFile
作用:下載文件。
原型:共有以下三個原型可用,第一個最常用,后兩個用于特殊情況下的文件下載(如更改內容類型,更改另存的文件名)。
① public void downloadFile(String sourceFilePathName)
其中,sourceFilePathName為要下載的文件名(帶目錄的文件全名)
② public void downloadFile(String sourceFilePathName,String contentType)
其中,sourceFilePathName為要下載的文件名(帶目錄的文件全名),contentType為內容類型(MIME格式的文件類型信息,可被瀏覽器識別)。
③ public void downloadFile(String sourceFilePathName,String contentType,String destFileName)
其中,sourceFilePathName為要下載的文件名(帶目錄的文件全名),contentType為內容類型(MIME格式的文件類型信息,可被瀏覽器識別),destFileName為下載后默認的另存文件名。