posts - 13,comments - 19,trackbacks - 0
          軟件界面設(shè)計盡量簡潔明了,功能點擊盡量做到一次。
          普通的工作站的使用者,給功能提供盡量直接、方便的來回切換、跳轉(zhuǎn)、導(dǎo)航,應(yīng)當顯眼、直接、簡約,一步到位。
          manager的管理決策用戶,他們的時間寶貴,最好設(shè)計成傻瓜式的操作,同時,將最關(guān)鍵、最重要的信息,組織、放置在一屏當中。
          posted @ 2011-08-17 16:48 南山隱士 閱讀(195) | 評論 (0)編輯 收藏

          本原則是本人結(jié)合項目的實施開發(fā)編寫代碼情況,對多年以來帶領(lǐng)項目實施奮戰(zhàn)在開發(fā)一線經(jīng)驗的提煉與概括。這十條開發(fā)指導(dǎo)原則,最基本的思想是“高效,高質(zhì)量的寫出滿足業(yè)務(wù)功能目標的代碼。”每人可以結(jié)合當前項目的實際情況應(yīng)用,可以補充,修訂刪改進一步總結(jié)提煉。
          1.先開發(fā)簡單明確的功能模塊,后開發(fā)復(fù)雜的功能模塊。
          2.先做簡單的子功能,再做稍微復(fù)雜的子功能,后開發(fā)有難度邏輯復(fù)雜的子功能。
          3.以滿足業(yè)務(wù)功能要求為主要目標,不保留無用的垃圾代碼。寫出高質(zhì)量滿足功能要求的代碼,是建立在對業(yè)務(wù)需求理解,明確業(yè)務(wù)目標,邏輯思路清晰的結(jié)果。有時往往需要反復(fù)多次修改精益求精才能最后實現(xiàn)客戶滿意的功能。
          4.每開發(fā)一個功能模塊,都要頭腦清晰。(功能目的,界面表現(xiàn),程序邏輯思路,各層函數(shù)調(diào)用關(guān)系,數(shù)據(jù)存儲),全面系統(tǒng)考慮,力求每個細節(jié)都思考一遍,不使疏漏。在一般情況下比葫蘆畫瓢,充分借鑒一般常用的邏輯代碼,業(yè)界常用的一般方法,已有類庫函數(shù)。能夠迅速高效寫出高質(zhì)量的一般性代碼,以便騰出精力解決關(guān)鍵問題。力求避免功能函數(shù)重復(fù)開發(fā),代碼隨意復(fù)制,邏輯思路混亂,代碼隨意修改,瞎寫代碼。保證所寫的每一個函數(shù),每行代碼,都有意義,都有目的,堅決刪除無用的垃圾代碼。這樣就保證了,我們寫出的代碼是簡潔的,思路明確的。隨著時間的推移,我們寫的代碼越來越多,就會積累出跟本項目相關(guān)的很多通用的類庫,函數(shù)。通過對比,更能深入的理解業(yè)務(wù),抽象出公用的方法,邏輯規(guī)范。進而提高整個團隊的工作效率。通過循環(huán)迭代的思路,不斷地擴大成功經(jīng)驗。
          5.我們開發(fā)程序過程中,總有一些公用的函數(shù)類庫,可以調(diào)用。每次都不是從零開始,不是每行代碼都一行一行的手工輸入。要充分的利用工具,靈活應(yīng)用學(xué)過的方法。  
          6.發(fā)揚團隊協(xié)作精神,提高整體測試交叉測試意識,積極總結(jié)開發(fā)一般性類庫函數(shù),提供給大家調(diào)用。分享成功經(jīng)驗。避免一個人孤軍開發(fā),愁眉苦臉的編寫程序。共同攻克業(yè)務(wù)技術(shù)難題,苦中有樂。
          7.力求高質(zhì)量高效的完成開發(fā)模塊,不要鉆牛角尖,經(jīng)常交流,不懂就問。注意不要把問題復(fù)雜化,想當然,自己跟自己制造困難。如果問題越來越復(fù)雜,越開發(fā)代碼越?jīng)]頭緒就立即停止編寫,回到問題的原點重新考慮或跟大家交流聽聽別人的意見。
          8,在解決技術(shù)問題上,如果是關(guān)鍵問題,堅決研究,要徹底搞明白。與項目相關(guān)不影響全局的問題,可以根據(jù)實際情況優(yōu)先級放低一級。針對難點業(yè)務(wù)復(fù)雜的問題,先做外圍知識技術(shù)準備,找出關(guān)鍵點,先易后難分步驟逐漸深入的去解決。最后將其貫穿成一個整體。
          9.經(jīng)常查看別人代碼,吸取別人的經(jīng)驗,充實自己。我們的知識積累主要來自別人,主要在當前項目。取之于別人,受益于自己。受益于項目。
          10.善于利用零星時間,比較已經(jīng)做過的功能模塊。不斷的整理,優(yōu)化已經(jīng)開發(fā)過的代碼。發(fā)現(xiàn)Bug及時修正,精益求精。

          本文來自CSDN博客,轉(zhuǎn)載請標明出處:http://blog.csdn.net/zhaoyu_1979/archive/2011/03/16/6254021.aspx

          posted @ 2011-03-23 16:45 南山隱士 閱讀(228) | 評論 (0)編輯 收藏
           一相關(guān)下載

          (1) java JDK下載:

          進入該網(wǎng)頁: http://java.sun.com/javase/downloads/index.jsp (或者直接點擊下載)如下圖:
          選擇 Download JDK 只下載JDK,無需下載jre.

          (2)eclipse下載

             進入該網(wǎng)頁: 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   安裝完成即可,無需配置環(huán)境變量

             (2)解壓eclipse       eclipse無需安裝,解壓后,直接打開就行

             (3)解壓android sdk     這個也無需安裝,解壓后供后面使用

             (4)最終有三個文件夾,如下圖:

             

          三 Eclipse配置

             1 安裝android 開發(fā)插件

               (1)打開Eclipse, 在菜單欄上選擇 help->Install New SoftWare 出現(xiàn)如下界面:


              點擊 Add按鈕,出現(xiàn)如下界面


               輸入網(wǎng)址: https://dl-ssl.google.com/android/eclipse/    (如果出錯,請將https改成http)

               名稱: Android (這里可以自定義)

             點擊OK,將出現(xiàn)如下界面


          點擊 Next按鈕 ,出現(xiàn)如下界面:


            

          點擊Next按鈕,出現(xiàn)如下界面:


          選擇 I accept the terms of the license agreements   點擊Next,進入安裝插件界面

          安裝完成后,出現(xiàn)如下界面


          點擊Yes按鈕,重啟Eclipse

          2 配置android sdk

               (1)點擊菜單window->preferences,進入如下界面


             選擇你的android SDK解壓后的目錄,選錯了就會報錯,這個是升級工具,目前還沒有一個版本的SDK

          (2)升級SDK版本,選擇菜單 window->Android sdk and avd manager 出現(xiàn)如下界面

                

             選擇update all按鈕,出現(xiàn)如下界面


          選擇左邊的某一項,點擊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,得到如下結(jié)果

          如上顯示創(chuàng)建AVD完畢





          3 新建Android項目

          (1)選擇菜單file->new->other 進入如下界面:

          選擇新建Android Project項目,點擊Next按鈕,進入如下界面


          名稱自定義,應(yīng)用程序名自定義,報名必須包含一個點以上,min SDK version里面必須輸入整數(shù)

          點擊Next出現(xiàn)如下界面:


          注: 若有錯誤如: Project ... is missing required source folder: 'gen' ,則將gen->Android.Test->R.java這個文件刪掉,Eclipse會為我們重新生成這個文件,并且不會報錯。

          (3)配置運行

             右鍵項目->Run as -> Run Configuration 進入如下界面:
          該界面,點擊Browse 按鈕,選擇你要運行的項目

          選擇Target切換到以下界面


          該界面選擇運行的AVD,將AVD前面的方框設(shè)置為選擇狀態(tài)。

          (4)測試項目運行

             右鍵項目名稱->run as ->Android Application 即可啟動運行該Android程序,如下所示:


          正在進入


          測試程序運行結(jié)果

           

          四 結(jié)束語

                 至此,android開發(fā)環(huán)境搭建完畢,有問題請留言。在這里要注意,我這里只是下載了android sdk r4升級工具,沒有下載具體的SDK,而是通過在Eclipse里面的Android Sdk管理工具升級的,你也可以直接下載具體的SDK版本,如: Android sdk 2.1 r1 上面有這個的下載鏈接,但我任務(wù)用升級工具更好。

          posted @ 2010-07-13 14:35 南山隱士 閱讀(635) | 評論 (0)編輯 收藏
          建立一個Silverlight項目,添加一個子窗口ChildWindow1.xaml.

          在子窗口設(shè)計中添加一個輸入框:<TextBox x:Name="txtUserInfor" Grid.Row="0" />
          添加子窗體的CS代碼:

           string testString;

                  public string TestString
                  {
                      get { return testString; }
                      set { testString = value; }
                  }


          增加一個事件: public event EventHandler OkClicked;
          修改OKButton_Click方法:


                  private void OKButton_Click(object sender, RoutedEventArgs e)
                  {
                      if (OkClicked != null)
                      {
                          TestString = txtUserInfor.Text;
                          OkClicked(this,new EventArgs());
                      }

                      this.DialogResult = true;
                  }

          子窗口修改完畢。

          父窗體:
          設(shè)計中添加一個輸入框和一個Button:

          <TextBox x:Name="tbInfo" Width="100" Height="50"></TextBox>
           <Button Click="Button_Click" Width="100" Height="60" Content="子窗口測試" HorizontalAlignment="Right"></Button>

           修改父窗體代碼:

             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();
                  }
          完畢。
          運行,點擊父窗體按鈕,彈出子窗體。在子窗體的輸入框中輸入內(nèi)容,點擊確認后關(guān)閉子窗體,同時子窗體的數(shù)據(jù)更新到父窗體的輸入框中。

          posted @ 2009-12-11 09:56 南山隱士 閱讀(1025) | 評論 (1)編輯 收藏
          可以總結(jié)為兩大關(guān)鍵點:一是養(yǎng)成好的編程習(xí)慣,二是針對自已的工作提高自已的知識含量.

          一.    好的編程習(xí)慣

          1.       寫程序前打個草稿可以在心里,最好在紙上:目的要從整體上考慮程序的實現(xiàn)。

          如果公司采用建模的方式,有建模工具(rose ,visio )那是最好不過的了。

           2.    注意休息,不要浪費自已的休息時間,用去了自已的時間不但會寫出的代碼因為注意力不集中而會常常出現(xiàn)代碼的質(zhì)量有問題,邏輯常出錯

          3.    要善于收集相關(guān)的專業(yè)開發(fā)上的資料,以便以后能更快更好的解決問題目。提倡公司能提供內(nèi)部知識勾通的工具(如知識論壇,內(nèi)部即時聊天器);提倡公司內(nèi)部有技術(shù)資料的共享庫,提高解決問題的能力.

          4.    提高對所寫的模塊的相關(guān)全局把握能力,在寫程序中要最好先詳細設(shè)計后再發(fā)布.

          5.    要學(xué)會與他人溝通如非工程師,學(xué)會溝通的不同方式,提高溝通的效率。

           二.    不同的目標不同的知識重點

          (一)        目標:程序員

          職責(zé):根據(jù)詳細設(shè)計文檔,或根據(jù)高級程序員的設(shè)計進行相關(guān)的開發(fā)。

          1.    要學(xué)會看相關(guān)的需求文檔及詳細設(shè)計文檔。

          注意:你必須要通過閱讀這些文檔把握住其中的重點,關(guān)鍵點,相關(guān)易漏點

          2.    如果公司里會用UML來相互的溝通,這時你必須要深刻理解UML 的相關(guān)知識,一定要注意千萬不要對UML圖一知半解的情況下,就著寫代碼,那樣會錯的很慘。

          3.    學(xué)好對應(yīng)的計算機語言的基礎(chǔ)知識,如:程序的語法,關(guān)鍵點,易錯點,對應(yīng)的出錯如何出理,如何才能把對就的程序?qū)懙逆I壯一些

          4.    如果用到數(shù)據(jù)庫的內(nèi)容,在學(xué)會sql的前提下,盡量學(xué)會數(shù)據(jù)庫原理中的相關(guān)sql內(nèi)容, 當然為了提高查詢的能力也可以增加一點

          5.    如果用到面向?qū)ο竦恼Z言那最好學(xué)點相關(guān)的設(shè)計模式,這樣的可以增加代碼的擴展性,及可維護性等,能夠理解詳細設(shè)計中的模塊間的設(shè)計原則這個也可以提高對模塊的內(nèi)容編寫的正確性.

          6.    你一定要學(xué)會公司內(nèi)部的通用的編碼規(guī)范。

          7.    學(xué)習(xí)如何做單元測試比較好.必須要熟悉相關(guān)的單元測試工具.

          8.    要不斷的對相關(guān)知識進行總結(jié),同時也要必須把相關(guān)的資料進行整理和學(xué)習(xí),在學(xué)習(xí)過后的資料中你可以在遇到問題時更快的找到問題的答題。

          9.    在開發(fā)你必須記錄下大家常出錯的地方及大家的解決方法,這個對你以后錯誤的避免有很大的作用.

          10.    在寫代碼中時必須把上面寫過代碼記在心里,這樣就可以養(yǎng)成習(xí)慣,提高代碼的速度

          11.    對數(shù)據(jù)庫操作時,要盡量共用Connection,并小用以減少Connection的數(shù)量

          (二)    目標:高級程序員

          職責(zé):對需求文檔進行系統(tǒng)相關(guān)模塊的詳細設(shè)計,并負責(zé)對程序員的支持及指導(dǎo)和相關(guān)核心模塊的編寫

          所以不但要學(xué)會相關(guān)程序員要的知識,同時還要學(xué)會難度比較大的知識。

          1. 程序員的知識,如設(shè)計模式你一定要不是簡單的看要懂,你還要應(yīng)用設(shè)計模式對相應(yīng)的模塊進行相關(guān)的詳細設(shè)計。

          2.  要學(xué)好相關(guān)詳細設(shè)計的工具做的有的放矢,這樣可以更好提高對自已的設(shè)計的表達

          3.  為了提高系統(tǒng)的運行效率會運用到

          a.         數(shù)據(jù)庫的表結(jié)構(gòu)如何建才能使應(yīng)用的要查詢sql 更快。這時可要認真認真的學(xué)習(xí)一樣數(shù)據(jù)庫原理,千萬不要以為采用數(shù)據(jù)庫的范式越高系統(tǒng)的運行效率會越好,有時候適當?shù)谋砣哂嗫梢源蠓鹊奶岣呦到y(tǒng)的查詢效率.  同時適當?shù)慕ㄋ饕?視圖,存儲過程也是提高系統(tǒng)對數(shù)據(jù)庫的查詢的效率之一。

          b.         學(xué)習(xí)多線程的編程,不過千萬不要以為線程數(shù)越多運行的速度會越快,一般線程的數(shù)量超過一定的數(shù)量后,系統(tǒng)的運行速度反而會變慢。為了應(yīng)用好多線程,操作系統(tǒng)這本書也要關(guān)于同步及相關(guān)進程和線程的知識必不可少。

          c.         設(shè)計好的一程序的好的算法,可要比起解一道同一復(fù)雜的數(shù)學(xué)題,要難的多,所以要在學(xué)好的相關(guān)數(shù)學(xué)的知識上(如線性代數(shù),離散數(shù)學(xué),概率論,數(shù)理統(tǒng)計)。更要深入計算方法,及數(shù)據(jù)結(jié)構(gòu),讓數(shù)學(xué)問題用計算機來解決。

                   4.為了讓系統(tǒng)設(shè)計的更加的可擴展性,穩(wěn)定性,設(shè)計模式和軟件工程可是不能少的東西。所以必須把設(shè)計模式用于模式級的設(shè)計.

                   5. 如果公司采用的是Rose (UML)進行設(shè)計的話,你對于UML 的理解一定要非常的準確,同時你要跟小組中的程序之間進行充分的UML概念上及對應(yīng)用例圖,類型圖,對象圖,協(xié)作圖的意思多寫一些注釋加深大家對你的設(shè)計上的理解。

          (三)         目標:系統(tǒng)分析員

          職責(zé):做好與客戶之間的關(guān)系,同時對客戶的需求要正確的理解,要選擇合適的開發(fā)技術(shù),同時做好與客戶間溝通交流,學(xué)會說服對方。

          1.  學(xué)會對客戶的溝通:要正確理解客戶的需求同時要保證相互之間的溝通順暢。

          2.  對了解來的需求要能用筆正確的描述下來,并能很好的傳敘給其他人。這時要學(xué)會用如ROSE 等的軟件建模的工具。和powerdesign等的數(shù)據(jù)庫建模工具。和相關(guān)的UML,數(shù)據(jù)流程圖及相關(guān)的內(nèi)容的知識。

          3.  不但要全面的了解客戶的需求而且還要對需求進行未來的可能的改變要有相當多的了解。

          4.  全面的了解客戶的需求后,要選擇合適的相關(guān)技術(shù)用于開發(fā),:

          這時要學(xué)習(xí)各種知識

          a.  先擇數(shù)據(jù)庫:db2,infomix ,oracle ,sql server,mysql 的優(yōu)缺點,可以從中選擇最適合的數(shù)據(jù)庫及理由。

          b. 設(shè)計數(shù)據(jù)庫:要扎實在數(shù)據(jù)庫的理論(數(shù)據(jù)庫原理,數(shù)據(jù)庫系統(tǒng)設(shè)計)及相關(guān)數(shù)據(jù)庫設(shè)計經(jīng)驗,要盡量多的分析過去數(shù)據(jù)庫設(shè)計,分析這么設(shè)計數(shù)據(jù)庫的好處。這時可能要用到 powerdesign等工具。

          c. 寫需求說明文檔和概要設(shè)計文檔,同時要學(xué)會要分析相關(guān)需求說明文檔的需要的內(nèi)容的相關(guān)知識,如人員工時的計算方法, 一般會用 project 來分析相關(guān)的項目的內(nèi)容。

          d. 選擇合適的程序語言及相關(guān)的架構(gòu),一般主流的架構(gòu)是 J2EE和.net的相應(yīng)的優(yōu)點及它們之間的結(jié)合,如采用soap xml進行相關(guān)的結(jié)合,或用java-com 橋 進行相關(guān)的功能的調(diào)用。和它們之間的相關(guān)語言優(yōu)缺點

          e.  還要根據(jù)b/s,c/s 結(jié)構(gòu)對開發(fā)的網(wǎng)絡(luò)影響的相關(guān)內(nèi)容采取選擇。

           5. 學(xué)會說服對方,畢竟客戶都不是個個是軟件專家,他們的選擇有時未必是正確的所以學(xué)會說服對方,是系統(tǒng)分析員必備的能力條件.                           

           三.    訓(xùn)練的方法:

          1.       計劃行事:

          (1 設(shè)定你的未來的學(xué)習(xí)目標

          a.         未來要成為什么樣的人(主要是工作角色,如程序員,高級程序員,系統(tǒng)分析員)

          b.         你近期要成為什么樣的人(當前的工作職責(zé)是什么,如果只寫代碼是程序員等)

          c.         要完成近期的工作所必須要知識(如java 程序員,要學(xué)習(xí)java 基礎(chǔ)知識,等),關(guān)鍵的知識(如java中關(guān)鍵要用到的知識有,面向?qū)ο蟮龋?易錯的知識(比較原來的已有知識進行合對)

          (2      設(shè)定你的學(xué)習(xí)目標后,并要有針對性的對應(yīng)目標設(shè)定學(xué)習(xí)時間的按排及學(xué)習(xí)路線。并直觀的記錄在案,以便以后隨時核對,

          (3      常常抽出一定的時間認真核對計劃的完成情況,如果沒有按時完成計劃的內(nèi)容。分析原因,盡量想法趕上計劃內(nèi)容如果存認是計劃有誤,要認真總結(jié)計劃失敗出錯的原因,對你的未來有很大的幫助。

          注意:不要對計劃的按排過于樂觀 要盡量的考慮實現(xiàn)中的各種情況,同時適當按排一些緩沖時間,以便真正能按照計劃行事,以提高按計劃行事信心,同時這能有效避免出現(xiàn)計劃中途成沒有意義的東西。

          2.  針對工作角色對自已的能力進行培養(yǎng)和知識進行學(xué)習(xí)。

          關(guān)鍵的能力:

           (1. 記憶能力:要學(xué)會把自已的寫的代碼和改的代碼記的清清楚楚。要能提高效率。

           (2. 邏輯思維能力:要多多的看別人的復(fù)雜邏輯的代碼,分析復(fù)雜邏輯的運算。

           (3.全局能力: 不要再范改了東,卻西出錯。(構(gòu)造軟件這個很重要)

           (4.學(xué)習(xí)能力: 并不是每個項目都你是所熟悉的項目的,并不是每個項目中的知識你都知道,要掌握最新的技術(shù)和最有用的知識,是最關(guān)鍵的。要學(xué)會,提高能力,這個東西是永遠對自己有好處的。

           (5. 溝通能力; 學(xué)會幽默,學(xué)會講故事,學(xué)會交朋友,學(xué)會禮節(jié)。

           (6.自制能力:如果一個人不能自制那這個人以后,不會有很大成果,即使很大機會發(fā)展起了,可是因為沒有自制能力很容易被人利用,或自己明明知道怎么做,可是就是不能控制自己的欲望.而常做下無法挽回在錯誤.

           四.    例:java 程序員的知識結(jié)構(gòu)及學(xué)習(xí)流程:

            (一) 學(xué)習(xí)相關(guān)工作必須的知識

             1.Java 語言的基礎(chǔ)(推薦書:《 java 編程思想》)

          關(guān)鍵:

          (1.     java 面向?qū)ο蠹皩?yīng)的程序現(xiàn)實

          (2.     java  多線程

          (3.     java  網(wǎng)絡(luò) socket

          (4.     應(yīng)用界面

             2.學(xué)會用智能集成開發(fā)工具jbuilder,eclipse等一種,根據(jù)資料里的內(nèi)容,自已寫與例程類似的代碼,但注意不要直接抄它,一定要自已寫。同時最好寫到一個工程中以便對比。

             3.如果用b/s結(jié)構(gòu)要學(xué)習(xí)jsp的知識(推薦書:《 JSP 2.0技術(shù)手冊 》)

          關(guān)鍵:

          (1. 界面處理:

          a . HTML——超文本標志語言:用于顯示頁面如:超文本鏈接, 表格,各種標志等。

          b. CSS———層疊樣式表:控制正文外觀的一組格式.用于美化HTML頁面。

          c. javaScript—嵌入HTML頁面瀏覽器來執(zhí)行的腳本語言:讓頁面可以根據(jù)用戶的操作或事先設(shè)置等在客戶端進行動態(tài)變化,而且不需傳回服務(wù)器。比如: 對表單輸入的正確性做客戶端驗證.

          (2.jsp元素:如java代碼寫法,對應(yīng)標志---jsp:include,jsp:useBean,jsp:setProperty,

          jsp:getProperty等.jsp的幾大對

           (3.  javaBean及其在jsp 中的調(diào)用和相關(guān)應(yīng)用.

           (4. 其他技術(shù):

            a. 如何操作數(shù)據(jù)庫—用jdbc(可能要補充一些數(shù)據(jù)庫的知識,如oracle ,sql server,

          包括如何寫高效率的查詢sql,存儲過程等) ,

          b. 如何發(fā)送email—用javaMail,

          c. 如何學(xué)習(xí)如何用實現(xiàn)文件的上傳下載,如果操作文件,

          d. 如何操作xml  --用jdom 及 jaxp(這時有必要學(xué)習(xí)一下xml 的語法如 dtd等)

          e. 如何遠程方法調(diào)用—用 rmi

          f. 如何進行消息服務(wù) ---用 jms

           5.再有些公司會用到 J2EE 的架構(gòu)如 EJB 作為業(yè)務(wù)邏輯.

          (1.EJB中要分清

          (2. struts  MVC

          (3. Hibernate 操作數(shù)據(jù)庫

           6.最好學(xué)習(xí)一下UML

          學(xué)用Rose建模

           五 忠告:

             1. 不要以為自已很差,要明白每個人都是這樣一步一個腳印的走過來的。(我們要有信心)

          告訴自已:比爾蓋次,也是同我們一樣,出生時也是巴掌大.

          我們只有多學(xué),多練才可能有出路.

             2. 不要以為自已學(xué)的多就很強,世界上的高手多的是,問問自己,你每小時可以寫幾行代碼,代碼一次寫下來有多少錯誤,如果你一次寫下沒有錯誤,一小時可以寫1000代碼,那才是真正的高手.

             3 . 不要以為自已沒有項目做就會落后于他人,人家是參加了很多項目,可是人家只是項目中的一個小角色,如果我們在空時能都寫一些開源的項目,或自己開發(fā)和設(shè)計一些有用的開源的項目,水平及能力很快就上來了.

             4.   不要以為自己做過很多的項目就很了不起了。你能說你做的項目中,你能體會整個項目為什么要這樣設(shè)計,為什么要這樣開發(fā)嗎?相信絕大多數(shù)是否定的回答。那還不如多學(xué)習(xí)一些已做的項目,了解他們?yōu)槭裁匆@么做,為什么這么開發(fā),多看一下它們的項目的文檔,我們能明白很多,這樣把他們的經(jīng)驗放于你未來可能要接手的項目,這樣不是更好嗎?

             5. 不要以為自己的學(xué)習(xí)能力很牛,你能快速閱讀一本書又能快速掌握它的內(nèi)容嗎

          posted @ 2008-12-11 19:12 南山隱士 閱讀(266) | 評論 (0)編輯 收藏
          安全永遠是WEB應(yīng)用系統(tǒng)必須面對的頭等大事, 也是最頭疼的事, 其實安全系統(tǒng)就只包括兩個問題: 認證和授權(quán).    以前做些網(wǎng)站系統(tǒng), 安全檢測邏輯都在放在須要安全控制的代碼前面, 這樣做有很多不好的地方, 重復(fù)多次的編碼就不用說了, 代碼移植性, 重用性都得不到體現(xiàn), 安全檢測邏輯要永遠和業(yè)務(wù)邏輯放在一起.
              那么, 能不能夠在進入方法前就調(diào)用一些安全檢測? 其實Spring AOP就是這個思想, 那么又如何實現(xiàn)安全檢測呢? Spring Acegi Security 框架就是做這個事情.
               本文主要是討論下在已有的SSH系統(tǒng)中, 如何使用Acegi作為安全框架實現(xiàn)基于角色的權(quán)限控制(Role Based Access Control RBAC) , 本文主要是以Java 5注解的形式來配置安全框架, 大大減化配置和操作.
              本文的主要參考資料: <Spring 2.0 核心技術(shù)與最佳實踐> 第10章 (Spring Acegi 安全框架)
                          <精通Spring 2.X -- 企業(yè)應(yīng)用開發(fā)詳解> 第17章 (使用Acegi 實施應(yīng)用系統(tǒng)安全)
                          acegi-security-1.0.6 官方文檔
              說明: 本文介紹的是RBAC, 在官方文檔的基礎(chǔ)上有所擴展或改動, 以更適合WEB應(yīng)用系統(tǒng). 其實我覺得大多數(shù)的網(wǎng)站基于角色已經(jīng)足夠了, 一般都沒必要基于權(quán)限.
               文章開始:
          一. 下載所要的軟件或JAR包:
              我的相關(guān)配置是: Java 5, Tomcat 5.5.26, Struts 2.0.11, Spring 2.5.1, Hibernate 3.2, Acegi 1.0.6
          二. 建立相關(guān)的數(shù)據(jù)庫:
               數(shù)據(jù)表: 用戶信息表User: id, enable, user_name, user_pass, email_box
                           角色信息表RoleInfo: id, role_name, role_title, descp
                           用戶與角色關(guān)聯(lián)表(用戶與角色是多對多關(guān)系)UserRole: user_id, user_name, role_id, role_name
                          并在這三個表中插入相關(guān)的數(shù)據(jù), 我是定義了兩種角色(role_name): ROLE_USER, ROLE_ADMIN
                          和三個用戶, 一個用戶角色為: ROLE_USER, ROLE_ADMIN
                           另一個用戶角色為: ROLE_USER
                          第三個沒有角色.
          二. 修改配置文件:
              其實對Acegi框架的應(yīng)用難點就在配置文件, 所以要特別注意了:
              在 src 建立Acegi的配置文件: acegi-security.xml 當然這個文件的名稱是可以任意的.
              acegi-security.xml 說白了就是配置: 安全攔截器, 認證管理器, 決策管理器.
              其內(nèi)容如下:
          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          <!-- ========================= 認證管理器 ========================= -->
          <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>
          <!-- 是否全部棄權(quán)就通過 -->
          <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="/" />
          <constructor-arg>
             <list>
              <ref bean="rememberMeServices" />
              <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
             </list>
          </constructor-arg>
          <!-- 登錄退出的URL -->
          <property name="filterProcessesUrl" value="/j_logout.j" />
          </bean>
          <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">
          <!-- 出現(xiàn)AuthenticationException時的登錄入口 -->
          <property name="authenticationEntryPoint">
             <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
             <property name="loginFormUrl" value="/login.jsp" />
              <property name="forceHttps" value="false" />
             </bean>
          </property>
          <!-- 出現(xiàn)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>
              在上面的配置文件中, 紅色部分要特別注意, 其余的內(nèi)容都差不多了.
          <bean id="userDetailsService" class="org.ymcn.security.AcegiUserDeitailsService">
          <property name="userDao" ref="userDao" />
          <property name="userRoleDao" ref="userRoleDao" />
          </bean>

              在整個應(yīng)用的安全控制中, 我們唯一要編寫代碼的類就是: 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>

              注意: 這個過濾器一定要在MVC轉(zhuǎn)發(fā)過濾器的前面!!!!
          四. 在 applicationContext.xml 中增加 Acegi安全控制攔截器Spring的自動代理功能實現(xiàn)AOP代理
          <!-- 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的自動代理功能實現(xiàn)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;
          }

          /* 用戶所有的權(quán)限 */
          //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.");
             }
             /* 取得所有用戶權(quán)限 */
             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);
          }
          }
          六. 在業(yè)務(wù)邏輯代碼中利用Java 5注釋實現(xiàn)安全控制
          @Secured({"ROLE_USER"})
          void sendSimpleMail(Long userId);

          @Secured({"ROLE_ADMIN"})
          void sendAttachmentMail() throws Exception;

              其實就是在需要安全控制的方法前加上: @Secured({"角色名"}), 非常的簡單
          七. 整個工作完成
              Acegi框架完全是一種可插拔式的, 完全可以在原有的系統(tǒng)中加個一個配置文件, 和在每個方法前加上: @Secured({"角色名"}) 就可完成.
               上面的 AcegiUserDeitailsService.java 中的有 UserDao, UserRoleDao, 我想一看就知道它們是干什么的了, 這完全取決于個人的實現(xiàn), 與Acegi無關(guān), 它僅僅只要返回一個 return new org.acegisecurity.userdetails.User(userName, user.getUserPass(),
                    true, true, true, true, this.grantedAuthArray) 就可以了.
          posted @ 2008-12-11 18:51 南山隱士 閱讀(689) | 評論 (0)編輯 收藏

          上個世紀90年代中期,為了推進我國企業(yè)管理信息化,尋求更大的企業(yè)發(fā)展空間,一批具有一定規(guī)模的財務(wù)軟件公司紛紛轉(zhuǎn)向企業(yè)管理軟件,大量冠名為某某管理的軟件產(chǎn)品迅速涌現(xiàn),同時國際管理軟件巨頭紛紛搶灘國內(nèi)市場,在這些軟件企業(yè)的大力推動下,我國企業(yè)界開始廣泛了解管理軟禁先進性,2004年-2005年,管理軟件開始成為市場迅速增長的需求,國內(nèi)眾多公司開始使用管理軟件成為一種趨勢。

           
          但是,現(xiàn)在回過頭看來,真正成功、成熟的管理應(yīng)用案例在中國市場仍然鳳毛麟角。
           
          目前市面上,叫“管理軟件”的成千上萬,很多的管理軟件,他們的界面、輸入、操作是那么的千篇一律,這類軟件,開發(fā)就是搭積木,裝配的痕跡太重,沒有個性。有專家指出,管理思想很難“落地”的核心原因就在于對信息層次管理的認識的缺失或不足,往往被意識層次中的一種習(xí)慣性思維--試圖用思想讓思想“落地”所束縛,而現(xiàn)實中,阻礙管理思想“落地”的核心問題,恰恰更多的都集中到信息層次的管理問題上了。所以,要想真正讓管理思想“落地”,我們管理者必須跳出意識層次來看問題,并采用信息層次的管理手段來進一步解決問題。
           
          從這里我們不難發(fā)現(xiàn),問題的根源就在于沒有把管理思想真正通過信息化落實下去。很多管理軟件應(yīng)用企業(yè),僅僅只是把管理軟件當做一個統(tǒng)計或者發(fā)發(fā)信息的工具。
           
          而用戶真正需要的是解決企業(yè)在經(jīng)營管理中遇到的問題,而這些問題的解決需要一個從單項產(chǎn)品到整合應(yīng)用的發(fā)展過程。我國企業(yè)最初的需求是財務(wù)管理、進銷存管理,這已經(jīng)在前些年的財務(wù)軟件發(fā)展浪潮中得到普及。我國企業(yè)現(xiàn)在的需求,是面對著工業(yè)化改革與信息化顛覆的雙重革命,需要利用最少的成本代價,將舊的系統(tǒng)遷移到新的平臺上,從而適應(yīng)網(wǎng)絡(luò)經(jīng)濟和電子商務(wù)帶來的供應(yīng)鏈管理、客戶關(guān)系管理等領(lǐng)域的時代變化。我國企業(yè)未來的需求,是將企業(yè)內(nèi)外資源的管理納入到統(tǒng)一的符合我國特色國情的管理平臺之上,徹底改造企業(yè)管理體制和機制。
           
          我們國家的管理軟件,這么多年來最缺的是管理思想和管理方法,沒有科學(xué)的管理模型作為支撐,管理軟件是不能稱之為“管理軟件”的。因為管理軟件的核心不在于軟件技術(shù)本身,而是在于管理思想的問題。
           
          一位業(yè)內(nèi)資深人士就說了:“我們國家十幾年來管理軟件產(chǎn)業(yè)的發(fā)展,最致命的問題就出在這個地方,我們很多的軟件公司、很多編程人員不懂管理,不知道企業(yè)的管理問題是什么,更不知道解決這些問題的管理思想和管理模型是什么,他們開發(fā)出來的“管理軟件”,當然也就不能真正幫助企業(yè)解決管理問題。”這種“管理軟件”充斥著市場,客戶的普遍不滿意也就是情理之中的事情了。
           
          管理軟件是用來解決管理問題,其關(guān)鍵在于管理的思想和方法。可以說,管理思想和方法是管理軟件的靈魂。今天,我們很多人仍然以為管理軟件門檻很低,大學(xué)畢業(yè)出來就能做,只要會編程的人員就能做。開發(fā)管理軟件產(chǎn)品,必須先把要解決的管理問題研究清楚,把解決這些問題的管理方法和管理模型的研究清楚,然后再開發(fā)軟件產(chǎn)品。
           
          前沿的軟件技術(shù)、獨特的行業(yè)業(yè)務(wù)模型加上科學(xué)的管理思想和方法,三者的創(chuàng)造性融合,才有可能產(chǎn)生一個真正能創(chuàng)造客戶價值的管理軟件產(chǎn)品。著名的金和軟件產(chǎn)品一直被業(yè)界稱為“有思想的軟件”,關(guān)鍵在于金和軟件對協(xié)同管理軟件的準確定位,以及為客戶帶來真正的價值。眾所周知,無論前端OA系統(tǒng)還是后端ERP等業(yè)務(wù)系統(tǒng),都是遵循固定流程的,產(chǎn)品之間并無明顯的差異,但是在這兩者之間的協(xié)同領(lǐng)域,卻存在很高的準入壁壘。金和軟件創(chuàng)造性地發(fā)揮獨創(chuàng)的精確管理思想和協(xié)同理念優(yōu)勢,以產(chǎn)品、工具和行業(yè)解決方案為基礎(chǔ),構(gòu)建了適合各個行業(yè)的協(xié)同管理平臺。
           
          協(xié)同企業(yè)是現(xiàn)代企業(yè)運營的高級狀態(tài),企業(yè)作為一個整體,一定是一個協(xié)同的系統(tǒng),有效的協(xié)同決定了企業(yè)的經(jīng)營效率、達成目標的能力、資源的有效利用以及企業(yè)核心能力。金和C6的設(shè)計完全符合這種柔性的企業(yè)協(xié)同理念。協(xié)同企業(yè)的主要基礎(chǔ)是企業(yè)流程和知識系統(tǒng),它們本身是剛性的和持續(xù)積累的,但是以此為基礎(chǔ)的協(xié)同管理平臺卻是整合的、柔性的,通過長期的應(yīng)用和優(yōu)化,最終使企業(yè)的協(xié)同能力不斷提高,真正成為協(xié)同企業(yè)。
           
          作為國產(chǎn)軟件企業(yè)的責(zé)任之一,不能僅僅是銷售軟件,更重要的是交給企業(yè)一把“利劍”。這就要把先進的技術(shù)和先進的管理思想一起交給企業(yè)。僅僅“把軟件用起來”或“提高工作效率”并不是最終目的,只有通過管理思想的落實,真正提高了企業(yè)的管理水平,才是實施管理軟件系統(tǒng)的真實目標。在當前的管理軟件市場中,過分強調(diào)技術(shù)含金量以突出產(chǎn)品的先進性也是一種不良的傾向。
           
          管理軟件的開發(fā)設(shè)計上,必須具體兩個條件:一是對業(yè)務(wù)流程的深刻理解;二是設(shè)計者所具備的能力。只有好的理解,在軟件設(shè)計上沒有可供操作的控件,就不能隨心所欲的去實現(xiàn)設(shè)計的初衷,表現(xiàn)在使用上,則是讓用戶改變它們過去的工作習(xí)慣和方式。對于管理軟件領(lǐng)域而言,如果不能將先進的技術(shù)通過先進的管理思想把企業(yè)用戶的應(yīng)用實際統(tǒng)一起來,再高的技術(shù)含金量也只能是事倍功半。技術(shù)與應(yīng)用的融合,其目的是貫徹一種核心管理思想,其目的是幫助企業(yè)實現(xiàn)體制機制創(chuàng)新。建設(shè)信息交流完備的組織系統(tǒng),確立供應(yīng)鏈管理的核心地位,全面拓展客戶關(guān)系管理,最終實現(xiàn)企業(yè)的資源整合。
           
           
          經(jīng)歷了十年風(fēng)雨,我們有理由相信,跨入新世紀的我國企業(yè)管理軟件市場將能更為準確地把握各類管理軟件的精髓,解開中國管理軟件發(fā)展癥結(jié),最終推動企業(yè)管理進步,促進整個市場朝著健康、有序和獨立的方向蓬勃發(fā)展。
          posted @ 2008-08-27 13:38 南山隱士 閱讀(171) | 評論 (0)編輯 收藏

          一、安裝篇
          jspSmartUpload是由www.jspsmart.com網(wǎng)站開發(fā)的一個可免費使用的全功能的文件上傳下載組件,適于嵌入執(zhí)行上傳下載操作的JSP文件中。該組件有以下幾個特點:
          1、使用簡單。在JSP文件中僅僅書寫三五行JAVA代碼就可以搞定文件的上傳或下載,方便。
          2、能全程控制上傳。利用jspSmartUpload組件提供的對象及其操作方法,可以獲得全部上傳文件的信息(包括文件名,大小,類型,擴展名,文件數(shù)據(jù)等),方便存取。
          3、能對上傳的文件在大小、類型等方面做出限制。如此可以濾掉不符合要求的文件。
          4、下載靈活。僅寫兩行代碼,就能把Web服務(wù)器變成文件服務(wù)器。不管文件在Web服務(wù)器的目錄下或在其它任何目錄下,都可以利用jspSmartUpload進行下載。
          5、能將文件上傳到數(shù)據(jù)庫中,也能將數(shù)據(jù)庫中的數(shù)據(jù)下載下來。這種功能針對的是MYSQL數(shù)據(jù)庫,因為不具有通用性,所以本文不準備舉例介紹這種用法。
          jspSmartUpload組件可以從www.jspsmart.com網(wǎng)站上自由下載,壓縮包的名字是jspSmartUpload.zip。下載后,用WinZip或WinRAR將其解壓到Tomcat的webapps目錄下(本文以Tomcat服務(wù)器為例進行介紹)。解壓后,將webapps/jspsmartupload目錄下的子目錄Web-inf名字改為全大寫的WEB-INF,這樣一改jspSmartUpload類才能使用。因為Tomcat對文件名大小寫敏感,它要求Web應(yīng)用程序相關(guān)的類所在目錄為WEB-INF,且必須是大寫。接著重新啟動Tomcat,這樣就可以在JSP文件中使用jspSmartUpload組件了。
          注意,按上述方法安裝后,只有webapps/jspsmartupload目錄下的程序可以使用jspSmartUpload組件,如果想讓Tomcat服務(wù)器的所有Web應(yīng)用程序都能用它,必須做如下工作:
          1.進入命令行狀態(tài),將目錄切換到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目錄下。
          二、相關(guān)類說明篇
          ㈠ File類
          這個類包裝了一個上傳文件的所有信息。通過它,可以得到上傳文件的文件名、文件大小、擴展名、文件數(shù)據(jù)等信息。
          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表明以操作系統(tǒng)的根目錄為文件根目錄另存文件,SAVEAS_VIRTUAL表明以Web應(yīng)用程序的根目錄為文件根目錄另存文件,SAVEAS_AUTO則表示讓組件決定,當Web應(yīng)用程序的根目錄存在另存文件的目錄時,它會選擇SAVEAS_VIRTUAL,否則會選擇SAVEAS_PHYSICAL。
          例如,saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)執(zhí)行后若Web服務(wù)器安裝在C盤,則另存的文件名實際是c:\upload\sample.zip。而saveAs("/upload/sample.zip",SAVEAS_VIRTUAL)執(zhí)行后若Web應(yīng)用程序的根目錄是webapps/jspsmartupload,則另存的文件名實際是webapps/jspsmartupload/upload/sample.zip。saveAs("/upload/sample.zip",SAVEAS_AUTO)執(zhí)行時若Web應(yīng)用程序根目錄下存在upload目錄,則其效果同saveAs("/upload/sample.zip",SAVEAS_VIRTUAL),否則同saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)。
          建議:對于Web程序的開發(fā)來說,最好使用SAVEAS_VIRTUAL,以便移植。
          2、isMissing
          作用:這個方法用于判斷用戶是否選擇了文件,也即對應(yīng)的表單項是否有值。選擇了文件時,它返回false。未選文件時,它返回true。
          原型:public boolean isMissing()
          3、getFieldName
          作用:取HTML表單中對應(yīng)于此上傳文件的表單項的名字。
          原型:public String getFieldName()
          4、getFileName
          作用:取文件名(不含目錄信息)
          原型:public String getFileName()
          5、getFilePathName
          作用:取文件全名(帶目錄)
          原型:public String getFilePathName
          6、getFileExt
          作用:取文件擴展名(后綴)
          原型:public String getFileExt()
          7、getSize
          作用:取文件長度(以字節(jié)計)
          原型:public int getSize()
          8、getBinaryData
          作用:取文件數(shù)據(jù)中指定位移處的一個字節(jié),用于檢測文件等處理。
          原型:public byte getBinaryData(int index)。其中,index表示位移,其值在0到getSize()-1之間。
          ㈡ Files類
          這個類表示所有上傳文件的集合,通過它可以得到上傳文件的數(shù)目、大小等信息。有以下方法:
          1、getCount
          作用:取得上傳文件的數(shù)目。
          原型:public int getCount()
          2、getFile
          作用:取得指定位移處的文件對象File(這是com.jspsmart.upload.File,不是java.io.File,注意區(qū)分)。
          原型:public File getFile(int index)。其中,index為指定位移,其值在0到getCount()-1之間。
          3、getSize
          作用:取得上傳文件的總長度,可用于限制一次性上傳的數(shù)據(jù)量大小。
          原型:public long getSize()
          4、getCollection
          作用:將所有上傳文件對象以Collection的形式返回,以便其它應(yīng)用程序引用,瀏覽上傳文件信息。
          原型:public Collection getCollection()
          5、getEnumeration
          作用:將所有上傳文件對象以Enumeration(枚舉)的形式返回,以便其它應(yīng)用程序瀏覽上傳文件信息。
          原型:public Enumeration getEnumeration()
          ㈢ Request類
          這個類的功能等同于JSP內(nèi)置的對象request。只所以提供這個類,是因為對于文件上傳表單,通過request對象無法獲得表單項的值,必須通過jspSmartUpload組件提供的Request對象來獲取。該類提供如下方法:
          1、getParameter
          作用:獲取指定參數(shù)之值。當參數(shù)不存在時,返回值為null。
          原型:public String getParameter(String name)。其中,name為參數(shù)的名字。
          2、getParameterValues
          作用:當一個參數(shù)可以有多個值時,用此方法來取其值。它返回的是一個字符串數(shù)組。當參數(shù)不存在時,返回值為null。
          原型:public String[] getParameterValues(String name)。其中,name為參數(shù)的名字。
          3、getParameterNames
          作用:取得Request對象中所有參數(shù)的名字,用于遍歷所有參數(shù)。它返回的是一個枚舉型的對象。
          原型:public Enumeration getParameterNames()
          ㈣ SmartUpload類這個類完成上傳下載工作。
          A.上傳與下載共用的方法:
          只有一個:initialize。
          作用:執(zhí)行上傳下載的初始化工作,必須第一個執(zhí)行。
          原型:有多個,主要使用下面這個:
          public final void initialize(javax.servlet.jsp.PageContext pageContext)
          其中,pageContext為JSP頁面內(nèi)置對象(頁面上下文)。
          B.上傳文件使用的方法:
          1、upload
          作用:上傳文件數(shù)據(jù)。對于上傳操作,第一步執(zhí)行initialize方法,第二步就要執(zhí)行這個方法。
          原型:public void upload()
          2、save
          作用:將全部上傳文件保存到指定目錄下,并返回保存的文件個數(shù)。
          原型:public int save(String destPathName)
          和public int save(String destPathName,int option)
          其中,destPathName為文件保存目錄,option為保存選項,它有三個值,分別是SAVE_PHYSICAL,SAVE_VIRTUAL和SAVE_AUTO。(同F(xiàn)ile類的saveAs方法的選項之值類似)SAVE_PHYSICAL指示組件將文件保存到以操作系統(tǒng)根目錄為文件根目錄的目錄下,SAVE_VIRTUAL指示組件將文件保存到以Web應(yīng)用程序根目錄為文件根目錄的目錄下,而SAVE_AUTO則表示由組件自動選擇。
          注:save(destPathName)作用等同于save(destPathName,SAVE_AUTO)。
          3、getSize
          作用:取上傳文件數(shù)據(jù)的總長度
          原型:public int getSize()
          4、getFiles
          作用:取全部上傳文件,以Files對象形式返回,可以利用Files類的操作方法來獲得上傳文件的數(shù)目等信息。
          原型:public Files getFiles()
          5、getRequest
          作用:取得Request對象,以便由此對象獲得上傳表單參數(shù)之值。
          原型:public Request getRequest()
          6、setAllowedFilesList
          作用:設(shè)定允許上傳帶有指定擴展名的文件,當上傳過程中有文件名不允許時,組件將拋出異常。
          原型: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
          作用:設(shè)定每個文件允許上傳的最大長度。
          原型:public void setMaxFileSize(long maxFileSize)
          其中,maxFileSize為為每個文件允許上傳的最大長度,當文件超出此長度時,將不被上傳。
          9、setTotalMaxFileSize
          作用:設(shè)定允許上傳的文件的總長度,用于限制一次性上傳的數(shù)據(jù)量大小。
          原型:public void setTotalMaxFileSize(long totalMaxFileSize)
          其中,totalMaxFileSize為允許上傳的文件的總長度。
          C.下載文件常用的方法
          1、setContentDisposition
          作用:將數(shù)據(jù)追加到MIME文件頭的CONTENT-DISPOSITION域。jspSmartUpload組件會在返回下載的信息時自動填寫MIME文件頭的CONTENT-DISPOSITION域,如果用戶需要添加額外信息,請用此方法。
          原型:public void setContentDisposition(String contentDisposition)
          其中,contentDisposition為要添加的數(shù)據(jù)。如果contentDisposition為null,則組件將自動添加"attachment;",以表明將下載的文件作為附件,結(jié)果是IE瀏覽器將會提示另存文件,而不是自動打開這個文件(IE瀏覽器一般根據(jù)下載的文件擴展名決定執(zhí)行什么操作,擴展名為doc的將用word程序打開,擴展名為pdf的將用acrobat程序打開,等等)。
          2、downloadFile
          作用:下載文件。
          原型:共有以下三個原型可用,第一個最常用,后兩個用于特殊情況下的文件下載(如更改內(nèi)容類型,更改另存的文件名)。
          ① public void downloadFile(String sourceFilePathName)
          其中,sourceFilePathName為要下載的文件名(帶目錄的文件全名)
          ② public void downloadFile(String sourceFilePathName,String contentType)
          其中,sourceFilePathName為要下載的文件名(帶目錄的文件全名),contentType為內(nèi)容類型(MIME格式的文件類型信息,可被瀏覽器識別)。
          ③ public void downloadFile(String sourceFilePathName,String contentType,String destFileName)
          其中,sourceFilePathName為要下載的文件名(帶目錄的文件全名),contentType為內(nèi)容類型(MIME格式的文件類型信息,可被瀏覽器識別),destFileName為下載后默認的另存文件名。

          posted @ 2008-08-26 16:12 南山隱士 閱讀(251) | 評論 (0)編輯 收藏
          現(xiàn)在想要獲得在特定時間或者指定時間執(zhí)行相應(yīng)功能
          有兩種做法
          在applicationContext.xml中寫入如下Bean
          <bean id="repeatingTrigger"
             class="org.springframework.scheduling.timer.ScheduledTimerTask">
             <!--啟動一秒后執(zhí)行 -->
             <property name="delay">
              <value>1000</value>
             </property>
             <!--每隔一小時執(zhí)行一次 -->
             <property name="period">
              <value>3600000</value>
             </property>
             <!--注入要監(jiān)控的javaBean -->
             <property name="timerTask">
              <ref bean="task" />
             </property>
             <!--類型是否為fixedRate型,默認為fixedDelay-->
             <property name="fixedRate">
              <value>true</value>
             </property>


          </bean>
          <bean id="scheduler"
             class="org.springframework.scheduling.timer.TimerFactoryBean">
             <property name="scheduledTimerTasks">
              <list>
               <ref bean="repeatingTrigger" />
              </list>
             </property>
          </bean>

          <bean id="task" class="com.css.wam.portlet.SampleTask">
             <property name="workService">
              <ref bean="workService" />
             </property>
             <property name="work">
              <ref bean="work" />
             </property>
          </bean>

          然后寫SampleTask類,如下:

           

          package com.css.wam.portlet;

           

          import java.util.ArrayList;
          import java.util.Calendar;
          import java.util.Iterator;
          import java.util.List;
          import java.util.TimerTask;

           

           

          import javax.servlet.ServletContext; 字串2

          import org.apache.jetspeed.security.SecurityException; 字串9

          import com.css.wam.service.WorkService; 字串1

          @SuppressWarnings("unused")
          class SampleTask extends TimerTask{    字串2

              private static final int C_SCHEDULE_HOUR = 23;//設(shè)置指定時間
              private WorkService workService;
              private List users;
              private List teams;
              private WorkPortlet work;
             
              public void setWorkService(WorkService workService) {
             this.workService = workService;
          } 字串7

          public void setWork(WorkPortlet work) {
             this.work = work;
          } 字串4

              public SampleTask(){
              }
             
              @SuppressWarnings("unchecked")
          public void run() {
             
                  Calendar cal = Calendar.getInstance();
                  try {
                    users = work.getUsers();
                    teams = new ArrayList();
                 for(Iterator it = users.iterator(); it.hasNext();)
                 {
                  String teamname = work.getGroupsByUser((String)it.next());
                  teams.add(teamname);
                 }
                      //查看當前時間與指定是否一致,一致則執(zhí)行任務(wù)
                       if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY) ) 字串6
                           workService.autoWorkOff(users, teams);    字串8

                  } catch (SecurityException e) {
               e.printStackTrace();
              }
                }
          }

          posted @ 2008-06-25 17:14 南山隱士 閱讀(1400) | 評論 (0)編輯 收藏
          /*
          * @(#)BeanXML.java 1.00 2005-10-7
          *
          * Copyright 2005 BeanSoft Studio. All rights reserved.
          * PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
          */
          package beansoft.xml;

          import java.beans.XMLDecoder;
          import java.beans.XMLEncoder;
          import java.io.ByteArrayInputStream;
          import java.io.ByteArrayOutputStream;
          import java.io.UnsupportedEncodingException;

          /**
          * BeanXML
          *
          * Chinese documents:
          *
          * @author BeanSoft
          * @version 1.00 2005-10-7
          */
          public class BeanXML {
          /**
          * 使用 java.beans.XMLEncoder 將 對象編碼為 XML.
          * @param bean 對象
          * @return String - 編碼后的 XML
          */
          public static String encodeBean(Object bean) {
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          XMLEncoder encoder = new XMLEncoder(out);
          encoder.writeObject(bean);
          encoder.close();

          return out.toString();
          }

          /**
          * 使用 java.beans.XMLDecoder 將 XML 解碼為 對象.
          * @param xml - 編碼后的 XML
          * @return Object 反編碼后的對象
          */
          public static Object decodeBean(String xml) {
          try {
          // FIXME 必須使用 GBK 解碼才對, 否則出來的文字是亂碼?
          XMLDecoder decoder = new XMLDecoder(new ByteArrayInputStream(xml.getBytes("GBK")));
          return decoder.readObject();
          } catch (UnsupportedEncodingException e) {
          }

          return null;
          }
          }
          posted @ 2008-06-25 16:12 南山隱士 閱讀(1944) | 評論 (0)編輯 收藏
          這需要導(dǎo)入java.io類
          import java.io.*;

          public class FileOperate {
            public FileOperate() {
            }

            /**
             * 新建目錄
             * @param folderPath String 如 c:/fqf
             * @return boolean
             */
            public void newFolder(String folderPath) {
              try {
                String filePath = folderPath;
                filePath = filePath.toString();
                java.io.File myFilePath = new java.io.File(filePath);
                if (!myFilePath.exists()) {
                  myFilePath.mkdir();
                }
              }
              catch (Exception e) {
                System.out.println("新建目錄操作出錯");
                e.printStackTrace();
              }
            }

            /**
             * 新建文件
             * @param filePathAndName String 文件路徑及名稱 如c:/fqf.txt
             * @param fileContent String 文件內(nèi)容
             * @return boolean
             */
            public void newFile(String filePathAndName, String fileContent) {

              try {
                String filePath = filePathAndName;
                filePath = filePath.toString();
                File myFilePath = new File(filePath);
                if (!myFilePath.exists()) {
                  myFilePath.createNewFile();
                }
                FileWriter resultFile = new FileWriter(myFilePath);
                PrintWriter myFile = new PrintWriter(resultFile);
                String strContent = fileContent;
                myFile.println(strContent);
                resultFile.close();

              }
              catch (Exception e) {
                System.out.println("新建目錄操作出錯");
                e.printStackTrace();

              }

            }

            /**
             * 刪除文件
             * @param filePathAndName String 文件路徑及名稱 如c:/fqf.txt
             * @param fileContent String
             * @return boolean
             */
            public void delFile(String filePathAndName) {
              try {
                String filePath = filePathAndName;
                filePath = filePath.toString();
                java.io.File myDelFile = new java.io.File(filePath);
                myDelFile.delete();

              }
              catch (Exception e) {
                System.out.println("刪除文件操作出錯");
                e.printStackTrace();

              }

            }

            /**
             * 刪除文件夾
             * @param filePathAndName String 文件夾路徑及名稱 如c:/fqf
             * @param fileContent String
             * @return boolean
             */
            public void delFolder(String folderPath) {
              try {
                delAllFile(folderPath); //刪除完里面所有內(nèi)容
                String filePath = folderPath;
                filePath = filePath.toString();
                java.io.File myFilePath = new java.io.File(filePath);
                myFilePath.delete(); //刪除空文件夾

              }
              catch (Exception e) {
                System.out.println("刪除文件夾操作出錯");
                e.printStackTrace();

              }

            }

            /**
             * 刪除文件夾里面的所有文件
             * @param path String 文件夾路徑 如 c:/fqf
             */
            public void delAllFile(String path) {
              File file = new File(path);
              if (!file.exists()) {
                return;
              }
              if (!file.isDirectory()) {
                return;
              }
              String[] tempList = file.list();
              File temp = null;
              for (int i = 0; i < tempList.length; i++) {
                if (path.endsWith(File.separator)) {
                  temp = new File(path + tempList[i]);
                }
                else {
                  temp = new File(path + File.separator + tempList[i]);
                }
                if (temp.isFile()) {
                  temp.delete();
                }
                if (temp.isDirectory()) {
                  delAllFile(path+"/"+ tempList[i]);//先刪除文件夾里面的文件
                  delFolder(path+"/"+ tempList[i]);//再刪除空文件夾
                }
              }
            }

            /**
             * 復(fù)制單個文件
             * @param oldPath String 原文件路徑 如:c:/fqf.txt
             * @param newPath String 復(fù)制后路徑 如:f:/fqf.txt
             * @return boolean
             */
            public void copyFile(String oldPath, String newPath) {
              try {
                int bytesum = 0;
                int byteread = 0;
                File oldfile = new File(oldPath);
                if (oldfile.exists()) { //文件存在時
                  InputStream inStream = new FileInputStream(oldPath); //讀入原文件
                  FileOutputStream fs = new FileOutputStream(newPath);
                  byte[] buffer = new byte[1444];
                  int length;
                  while ( (byteread = inStream.read(buffer)) != -1) {
                    bytesum += byteread; //字節(jié)數(shù) 文件大小
                    System.out.println(bytesum);
                    fs.write(buffer, 0, byteread);
                  }
                  inStream.close();
                }
              }
              catch (Exception e) {
                System.out.println("復(fù)制單個文件操作出錯");
                e.printStackTrace();

              }

            }

            /**
             * 復(fù)制整個文件夾內(nèi)容
             * @param oldPath String 原文件路徑 如:c:/fqf
             * @param newPath String 復(fù)制后路徑 如:f:/fqf/ff
             * @return boolean
             */
            public void copyFolder(String oldPath, String newPath) {

              try {
                (new File(newPath)).mkdirs(); //如果文件夾不存在 則建立新文件夾
                File a=new File(oldPath);
                String[] file=a.list();
                File temp=null;
                for (int i = 0; i < file.length; i++) {
                  if(oldPath.endsWith(File.separator)){
                    temp=new File(oldPath+file[i]);
                  }
                  else{
                    temp=new File(oldPath+File.separator+file[i]);
                  }

                  if(temp.isFile()){
                    FileInputStream input = new FileInputStream(temp);
                    FileOutputStream output = new FileOutputStream(newPath + "/" +
                        (temp.getName()).toString());
                    byte[] b = new byte[1024 * 5];
                    int len;
                    while ( (len = input.read(b)) != -1) {
                      output.write(b, 0, len);
                    }
                    output.flush();
                    output.close();
                    input.close();
                  }
                  if(temp.isDirectory()){//如果是子文件夾
                    copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]);
                  }
                }
              }
              catch (Exception e) {
                System.out.println("復(fù)制整個文件夾內(nèi)容操作出錯");
                e.printStackTrace();

              }

            }

            /**
             * 移動文件到指定目錄
             * @param oldPath String 如:c:/fqf.txt
             * @param newPath String 如:d:/fqf.txt
             */
            public void moveFile(String oldPath, String newPath) {
              copyFile(oldPath, newPath);
              delFile(oldPath);

            }

            /**
             * 移動文件到指定目錄
             * @param oldPath String 如:c:/fqf.txt
             * @param newPath String 如:d:/fqf.txt
             */
            public void moveFolder(String oldPath, String newPath) {
              copyFolder(oldPath, newPath);
              delFolder(oldPath);

            }
          }



          java中刪除目錄事先要刪除目錄下的文件或子目錄。用遞歸就可以實現(xiàn)。這是我第一個用到算法作的程序,哎看來沒白學(xué)。
          public void del(String filepath) throws IOException{
          File f = new File(filepath);//定義文件路徑       
          if(f.exists() && f.isDirectory()){//判斷是文件還是目錄
              if(f.listFiles().length==0){//若目錄下沒有文件則直接刪除
                  f.delete();
              }else{//若有則把文件放進數(shù)組,并判斷是否有下級目錄
                  File delFile[]=f.listFiles();
                  int i =f.listFiles().length;
                  for(int j=0;j<i;j++){
                      if (delFile[j].isDirectory()){                                                del (delFile[j].getAbsolutePath());//遞歸調(diào)用del方法并取得子目錄路徑
                      }
                      delFile[j].delete();//刪除文件
                  }
              }
              del(filepath);//遞歸調(diào)用
          }

          }    


          刪除一個非空目錄并不是簡單地創(chuàng)建一個文件對象,然后再調(diào)用delete()就可以完成的。要在平臺無關(guān)的方式下安全地刪除一個非空目錄,你還需要一個算法。該算法首先刪除文件,然后再從目錄樹的底部由下至上地刪除其中所有的目錄。

          只要簡單地在目錄中循環(huán)查找文件,再調(diào)用delete就可以清除目錄中的所有文件:

          static public void emptyDirectory(File directory) {
             File[ ] entries = directory.listFiles( );
             for(int i=0; i<entries.length; i++) {
                 entries[i].delete( );
             }
          }
          這個簡單的方法也可以用來刪除整個目錄結(jié)構(gòu)。當在循環(huán)中遇到一個目錄時它就遞歸調(diào)用deleteDirectory,而且它也會檢查傳入的參數(shù)是否是一個真正的目錄。最后,它將刪除作為參數(shù)傳入的整個目錄。
          static public void deleteDirectory(File dir) throws IOException {
             if( (dir == null) || !dir.isDirectory) {
                 throw new IllegalArgumentException(

                           "Argument "+dir+" is not a directory. "
                       );
             }

             File[ ] entries = dir.listFiles( );
             int sz = entries.length;

             for(int i=0; i<sz; i++) {
                 if(entries[i].isDirectory( )) {
                     deleteDirectory(entries[i]);
                 } else {
                     entries[i].delete( );
                 }
             }

            dir.delete();
          }
          在Java 1.1以及一些J2ME/PersonalJava的變種中沒有File.listFiles方法。所以只能用File.list,它的返回值一個字符串數(shù)組,你要為每個字符串構(gòu)造一個新的文件對象。
          posted @ 2008-06-25 08:25 南山隱士 閱讀(1246) | 評論 (0)編輯 收藏

          WebLogic Server包含了Timer Service功能,你可以指定某一時刻或某一時間間隔產(chǎn)生Timer事件,同時你可以使用委托代理的機制,為這個事件注冊事件監(jiān)聽器,以實現(xiàn)Timer Service功能。

            WebLogic Server 7.0以后的版本,WebLogic Timer Service擴展自標準的JMX Timer Service,使其可以運行于WebLogic Server的執(zhí)行線程中,并且享有WebLogic Server的安全上下文環(huán)境,也就是說,可以在代碼中得到安全信息,如用戶名等。下面結(jié)合一個實例演示其功能。

          File:TimerServiceListener.java

          package org.yekki.weblogic.timer;

          import java.util.Date;

          import java.util.Random;

          import javax.jms.JMSException;

          import javax.jms.Queue;

          import javax.jms.QueueConnection;

          import javax.jms.QueueConnectionFactory;

          import javax.jms.QueueSender;

          import javax.jms.QueueSession;

          import javax.jms.Session;

          import javax.jms.TextMessage;

          import javax.management.InstanceNotFoundException;

          import javax.management.Notification;

          import javax.management.NotificationListener;

          import javax.naming.Context;

          import javax.naming.InitialContext;

          import javax.servlet.ServletContext;

          import javax.servlet.ServletContextEvent;

          import javax.servlet.ServletContextListener;

          import org.apache.ecs.xml.XML;

          import weblogic.management.timer.Timer;

          public class TimerServiceListener

                 implements ServletContextListener, NotificationListener {

                 private long period;

                 private boolean debug;

                 private Timer timer;

                 private Integer notificationId;

                 private QueueConnectionFactory factory;

                 private QueueConnection connection;

                 private QueueSession session;

                 private QueueSender sender;

                 private Queue queue;

                 private Context ctx;

                 public void contextInitialized(ServletContextEvent event) {

                        initParams(event);

                        initJMS();

                        debug(">>> contextInitialized called.");

                        timer = new Timer();

                        timer.addNotificationListener(this, null, "Message Broker ");

                        Date timerTriggerAt = new Date((new Date()).getTime() + 5000L);

                        notificationId =

                               timer.addNotification(

                                      "Timer Type",

                                      "Timer Message",

                                      this,

                                      timerTriggerAt,

                                      period);

                        timer.start();

                        debug(">>> timer started.");

                        printBrief();

                 }

                 public void initParams(ServletContextEvent event) {

                        ServletContext ctx = event.getServletContext();

                        try {

                               debug = Boolean.valueOf((String)ctx.getInitParameter("debug")).booleanValue();

                        }

                        catch (Exception e) {

                               debug = false;

                               e.printStackTrace();

                        }

                        try {

                               /*

                                second:1000L

                                minute:60000L

                                hour:3600000L

                                day:86400000L

                                week:604800000L

                                */

                               period =

                                      Long

                                             .valueOf((String)ctx.getInitParameter("period"))

                                             .longValue();

                        }

                        catch (Exception e) {

                               period = Timer.ONE_MINUTE;

                               e.printStackTrace();

                        }

                        debug(">>> initialized application parameters.");

                 }

                 private void initJMS() {

                        try {

                               ctx = new InitialContext();

                               factory =

                                      (QueueConnectionFactory)ctx.lookup(

                                             "javax.jms.QueueConnectionFactory");

                               queue = (Queue)ctx.lookup("queue");

                               connection = factory.createQueueConnection();

                               session =

                                      connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

                               sender = session.createSender(queue);

                               connection.start();

                               debug(">>> initialized jms.");

                        }

                        catch (Exception e) {

                               e.printStackTrace();

                        }

                 }

                 public void sendMessage(String message) {

                        try {

                               TextMessage msg = session.createTextMessage();

                               msg.setText(message);

                               sender.send(msg);

                               debug(">>> ################################");

                               debug("Send a message on " + new Date());

                               debug(message);

                               debug(">>> ################################");

                        }

                        catch (JMSException e) {

                               e.printStackTrace();

                        }

                 }

                 public void contextDestroyed(ServletContextEvent event) {

                        debug(">>> contextDestroyed called.");

                        try {

                               timer.stop();

                               timer.removeNotification(notificationId);

                               debug(">>> timer stopped.");

                        }

                        catch (InstanceNotFoundException e) {

                               e.printStackTrace();

                        }

                        try {

                               if (session != null)

                                      session.close();

                               if (connection != null)

                                      connection.close();

                               debug(">>> closed jms connection and session.");

                        }

                        catch (JMSException e) {

                               e.printStackTrace();

                        }

                 }

                 private void printBrief() {

                        String d = "";

                        d = debug ? "ON" : "OFF";

                        print(">>> ################################");

                        print(">>> Author: Niu Xiuyuan");

                        print(">>> EMail: niuxiuyuan@bea.com.cn");

                        print(">>> Company: BEA Systems");

                        print("");

                        print(">>> Debug: " + d);

                        print(">>> Period: " + getPeriodInfo(period));

                        print(">>> ################################");

                 }

                 private void print(String str) {

                        System.out.println(str);

                 }

                 private String getPeriodInfo(long p) {

                        if (p == Timer.ONE_DAY)

                               return "One Day";

                        if (p == Timer.ONE_HOUR)

                               return "One Hour";

                        if (p == Timer.ONE_MINUTE)

                               return "One Minute";

                        if (p == Timer.ONE_SECOND)

                               return "One Second";

                        if (p == Timer.ONE_WEEK)

                               return "One Week";

                        return "Unsupported time period!! period=" + p;

                 }

                 public void handleNotification(Notification notif, Object handback) {

                        Random rnd = new Random();

                        sendMessage(genXML(rnd.nextInt(10)));

                 }

                 public String genXML(int id) {

                        String username = "guru";

                        String password = "niu986";

                        XML usernameXML = null;

                        XML idXML = null;

                        XML passwordXML = null;

                        XML userXML = null;

                        XML profileXML = new XML("profiles");

                        for (int i = 1; i <= id; i++) {

                               usernameXML = (new XML("user")).addElement(username);

                               idXML = (new XML("id")).addElement(Integer.toString(id));

                               passwordXML = (new XML("password")).addElement(password);

                               userXML =

                                      (new XML("user"))

                                             .addXMLAttribute("age", "27")

                                             .addElement(idXML)

                                             .addElement(usernameXML)

                                             .addElement(passwordXML);

                               profileXML.addElement(userXML);

                        }

                        return profileXML.toString();

                 }

                 private void debug(String msg) {

                        if (debug) {

                               System.out.println(msg);

                        }

                 }

                 public static void main(String[] args) {

                 }

          }

            說明:為了方便演示,此類中包含了事件產(chǎn)生器代碼與事件監(jiān)聽器代碼。使用ServletContextListener接口來控制Timer的啟動與停止。

          File:web.xml

          <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

          <web-app>

            <context-param>

              <param-name>debug</param-name>

              <param-value>false</param-value>

            </context-param>

            <context-param>

              <param-name>period</param-name>

              <param-value>60000</param-value>

            </context-param>

            <listener>

              <listener-class>org.yekki.weblogic.timer.TimerServiceListener</listener-class>

            </listener>

            <login-config>

              <auth-method></auth-method>

            </login-config>

          </web-app>

            說明:我們將webappLisener注冊,并且指定事件產(chǎn)生的時間間隔

              將此WebApp部署到WebLogic Server上,然后通過中端(例如:DOS窗口)查看實驗結(jié)果。

            附:本例中使用了ApacheECS項目類庫,您可以訪問如下URL:

            http://jakarta.apache.org/ecs/index.html

          posted @ 2008-06-23 10:16 南山隱士 閱讀(749) | 評論 (0)編輯 收藏

          上善若水。水善利萬物而不爭,處眾人之所惡,故幾于道。居善地,心善淵,與善仁,言善信,政善治,事善能,動善時。 【解釋】 最上等的善要象水一樣。水善于滋潤萬物而不與之爭奪,停留在眾人討厭的低洼低方,所以最接近道。居住在善于選擇地方,存心善于保持深沉,交友善于真誠相愛,說話善于遵守信用,為政善于有條有理,辦事善于發(fā)揮能力,行動善于掌握時機。正因為他與事無爭,所以才不會招惹怨恨。

          posted @ 2008-06-18 15:22 南山隱士 閱讀(141) | 評論 (0)編輯 收藏
          主站蜘蛛池模板: 毕节市| 阿合奇县| 石景山区| 姜堰市| 页游| 乌鲁木齐市| 拜城县| 邯郸市| 上犹县| 塘沽区| 南汇区| 浠水县| 景泰县| 休宁县| 蓬莱市| 茶陵县| 玉屏| 古田县| 嵊泗县| 通山县| 许昌市| 济南市| 原阳县| 灌云县| 南宫市| 富川| 若羌县| 仁化县| 永定县| 通海县| 白山市| 巩留县| 泰和县| 通江县| 吴江市| 鲁山县| 垫江县| 岚皋县| 鄯善县| 鄄城县| 江安县|