<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-295  評論-26  文章-1  trackbacks-0
     
    public class ssss {
    ???
    ??? /** Creates a new instance of ssss */
    ??? public ssss() {
    ??? }
    ??? public static void main(String s[]) throws IOException{
    ?//?????? java.net.URL? m=new java.net.URL("?? //???? HttpURLConnection sst=(HttpURLConnection) m.openConnection();
    //?????????? DataInputStream in = new DataInputStream(connection.getInputStream());
    ? //????????? DataOutputStream out = new DataOutputStream(new FileOutputStream(fileName));
    ????? DataInputStream? tttt= new?? DataInputStream((InputStream)new FileInputStream("c://ffffff.java.bak"));
    ? //????? DataInputStream tttt=new DataInputStream(sst.getInputStream());
    ??????? DataOutputStream out = new DataOutputStream(new FileOutputStream("D://ffffff.java.bak"));
    ??????? byte[] buffer = new byte[4096];
    ??????? int count=0;
    ??????? while ((count = tttt.read(buffer))>0){
    ??????????? out.write(buffer,0,count);
    ??????? }
    ??????? out.close();
    ??????? tttt.close();
    ??? }
    http://www.java2s.com
    http//www.dxiaoshuo.com
    http://www.mdianying.com
    posted @ 2007-10-26 16:51 華夢行 閱讀(205) | 評論 (0)編輯 收藏

    1.表名要以模塊簡稱為前綴, 如:Bse_, Crm_, Sys_, Scm_, OA_, Mrp_, Ftm_等,后面部分與字段名稱都盡量使用有意義的英文單詞,第一個字母要大寫,單詞之間直接連接,不需要連接符號;

    2.每個表必須要有主鍵,而且對經常使用的字段建立索引,除了必要的字段,盡可能設置字段允許為空而且不需要缺省值;

    3.主鍵規則:對于經常增刪的數據表,主鍵字段建議為varchar(36),用GUID生成,其它表原則上以性能為參考來建立主鍵,但要考慮可移植性,并發性與易初始化;主鍵本身在業務邏輯上不體現,不具有實際意義;

    4.避免使用復合主鍵,只比較一個字段比比較多個字段快很多;

    5.除了必要的冗余數據外,盡量避免冗余數據的出現,容易保證數據的一致性;

    6.完全符合建立聚集索引要求:“既不能絕大多數都相同,又不能只有極少數相同”的規則;

    7.用聚合索引比用不是聚合索引的主鍵速度快;

    8.用聚合索引比用一般的主鍵作order by時速度快;

    9.使用聚合索引內的字段,搜索時間會按數據占整個數據表的百分比成比例減少;

    10.索引有助于提高檢索性能,但過多或不當的索引也會導致系統低效,過多的索引甚至會導致索引碎片;

    11.Like條件中,通配符%在字符串的開頭使得索引無法使用;

    12.OR條件,會引起全表掃描;

    13.不推薦使用以下條件語句:NOT、!=、<>、!<、!>、NOT EXISTS、NOT IN、NOT LIKE;

    14.IN 的作用相當與OR;

    15.盡量少用NOT;

    16.exists 和 in 的執行效率是一樣的;

    17.用函數charindex()和前面加通配符%的LIKE執行效率一樣;

    18.union在通常情況下比用or的效率要高的多,但如果or兩邊的查詢列是一樣的話,那么用union則反倒和用or的執行速度差很多;

    19.字段提取要按照“需多少、提多少”的原則,避免“select *”;

    20.count(*)不比count(主鍵)慢,而count(*)卻比其他任何除主鍵以外的字段匯總速度要快,而且字段越長,匯總速度就越慢;

    21.order by按聚集索引列排序效率最高;

    22.高效的TOP,提高性能;

    23.聚集索引有兩個最大的優勢:1、以最快的速度縮小查詢范圍;2、以最快的速度進行字段排序;

    24.一定要將聚集索引建立在:1、您最頻繁使用的、用以縮小查詢范圍的字段上;2、您最頻繁使用的、需要排序的字段上;

    25. 由于改變一個表的內容,將會引起索引的變化。頻繁的insert,update,delete語句將導致系統花費較大的代價進行索引更新,引起整體性能的下降。一般來講,在對查詢性能的要求高于對數據維護性能要求時,應該盡量使用索引,否則,就要慎重考慮一下付出的代價;

    26. 不同類型的索引效能是不一樣的,應盡可能先使用效能高的,比如:數字類型的索引查找效率高于字符串類型,定長字符串char,nchar的索引效率高于變長字符串varchar,nvarchar的索引;

    27. 有嵌套查詢時,盡可能在內層過濾掉數據;

    28. 多表關聯查詢時,需注意表順序,并盡可能早的過濾掉數據,只將必須的數據帶到后續的操作中去;

    29. 任何對列的操作都導致全表掃描,如數據庫函數、計算表達式等,查詢時應盡可能將操作移至等號的某一邊;

    30. 存儲過程如果有返回結果集的話, 就不能通過返回一個狀態值來進行邏輯判斷,否則會導致執行兩次存儲過程,影響性能;

    31. Where條件中如果存在以下情況,則索引無效,嚴重影響性能: 索引列不要使用函數; 索引列不要使用NOT; 索引列不要用NULL; 不要對索引列進行計算;

    posted @ 2007-10-26 15:34 華夢行 閱讀(217) | 評論 (0)編輯 收藏

    1. JSP頁面的編碼標準: UTF-8;

    2. 有調用request對象的頁面加上: <%request.setCharacterEncoding("UTF-8");%>;

    3. 有調用response對象的頁面加上: <%response.setCharacterEncoding("UTF-8");%>;

    4. sendRedirect的調用需對中文等多字節參數進行編碼: URLEncoder.encode(argname,"UTF-8");

    5. 不要在頁面中調用以下函數: out.close();

    6. 不要在頁面中調用以下函數: response.getOutputStream(),應該使用out對象,或者使用Servlet;

    7. 頁面文件轉換為UTF-8文件的方法: 先用記事本打開,另存為UTF-8字符集, 加入編碼UTF-8字符集, 然后再用NB IDE打開即可;

    8. 不要調用標記為廢棄的函數;

    9. 所有可以點擊查看內容的文字, 使用類: LinkText; 如: <span class="LinkText" ...

    10. 取記錄集顯示時,循環中不能再進行數據庫連接操作, 用Left Join或存儲過程替換;

    11. 程序文件目錄與文件名稱,命名一定要統一,采用JAVA的命名規則,用英文且大小寫分開,同樣功能的頁面命名保持統一, 以便維護;

    posted @ 2007-10-26 15:30 華夢行 閱讀(239) | 評論 (0)編輯 收藏

    1. 每個文件的頭部注釋: 版權說明、版本號、生成日期、作者、內容、功能、與其它文件的關系、修改日志等,頭文件的注釋中還應有函數功能簡要說明;

    2. 函數頭部應進行注釋:函數的目的/功能、輸入參數、輸出參數、返回值、調用關系(函數、表)、作者或修改人等;

    3. 對變量的定義和分支語句(條件分支、循環語句等)必須編寫注釋;

    4. 自己特有的命名風格,要自始至終保持一致,不可來回變化;

    5. 類命名標準: 由兩個或以上的相近意義的英文單詞組成,首字母大寫;

    6. 一個類里面只能實現一個單據或一個功能的不同操作方面,盡可能減少類之間的耦合性;

    7. 一些通用功能,都分類封裝成不同的實用操作類;

    8. 對以前的對象或函數重構或重命名時, 必須由修改人搜索以前的所有調用并替換,同時通知其它人以后使用新的調用;

    9. 注釋格式 /** * Setting to true will enable the display of debug information. * * @param d A boolean. * @return An Email. * @throws EmailException * @version Version * @author Author * @since 1.0 */

    10. 類包規范: path.crm(itm,system,basic,oa,wms,mrp,scm).entity(manager),按模塊分開類,同時實體類與操作類分開,映射文件跟實體類同目錄;path.util下為實用類;Servlet映射為二級目錄,目前為/path/system;

    11. 頁面不允許RS對象引用,全部用List或HashMap來實現;

    12. 參數傳遞盡可能使用實體類, 沒有實體類的使用HashMap;

    13. 方法重載時, 可替換的不能使用重載;

    14. 嚴格按照代碼縮進格式進行代碼書寫,包括各種操作與分隔符號兩邊的空格;

    15. 模糊搜索關鍵字,可以輸入如"ab,abc"以逗號分隔的多個關鍵字進行搜索;

    16. 變量命名規則: 數據類型簡寫+首字母大寫的變量英文名稱, 如果是全局變量加上小寫g, 如: gszLimitString, gnModuleFlag, gnPageSize;

    17. 程序中,SQL語句不能包含方括號, SQL語句中的表別名不能加AS,用空格代替;

    18. SQL字符串,不能直接拼接字符串變量,用SET方法實現變量賦值,避免非法字符串變量引起安全問題;

    19. 必須隨時關閉所用的ResultSet,Statement對象,最好用finally實現,避免錯誤時沒有關閉的問題;

    20. 附件管理: 文件大小統一用text.formatFileSize()進行格式化;查看與下載鏈接用SPAN標簽;

    21. 其它詳細的請參見公司的“軟件編程規范檢查”;

    posted @ 2007-10-26 15:29 華夢行 閱讀(148) | 評論 (0)編輯 收藏

    1. 有"+"操作的字符串, 使用StringBuffer代替String;

    2. 生成對象時,分配合理的空間和大小,如StringBuffer,Vector的初始化大小;

    3. 優化循環體,避免在循環中生成同一個變量或調用同一個函數(參數變量也一樣);

    4. 盡量在使用時才創建該對象; 應該盡量重復使用一個對象,而不是聲明新的同類對象;

    5. 盡量使用局部變量; 盡量使用靜態變量,從而使他所有的實例都共享這個變量;

    6. 盡量減少方法的調用, 可事先判斷, 同時用變量替換;

    7. 盡量使用Java系統API,如復制大量數據時,使用System.arraycopy();

    8. 盡可能使用帶有Buffer的類代替沒有Buffer的類;

    9. 不用保存太多的信息在HttpSession中, 同時注意清除Session;

    10. 大型數據量處理或批處理數據記錄,盡量使用直接訪問數據庫的方法,用SQL直接存取數據;

    11. 在生產環境下,禁止servlet和jsp的自動重載;

    12. 插入下述“顯式”計時代碼,對程序進行評測:

    long start = System.currentTimeMillis(); // 要計時的運算代碼放在這兒,返回的時間以千分之一秒(1毫秒)為單位 long time = System.currentTimeMillis() - start;

    13. 常用運算時間單位: 運算 示例 標準時間本地賦值 i=n; 1.0 實例賦值 this.i=n; 1.2 int增值 i++; 1.5 byte增值 b++; 2.0 short增值 s++; 2.0 float增值 f++; 2.0 double增值 d++; 2.0 空循環 while(true) n++; 2.0 三元表達式 (x<0) ?-x : x 2.2 算術調用 Math.abs(x); 2.5 數組賦值 a[0] = n; 2.7 long增值 l++; 3.5 方法調用 funct(); 5.9 throw或catch異常 try{ throw e; }或catch(e){} 320 同步方法調用 synchMehod(); 570 新建對象 new Object(); 980 新建數組 new int[10]; 3100

    posted @ 2007-10-26 15:27 華夢行 閱讀(271) | 評論 (0)編輯 收藏
    多線程編程——基礎篇 (二)

    時間:2006-08-16
    作者:axman
    瀏覽次數: 3723
    本文關鍵字:Java,?多線程,?線程,?線程對象,?單線程,?go deep into java
    文章工具
    推薦給朋友?推薦給朋友
    打印文章?打印文章

      在進入java平臺的線程對象之前,基于基礎篇(一)的一些問題,我先插入兩個基本概念。

    [線程的并發與并行]

      在單CPU系統中,系統調度在某一時刻只能讓一個線程運行,雖然這種調試機制有多種形式(大多數是時間片輪巡為主),但無論如何,要通過不斷切換需要運行的線程讓其運行的方式就叫并發(concurrent)。而在多CPU系統中,可以讓兩個以上的線程同時運行,這種可以同時讓兩個以上線程同時運行的方式叫做并行(parallel)

      在上面包括以后的所有論述中,請各位朋友諒解,我無法用最準確的詞語來定義儲如并發和并行這類術語,但我以我的經驗能通俗地告訴大家它是怎么一回事,如果您看到我說的一些"標準"文檔上說的不一樣,只要意思一致,那您就不要挑刺了。

    [JAVA線程對象]

      現在我們來開始考察JAVA中線程對象。

      在JAVA中,要開始一個線程,有兩種方式。一是直接調用Thread實例的start()方法,二是
    將Runable實例傳給一個Thread實例然后調用它的start()方法。

      在前面已經說過,線程對象和線程是兩個完全不同的概念。這里我們再次深入一下,生成一個線程的實例,并不代表啟動了線程。而啟動線程是說在某個線程對象上啟動了該實例對應的線程,當該線程結束后,并不會就立即消失。

      對于從很多書籍上可以看到的基礎知識我就不用多說了。既然是基礎知識,我也著重于從普通文檔上讀不到的內容。所以本節我重點要說的是兩種線程對象產生線程方式的區別。

    class MyThread extends Thread{
      public int x = 0;
      
      public void run(){
        
        for(int i=0;i<100;i++){
          try{
            Thread.sleep(10);
          }catch(Exception e){}
          System.out.println(x++);
          
        }
      }
    }
    

      如果我們生成MyThread的一個實例,然后調用它的start()方法,那么就產生了這個實例對應的線程:

    public class Test {
      public static void main(String[] args) throws Exception{
        MyThread mt = new MyThread();
        mt.start();
      }
    }
    

      不用說,最終會打印出0到99,現在我們稍微玩一點花樣:

    public class Test {
      public static void main(String[] args) throws Exception{
        MyThread mt = new MyThread();
        mt.start();
        System.out.println(101);
      }
    }
    

      也不用說,在基礎篇(一)中我們知道由于單CPU的原因,一般會先打印101,然后打印0到99。不過我們可以控制線程讓它按我們的意思來運行:

    public class Test {
      public static void main(String[] args) throws Exception{
        MyThread mt = new MyThread();
        mt.start();
        mt.join();
        System.out.println(101);
      }
    }
    

      好了,我們終于看到,mt實例對應的線程(假如我有時說mt線程請你不要怪我,不過我盡量不這么說)。在運行完成后,主線程才打印101。因為我們讓當前線程(這里是主線程)等待mt線程的運行結束。"在線程對象a上調用join()方法,就是讓當前正在執行的線程等待線程對象a對應的線程運行完成后才繼續運行。"?請大家一定要深刻理解并熟記這句話,而我這里引出這個知識點的目的是為了讓你繼續看下面的例子:

    public class Test {
      public static void main(String[] args) throws Exception{
        MyThread mt = new MyThread();
        mt.start();
        mt.join();
        Thread.sleep(3000);
        mt.start();
      }
    }
    

      當線程對象mt運行完成后,我們讓主線程休息一下,然后我們再次在這個線程對象上啟動線程。結果我們看到:

      Exception?in?thread?"main"?java.lang.IllegalThreadStateException

      也就是這種線程對象一時運行一次完成后,它就再也不能運行第二次了。我們可以看一下它有具體實現:

        public synchronized void start() {
            if (started)
                throw new IllegalThreadStateException();
            started = true;
            group.add(this);
            start0();
        }
    

      一個Thread的實例一旦調用start()方法,這個實例的started標記就標記為true,事實中不管這個線程后來有沒有執行到底,只要調用了一次start()就再也沒有機會運行了,這意味著:

    [通過Thread實例的start(),一個Thread的實例只能產生一個線程]

      那么如果要在一個實例上產生多個線程(也就是我們常說的線程池),我們應該如何做呢?這就是Runnable接口給我們帶來的偉大的功能。

    class R implements Runnable{
      private int x = 0;
      public void run(){
    
        for(int i=0;i<100;i++){
          try{
            Thread.sleep(10);
          }catch(Exception e){}
          System.out.println(x++);
    
        }
      }
    }
    

      
    正如它的名字一樣,Runnable的實例是可運行的,但它自己并不能直接運行,它需要被Thread對象來包裝才行運行:

    public class Test {
      public static void main(String[] args) throws Exception{
        new Thread(new R()).start();
      }
    }
    

      當然這個結果和mt.start()沒有什么區別。但如果我們把一個Runnable實例給Thread對象多次包裝,我們就可以看到它們實際是在同一實例上啟動線程:

    public class Test {
      public static void main(String[] args) throws Exception{
        R r = new R();
        for(int i=0;i<10;i++)
          new Thread(r).start();
      }
    }
    

      x是實例對象,但結果是x被加到了999,說明這10個線程是在同一個r對象上運行的。請大家注意,因為這個例子是在單CPU上運行的,所以沒有對多個線程同時操作共同的對象進行同步。這里是為了說明的方便而簡化了同步,而真正的環境中你無法預知程序會在什么環境下運行,所以一定要考慮同步。

      到這里我們做一個完整的例子來說明線程產生的方式不同而生成的線程的區別:

    package debug;
    
    import java.io.*;
    import java.lang.Thread;
    
    
    class MyThread extends Thread{
      public int x = 0;
    
      public void run(){
        System.out.println(++x);
      }
    }
    
    class R implements Runnable{
      private int x = 0;
      public void run(){
        System.out.println(++x);
      }
    }
    
    public class Test {
      public static void main(String[] args) throws Exception{
        
        for(int i=0;i<10;i++){
          Thread t = new MyThread();
          t.start();
        }
        Thread.sleep(10000);//讓上面的線程運行完成
        R r = new R();
        for(int i=0;i<10;i++){
          Thread t = new Thread(r);
          t.start();
        }
      }
    }
    

      上面10個線程對象產生的10個線程運行時打印了10次1。下面10個線程對象產生的10個線程運行時打印了1到10。我們把下面的10個線程稱為同一實例(Runnable實例)的多個線程

      下節我們將研究線程對象方法,還是那句話,一般文檔中可以讀到的內容我不會介紹太多
    請大家自己了解。

    轉載自dev2dev網友axman的go deep into java專欄。

    個人自述

    一個男人.
    一個寫程序的男人.
    一個寫程序并正在從程序中尋找快樂的男人.
    一個寫程序并正在從程序中尋找快樂并把快樂傳遞給大家的男人.

    一個書生.
    一個寂寞的書生.
    一個寂寞的梅香竹影下敲聲寫韻的書生.
    一個寂寞的梅香竹影下敲聲寫韻晨鐘暮鼓中逸氣揚劍的書生.

    那個男人是位書生。沒有人知道他的姓名,居無定所,行無定蹤,亦耕變讀,或漁或樵。
    所以有人叫他樵夫(Axman),有人叫他漁郎(fisher)。

    posted @ 2007-10-22 11:25 華夢行 閱讀(238) | 評論 (0)編輯 收藏
    多線程編程——基礎篇 (一)

    時間:2006-08-08
    作者:axman
    瀏覽次數: 5279
    本文關鍵字:Java,?多線程,?線程,?線程對象,?單線程,?go deep into java
    文章工具
    推薦給朋友?推薦給朋友
    打印文章?打印文章

      [寫在前面]

      隨著計算機技術的發展,編程模型也越來越復雜多樣化。但多線程編程模型是目前計算機系統架構的最終模型。隨著CPU主頻的不斷攀升,X86架構的硬件已經成為瓶,在這種架構的CPU主頻最高為4G。事實上目前3.6G主頻的CPU已經接近了頂峰。

      如果不能從根本上更新當前CPU的架構(在很長一段時間內還不太可能),那么繼續提高CPU性能的方法就是超線程CPU模式。那么,作業系統、應用程序要發揮CPU的最大性能,就是要改變到以多線程編程模型為主的并行處理系統和并發式應用程序。

      所以,掌握多線程編程模型,不僅是目前提高應用性能的手段,更是下一代編程模型的核心思想。多線程編程的目的,就是"最大限度地利用CPU資源",當某一線程的處理不需要占用CPU而只和I/O,OEMBIOS等資源打交道時,讓需要占用CPU資源的其它線程有機會獲得CPU資源。從根本上說,這就是多線程編程的最終目的。

      [第一需要弄清的問題]

      如同程序和進程的區別,要掌握多線程編程,第一要弄清的問題是:線程對象和線程的區別

      線程對象是可以產生線程的對象。比如在java平臺中Thread對象,Runnable對象。線程,是指正在執行的一個指點令序列。在java平臺上是指從一個線程對象的start()開始,運行run方法體中的那一段相對獨立的過程。

      鑒于作者的水平,無法用更確切的詞匯來描述它們的定義。但這兩個有本質區別的概念請初學者細細體會,隨著介紹的深入和例程分析的增加,就會慢慢明白它們所代表的真實含義。

      天下難事必始于易,天下大事必始于細。

      讓我們先從最簡單的"單線程"來入手:(1)帶引號說明只是相對而言的單線程,(2)基于java。

        class BeginClass{
            public static void main(String[] args){
                for(int i=0;i<100;i++)
                    System.out.println("Hello,World!");
            }
        }
    

      如果我們成功編譯了該java文件,然后在命令行上敲入:

      java?BeginClass

      現在發生了什么呢?每一個java程序員,從他開始學習java的第一分鐘里都會接觸到這個問

      題,但是,你知道它到底發生發什么?

      JVM進程被啟動,在同一個JVM進程中,有且只有一個進程,就是它自己。然后在這個JVM環境中,所有程序的運行都是以線程來運行。JVM最先會產生一個主線程,由它來運行指定程序的入口點。在這個程序中,就是主線程從main方法開始運行。當main方法結束后,主線程運行完成。JVM進程也隨之退出。

      我們看到的是一個主線程在運行main方法,這樣的只有一個線程執行程序邏輯的流程我們稱

      之為單線程。這是JVM提供給我們的單線程環境,事實上,JVM底層還至少有垃圾回收這樣的后臺線程以及其它非java線程,但這些線程對我們而言不可訪問,我們只認為它是單線程的。

      主線程是JVM自己啟動的,在這里它不是從線程對象產生的。在這個線程中,它運行了main方法這個指令序列。理解它,但它沒有更多可以研究的內容。

      [接觸多線程]

        class MyThread extends Thread{
            public void run(){
                System.out.println("Thread say:Hello,World!");
            }
        }
    
        public class MoreThreads{
            public static void main(String[] args){
                new MyThread();
                new MyThread().start();
                System.out.println("Main say:Hello,World");
            }
        }
    

      執行這個程序,main方法第一行產生了一個線程對象,但并沒有線程啟動。

      main方法第二行產生了一個線程對象,并啟動了一個線程。

      main方法第三行,產生并啟動一個線程后,主線程自己也繼續執行其它語句。

      我們先不研究Thread對象的具體內容,稍微來回想一下上面的兩個概念,線程對象線程。在JAVA中,線程對象是JVM產生的一個普通的Object子類。而線程是CPU分配給這個對象的一個運行過程。我們說的這個線程在干什么,不是說一個線程對象在干什么,而是這個運行過程在干什么。如果一時想不明白,不要急,但你要記得它們不是一回事就行了。

      累了吧?為不么不繼續了?

      基于這種風格來介紹多線程,并不是每個人都喜歡和接受的,如果你不喜歡,正好不浪費你的時間了,而如果你接受的話,那就看下一節吧。

      轉載自dev2dev網友axman的go deep into java專欄

    個人自述

    一個男人.
    一個寫程序的男人.
    一個寫程序并正在從程序中尋找快樂的男人.
    一個寫程序并正在從程序中尋找快樂并把快樂傳遞給大家的男人.

    一個書生.
    一個寂寞的書生.
    一個寂寞的梅香竹影下敲聲寫韻的書生.
    一個寂寞的梅香竹影下敲聲寫韻晨鐘暮鼓中逸氣揚劍的書生.

    那個男人是位書生。沒有人知道他的姓名,居無定所,行無定蹤,亦耕變讀,或漁或樵。
    所以有人叫他樵夫(Axman),有人叫他漁郎(fisher)。

    posted @ 2007-10-22 11:17 華夢行 閱讀(251) | 評論 (0)編輯 收藏

    多線程設計要點

    板橋里人 http://www.jdon.com 2002/01/10

    ?

    1 .多線程中有主內存和工作內存之分, 在JVM中,有一個主內存,專門負責所有線程共享數據;而每個線程都有他自己私有的工作內存, 主內存和工作內存分貝在JVM的stack區和heap區。

    2. 線程的狀態有'Ready', 'Running', 'Sleeping', 'Blocked', 和 'Waiting'幾個狀態,
    'Ready' 表示線程正在等待CPU分配允許運行的時間。

    3. 線程運行次序并不是按照我們創建他們時的順序來運行的,CPU處理線程的順序是不確定的,如果需要確定,那么必須手工介入,使用setPriority()方法設置優先級。

    4. 我們無從知道一個線程什么時候運行,兩個或多個線程在訪問同一個資源時,需要synchronized

    5. 每個線程會注冊自己,實際某處存在著對它的引用,因此,垃圾回收機制對它就“束手無策”了。

    6. Daemon線程區別一般線程之處是:主程序一旦結束,Daemon線程就會結束。

    7. 一個對象中的所有synchronized方法都共享一把鎖,這把鎖能夠防止多個方法對通用內存同時進行的寫操作。synchronized static方法可在一個類范圍內被相互間鎖定起來。

    8. 對于訪問某個關鍵共享資源的所有方法,都必須把它們設為synchronized,否則就不能正常工作。

    9. 假設已知一個方法不會造成沖突,最明智的方法是不要使用synchronized,能提高些性能。

    10 . 如果一個"同步"方法修改了一個變量,而我們的方法要用到這個變量(可能是只讀),最好將自己的這個方法也設為 synchronized。

    11. synchronized不能繼承, 父類的方法是synchronized,那么其子類重載方法中就不會繼承“同步”。

    12. 線程堵塞Blocked有幾個原因造成:

    (1)線程在等候一些IO操作
    (2)線程試圖調用另外一個對象的“同步”方法,但那個對象處于鎖定狀態,暫時無法使用。

    13. 原子型操作(atomic), 對原始型變量(primitive)的操作是原子型的atomic. 意味著這些操作是線程安全的, 但是大部分情況下,我們并不能正確使用,來看看 i = i + 1 , i是int型,屬于原始型變量:

    (1)從主內存中讀取i值到本地內存.
    (2)將值從本地內存裝載到線程工作拷貝中.
    (3)裝載變量1.
    (4)將i 加 1.
    (5)將結果給變量i.
    (6)將i保存到線程本地工作拷貝中.
    (7)寫回主內存.

    注意原子型操作只限于第1步到第2步的讀取以及第6到第7步的寫, i的值還是可能被同時執行i=i+1的多線程中斷打擾(在第4步)。

    double 和long 變量是非原子型的(non-atomic)。數組是object 非原子型。

    14. 由于13條的原因,我們解決辦法是:

    class xxx extends Thread{

    //i會被經常修改
    private int i;

    public synchronized int read(){ return i;}

    public synchronized void update(){ i = i + 1;}

    ..........

    }

    15. Volatile變量, volatile變量表示保證它必須是與主內存保持一致,它實際是"變量的同步", 也就是說對于volatile變量的操作是原子型的,如用在long 或 double變量前。

    16. 使用yield()會自動放棄CPU,有時比sleep更能提升性能。

    17. sleep()和wait()的區別是:wait()方法被調用時會解除鎖定,但是我們能使用它的地方只是在一個同步的方法或代碼塊內。

    18. 通過制造縮小同步范圍,盡可能的實現代碼塊同步,wait(毫秒數)可在指定的毫秒數可退出wait;對于wait()需要被notisfy()或notifyAll()踢醒。

    19. 構造兩個線程之間實時通信的方法分幾步:
    (1). 創建一個PipedWriter和一個PipedReader和它們之間的管道;
    PipedReader in = new PipedReader(new PipedWriter())
    (2). 在需要發送信息的線程開始之前,將外部的PipedWriter導向給其內部的Writer實例out
    (3). 在需要接受信息的線程開始之前,將外部的PipedReader導向給其內部的Reader實例in
    (4). 這樣放入out的所有東西度可從in中提取出來。

    20. synchronized帶來的問題除性能有所下降外,最大的缺點是會帶來死鎖DeadLock,只有通過謹慎設計來防止死鎖,其他毫無辦法,這也是線程難以馴服的一個原因。不要再使用stop() suspend() resume()和destory()方法

    21. 在大量線程被堵塞時,最高優先級的線程先運行。但是不表示低級別線程不會運行,運行概率小而已。

    22. 線程組的主要優點是:使用單個命令可完成對整個線程組的操作。很少需要用到線程組。

    23. 從以下幾個方面提升多線程的性能:

    檢查所有可能Block的地方,盡可能的多的使用sleep或yield()以及wait();

    盡可能延長sleep(毫秒數)的時間;

    運行的線程不用超過100個,不能太多;

    不同平臺linux或windows以及不同JVM運行性能差別很大。

    24. 推薦幾篇相關英文文章:

    posted @ 2007-10-22 10:21 華夢行 閱讀(235) | 評論 (1)編輯 收藏
     名稱 Java語言編碼規范(Java Code Conventions)
     譯者 晨光(Morning)
     簡介 本文檔講述了Java語言的編碼規范,較之陳世忠先生《c++編碼規范》的浩繁詳盡,此文當屬短小精悍了。而其中所列之各項條款,從編碼風格,到注意事項,不單只Java,對于其他語言,也都很有借鑒意義。因為簡短,所以易記,大家不妨將此作為handbook,常備案頭,逐一對驗。
     聲明 如需復制、傳播,請附上本聲明,謝謝。
    原文出處:http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html,
    譯文出處:http://morningspace.51.net/,moyingzz@etang.com

     目錄

    1 介紹 2 文件名 3 文件組織 4 縮進排版 5 注釋 6 聲明 7 語句 8 空白 9 命名規范
    10 編程慣例 11 代碼范例

    1 介紹(Introduction)

    1.1 為什么要有編碼規范(Why Have Code Conventions)

    編碼規范對于程序員而言尤為重要,有以下幾個原因:

    - 一個軟件的生命周期中,80%的花費在于維護
    - 幾乎沒有任何一個軟件,在其整個生命周期中,均由最初的開發人員來維護
    - 編碼規范可以改善軟件的可讀性,可以讓程序員盡快而徹底地理解新的代碼
    - 如果你將源碼作為產品發布,就需要確任它是否被很好的打包并且清晰無誤,一如你已構建的其它任何產品

    為了執行規范,每個軟件開發人員必須一致遵守編碼規范。每個人。

    1.2 版權聲明(Acknowledgments)

    本文檔反映的是Sun MicroSystems公司,Java語言規范中的編碼標準部分。主要貢獻者包括:Peter King,Patrick Naughton,Mike DeMoney,Jonni Kanerva,Kathy Walrath以及Scott Hommel。

    本文檔現由Scott Hommel維護,有關評論意見請發至shommel@eng.sun.com

    2 文件名(File Names)

    這部分列出了常用的文件名及其后綴。

    2.1 文件后綴(File Suffixes)

    Java程序使用下列文件后綴:

    文件類別 文件后綴
    Java源文件 .java
    Java字節碼文件 .class

    2.2 常用文件名(Common File Names)

    常用的文件名包括:

    文件名 用途
    GNUmakefile makefiles的首選文件名。我們采用gnumake來創建(build)軟件。
    README 概述特定目錄下所含內容的文件的首選文件名

    3 文件組織(File Organization)

    一個文件由被空行分割而成的段落以及標識每個段落的可選注釋共同組成。超過2000行的程序難以閱讀,應該盡量避免。"Java源文件范例"提供了一個布局合理的Java程序范例。

    3.1 Java源文件(Java Source Files)

    每個Java源文件都包含一個單一的公共類或接口。若私有類和接口與一個公共類相關聯,可以將它們和公共類放入同一個源文件。公共類必須是這個文件中的第一個類或接口。

    Java源文件還遵循以下規則:

    - 開頭注釋(參見"- 包和引入語句(參見"- 類和接口聲明(參見"

    3.1.1 開頭注釋(Beginning Comments)

    所有的源文件都應該在開頭有一個C語言風格的注釋,其中列出類名、版本信息、日期和版權聲明:

      /*
       * Classname
       *
       * Version information
       *
       * Date
       *
       * Copyright notice
       */
    	  

    3.1.2 包和引入語句(Package and Import Statements)

    在多數Java源文件中,第一個非注釋行是包語句。在它之后可以跟引入語句。例如:

      package java.awt;
    
      import java.awt.peer.CanvasPeer;
    	  

    3.1.3 類和接口聲明(Class and Interface Declarations)

    下表描述了類和接口聲明的各個部分以及它們出現的先后次序。參見"

    ? 類/接口聲明的各部分 注解
    1 類/接口文檔注釋(/**……*/) 該注釋中所需包含的信息,參見"
    2 類或接口的聲明 ?
    3 類/接口實現的注釋(/*……*/)如果有必要的話 該注釋應包含任何有關整個類或接口的信息,而這些信息又不適合作為類/接口文檔注釋。
    4 類的(靜態)變量 首先是類的公共變量,隨后是保護變量,再后是包一級別的變量(沒有訪問修飾符,access modifier),最后是私有變量。
    5 實例變量 首先是公共級別的,隨后是保護級別的,再后是包一級別的(沒有訪問修飾符),最后是私有級別的。
    6 構造器 ?
    7 方法 這些方法應該按功能,而非作用域或訪問權限,分組。例如,一個私有的類方法可以置于兩個公有的實例方法之間。其目的是為了更便于閱讀和理解代碼。

    4 縮進排版(Indentation)

    4個空格常被作為縮進排版的一個單位。縮進的確切解釋并未詳細指定(空格 vs. 制表符)。一個制表符等于8個空格(而非4個)。

    4.1 行長度(Line Length)

    盡量避免一行的長度超過80個字符,因為很多終端和工具不能很好處理之。

    注意:用于文檔中的例子應該使用更短的行長,長度一般不超過70個字符。

    4.2 換行(Wrapping Lines)

    當一個表達式無法容納在一行內時,可以依據如下一般規則斷開之:

    - 在一個逗號后面斷開
    - 在一個操作符前面斷開
    - 寧可選擇較高級別(higher-level)的斷開,而非較低級別(lower-level)的斷開
    - 新的一行應該與上一行同一級別表達式的開頭處對齊
    - 如果以上規則導致你的代碼混亂或者使你的代碼都堆擠在右邊,那就代之以縮進8個空格。

    以下是斷開方法調用的一些例子:

      someMethod(longExpression1, longExpression2, longExpression3, 
                       longExpression4, longExpression5);
    
      var = someMethod1(longExpression1, 
                                someMethod2(longExpression2, 
                                                   longExpression3));
    	  

    以下是兩個斷開算術表達式的例子。前者更好,因為斷開處位于括號表達式的外邊,這是個較高級別的斷開。

      longName1 = longName2 * (longName3 + longName4 - longName5)
                         + 4 * longname6; //PREFFER
    
      longName1 = longName2 * (longName3 + longName4 
                                             - longName5) + 4 * longname6; //AVOID
    	  

    以下是兩個縮進方法聲明的例子。前者是常規情形。后者若使用常規的縮進方式將會使第二行和第三行移得很靠右,所以代之以縮進8個空格

      //CONVENTIONAL INDENTATION
      someMethod(int anArg, Object anotherArg, String yetAnotherArg, 
                        Object andStillAnother) {
        ...
      }
    
      //INDENT 8 SPACES TO AVOID VERY DEEP INDENTS
      private static synchronized horkingLongMethodName(int anArg,
              Object anotherArg, String yetAnotherArg,
              Object andStillAnother) {
        ...
      }
    	  

    if語句的換行通常使用8個空格的規則,因為常規縮進(4個空格)會使語句體看起來比較費勁。比如:

      //DON’T USE THIS INDENTATION
      if ((condition1 && condition2)
          || (condition3 && condition4)
          ||!(condition5 && condition6)) { //BAD WRAPS
          doSomethingAboutIt();             //MAKE THIS LINE EASY TO MISS
      }
    
      //USE THIS INDENTATION INSTEAD
      if ((condition1 && condition2)
              || (condition3 && condition4)
              ||!(condition5 && condition6)) {
          doSomethingAboutIt();
      }
    
      //OR USE THIS
      if ((condition1 && condition2) || (condition3 && condition4)
              ||!(condition5 && condition6)) {
          doSomethingAboutIt();
      }
    	  

    這里有三種可行的方法用于處理三元運算表達式:

      alpha = (aLongBooleanExpression) ? beta : gamma;
    
      alpha = (aLongBooleanExpression) ? beta
                                       : gamma;
    
      alpha = (aLongBooleanExpression)
              ? beta
              : gamma;
    	  

    5 注釋(Comments)

    Java程序有兩類注釋:實現注釋(implementation comments)和文檔注釋(document comments)。實現注釋是那些在C++中見過的,使用/*...*/和//界定的注釋。文檔注釋(被稱為"doc comments")是Java獨有的,并由/**...*/界定。文檔注釋可以通過javadoc工具轉換成HTML文件。

    實現注釋用以注釋代碼或者實現細節。文檔注釋從實現自由(implementation-free)的角度描述代碼的規范。它可以被那些手頭沒有源碼的開發人員讀懂。

    注釋應被用來給出代碼的總括,并提供代碼自身沒有提供的附加信息。注釋應該僅包含與閱讀和理解程序有關的信息。例如,相應的包如何被建立或位于哪個目錄下之類的信息不應包括在注釋中。

    在注釋里,對設計決策中重要的或者不是顯而易見的地方進行說明是可以的,但應避免提供代碼中己清晰表達出來的重復信息。多余的的注釋很容易過時。通常應避免那些代碼更新就可能過時的注釋。

    注意:頻繁的注釋有時反映出代碼的低質量。當你覺得被迫要加注釋的時候,考慮一下重寫代碼使其更清晰。

    注釋不應寫在用星號或其他字符畫出來的大框里。注釋不應包括諸如制表符和回退符之類的特殊字符。

    5.1 實現注釋的格式(Implementation Comment Formats)

    程序可以有4種實現注釋的風格:塊(block)、單行(single-line)、尾端(trailing)和行末(end-of-line)。

    5.1.1 塊注釋(Block Comments)

    塊注釋通常用于提供對文件,方法,數據結構和算法的描述。塊注釋被置于每個文件的開始處以及每個方法之前。它們也可以被用于其他地方,比如方法內部。在功能和方法內部的塊注釋應該和它們所描述的代碼具有一樣的縮進格式。

    塊注釋之首應該有一個空行,用于把塊注釋和代碼分割開來,比如:

      /*
       * Here is a block comment.
       */
    	  

    塊注釋可以以/*-開頭,這樣indent(1)就可以將之識別為一個代碼塊的開始,而不會重排它。

      /*-
        * Here is a block comment with some very special
        * formatting that I want indent(1) to ignore.
        *
        *    one
        *        two
        *            three
        */
    	  

    注意:如果你不使用indent(1),就不必在代碼中使用/*-,或為他人可能對你的代碼運行indent(1)作讓步。

    參見"

    5.1.2 單行注釋(Single-Line Comments)

    短注釋可以顯示在一行內,并與其后的代碼具有一樣的縮進層級。如果一個注釋不能在一行內寫完,就該采用塊注釋(參見"

      if (condition) {
    
        /* Handle the condition. */
        ...
      }
    	  

    5.1.3 尾端注釋(Trailing Comments)

    極短的注釋可以與它們所要描述的代碼位于同一行,但是應該有足夠的空白來分開代碼和注釋。若有多個短注釋出現于大段代碼中,它們應該具有相同的縮進。

    以下是一個Java代碼中尾端注釋的例子:

      if (a == 2) {
          return TRUE;              /* special case */
      } else {
          return isPrime(a);         /* works only for odd a */
      }
    	  

    5.1.4 行末注釋(End-Of-Line Comments)

    注釋界定符"http://",可以注釋掉整行或者一行中的一部分。它一般不用于連續多行的注釋文本;然而,它可以用來注釋掉連續多行的代碼段。以下是所有三種風格的例子:

      if (foo > 1) {
    
          // Do a double-flip.
          ...
      }
      else {
          return false;          // Explain why here.
      }
    
      //if (bar > 1) {
      //
      //    // Do a triple-flip.
      //    ...
      //}
      //else {
      //    return false;
      //}
    	  

    5.2 文檔注釋(Documentation Comments)

    注意:此處描述的注釋格式之范例,參見"

    若想了解更多,參見"How to Write Doc Comments for Javadoc",其中包含了有關文檔注釋標記的信息(@return, @param, @see):

    http://java.sun.com/javadoc/writingdoccomments/index.html

    若想了解更多有關文檔注釋和javadoc的詳細資料,參見javadoc的主頁:

    http://java.sun.com/javadoc/index.html

    文檔注釋描述Java的類、接口、構造器,方法,以及字段(field)。每個文檔注釋都會被置于注釋定界符/**...*/之中,一個注釋對應一個類、接口或成員。該注釋應位于聲明之前:

      /**
        * The Example class provides ...
        */
      public class Example { ...
    	  

    注意頂層(top-level)的類和接口是不縮進的,而其成員是縮進的。描述類和接口的文檔注釋的第一行(/**)不需縮進;隨后的文檔注釋每行都縮進1格(使星號縱向對齊)。成員,包括構造函數在內,其文檔注釋的第一行縮進4格,隨后每行都縮進5格。

    若你想給出有關類、接口、變量或方法的信息,而這些信息又不適合寫在文檔中,則可使用實現塊注釋(見5.1.1)或緊跟在聲明后面的單行注釋(見5.1.2)。例如,有關一個類實現的細節,應放入緊跟在類聲明后面的實現塊注釋中,而不是放在文檔注釋中。

    文檔注釋不能放在一個方法或構造器的定義塊中,因為Java會將位于文檔注釋之后的第一個聲明與其相關聯。

    6 聲明(Declarations)

    6.1 每行聲明變量的數量(Number Per Line)

    推薦一行一個聲明,因為這樣以利于寫注釋。亦即,

      int level;  // indentation level
      int size;   // size of table
    	  

    要優于,

    int level, size;

    不要將不同類型變量的聲明放在同一行,例如:

      int foo,  fooarray[];   //WRONG!
    	  

    注意:上面的例子中,在類型和標識符之間放了一個空格,另一種被允許的替代方式是使用制表符:

      int		level;         // indentation level
      int		size;          // size of table
      Object	currentEntry;  // currently selected table entry
    	  

    6.2 初始化(Initialization)

    盡量在聲明局部變量的同時初始化。唯一不這么做的理由是變量的初始值依賴于某些先前發生的計算。

    6.3 布局(Placement)

    只在代碼塊的開始處聲明變量。(一個塊是指任何被包含在大括號"{"和"}"中間的代碼。)不要在首次用到該變量時才聲明之。這會把注意力不集中的程序員搞糊涂,同時會妨礙代碼在該作用域內的可移植性。

      void myMethod() {
          int int1 = 0;         // beginning of method block
    
          if (condition) {
              int int2 = 0;     // beginning of "if" block
              ...
          }
      }
    	  

    該規則的一個例外是for循環的索引變量

      for (int i = 0; i < maxLoops; i++) { ... }
    	  

    避免聲明的局部變量覆蓋上一級聲明的變量。例如,不要在內部代碼塊中聲明相同的變量名:

      int count;
      ...
      myMethod() {
          if (condition) {
              int count = 0;     // AVOID!
              ...
          }
          ...
      }
    	  

    6.4 類和接口的聲明(Class and Interface Declarations)

    當編寫類和接口是,應該遵守以下格式規則:

    - 在方法名與其參數列表之前的左括號"("間不要有空格
    - 左大括號"{"位于聲明語句同行的末尾
    - 右大括號"}"另起一行,與相應的聲明語句對齊,除非是一個空語句,"}"應緊跟在"{"之后

      class Sample extends Object {
          int ivar1;
          int ivar2;
    
          Sample(int i, int j) {
              ivar1 = i;
              ivar2 = j;
          }
    
          int emptyMethod() {}
    
          ...
      }
    	  
    - 方法與方法之間以空行分隔

    7 語句(Statements)

    7.1 簡單語句(Simple Statements)

    每行至多包含一條語句,例如:

      argv++;       // Correct
      argc--;       // Correct
      argv++; argc--;       // AVOID!
    	  

    7.2 復合語句(Compound Statements)

    復合語句是包含在大括號中的語句序列,形如"{ 語句 }"。例如下面各段。

    - 被括其中的語句應該較之復合語句縮進一個層次
    - 左大括號"{"應位于復合語句起始行的行尾;右大括號"}"應另起一行并與復合語句首行對齊。
    - 大括號可以被用于所有語句,包括單個語句,只要這些語句是諸如if-else或for控制結構的一部分。這樣便于添加語句而無需擔心由于忘了加括號而引入bug。

    7.3 返回語句(return Statements)

    一個帶返回值的return語句不使用小括號"()",除非它們以某種方式使返回值更為顯見。例如:

      return;
    
      return myDisk.size();
    
      return (size ? size : defaultSize);
    	  

    7.4 if,if-else,if else-if else語句(if, if-else, if else-if else Statements)

    if-else語句應該具有如下格式:

      if (condition) {
          statements;
      }
    
      if (condition) {
          statements;
      } else {
          statements;
      }
    
      if (condition) {
          statements;
      } else if (condition) {
          statements;
      } else{
          statements;
      }
    	  

    注意:if語句總是用"{"和"}"括起來,避免使用如下容易引起錯誤的格式:

      if (condition) //AVOID! THIS OMITS THE BRACES {}!
          statement;
    	  

    7.5 for語句(for Statements)

    一個for語句應該具有如下格式:

      for (initialization; condition; update) {
          statements;
      }
    	  

    一個空的for語句(所有工作都在初始化,條件判斷,更新子句中完成)應該具有如下格式:

      for (initialization; condition; update);
    	  

    當在for語句的初始化或更新子句中使用逗號時,避免因使用三個以上變量,而導致復雜度提高。若需要,可以在for循環之前(為初始化子句)或for循環末尾(為更新子句)使用單獨的語句。

    7.6 while語句(while Statements)

    一個while語句應該具有如下格式

      while (condition) {
          statements;
      }
    	  

    一個空的while語句應該具有如下格式:

      while (condition);
    	  

    7.7 do-while語句(do-while Statements)

    一個do-while語句應該具有如下格式:

      do {
          statements;
      } while (condition);
    	  

    7.8 switch語句(switch Statements)

    一個switch語句應該具有如下格式:

      switch (condition) {
      case ABC:
          statements;
          /* falls through */
      case DEF:
          statements;
          break;
    
      case XYZ:
          statements;
          break;
    
      default:
          statements;
          break;
      }
    	  

    每當一個case順著往下執行時(因為沒有break語句),通常應在break語句的位置添加注釋。上面的示例代碼中就包含注釋/* falls through */。

    7.9 try-catch語句(try-catch Statements)

    一個try-catch語句應該具有如下格式:

      try {
          statements;
      } catch (ExceptionClass e) {
          statements;
      }
    	  

    一個try-catch語句后面也可能跟著一個finally語句,不論try代碼塊是否順利執行完,它都會被執行。

      try {
          statements;
      } catch (ExceptionClass e) {
          statements;
      } finally {
          statements;
      }
    	  

    8 空白(White Space)

    8.1 空行(Blank Lines)

    空行將邏輯相關的代碼段分隔開,以提高可讀性。

    下列情況應該總是使用兩個空行:

    - 一個源文件的兩個片段(section)之間
    - 類聲明和接口聲明之間

    下列情況應該總是使用一個空行:

    - 兩個方法之間
    - 方法內的局部變量和方法的第一條語句之間
    - 塊注釋(參見"- 一個方法內的兩個邏輯段之間,用以提高可讀性

    8.2 空格(Blank Spaces)

    下列情況應該使用空格:

    - 一個緊跟著括號的關鍵字應該被空格分開,例如:

      while (true) {
          ...
      }
    	  
    注意:空格不應該置于方法名與其左括號之間。這將有助于區分關鍵字和方法調用。
    - 空白應該位于參數列表中逗號的后面
    - 所有的二元運算符,除了".",應該使用空格將之與操作數分開。一元操作符和操作數之間不因該加空格,比如:負號("-")、自增("++")和自減("--")。例如:
        a += c + d;
        a = (a + b) / (c * d);
    
        while (d++ = s++) {
            n++;
        }
        printSize("size is " + foo + "\n");
    	  
    - for語句中的表達式應該被空格分開,例如:
        for (expr1; expr2; expr3)
    	  
    - 強制轉型后應該跟一個空格,例如:
        myMethod((byte) aNum, (Object) x);
        myMethod((int) (cp + 5), ((int) (i + 3)) + 1);
    	  

    9 命名規范(Naming Conventions)

    命名規范使程序更易讀,從而更易于理解。它們也可以提供一些有關標識符功能的信息,以助于理解代碼,例如,不論它是一個常量,包,還是類。

    標識符類型命名規則例子
    包(Packages)一個唯一包名的前綴總是全部小寫的ASCII字母并且是一個頂級域名,通常是com,edu,gov,mil,net,org,或1981年ISO 3166標準所指定的標識國家的英文雙字符代碼。包名的后續部分根據不同機構各自內部的命名規范而不盡相同。這類命名規范可能以特定目錄名的組成來區分部門(department),項目(project),機器(machine),或注冊名(login names)。com.sun.eng
    com.apple.quicktime.v2
    edu.cmu.cs.bovik.cheese
    類(Classes)命名規則:類名是個一名詞,采用大小寫混合的方式,每個單詞的首字母大寫。盡量使你的類名簡潔而富于描述。使用完整單詞,避免縮寫詞(除非該縮寫詞被更廣泛使用,像URL,HTML)class Raster;
    class ImageSprite;
    接口(Interfaces)命名規則:大小寫規則與類名相似interface RasterDelegate;
    interface Storing;
    方法(Methods)方法名是一個動詞,采用大小寫混合的方式,第一個單詞的首字母小寫,其后單詞的首字母大寫。run();
    runFast();
    getBackground();
    變量(Variables)除了變量名外,所有實例,包括類,類常量,均采用大小寫混合的方式,第一個單詞的首字母小寫,其后單詞的首字母大寫。變量名不應以下劃線或美元符號開頭,盡管這在語法上是允許的。
    變量名應簡短且富于描述。變量名的選用應該易于記憶,即,能夠指出其用途。盡量避免單個字符的變量名,除非是一次性的臨時變量。臨時變量通常被取名為i,j,k,m和n,它們一般用于整型;c,d,e,它們一般用于字符型。
    char c;
    int i;
    float myWidth;
    實例變量(Instance Variables)大小寫規則和變量名相似,除了前面需要一個下劃線int _employeeId;
    String _name;
    Customer _customer;
    常量(Constants)類常量和ANSI常量的聲明,應該全部大寫,單詞間用下劃線隔開。(盡量避免ANSI常量,容易引起錯誤)static final int MIN_WIDTH = 4;
    static final int MAX_WIDTH = 999;
    static final int GET_THE_CPU = 1;

    10 編程慣例(Programming Practices)

    10.1 提供對實例以及類變量的訪問控制(Providing Access to Instance and Class Variables)

    若沒有足夠理由,不要把實例或類變量聲明為公有。通常,實例變量無需顯式的設置(set)和獲取(gotten),通常這作為方法調用的邊緣效應 (side effect)而產生。

    一個具有公有實例變量的恰當例子,是類僅作為數據結構,沒有行為。亦即,若你要使用一個結構(struct)而非一個類(如果java支持結構的話),那么把類的實例變量聲明為公有是合適的。

    10.2 引用類變量和類方法(Referring to Class Variables and Methods)

    避免用一個對象訪問一個類的靜態變量和方法。應該用類名替代。例如:

      classMethod();             //OK
      AClass.classMethod();      //OK
      anObject.classMethod();    //AVOID!
    	  

    10.3 常量(Constants)

    位于for循環中作為計數器值的數字常量,除了-1,0和1之外,不應被直接寫入代碼。

    10.4 變量賦值(Variable Assignments)

    避免在一個語句中給多個變量賦相同的值。它很難讀懂。例如:

      fooBar.fChar = barFoo.lchar = 'c'; // AVOID!
    	  

    不要將賦值運算符用在容易與相等關系運算符混淆的地方。例如:

      if (c++ = d++) {        // AVOID! (Java disallows)
          ...
      }
    	  

    應該寫成

      if ((c++ = d++) != 0) {
        ...
      }
    	  

    不要使用內嵌(embedded)賦值運算符試圖提高運行時的效率,這是編譯器的工作。例如:

      d = (a = b + c) + r;        // AVOID!
    	  

    應該寫成

      a = b + c;
      d = a + r;
    	  

    10.5 其它慣例(Miscellaneous Practices)

    10.5.1 圓括號(Parentheses)

    一般而言,在含有多種運算符的表達式中使用圓括號來避免運算符優先級問題,是個好方法。即使運算符的優先級對你而言可能很清楚,但對其他人未必如此。你不能假設別的程序員和你一樣清楚運算符的優先級。

      if (a == b && c == d)     // AVOID!
      if ((a == b) && (c == d))  // RIGHT
    	  

    10.5.2 返回值(Returning Values)

    設法讓你的程序結構符合目的。例如:

      if (booleanExpression) {
          return true;
      } else {
          return false;
      }
    	  

    應該代之以如下方法:

      return booleanExpression;
    	  

    類似地:

      if (condition) {
          return x;
      }
      return y;
    	  

    應該寫做:

      return (condition ? x : y);
    	  

    10.5.3 條件運算符"?"前的表達式(Expressions before '?' in the Conditional Operator)

    如果一個包含二元運算符的表達式出現在三元運算符" ? : "的"?"之前,那么應該給表達式添上一對圓括號。例如:

      (x >= 0) ? x : -x;
    	  

    10.5.4 特殊注釋(Special Comments)

    在注釋中使用XXX來標識某些未實現(bogus)的但可以工作(works)的內容。用FIXME來標識某些假的和錯誤的內容。

    11 代碼范例(Code Examples)

    11.1 Java源文件范例(Java Source File Example)

    下面的例子,展示了如何合理布局一個包含單一公共類的Java源程序。接口的布局與其相似。更多信息參見"

    /*
     * @(#)Blah.java        1.82 99/03/18
     *
     * Copyright (c) 1994-1999 Sun Microsystems, Inc.
     * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
     * All rights reserved.
     *
     * This software is the confidential and proprietary information of Sun
     * Microsystems, Inc. ("Confidential Information").  You shall not
     * disclose such Confidential Information and shall use it only in
     * accordance with the terms of the license agreement you entered into
     * with Sun.
     */
    
    
    package java.blah;
    
    import java.blah.blahdy.BlahBlah;
    
    /**
     * Class description goes here.
     *
     * @version 	1.82 18 Mar 1999
     * @author 	Firstname Lastname
     */
    public class Blah extends SomeClass {
        /* A class implementation comment can go here. */
    
        /** classVar1 documentation comment */
        public static int classVar1;
    
        /**
         * classVar2 documentation comment that happens to be
         * more than one line long
         */
        private static Object classVar2;
    
        /** instanceVar1 documentation comment */
        public Object instanceVar1;
    
        /** instanceVar2 documentation comment */
        protected int instanceVar2;
    
        /** instanceVar3 documentation comment */
        private Object[] instanceVar3;
    
        /**
         * ...constructor Blah documentation comment...
         */
        public Blah() {
            // ...implementation goes here...
        }
    
        /**
         * ...method doSomething documentation comment...
         */
        public void doSomething() {
            // ...implementation goes here...
        }
    
        /**
         * ...method doSomethingElse documentation comment...
         * @param someParam description
         */
        public void doSomethingElse(Object someParam) {
            // ...implementation goes here...
        }
    }
    	  
    posted @ 2007-10-15 11:21 華夢行 閱讀(132) | 評論 (0)編輯 收藏
    世界上并沒有成為高手的捷徑,但一些基本原則是可以遵循的。??

    1、扎實的基礎??


      數據結構、離散數學、編譯原理,這些是所有計算機科學的基礎,如果不掌握它們,很難寫出高水平的程序。程序人人都會寫,但當你發現寫到一定程度很難再提高的時候,就應該想想是不是要回過頭來學學這些最基本的理論。不要一開始就去學OOP,即使你再精通OOP,遇到一些基本算法的時候可能也會束手無策。因此多讀一些計算機基礎理論方面的書籍是非常有必要的。??


    2、豐富的想像力??


      不要拘泥于固定的思維方式,遇到問題的時候要多想幾種解決問題的方案,試試別人從沒想過的方法。豐富的想像力是建立在豐富的知識的基礎上,除計算機以外,多涉獵其他的學科,比如天文、物理、數學等等。開闊的思維對程序員來說很重要。??


    3、最簡單的是最好的??


      這也許是所有科學都遵循的一條準則,復雜的質能轉換原理在愛因斯坦眼里不過是一個簡單得不能再簡單的公式:E=mc2。簡單的方法更容易被人理解,更容易實現,也更容易維護。遇到問題時要優先考慮最簡單的方案,只有簡單方案不能滿足要求時再考慮復雜的方案。??


    4、不鉆牛角尖??


      當你遇到障礙的時候,不妨暫時遠離電腦,看看窗外的風景,聽聽輕音樂,和朋友聊聊天。當我遇到難題的時候會去玩游戲,當負責游戲的那部分大腦細胞極度亢奮的時候,負責編程的那部分大腦細胞就得到了充分的休息。當重新開始工作的時候,我會發現那些難題現在竟然可以迎刃而解。??


      5、對答案的渴求??


      人類自然科學的發展史就是一個渴求得到答案的過程,即使只能知道答案的一小部分也值得我們去付出。只要你堅定信念,一定要找到問題的答案,你才會付出精力去探索,即使最后沒有得到答案,在過程中你也會學到很多東西。??


      6、多與別人交流??


      三人行必有我師,也許在一次和別人不經意的談話中,就可以迸出靈感的火花。多上上網,看看別人對同一問題的看法,會給你很大的啟發。??


      7、良好的編程風格??


      注意養成良好的習慣,代碼的縮進編排,變量的命名規則要始終保持一致。大家都知道如何排除代碼中錯誤,卻往往忽視了對注釋的排錯。注釋是程序的一個重要組成部分,它可以使你的代碼更容易理解,而如果代碼已經清楚地表達了你的思想,就不必再加注釋了,如果注釋和代碼不一致,那就更加糟糕。??


      8、韌性和毅力??


      這也許是“高手”和一般程序員最大的區別。高手們并不是天才,他們是在無數個日日夜夜中磨煉出來的。成功能給我們帶來無比的喜悅,但過程卻是無比的枯燥乏味。你不妨做個測試,找個10000以內的素數表,把它們全都抄下來,然后再檢查三遍,如果能夠不間斷地完成這一工作,你就可以滿足這一條。
    posted @ 2007-10-15 11:09 華夢行 閱讀(99) | 評論 (0)編輯 收藏
    select S_10994_1_SYS_MODELTYPE.nextval,a.typeid,'SYS','Mail_Forward','郵件轉發模板','Mail Forward Model' from
    bse_organization a where not exists (select orgtypeid from SYS_MODELTYPE b where b.orgtypeid=a.typeid and modelcode ='Mail_Forward')
    --

    select S_10994_1_SYS_MODELTYPE.nextval,typeid,'SYS','Mail_Forward','郵件轉發模板','Mail Forward Model' from
    bse_organization where typeid not in (
    select orgtypeid from SYS_MODELTYPE where modelcode='Mail_Forward'
    )

    請注意not in 邏輯上不完全等同于not exists,如果你誤用了not in,小心你的程序存在致命的BUG:


    請看下面的例子:
    create table t1 (c1 number,c2 number);
    create table t2 (c1 number,c2 number);

    insert into t1 values (1,2);
    insert into t1 values (1,3);
    insert into t2 values (1,2);
    insert into t2 values (1,null);

    select * from t1 where c2 not in (select c2 from t2);
    no rows found
    select * from t1 where not exists (select 1 from t2 where t1.c2=t2.c2);
    c1 c2
    1 3

    正如所看到的,not in 出現了不期望的結果集,存在邏輯錯誤。如果看一下上述兩個select語句的執行計劃,也會不同。后者使用了hash_aj。
    因此,請盡量不要使用not in(它會調用子查詢),而盡量使用not exists(它會調用關聯子查詢)。如果子查詢中返回的任意一條記錄含有空值,則查詢將不返回任何記錄,正如上面例子所示。
    除非子查詢字段有非空限制,這時可以使用not in ,并且也可以通過提示讓它使用hasg_aj或merge_aj連接。

    posted @ 2007-10-11 16:51 華夢行 閱讀(187) | 評論 (0)編輯 收藏

    public class PlatContextListener implements ServletContextListener{
    ??? private Timer timer = null;
    ??? /** 應用程序的根目錄 */
    ??? private static String contextPath = null;
    ???
    ??? /** Creates a new instance of PlatContextListener */
    ??? public PlatContextListener() {
    ??? }

    ??? public void contextInitialized(ServletContextEvent sce) {
    ??????? ServletContext sc = sce.getServletContext();
    ??????? contextPath = sc.getRealPath("").replace("\\", "/");
    ???????
    ??????? int nInterval=24*60*60*1000;
    ???????
    ??????? timer = new Timer(true);
    ???????
    ??????? //每天零晨3點執行清理工作
    ??????? Calendar calendar = Calendar.getInstance();
    ??????? calendar.set(Calendar.HOUR_OF_DAY,3);
    ??????? calendar.set(Calendar.MINUTE,0);
    ??????? calendar.set(Calendar.SECOND,0);
    ??????? Date time = calendar.getTime();
    ???
    ??????? timer.scheduleAtFixedRate(new PlatTimerClearTask(), time,nInterval);
    ???????

    ??? }

    ??? public void contextDestroyed(ServletContextEvent sce) {
    ??????? timer.cancel();
    ??? }
    ???
    ??? public static String getContextPath() {
    ??????? return contextPath;
    ??? }
    ???
    }

    posted @ 2007-10-11 14:50 華夢行 閱讀(164) | 評論 (0)編輯 收藏

    在 IE6 中,可以很方便地利用 img 的 src 屬性,實現本地圖片預覽,然而在 IE7 中,這種辦法卻行不通。需要用 AlphaImageLoader


    AlphaImageLoader

    說明:

    在對象容器邊界內,在對象的背景和內容之間顯示一張圖片。并提供對此圖片的剪切和改變尺寸的操作。如果載入的是PNG(Portable Network Graphics)格式,則0%-100%的透明度也被提供。

    語法:

    filter : progid:DXImageTransform.Microsoft.AlphaImageLoader ( enabled=bEnabled , sizingMethod=sSize , src=sURL )

    enabled:可選項。布爾值(Boolean)。設置或檢索濾鏡是否激活。
    true:默認值。濾鏡激活。
    false:濾鏡被禁止。

    sizingMethod:可選項。字符串(String)。設置或檢索濾鏡作用的對象的圖片在對象容器邊界內的顯示方式。
    crop:剪切圖片以適應對象尺寸。
    image:默認值。增大或減小對象的尺寸邊界以適應圖片的尺寸。
    scale:縮放圖片以適應對象的尺寸邊界。

    src:必選項。字符串(String)。使用絕對或相對 url 地址指定背景圖像。假如忽略此參數,濾鏡將不會作用。


    具體操作:

    1. 為預覽區域(比如要在某個?div 中預覽)添加樣式:filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);。
    2. 為 AlphaImageLoader 設置 src 屬性。

    ?

    示例代碼:

    <? xml?version="1.0"?encoding="gb2312" ?>
    <! DOCTYPE?html?PUBLIC?"-//W3C//DTD?XHTML?1.0?Transitional//EN"?"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
    < html? xmlns ="http://www.w3.org/1999/xhtml" >

    < head >
    < meta? http-equiv ="Content-Type" ?content ="text/html;?charset=gb2312" ? />
    < title > 本地圖片預覽代碼(支持?IE6、IE7) </ title >
    < style? type ="text/css" >
    #newPreview
    {
    ????filter
    : progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale) ;
    }

    </ style >
    < script? type ="text/javascript" ?language ="javascript" >
    <!--
    function ?PreviewImg(imgFile)
    {
    ????
    // 原來的預覽代碼,不支持?IE7。
    ???? var ?oldPreview? = ?document.getElementById( " oldPreview " );
    ????oldPreview.innerHTML?
    = ? " <img?src=\ " file:\\\\ " ?+?imgFile.value?+? " \ " ?width=\ " 80 \ " ?height=\ " 60 \ " ?/> " ;
    ????
    ????
    // 新的預覽代碼,支持?IE6、IE7。
    ???? var ?newPreview? = ?document.getElementById( " newPreview " );
    ????newPreview.filters.item(
    " DXImageTransform.Microsoft.AlphaImageLoader " ).src? = ?imgFile.value;
    ????newPreview.style.width?
    = ? " 80px " ;
    ????newPreview.style.height?
    = ? " 60px " ;
    }

    -->
    </ script >
    </ head >

    < body >

    < p > 說明:以下針對的是互聯網情況,如果您在本地作測試,比如輸入的地址是:http://127.0.0.1/,則可以看到全部預覽。 </ p >

    < hr? />

    < p > 如果您使用的是?IE6,則可以看到以下預覽;如果您使用的是?IE7,則看不到以下預覽。 </ p >
    < div? id ="oldPreview" ></ div >

    < hr? />

    < p > 不論您使用的是?IE6?還是?IE7,均可以看到以下預覽。 </ p >
    < div? id ="newPreview" ></ div >

    < hr? />

    < p > 請選擇一個圖片進行預覽: < input? type ="file" ?size ="20" ?onchange ="javascript:PreviewImg(this);" ? /></ p >

    </ body >

    </ html >
    posted @ 2007-09-29 13:16 華夢行 閱讀(2707) | 評論 (4)編輯 收藏
    <!--#include file = conn.asp -->
    posted @ 2007-09-25 14:55 華夢行 閱讀(114) | 評論 (0)編輯 收藏
    Oracle? 查詢如果? a.typeName=a.typeName? 查出所有的a.typeName? 不為null的記錄。這點一定要注意null問題
    posted @ 2007-09-14 18:19 華夢行 閱讀(123) | 評論 (0)編輯 收藏

    異常控制

    ??Author: 江南白衣

    1.業務異常類

    ????? 1.所以業務異常類派生于BusinessException基類。

    ????? 2.原則上,要進行相同處理的異常分為一類,用ERROR_CODE標識不同。

    ????? 3.出錯信息統一寫在errors.properties,以ERROR_CODE為主鍵,支持i18N,由基類提供默認的getMessage()函數。

    ????? 參考BussinessException.java和OrderException.java。

    2.Servlet規范里的異常控制

    ?2.1按error-code統一定義錯誤頁面

    <error-page>
    ? <error-code>404</error-code>
    ? <location>/404.jsp</location>
    </error-page>
    <error-page>
    ? <error-code>500</error-code>
    ? <location>/error.jsp</location>
    </error-page>

    2.2按異常類型定義單獨錯誤頁面

    <error-page>
    ? <exception-type>org.sprngside.bookstore.UserNotFound</exception-type>
    ? <location>/userNotFound.jsp</location>
    </error-page>

    2.3 在JSP里單獨定義錯誤頁面

    <@ errorPage="error.jsp">

    3.Spring MVC里的異常控制

    ?? spring-mvc可在xxx-serverlet.xml里定義default和 按Excepiton類型影射的錯誤頁面, 和Servlet規范比,主要作了Spring特色的JSP路徑轉向和日志記錄.參見bookstore-servlet.xml

      <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    ??????? <property name="defaultErrorView" value="/error.jsp"/>
    ??????? <property name="exceptionMappings">
    ??????????? <props>
    ??????????????? <prop key="org.springside.framework.base.BusinessException">/businessError.jsp</prop>
    ??????????? </props>
    ??????? </property>
    ??? </bean>

    4. error.jsp的處理

    ???????? error.jsp會同時處理jsp,servlet,和spring拋過來的異常

    ???????? 其中jsp的異常在exception 變量中.

    ???????? servlet的異常在(Exception)request.getAttribute("javax.servlet.error.exception")

    ???????? spring的異常在(Exception) request.getAttribute("exception")

    ???????? 使用 (String) request.getAttribute("javax.servlet.error.request_uri")獲得 request_uri
    ?????????使用 logger.error(exception.getMessage(), exception); 記錄整個異常棧

    posted @ 2007-09-13 11:23 華夢行 閱讀(1830) | 評論 (0)編輯 收藏
    http://www.cnpack.org/upgrade/cvstracnt/CVSTracNT_1.2.1_20060112.exe
    posted @ 2007-09-12 18:22 華夢行 閱讀(104) | 評論 (0)編輯 收藏
    Class FilterChainProxy
    java.lang.Objectextended by org.acegisecurity.util.FilterChainProxy
    All Implemented Interfaces:
    Filter, InitializingBean, ApplicationContextAware

    public class FilterChainProxy
    extends Object
    implements Filter, InitializingBean, ApplicationContextAware

    Delegates Filter requests to a list of Spring-managed beans.

    通過一系列的由spring托管的beans ,代理過濾請求。
    FilterChainProxy 通過在web.xml中定義的FilterToBeanProxy 被加載,FilterChainProxy 將會通過init(FilterConfig), destroy() and doFilter(ServletRequest, ServletResponse, FilterChain)調用,調用每一個在其中定義的過濾器。

    The FilterChainProxy is loaded via a standard FilterToBeanProxy declaration in web.xml. FilterChainProxy will then pass init(FilterConfig), destroy() and doFilter(ServletRequest, ServletResponse, FilterChain) invocations through to each Filter defined against FilterChainProxy.

    ?
    ??? FilterChainProxy? 是通過一個標準的FilterInvocationDefinitionSource 來實現配置的,每個可能的FilterChainProxy應該服務的URI模式都必須進入
    ??????????? 第一個搭配的URI模式將會被用來定義處理請求的所有的過濾器,就是說只適配第一組過濾器,后面的其他過濾器將無效。
    FilterChainProxy
    is configured using a standard FilterInvocationDefinitionSource. Each possible URI pattern that FilterChainProxy should service must be entered. The first matching URI pattern located by FilterInvocationDefinitionSource for a given request will be used to define all of the Filters that apply to that request. NB: This means you must put most specific URI patterns at the top of the list, and ensure all Filters that should apply for a given URI pattern are entered against the respective entry. The FilterChainProxy will not iterate the remainder of the URI patterns to locate additional Filters. The FilterInvocationDefinitionSource described the applicable URI pattern to fire the filter chain, followed by a list of configuration attributes. Each configuration attribute's ConfigAttribute.getAttribute() corresponds to a bean name that is available from the application context.

    FilterChainProxy respects normal handling of Filters that elect not to call Filter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain), in that the remainder of the origial or FilterChainProxy-declared filter chain will not be called.

    It is particularly noted the Filter lifecycle mismatch between the servlet container and IoC container. As per FilterToBeanProxy JavaDocs, we recommend you allow the IoC container to manage lifecycle instead of the servlet container. By default the FilterToBeanProxy will never call this class' init(FilterConfig) and destroy() methods, meaning each of the filters defined against FilterInvocationDefinitionSource will not be called. If you do need your filters to be initialized and destroyed, please set the lifecycle initialization parameter against the FilterToBeanProxy to specify servlet container lifecycle management.

    If a filter name of TOKEN_NONE is used, this allows specification of a filter pattern which should never cause any filters to fire.

    posted @ 2007-09-12 16:20 華夢行 閱讀(1934) | 評論 (0)編輯 收藏

    四?Acegi ACL使用?

    4.1 基本概念

    ????? 在google中搜索'acl'會找到很多相關的介紹,而且涉及的范圍也特別廣泛。ACL是(Access Control List)的縮寫,顧名思義,ACL是‘訪問控制列表’的意思。通俗點說,ACL保存了所有用戶或角色對資源的訪問權限。最典型的ACL實現是流行操作系統(window, unix)的文件訪問控制系統,精確定義了某個用戶或角色對某個特定文件的讀、寫、執行等權限,更通俗的例子是可以定義某個管理員只能管一部分的訂單,而另一個管理員只能管另一部分的。

    4.2 Acegi ACL配置

    Acegi好早就實現了ACL(好像是0.5),但是使用起來確實有點麻煩,所以用的不是太廣泛。這里簡單的說明一下使用方法,希望有更多的朋友來試試。

    首先要理解Acegi里面Voter的概念,ACL正是在一個Voter上擴展起來的。現來看一下AclVoter的配置。

    ???? < bean? id ="aclBeanReadVoter" ?class ="org.acegisecurity.vote.BasicAclEntryVoter" >
    ????????
    < property? name ="processConfigAttribute" >
    ????????????
    < value > ACL_READ </ value >
    ????????
    </ property >
    ????????
    < property? name ="processDomainObjectClass" >
    ????????????
    < value > org.springside.modules.security.acl.domain.AclDomainAware </ value >
    ????????
    </ property >
    ????????
    < property? name ="aclManager" >
    ????????????
    < ref? local ="aclManager" />
    ????????
    </ property >
    ????????
    < property? name ="requirePermission" >
    ????????????
    < list >
    ????????????????
    < ref? local ="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION" />
    ????????????????
    < ref? local ="org.acegisecurity.acl.basic.SimpleAclEntry.READ" />
    ????????????
    </ list >
    ????????
    </ property >
    ????
    </ bean >
    1. ACL_READ指的是這個Voter對哪些SecurityConfig起作用,我們可以把ACL_READ配置在想要攔截的Method上。比方說我們要攔截readOrder這個方法,以實現ACL控制,可以這樣配置。
      orderManager.readOrder=ACL_READ
    2. processDomainObjectClass指出哪些DomainObject是要進行ACL校驗的。
    3. aclManager是一個比較重要的概念,主要負責在權限列表中根據用戶和DomainObject取得acl列表。
    4. requirePermission指出要進行這個操作必須具備的acl權限,比方說read操作就必須有ADMINISTRATION或READ兩個權限。

    其實整個過程看下來比較清晰,下面來看一下AclManager如何配置。

    ???? <!-- ?=========?ACCESS?CONTROL?LIST?LOOKUP?MANAGER?DEFINITIONS?=========? -->

    ????
    < bean? id ="aclManager" ?class ="org.acegisecurity.acl.AclProviderManager" >
    ????????
    < property? name ="providers" >
    ????????????
    < list >
    ????????????????
    < ref? local ="basicAclProvider" />
    ????????????
    </ list >
    ????????
    </ property >
    ????
    </ bean >

    ????
    < bean? id ="basicAclProvider" ?class ="org.acegisecurity.acl.basic.BasicAclProvider" >
    ????????
    < property? name ="basicAclDao" >
    ????????????
    < ref? local ="basicAclExtendedDao" />
    ????????
    </ property >
    ????
    </ bean >

    ????
    < bean? id ="basicAclExtendedDao" ?class ="org.acegisecurity.acl.basic.jdbc.JdbcExtendedDaoImpl" >
    ????????
    < property? name ="dataSource" >
    ????????????
    < ref? bean ="dataSource" />
    ????????
    </ property >
    ????
    </ bean >


    很明顯ACLManager繼承了Acegi的一貫風格,Provider可以提供多種取得ACL訪問列表的途徑,默認的是用basicAclProvider在數據庫中取得。既然提到了數據庫,那我們就來看一下Acegi默認提供的ACL在數據庫里的保存表結構:

    CREATE ? TABLE ?acl_object_identity?(
    id?
    IDENTITY ? NOT ? NULL ,
    object_identity?VARCHAR_IGNORECASE(
    250 )? NOT ? NULL ,
    parent_object?
    INTEGER ,
    acl_class?VARCHAR_IGNORECASE(
    250 )? NOT ? NULL ,
    CONSTRAINT ?unique_object_identity? UNIQUE (object_identity),
    FOREIGN ? KEY ?(parent_object)? REFERENCES ?acl_object_identity(id)
    );
    CREATE ? TABLE ?acl_permission?(
    id?
    IDENTITY ? NOT ? NULL ,
    acl_object_identity?
    INTEGER ? NOT ? NULL ,
    recipient?VARCHAR_IGNORECASE(
    100 )? NOT ? NULL ,
    mask?
    INTEGER ? NOT ? NULL ,
    CONSTRAINT ?unique_recipient? UNIQUE (acl_object_identity,?recipient),
    FOREIGN ? KEY ?(acl_object_identity)? REFERENCES ?acl_object_identity(id)
    );
    1. acl_object_identity表存放了所有受保護的domainObject的信息。其中object_identity字段保存了domainObject的class和id,默認的保存格式是:domainClass:domainObjectId。
    2. acl_permission?就是ACL權限列表了,recipient?是用戶或角色信息,mask表示了這個用戶或角色對這個domainObject的訪問權限。注意這些信息的保存格式都是可以根據自己的需要改變的。

    這樣讀取和刪除的時候Acegi就能很好的完成攔截工作,但是讀取一個List的時候,如何才能把該用戶不能操作的domainObject剔除掉呢?這就需要afterInvocationManager來完成這個工作。下面來看下配置:

    ???? <!-- ?==============?"AFTER?INTERCEPTION"?AUTHORIZATION?DEFINITIONS?===========? -->

    ????
    < bean? id ="afterInvocationManager" ?class ="org.acegisecurity.afterinvocation.AfterInvocationProviderManager" >
    ????????
    < property? name ="providers" >
    ????????????
    < list >
    ????????????????
    < ref? local ="afterAclCollectionRead" />
    ????????????
    </ list >
    ????????
    </ property >
    ????
    </ bean >
    ????
    <!-- ?Processes?AFTER_ACL_COLLECTION_READ?configuration?settings? -->
    ????
    < bean? id ="afterAclCollectionRead" ?class ="org.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationCollectionFilteringProvider" >
    ????????
    < property? name ="aclManager" >
    ????????????
    < ref? local ="aclManager" />
    ????????
    </ property >
    ????????
    < property? name ="requirePermission" >
    ????????????
    < list >
    ????????????????
    < ref? local ="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION" />
    ????????????????
    < ref? local ="org.acegisecurity.acl.basic.SimpleAclEntry.READ" />
    ????????????
    </ list >
    ????????
    </ property >
    ????
    </ bean >


    afterAclCollectionRead會在攔截的方法執行結束的時候執行。主要的作用就是在返回的List中挨個檢查domainObject的操作權限,然后根據requirePermission來剔除不符合的domainObject。

    4.3 使用RuleEngine設置的ACL規則

    在SpringSide里使用了RuleEngine來設置ACL規則,具體規則見
    bookstore-sample\resources\rules\drl

    posted @ 2007-09-12 14:46 華夢行 閱讀(285) | 評論 (0)編輯 收藏
    僅列出標題
    共15頁: First 上一頁 5 6 7 8 9 10 11 12 13 下一頁 Last 
    主站蜘蛛池模板: 国产亚洲漂亮白嫩美女在线| 麻豆国产VA免费精品高清在线| 国产亚洲精彩视频| 中文字幕亚洲免费无线观看日本 | 在线观看亚洲av每日更新 | 亚洲国产成人久久精品软件 | 国产黄在线播放免费观看| 亚洲精品V天堂中文字幕| 亚洲国产成人久久综合一区| 久久亚洲国产精品五月天| xvideos亚洲永久网址| 免费看大美女大黄大色| 国产成人免费网站| 亚洲精品视频在线观看免费| 欧洲人免费视频网站在线| eeuss影院免费92242部| 老司机福利在线免费观看| 亚洲av综合av一区二区三区 | 1000部拍拍拍18勿入免费视频软件| 99在线免费观看| 一级做受视频免费是看美女| 国产亚洲精品美女2020久久| 亚洲av永久无码精品秋霞电影秋| 亚洲一区精彩视频| 亚洲伦理一二三四| 亚洲另类图片另类电影| 亚洲免费在线视频播放| 亚洲国产午夜精品理论片| 亚洲国产精品综合久久久| 亚洲男人电影天堂| 亚洲欧洲综合在线| 亚洲国产精品免费在线观看| 亚洲手机中文字幕| 亚洲一区在线免费观看| 国产午夜亚洲精品| 亚洲熟妇av午夜无码不卡| 亚洲AV无码专区在线观看成人 | 男女免费观看在线爽爽爽视频| 国产福利视精品永久免费| 亚洲精品动漫免费二区| 免费被黄网站在观看|