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

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

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

    隨筆-314  評論-209  文章-0  trackbacks-0
     
         摘要:  pattern比對    (grep)字符串 命令 /pattern/修飾詞命令=~          表示比對符合pattern!~        &nbs...  閱讀全文
    posted @ 2012-03-10 15:44 xzc 閱讀(8220) | 評論 (0)編輯 收藏

    將ociuldr.exe復制到H:\oracle\product\10.2.0\db_1\BIN下, 或者path中的某個文件夾中

    用法:
    C:\Documents and Settings\tgm>ociuldr

    Usage: ociuldr user=... query=... field=... record=... file=...
    (@) Copyright Lou Fangxin 2004/2005, all rights reserved.
    Notes:
           -si   = enable logon as SYSDBA
           user = username/password@tnsname
           sql   = SQL file name,one sql per file, do not include ";"
           query = select statement
           field = seperator string between fields
           record= seperator string between records
           file = output file name(default: uldrdata.txt)
           read = set DB_FILE_MULTIBLOCK_READ_COUNT at session level
           sort = set SORT_AREA_SIZE & SORT_AREA_RETAINED_SIZE at session level (UNIT:MB)
           hash = set HASH_AREA_SIZE at session level (UNIT:MB)
           serial= set _serial_direct_read to TRUE at session level
           trace = set event 10046 to given level at session level
           table = table name in the sqlldr control file
           mode = sqlldr option, INSERT or APPEND or REPLACE or TRUNCATE
           log   = log file name, prefix with + to append mode
           long = maximum long field size
           array = array fetch size
            head = 第一行是否為字段名(head=on), 默認為off

    for field and record, you can use '0x' to specify hex character code,
    \r=0x0d \n=0x0a |=0x7c ,=0x2c \t=0x09

    一、導出數據

    d:\>ociuldr user=test/test@acf query="select * from test" file=test.txt table=test

    二、查看導出內容

    1,a
    2,b
    3,c
    4,d
    5,e
    6,f

    三、查看自動生成的控制文件

    --
    -- Generated by OCIULDR
    --
    OPTIONS(BINDSIZE=8388608,READSIZE=8388608,ERRORS=-1,ROWS=50000)
    LOAD DATA
    INFILE 'test.txt' "STR X'0a'"
    INTO TABLE test
    FIELDS TERMINATED BY X'2c' TRAILING NULLCOLS 
    (
    ID CHAR(40),
    NAME CHAR(10)
    )

    四、可以嘗試使用這個控制文件將數據加載到數據庫中

    d:\>sqlldr test/test@acf control=test_sqlldr.ctl

    這樣數據就加載到數據庫中。對于大數據庫表的導出ociuldr工具還支持按照不同的批量導出數據,這通過一個參數batch來實現,默認一個batch是50萬條記錄,如果不指定batch為2就表示100萬條記錄換一個文件,默認這個選項值是0,就是指不生成多個文件。

    在指定batch選項后,需要指定file選項來定義生成的文件名,文件名中間需要包含“%d”字樣,在生成文件時,“%d”會打印成序號,請看以下一個測試:

    D:\>ociuldr user=test/test@acf query="select * from test" batch=1 file=test_%d.txt table=test

    剛才測試了一下,果然是強悍, 用spool按要求導出10萬條記錄要好幾分鐘, 用ociuldr導出來用了一秒,或許一秒都不到, NB!

    posted @ 2012-03-03 15:39 xzc 閱讀(6006) | 評論 (1)編輯 收藏
    在ajax應用流行時,有時我們可能為了降低服務器的負擔,把動態內容生成靜態html頁面或者是xml文件,供客戶端訪問!但是在我們的網站或系統中往住頁面中某些部分是在后臺沒有進行修改時,其內容不會發生變化的。但是頁面中也往往有部分內容是動態的更新的,比如一個新聞頁面,新聞內容往往生成了之后就是靜態的,但是新聞的最新評論往往是變化的,在這個時候有幾種解決方案:

    1、重新生成該靜態頁面,優點是用戶訪問時頁面上的肉容可以實現全靜態,不與服務器程序及數據庫后端打交道!缺點是每次用戶對頁面任何部分更新都必須重新生成。

    2、js調用請求動態內容,優點是靜態頁面只生成一次,動態部分才動態加載,卻點是服務器端要用輸出一段js代碼并用js代碼輸出網頁內容,也不利于搜索引擎收錄。

    3、ajax調用動態內容,和js基本相似,只是與服務器交互的方式不同!并且頁面顯示不會受到因動態調用速度慢而影響整個頁面的加載速度!至于ajax不利于搜索收錄,當然在《ajax in acation》等相關書籍中也介紹有變向的解決方案!

    4、在服務器端ssl動態內容,用服務器端優化及緩存解決是時下最流行的方法!

    對于第二種和第三種方法都是我最青睞的靜態解決方法,適合以內容為主的中小型網站。那么在有時候可能會有js讀取url參數的需求,事實證明的確也有很多時候有這種需求,特別是在胖客戶端的情況下!以前也寫過這樣的代碼,其實原理很簡單就是利用javascript接口提供location對像得到url地址,然后通過分析url以取得參數,以下是我收錄的一些優秀的url參數讀取代碼:

    一、字符串分割分析法。
    這里是一個獲取URL+?帶QUESTRING參數的JAVASCRIPT客戶端解決方案,相當于asp的request.querystring,PHP的$_GET
    函數:

    <script>
    function GetRequest()
    {
    var url = location.search; //獲取url中"?"符后的字串
    var theRequest = new Object();
    if(url.indexOf("?") != -1)
    {
      var str = url.substr(1);
        strs = str.split("&");
      for(var i = 0; i < strs.length; i ++)
        {
         theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);
        }
    }
    return theRequest;
    }
    </script>

    然后我們通過調用此函數獲取對應參數值:

    <script>
    var Request=new Object();
    Request=GetRequest();
    var 參數1,參數2,參數3,參數N;
    參數1=Request['參數1'];
    參數2=Request['參數2'];
    參數3=Request['參數3'];
    參數N=Request['參數N'];
    </script>


    以此獲取url串中所帶的同名參數

    二、正則分析法。

    function     GetQueryString(name)   
    {   
         var     reg     =   new   RegExp("(^|&)"+     name     +"=([^&]*)(&|$)");   
         var     r     =     window.location.search.substr(1).match(reg);   
         if     (r!=null)   return     unescape(r[2]);   return   null;   
    }   
    alert(GetQueryString("參數名1"));   
    alert(GetQueryString("參數名2"));   
    alert(GetQueryString("參數名3"));
    posted @ 2011-12-12 17:15 xzc 閱讀(5067) | 評論 (0)編輯 收藏

    轉自:http://blog.csdn.net/wh62592855/article/details/4988336
    例如說吧,對DEPTNO 10中的每個員工,確定聘用他們的日期及聘用下一個員工(可能是其他部門的員工)的日期之間相差的天數。

    SQL> select ename,hiredate,deptno from emp order by hiredate;

    ENAME      HIREDATE            DEPTNO
    ---------- --------------- ----------
    SMITH      17-DEC-80               20
    ALLEN      20-FEB-81               30
    WARD       22-FEB-81               30
    JONES      02-APR-81               20
    BLAKE      01-MAY-81               30
    CLARK      09-JUN-81               10
    TURNER     08-SEP-81               30
    MARTIN     28-SEP-81               30
    KING       17-NOV-81               10
    JAMES      03-DEC-81               30
    FORD       03-DEC-81               20

    ENAME      HIREDATE            DEPTNO
    ---------- --------------- ----------
    MILLER     23-JAN-82               10
    SCOTT      19-APR-87               20
    ADAMS      23-MAY-87               20

    14 rows selected.

     

    SQL> select ename,hiredate,next_hd,
      2  next_hd-hiredate diff
      3  from
      4  (
      5  select deptno,ename,hiredate,
      6  lead(hiredate) over(order by hiredate) next_hd
      7  from emp
      8  )
      9  where deptno=10;

    ENAME      HIREDATE        NEXT_HD               DIFF
    ---------- --------------- --------------- ----------
    CLARK      09-JUN-81       08-SEP-81               91
    KING       17-NOV-81       03-DEC-81               16
    MILLER     23-JAN-82       19-APR-87             1912

    這里的LEAD OVER非常有用,它能夠訪問“未來的”行(“未來的”行相對于當前行,由ORDER BY子句決定)。這種無需添加聯接就能夠訪問當前行附近行的功能,提高了代碼的可讀性和有效性。在采用窗口函數時,一定要記住,它在WHERE子句之后求值,因此在該解決方案中,需要使用內聯視圖。如果把對DEPTNO的篩選移到內聯視圖,則結果會發生改變(僅考慮了DETPNO 10中的HIREDATE)。

    所以下面的結果是錯誤的:

    SQL> select ename,hiredate,next_hd,
      2  next_hd-hiredate diff
      3  from
      4  (
      5  select deptno,ename,hiredate,
      6  lead(hiredate) over(order by hiredate) next_hd
      7  from emp
      8  where deptno=10
      9  );

    ENAME      HIREDATE        NEXT_HD               DIFF
    ---------- --------------- --------------- ----------
    CLARK      09-JUN-81       17-NOV-81              161
    KING       17-NOV-81       23-JAN-82               67
    MILLER     23-JAN-82

     

    對于ORACLE的LEAD和LAG函數還需要特別注意,它們的結果中可能會有重復。在上面的例子中表EMP內不包含重復的HIREDATE,所以“看起來”似乎沒有什么問題。下面我們向表中插入4個重復值來看看

    SQL> insert into emp(empno,ename,deptno,hiredate)
      2  values(1,'a',10,to_date('17-NOV-1981'));

    1 row created.

    SQL> insert into emp(empno,ename,deptno,hiredate)
      2  values(2,'b',10,to_date('17-NOV-1981'));

    1 row created.

    SQL> insert into emp(empno,ename,deptno,hiredate)
      2  values(3,'c',10,to_date('17-NOV-1981'));

    1 row created.

    SQL> insert into emp(empno,ename,deptno,hiredate)
      2  values(4,'d',10,to_date('17-NOV-1981'));

    1 row created.

    SQL> select ename,hiredate
      2  from emp
      3  where deptno=10
      4  order by 2;

    ENAME      HIREDATE
    ---------- ---------------
    CLARK      09-JUN-81
    b          17-NOV-81
    c          17-NOV-81
    a          17-NOV-81
    d          17-NOV-81
    KING       17-NOV-81
    MILLER     23-JAN-82

    7 rows selected.

    現在還是用以前那個查詢語句來試試

    SQL> select ename,hiredate,next_hd,
      2  next_hd-hiredate diff
      3  from
      4  (
      5  select deptno,ename,hiredate,
      6  lead(hiredate) over(order by hiredate) next_hd
      7  from emp
      8  )
      9  where deptno=10;

    ENAME      HIREDATE        NEXT_HD               DIFF
    ---------- --------------- --------------- ----------
    CLARK      09-JUN-81       08-SEP-81               91
    d          17-NOV-81       17-NOV-81                0
    c          17-NOV-81       17-NOV-81                0
    a          17-NOV-81       17-NOV-81                0
    b          17-NOV-81       17-NOV-81                0
    KING       17-NOV-81       03-DEC-81               16
    MILLER     23-JAN-82       19-APR-87             1912

    7 rows selected.

    可以看到其中有4個員工的DIFF列值都是0,這是錯誤的,同一天聘用的所有員工都應該跟下一個聘用其他員工的HIREDATE進行計算。

    幸運的是ORACLE針對這類情況提供了一個非常簡單的措施:當調用LEAD函數時,可以給LEAD傳遞一個參數,以便準確的指定“未來的”行(是下一行?10行之后?等等)。

    select ename,hiredate,next_hd,
    next_hd-hiredate diff
    from
    (
    select deptno,ename,hiredate,
    lead(hiredate,cnt-rn+1) over(order by hiredate) next_hd
    from
    (
    select deptno,ename,hiredate,
    count(*) over(partition by hiredate) cnt,
    row_number() over(partition by hiredate order by empno) rn
    from emp
    where deptno=10
    )
    )

     

    posted @ 2011-12-09 10:40 xzc 閱讀(4199) | 評論 (1)編輯 收藏
    Java 定義的位運算(bitwise operators )直接對整數類型的位進行操作,這些整數類型包括long,int,short,char,and byte 。表4-2 列出了位運算: 
    表4.2 位運算符及其結果

    運算符 結果 
    ~ 按位非(NOT)(一元運算) 
    & 按位與(AND) 
    | 按位或(OR) 
    ^ 按位異或(XOR) 
    >> 右移 
    >>> 右移,左邊空出的位以0填充 
    運算符 結果 
    << 左移 
    &= 按位與賦值 
    |= 按位或賦值 
    ^= 按位異或賦值 
    >>= 右移賦值 
    >>>= 右移賦值,左邊空出的位以0填充 
    <<= 左移賦值 

    續表

    既然位運算符在整數范圍內對位操作,因此理解這樣的操作會對一個值產生什么效果是重要的。具體地說,知道Java 是如何存儲整數值并且如何表示負數的是有用的。因此,在繼續討論之前,讓我們簡短概述一下這兩個話題。

    所有的整數類型以二進制數字位的變化及其寬度來表示。例如,byte 型值42的二進制代碼是00101010 ,其中每個位置在此代表2的次方,在最右邊的位以20開始。向左下一個位置將是21,或2,依次向左是22,或4,然后是8,16,32等等,依此類推。因此42在其位置1,3,5的值為1(從右邊以0開始數);這樣42是21+23+25的和,也即是2+8+32 。

    所有的整數類型(除了char 類型之外)都是有符號的整數。這意味著他們既能表示正數,又能表示負數。Java 使用大家知道的2的補碼(two’s complement )這種編碼來表示負數,也就是通過將與其對應的正數的二進制代碼取反(即將1變成0,將0變成1),然后對其結果加1。例如,-42就是通過將42的二進制代碼的各個位取反,即對00101010 取反得到11010101 ,然后再加1,得到11010110 ,即-42 。要對一個負數解碼,首先對其所有的位取反,然后加1。例如-42,或11010110 取反后為00101001 ,或41,然后加1,這樣就得到了42。

    如果考慮到零的交叉(zero crossing )問題,你就容易理解Java (以及其他絕大多數語言)這樣用2的補碼的原因。假定byte 類型的值零用00000000 代表。它的補碼是僅僅將它的每一位取反,即生成11111111 ,它代表負零。但問題是負零在整數數學中是無效的。為了解決負零的問題,在使用2的補碼代表負數的值時,對其值加1。即負零11111111 加1后為100000000 。但這樣使1位太靠左而不適合返回到byte 類型的值,因此人們規定,-0和0的表示方法一樣,-1的解碼為11111111 。盡管我們在這個例子使用了byte 類型的值,但同樣的基本的原則也適用于所有Java 的整數類型。

    因為Java 使用2的補碼來存儲負數,并且因為Java 中的所有整數都是有符號的,這樣應用位運算符可以容易地達到意想不到的結果。例如,不管你如何打算,Java 用高位來代表負數。為避免這個討厭的意外,請記住不管高位的順序如何,它決定一個整數的符號。

    4.2.1 位邏輯運算符
    位邏輯運算符有“與”(AND)、“或”(OR)、“異或(XOR )”、“非(NOT)”,分別用“&”、“|”、“^”、“~”表示,4-3 表顯示了每個位邏輯運算的結果。在繼續討論之前,請記住位運算符應用于每個運算數內的每個單獨的位。
    表4-3 位邏輯運算符的結果 
    A 0 1 0 1 B 0 0 1 1 A | B 0 1 1 1 A & B 0 0 0 1 A ^ B 0 1 1 0 ~A 1 0 1 0 

    按位非(NOT)

    按位非也叫做補,一元運算符NOT“~”是對其運算數的每一位取反。例如,數字42,它的二進制代碼為:

    00101010 

    經過按位非運算成為

    11010101 

    按位與(AND)

    按位與運算符“&”,如果兩個運算數都是1,則結果為1。其他情況下,結果均為零。看下面的例子:

    00101010 42 &00001111 15 

    00001010 10 

    按位或(OR)

    按位或運算符“|”,任何一個運算數為1,則結果為1。如下面的例子所示:

    00101010 42 | 00001111 15 

    00101111 47 

    按位異或(XOR)

    按位異或運算符“^”,只有在兩個比較的位不同時其結果是 1。否則,結果是零。下面的例子顯示了“^”運算符的效果。這個例子也表明了XOR 運算符的一個有用的屬性。注意第二個運算數有數字1的位,42對應二進制代碼的對應位是如何被轉換的。第二個運算數有數字0的位,第一個運算數對應位的數字不變。當對某些類型進行位運算時,你將會看到這個屬性的用處。

    00101010 42 ^ 00001111 15 

    00100101 37
    位邏輯運算符的應用

    下面的例子說明了位邏輯運算符:

    // Demonstrate the bitwise logical operators.
    class BitLogic {
    public static void main(String args[]) {


    String binary[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" 

    };
    int a = 3; // 0 + 2 + 1 or 0011 in binary
    int b = 6; // 4 + 2 + 0 or 0110 in binary
    int c = a | b;
    int d = a & b; 
    int e = a ^ b; 
    int f = (~a & b) | (a & ~b);
    int g = ~a & 0x0f; 


    System.out.println(" a = " + binary[a]);
    System.out.println(" b = " + binary[b]);
    System.out.println(" a|b = " + binary[c]);
    System.out.println(" a&b = " + binary[d]);
    System.out.println(" a^b = " + binary[e]);
    System.out.println("~a&b|a&~b = " + binary[f]);
    System.out.println(" ~a = " + binary[g]);


    }
    }


    在本例中,變量a與b對應位的組合代表了二進制數所有的 4 種組合模式:0-0,0-1,1-0 ,和1-1 。“|”運算符和“&”運算符分別對變量a與b各個對應位的運算得到了變量c和變量d的值。對變量e和f的賦值說明了“^”運算符的功能。字符串數組binary 代表了0到15 對應的二進制的值。在本例中,數組各元素的排列順序顯示了變量對應值的二進制代碼。數組之所以這樣構造是因為變量的值n對應的二進制代碼可以被正確的存儲在數組對應元素binary[n] 中。例如變量a的值為3,則它的二進制代碼對應地存儲在數組元素binary[3] 中。~a的值與數字0x0f (對應二進制為0000 1111 )進行按位與運算的目的是減小~a的值,保證變量g的結果小于16。因此該程序的運行結果可以用數組binary 對應的元素來表示。該程序的輸出如下:

    a = 0011 b = 0110 a|b = 0111 a&b = 0010 a^b = 0101 ~a&b|a&~b = 0101 ~a = 1100 

    4.2.2 左移運算符
    左移運算符<<使指定值的所有位都左移規定的次數。它的通用格式如下所示:

    value << num
    這里,num 指定要移位值value 移動的位數。也就是,左移運算符<<使指定值的所有位都左移num位。每左移一個位,高階位都被移出(并且丟棄),并用0填充右邊。這意味著當左移的運算數是int 類型時,每移動1位它的第31位就要被移出并且丟棄;當左移的運算數是long 類型時,每移動1位它的第63位就要被移出并且丟棄。

    在對byte 和short類型的值進行移位運算時,你必須小心。因為你知道Java 在對表達式求值時,將自動把這些類型擴大為 int 型,而且,表達式的值也是int 型。對byte 和short類型的值進行移位運算的結果是int 型,而且如果左移不超過31位,原來對應各位的值也不會丟棄。但是,如果你對一個負的byte 或者short類型的值進行移位運算,它被擴大為int 型后,它的符號也被擴展。這樣,整數值結果的高位就會被1填充。因此,為了得到正確的結果,你就要舍棄得到結果的高位。這樣做的最簡單辦法是將結果轉換為byte 型。下面的程序說明了這一點:

    // Left shifting a byte value.
    class ByteShift {


    public static void main(String args[]) {
    byte a = 64, b;
    int i; 


    i = a << 2;
    b = (byte) (a << 2); 


    System.out.println("Original value of a: " + a);
    System.out.println("i and b: " + i + " " + b);
    }
    }


    該程序產生的輸出下所示:

    Original value of a: 64
    i and b: 256 0 


    因變量a在賦值表達式中,故被擴大為int 型,64(0100 0000 )被左移兩次生成值256 (10000 0000 )被賦給變量i。然而,經過左移后,變量b中惟一的1被移出,低位全部成了0,因此b的值也變成了0。

    既然每次左移都可以使原來的操作數翻倍,程序員們經常使用這個辦法來進行快速的2 的乘法。但是你要小心,如果你將1移進高階位(31或63位),那么該值將變為負值。下面的程序說明了這一點:

    // Left shifting as a quick way to multiply by 2.
    class MultByTwo {


    public static void main(String args[]) {
    int i;
    int num = 0xFFFFFFE; 


    for(i=0; i<4; i++) {
    num = num << 1; 
    System.out.println(num);


    }
    }
    這里,num 指定要移位值value 移動的位數。也就是,左移運算符<<使指定值的所有位都左移num位。每左移一個位,高階位都被移出(并且丟棄),并用0填充右邊。這意味著當左移的運算數是int 類型時,每移動1位它的第31位就要被移出并且丟棄;當左移的運算數是long 類型時,每移動1位它的第63位就要被移出并且丟棄。

    在對byte 和short類型的值進行移位運算時,你必須小心。因為你知道Java 在對表達式求值時,將自動把這些類型擴大為 int 型,而且,表達式的值也是int 型。對byte 和short類型的值進行移位運算的結果是int 型,而且如果左移不超過31位,原來對應各位的值也不會丟棄。但是,如果你對一個負的byte 或者short類型的值進行移位運算,它被擴大為int 型后,它的符號也被擴展。這樣,整數值結果的高位就會被1填充。因此,為了得到正確的結果,你就要舍棄得到結果的高位。這樣做的最簡單辦法是將結果轉換為byte 型。下面的程序說明了這一點:

    // Left shifting a byte value.
    class ByteShift {


    public static void main(String args[]) {
    byte a = 64, b;
    int i; 


    i = a << 2;
    b = (byte) (a << 2); 


    System.out.println("Original value of a: " + a);
    System.out.println("i and b: " + i + " " + b);
    }
    }


    該程序產生的輸出下所示:

    Original value of a: 64
    i and b: 256 0 


    因變量a在賦值表達式中,故被擴大為int 型,64(0100 0000 )被左移兩次生成值256 (10000 0000 )被賦給變量i。然而,經過左移后,變量b中惟一的1被移出,低位全部成了0,因此b的值也變成了0。

    既然每次左移都可以使原來的操作數翻倍,程序員們經常使用這個辦法來進行快速的2 的乘法。但是你要小心,如果你將1移進高階位(31或63位),那么該值將變為負值。下面的程序說明了這一點:

    // Left shifting as a quick way to multiply by 2.
    class MultByTwo {


    public static void main(String args[]) {
    int i;
    int num = 0xFFFFFFE; 


    for(i=0; i<4; i++) {
    num = num << 1; 
    System.out.println(num);


    }
    }


    該程序的輸出如下所示:

    536870908 
    1073741816 
    2147483632 
    -32 


    初值經過仔細選擇,以便在左移 4 位后,它會產生-32。正如你看到的,當1被移進31 位時,數字被解釋為負值。

    4.2.3 右移運算符
    右移運算符>>使指定值的所有位都右移規定的次數。它的通用格式如下所示:

    value >> num 

    這里,num 指定要移位值value 移動的位數。也就是,右移運算符>>使指定值的所有位都右移num位。下面的程序片段將值32右移2次,將結果8賦給變量a: 

    int a = 32;
    a = a >> 2; // a now contains 8 


    當值中的某些位被“移出”時,這些位的值將丟棄。例如,下面的程序片段將35右移2 次,它的2個低位被移出丟棄,也將結果8賦給變量a: 

    int a = 35; 
    a = a >> 2; // a still contains 8 


    用二進制表示該過程可以更清楚地看到程序的運行過程:

    00100011 35 
    >> 2 
    00001000 8 


    將值每右移一次,就相當于將該值除以2并且舍棄了余數。你可以利用這個特點將一個整數進行快速的2的除法。當然,你一定要確保你不會將該數原有的任何一位移出。

    右移時,被移走的最高位(最左邊的位)由原來最高位的數字補充。例如,如果要移走的值為負數,每一次右移都在左邊補1,如果要移走的值為正數,每一次右移都在左邊補0,這叫做符號位擴展(保留符號位)(sign extension ),在進行右移操作時用來保持負數的符號。例如,–8 >> 1 是–4,用二進制表示如下:

    11111000 –8 >>1 11111100 –4 

    一個要注意的有趣問題是,由于符號位擴展(保留符號位)每次都會在高位補1,因此-1右移的結果總是–1。有時你不希望在右移時保留符號。例如,下面的例子將一個byte 型的值轉換為用十六
    進制表示。注意右移后的值與0x0f進行按位與運算,這樣可以舍棄任何的符號位擴展,以便得到的值可以作為定義數組的下標,從而得到對應數組元素代表的十六進制字符。

    // Masking sign extension.
    class HexByte {
    static public void main(String args[]) {


    char hex[] = {
    ’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’, 
    ’8’, ’9’, ’a’, ’b’, ’c’, ’d’, ’e’, ’f’’ 


    };
    byte b = (byte) 0xf1; 


    System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);}} 

    該程序的輸出如下:

    b = 0xf1 

    4.2.4 無符號右移
    正如上面剛剛看到的,每一次右移,>>運算符總是自動地用它的先前最高位的內容補它的最高位。這樣做保留了原值的符號。但有時這并不是我們想要的。例如,如果你進行移位操作的運算數不是數字值,你就不希望進行符號位擴展(保留符號位)。當你處理像素值或圖形時,這種情況是相當普遍的。在這種情況下,不管運算數的初值是什么,你希望移位后總是在高位(最左邊)補0。這就是人們所說的無符號移動(unsigned shift )。這時你可以使用Java 的無符號右移運算符>>> ,它總是在左邊補0。

    下面的程序段說明了無符號右移運算符>>> 。在本例中,變量a被賦值為-1,用二進制表示就是32位全是1。這個值然后被無符號右移24位,當然它忽略了符號位擴展,在它的左邊總是補0。這樣得到的值255被賦給變量a。

    int a = -1; a = a >>> 24; 

    下面用二進制形式進一步說明該操作:

    11111111 11111111 11111111 11111111 int型-1的二進制代碼>>> 24 無符號右移24位00000000 00000000 00000000 11111111 int型255的二進制代碼

    由于無符號右移運算符>>> 只是對32位和64位的值有意義,所以它并不像你想象的那樣有用。因為你要記住,在表達式中過小的值總是被自動擴大為int 型。這意味著符號位擴展和移動總是發生在32位而不是8位或16位。這樣,對第7位以0開始的byte 型的值進行無符號移動是不可能的,因為在實際移動運算時,是對擴大后的32位值進行操作。下面的例子說明了這一點:

    // Unsigned shifting a byte value.
    class ByteUShift {
    static public void main(String args[]) {
    進制表示。注意右移后的值與0x0f進行按位與運算,這樣可以舍棄任何的符號位擴展,以便得到的值可以作為定義數組的下標,從而得到對應數組元素代表的十六進制字符。

    // Masking sign extension.
    class HexByte {
    static public void main(String args[]) {


    char hex[] = {
    ’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’, 
    ’8’, ’9’, ’a’, ’b’, ’c’, ’d’, ’e’, ’f’’ 


    };
    byte b = (byte) 0xf1; 


    System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);}} 

    該程序的輸出如下:

    b = 0xf1 

    4.2.4 無符號右移
    正如上面剛剛看到的,每一次右移,>>運算符總是自動地用它的先前最高位的內容補它的最高位。這樣做保留了原值的符號。但有時這并不是我們想要的。例如,如果你進行移位操作的運算數不是數字值,你就不希望進行符號位擴展(保留符號位)。當你處理像素值或圖形時,這種情況是相當普遍的。在這種情況下,不管運算數的初值是什么,你希望移位后總是在高位(最左邊)補0。這就是人們所說的無符號移動(unsigned shift )。這時你可以使用Java 的無符號右移運算符>>> ,它總是在左邊補0。

    下面的程序段說明了無符號右移運算符>>> 。在本例中,變量a被賦值為-1,用二進制表示就是32位全是1。這個值然后被無符號右移24位,當然它忽略了符號位擴展,在它的左邊總是補0。這樣得到的值255被賦給變量a。

    int a = -1; a = a >>> 24; 

    下面用二進制形式進一步說明該操作:

    11111111 11111111 11111111 11111111 int型-1的二進制代碼>>> 24 無符號右移24位00000000 00000000 00000000 11111111 int型255的二進制代碼

    由于無符號右移運算符>>> 只是對32位和64位的值有意義,所以它并不像你想象的那樣有用。因為你要記住,在表達式中過小的值總是被自動擴大為int 型。這意味著符號位擴展和移動總是發生在32位而不是8位或16位。這樣,對第7位以0開始的byte 型的值進行無符號移動是不可能的,因為在實際移動運算時,是對擴大后的32位值進行操作。下面的例子說明了這一點:

    // Unsigned shifting a byte value.
    class ByteUShift {
    static public void main(String args[]) {
    int b = 2;
    int c = 3; 


    a |= 4;
    b >>= 1; 
    c <<= 1; 
    a ^= c;
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    System.out.println("c = " + c);


    }
    }


    該程序的輸出如下所示:

    a = 3 
    b = 1 
    c = 6
    posted @ 2011-11-04 11:56 xzc 閱讀(269) | 評論 (1)編輯 收藏
    1. import java.net.*;    
    2. String   key=URLEncoder.encode("中文key","GBK");   
    3. String   value=URLEncoder.encode("中文value","GBK");   
    4. Cookie   cook=new Cookie(key,value);        
    5. String   key=cook.getName(),value=cook.getValue();      
    6. key=URLDecoder.decode(key,"GBK");      
    7. value=URLDecoder.decode(value,"GBK");   



     

    String value = java.net.URLEncoder.encode("中文","utf-8");

    Cookie cookie = new Cookie("chinese_code",value);

    cookie.setMaxAge(60*60*24*6);

    response.addCookie(cookie);

     

     

     

    encode() 只有一個參數的已經過時了,現在可以設置編碼格式, 取cookie值的時候 也不用解碼了。

     

    posted @ 2011-10-03 11:29 xzc 閱讀(6370) | 評論 (3)編輯 收藏
    如下一段配置,熟悉DWR的再熟悉不過了:
    <servlet>
       <servlet-name>dwr-invoker</servlet-name>
       <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
       <init-param>
        <param-name>debug</param-name>
        <param-value>true</param-value>
       </init-param>
       <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
       <servlet-name>dwr-invoker</servlet-name>
       <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

    我們注意到它里面包含了這段配置:<load-on-startup>1</load-on-startup>,那么這個配置有什么作用呢?

    貼一段英文原汁原味的解釋如下:
    Servlet specification:
    The load-on-startup element indicates that this servlet should be loaded (instantiated and have its init() called) on the startup of the web application. The optional contents of these element must be an integer indicating the order in which the servlet should be loaded. If the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses.   If the value is a positive integer or 0, the container must load and initialize the servlet as the application is deployed. The container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-start-up value.

    翻譯過來的意思大致如下:
    1)load-on-startup元素標記容器是否在啟動的時候就加載這個servlet(實例化并調用其init()方法)。

    2)它的值必須是一個整數,表示servlet應該被載入的順序

    2)當值為0或者大于0時,表示容器在應用啟動時就加載并初始化這個servlet;

    3)當值小于0或者沒有指定時,則表示容器在該servlet被選擇時才會去加載。

    4)正數的值越小,該servlet的優先級越高,應用啟動時就越先加載。

    5)當值相同時,容器就會自己選擇順序來加載。

    所以,<load-on-startup>x</load-on-startup>,中x的取值1,2,3,4,5代表的是優先級,而非啟動延遲時間。

    如下題目:

    2.web.xml中不包括哪些定義(多選)

    a.默認起始頁

    b.servlet啟動延遲時間定義

    c.error處理頁面

    d.jsp文件改動后重新載入時間

    答案:b,d

    通常大多數Servlet是在用戶第一次請求的時候由應用服務器創建并初始化,但<load-on-startup>n</load-on-startup>   可以用來改變這種狀況,根據自己需要改變加載的優先級!

    posted @ 2011-09-29 15:22 xzc 閱讀(149946) | 評論 (22)編輯 收藏

    Keytool是一個Java數據證書的管理工具 ,Keytool將密鑰(key)和證書(certificates)存在一個稱為keystore的文件中在keystore里,包含兩種數據:
    密鑰實體(Key entity)——密鑰(secret key)又或者是私鑰和配對公鑰(采用非對稱加密)
    可信任的證書實體(trusted certificate entries)——只包含公鑰


    ailas(別名)每個keystore都關聯這一個獨一無二的alias,這個alias通常不區分大小寫

     

    JDK中keytool常用命令:

    -genkey 在用戶主目錄中創建一個默認文件".keystore",還會產生一個mykey的別名,mykey中包含用戶的公鑰、私鑰和證書
    (在沒有指定生成位置的情況下,keystore會存在用戶系統默認目錄,如:對于window xp系統,會生成在系統的C:\Documents and Settings\UserName\文件名為“.keystore”)
    -alias 產生別名
    -keystore 指定密鑰庫的名稱(產生的各類信息將不在.keystore文件中)
    -keyalg 指定密鑰的算法 (如 RSA DSA(如果不指定默認采用DSA))
    -validity 指定創建的證書有效期多少天
    -keysize 指定密鑰長度
    -storepass 指定密鑰庫的密碼(獲取keystore信息所需的密碼)
    -keypass 指定別名條目的密碼(私鑰的密碼)
    -dname 指定證書擁有者信息 例如: "CN=名字與姓氏,OU=組織單位名稱,O=組織名稱,L=城市或區域名稱,ST=州或省份名稱,C=單位的兩字母國家代碼"
    -list 顯示密鑰庫中的證書信息 keytool -list -v -keystore 指定keystore -storepass 密碼
    -v 顯示密鑰庫中的證書詳細信息
    -export 將別名指定的證書導出到文件 keytool -export -alias 需要導出的別名 -keystore 指定keystore -file 指定導出的證書位置及證書名稱 -storepass 密碼
    -file 參數指定導出到文件的文件名
    -delete 刪除密鑰庫中某條目 keytool -delete -alias 指定需刪除的別 -keystore 指定keystore -storepass 密碼
    -printcert 查看導出的證書信息 keytool -printcert -file yushan.crt
    -keypasswd 修改密鑰庫中指定條目口令 keytool -keypasswd -alias 需修改的別名 -keypass 舊密碼 -new 新密碼 -storepass keystore密碼 -keystore sage
    -storepasswd 修改keystore口令 keytool -storepasswd -keystore e:\yushan.keystore(需修改口令的keystore) -storepass 123456(原始密碼) -new yushan(新密碼)
    -import 將已簽名數字證書導入密鑰庫 keytool -import -alias 指定導入條目的別名 -keystore 指定keystore -file 需導入的證書

     

    下面是各選項的缺省值。
    -alias "mykey"

    -keyalg "DSA"

    -keysize 1024

    -validity 90

    -keystore 用戶宿主目錄中名為 .keystore 的文件

    -file 讀時為標準輸入,寫時為標準輸出




    1、keystore的生成:

    分階段生成:
    keytool -genkey -alias yushan(別名) -keypass yushan(別名密碼) -keyalg RSA(算法) -keysize 1024(密鑰長度) -validity 365(有效期,天單位) -keystore

    e:\yushan.keystore(指定生成證書的位置和證書名稱) -storepass 123456(獲取keystore信息的密碼);回車輸入相關信息即可;

    一次性生成:
    keytool -genkey -alias yushan -keypass yushan -keyalg RSA -keysize 1024 -validity 365 -keystore e:\yushan.keystore -storepass 123456 -dname "CN=(名字與

    姓氏), OU=(組織單位名稱), O=(組織名稱), L=(城市或區域名稱), ST=(州或省份名稱), C=(單位的兩字母國家代碼)";(中英文即可)

    2、keystore信息的查看:
    keytool -list -v -keystore e:\keytool\yushan.keystore -storepass 123456
    顯示內容:
    ---------------------------------------------------------------------
    Keystore 類型: JKS
    Keystore 提供者: SUN

    您的 keystore 包含 1 輸入

    別名名稱: yushan
    創建日期: 2009-7-29
    項類型: PrivateKeyEntry
    認證鏈長度: 1
    認證 [1]:
    所有者:CN=yushan, OU=xx公司, O=xx協會, L=湘潭, ST=湖南, C=中國
    簽發人:CN=yushan, OU=xx公司, O=xx協會, L=湘潭, ST=湖南, C=中國
    序列號:4a6f29ed
    有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
    證書指紋:
    MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
    SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
    簽名算法名稱:SHA1withRSA
    版本: 3
    --------------------------------------------------------------------

     

    缺省情況下,-list 命令打印證書的 MD5 指紋。而如果指定了 -v 選項,將以可讀格式打印證書,如果指定了 -rfc 選項,將以可打印的編碼格式輸出證書。


    keytool -list -rfc -keystore e:\yushan.keystore -storepass 123456

    顯示:

    -------------------------------------------------------------------------------------------------------

    Keystore 類型: JKS
    Keystore 提供者: SUN

    您的 keystore 包含 1 輸入

    別名名稱: yushan
    創建日期: 2009-7-29
    項類型: PrivateKeyEntry
    認證鏈長度: 1
    認證 [1]:
    -----BEGIN CERTIFICATE-----
    MIICSzCCAbSgAwIBAgIESm8p7TANBgkqhkiG9w0BAQUFADBqMQ8wDQYDVQQGDAbkuK3lm70xDzAN
    BgNVBAgMBua5luWNlzEPMA0GA1UEBwwG5rmY5r2tMREwDwYDVQQKDAh4eOWNj+S8mjERMA8GA1UE
    CwwIeHjlhazlj7gxDzANBgNVBAMTBnl1c2hhbjAeFw0wOTA3MjgxNjQwMTNaFw0xMDA3MjgxNjQw
    MTNaMGoxDzANBgNVBAYMBuS4reWbvTEPMA0GA1UECAwG5rmW5Y2XMQ8wDQYDVQQHDAbmuZjmva0x
    ETAPBgNVBAoMCHh45Y2P5LyaMREwDwYDVQQLDAh4eOWFrOWPuDEPMA0GA1UEAxMGeXVzaGFuMIGf
    MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJoru1RQczRzTnBWxefVNspQBykS220rS8Y/oX3mZa
    hjL4wLfOURzUuxxuVQR2jx7QI+XKME+DHQj9r6aAcLBCi/T1jwF8mVYxtpRuTzE/6KEZdhowEe70
    liWLVE+hytLBHZ03Zhwcd6q5HUMu27du3MPQvqiwzTY7MrwIvQQ8iQIDAQABMA0GCSqGSIb3DQEB
    BQUAA4GBAGoQQ1/FnTfkpQh+Ni6h3fZdn3sR8ZzDMbOAIYVLAhBb85XDJ8QZTarHbZMJcIdHxAl1
    i08ct3E8U87V9t8GZFWVC4BFg/+zeFEv76SFpVE56iX7P1jpsu78z0m69hHlds77VJTdyfMSvtXv
    sYHP3fxfzx9WyhipBwd8VPK/NgEP
    -----END CERTIFICATE-----

    -------------------------------------------------------------------------------------------------------

    3、證書的導出:

    keytool -export -alias yushan -keystore e:\yushan.keystore -file e:\yushan.crt(指定導出的證書位置及證書名稱) -storepass 123456

    4、查看導出的證書信息
    keytool -printcert -file yushan.crt
    顯示:(在windows下可以雙擊yushan.crt查看)
    -----------------------------------------------------------------------
    所有者:CN=yushan, OU=xx公司, O=xx協會, L=湘潭, ST=湖南, C=中國
    簽發人:CN=yushan, OU=xx公司, O=xx協會, L=湘潭, ST=湖南, C=中國
    序列號:4a6f29ed
    有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
    證書指紋:
    MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
    SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
    簽名算法名稱:SHA1withRSA
    版本: 3
    -----------------------------------------------------------------------

    5、證書的導入:
    準備一個導入的證書:
    keytool -genkey -alias shuany -keypass shuany -keyalg RSA -keysize 1024 -validity 365 -keystore e:\shuany.keystore -storepass 123456 -dname "CN=shuany,

    OU=xx, O=xx, L=xx, ST=xx, C=xx";
    keytool -export -alias shuany -keystore e:\shuany.keystore -file e:\shuany.crt -storepass 123456

    現在將shuany.crt 加入到yushan.keystore中:
    keytool -import -alias shuany(指定導入證書的別名,如果不指定默認為mykey,別名唯一,否則導入出錯) -file e:\shuany.crt -keystore e:\yushan.keystore -storepass

    123456

    keytool -list -v -keystore e:\keytool\yushan.keystore -storepass 123456
    顯示:
    ------------------------------------------------------------------------------
    Keystore 類型: JKS
    Keystore 提供者: SUN

    您的 keystore 包含 2 輸入

    別名名稱: yushan
    創建日期: 2009-7-29
    項類型: PrivateKeyEntry
    認證鏈長度: 1
    認證 [1]:
    所有者:CN=yushan, OU=xx公司, O=xx協會, L=湘潭, ST=湖南, C=中國
    簽發人:CN=yushan, OU=xx公司, O=xx協會, L=湘潭, ST=湖南, C=中國
    序列號:4a6f29ed
    有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
    證書指紋:
    MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
    SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
    簽名算法名稱:SHA1withRSA
    版本: 3


    *******************************************
    *******************************************


    別名名稱: shuany
    創建日期: 2009-7-29
    輸入類型: trustedCertEntry

    所有者:CN=shuany, OU=xx, O=xx, L=xx, ST=xx, C=xx
    簽發人:CN=shuany, OU=xx, O=xx, L=xx, ST=xx, C=xx
    序列號:4a6f2cd9
    有效期: Wed Jul 29 00:52:41 CST 2009 至Thu Jul 29 00:52:41 CST 2010
    證書指紋:
    MD5:15:03:57:9B:14:BD:C5:50:21:15:47:1E:29:87:A4:E6
    SHA1:C1:4F:8B:CD:5E:C2:94:77:B7:42:29:35:5C:BB:BB:2E:9E:F0:89:F5
    簽名算法名稱:SHA1withRSA
    版本: 3


    *******************************************
    *******************************************
    ------------------------------------------------------------------------------

    6、證書條目的刪除:
    keytool -delete -alias shuany(指定需刪除的別名) -keystore yushan.keystore -storepass 123456

    7、證書條目口令的修改:
    keytool -keypasswd -alias yushan(需要修改密碼的別名) -keypass yushan(原始密碼) -new 123456(別名的新密碼) -keystore e:\yushan.keystore -storepass 123456

    8、keystore口令的修改:
    keytool -storepasswd -keystore e:\yushan.keystore(需修改口令的keystore) -storepass 123456(原始密碼) -new yushan(新密碼)

     

    9、修改keystore中別名為yushan的信息

     

    keytool -selfcert -alias yushan -keypass yushan -keystore e:\yushan.keystore -storepass 123456 -dname "cn=yushan,ou=yushan,o=yushan,c=us

    posted @ 2011-09-15 08:30 xzc 閱讀(421) | 評論 (0)編輯 收藏
    轉自:http://www.iteye.com/topic/255397

    1.那即將離我遠去的

    用buffalo作為我的ajax類庫也有些歷史了,幾乎是和Spring同時開始接觸的.

    按照官方的方式,Buffalo與Spring的集成是很簡單:

        在Spring中配置一個BuffaloServiceConfigure bean,把spring托管的服務在其中聲明即可,Buffalo可以通過ServletContext得到Spring的WebApplicationContext,進而得到所需的服務:

    Java代碼 復制代碼 收藏代碼
    1. <bean name="buffaloConfigBean"    
    2.                 class="net.buffalo.service.BuffaloServiceConfigurer">    
    3.                 <property name="services">    
    4.                         <map>    
    5.                                 <entry key="springSimpleService">    
    6.                                         <ref bean="systemService" />    
    7.                                 </entry>    
    8.                                 <entry key="springSimpleService2">    
    9.                                         <ref bean="systemService2" />    
    10.                                 </entry>    
    11.                         </map>    
    12.                 </property>    
    13.  </bean>   

     

         似乎很簡單,但,有沒有覺得似乎很傻?只是把Spring里已經配置好的bean再引用一次而已,

    一旦面臨協作開發,和所有的全局配置文件一樣,BuffaloServiceConfigure bean下面就會囊括幾十上百個service ref,一大堆人圍著這個配置文件轉,CVS沖突就成了家常便飯了,苦惱不已.當然,按我們這么多年的開發經驗是不會出現這種低級錯誤的,早早的在項目設計階段就會按模塊劃分出多個配置文件,一人獨用,無需和別人共享配置,輕松面對沖突問題,帶來的局面就是每個包里都塞著一個buffalo.xml,一個項目里配置文件到處有,不斷得copy/paste,層層套套,那可不是碩果累累的滿足感.

         當然,Spring本身在2.5之前也因XML配置繁瑣而讓人詬病,Guice才能異軍突起,那時Spring比Buffalo的配置更多,所以Buffalo的問題也就不是問題了.但有一天,我終于要正式升級到Spring2.5.

         世界清靜了!使用annotation,看到怎么多配置文件消失,看到簡潔的Bean/MVC配置,呵呵,還真是令人心情愉悅的.

         誒,等等,怎么還有大堆XML?哦?原來是Buffalo...

         Buffalo像個刺頭,傻愣愣地杵在XML里.

     

    2.于是我開始把Buffalo也Annotation化.

     

    話說Spring的擴展能力還是ganggang的,一天時間,就有成果了.

    先寫個注解:

    Java代碼 復制代碼 收藏代碼
    1. package cn.tohot.common.annotation;   
    2.   
    3. import java.lang.annotation.ElementType;   
    4. import java.lang.annotation.Retention;   
    5. import java.lang.annotation.RetentionPolicy;   
    6. import java.lang.annotation.Target;   
    7.   
    8. /**  
    9.  * buffalo擴展接口,用于表明該類是一個buffalo服務.  
    10.  * @author tedeyang  
    11.  *  
    12.  */  
    13. @Retention(RetentionPolicy.RUNTIME)   
    14. @Target(ElementType.TYPE)   
    15. public @interface Buffalo {   
    16.     /**  
    17.      * @return 遠程調用時的服務名.  
    18.      */    
    19.     String value();   
    20. }  

     

    接著再寫Spring的擴展

     

    Java代碼 復制代碼 收藏代碼
    1. /**  
    2.  *   
    3.  */  
    4. package cn.tohot.common.annotation;   
    5.   
    6. import java.util.HashMap;   
    7.   
    8. import net.buffalo.service.BuffaloServiceConfigurer;   
    9.   
    10. import org.apache.log4j.Logger;   
    11. import org.springframework.beans.BeansException;   
    12. import org.springframework.beans.factory.DisposableBean;   
    13. import org.springframework.beans.factory.FactoryBean;   
    14. import org.springframework.beans.factory.InitializingBean;   
    15. import org.springframework.beans.factory.config.BeanPostProcessor;   
    16.   
    17. /**  
    18.  * 該類作為FactoryBean可以無縫替換buffalo 2.0自帶的配置類,并使用annotation進行配置.  
    19.  * @author tedeyang  
    20.  *  
    21.  */  
    22. @SuppressWarnings("unchecked")   
    23. public class BuffaloAnnotationServiceFactoryBean implements FactoryBean, InitializingBean, DisposableBean, BeanPostProcessor {   
    24.     private static final Logger log = Logger.getLogger(BuffaloAnnotationServiceFactoryBean.class);   
    25.   
    26.     private BuffaloServiceConfigurer buffaloConfigurer = null;   
    27.   
    28.     public BuffaloAnnotationServiceFactoryBean() {   
    29.         buffaloConfigurer = new BuffaloServiceConfigurer();   
    30.         buffaloConfigurer.setServices(new HashMap());   
    31.     }   
    32.   
    33.     private void addBuffaloBean(String buffaloServiceName,Object bean) {   
    34.         buffaloConfigurer.getServices().put(buffaloServiceName, bean);   
    35.         log.info("Add a buffalo service :"+buffaloServiceName);   
    36.     }   
    37.   
    38.     public Object getObject() throws Exception {   
    39.         return this.buffaloConfigurer;   
    40.     }   
    41.   
    42.     public Class getObjectType() {   
    43.         return BuffaloServiceConfigurer.class;   
    44.     }   
    45.   
    46.     public boolean isSingleton() {   
    47.         return true;   
    48.     }   
    49.   
    50.     public void afterPropertiesSet() throws Exception {   
    51.     }   
    52.   
    53.     public void destroy() throws Exception {   
    54.         if (buffaloConfigurer != null)   
    55.             buffaloConfigurer.setServices(null);   
    56.         buffaloConfigurer = null;   
    57.     }   
    58.     
    59.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {   
    60.         return bean;   
    61.     }   
    62.   
    63.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {   
    64.         log.debug("find a bean:"+beanName);   
    65.         if (bean.getClass().isAnnotationPresent(Buffalo.class)) {   
    66.             Buffalo buffalo = bean.getClass().getAnnotation(Buffalo.class);   
    67.             addBuffaloBean(buffalo.value(), bean);    
    68.         }   
    69.         return bean;   
    70.     }   
    71.   
    72. }  

     

     主要思路是用FactoryBean替換原BuffaloServiceConfigurer,并掛上BeanPostProcessor的鉤子,檢測一下annotation,發現buffalo服務就添加到原BuffaloServiceConfigurer中去.

     

    3.今天我這樣配置Buffalo:

    Java代碼 復制代碼 收藏代碼
    1. <?xml version="1.0" encoding="UTF-8"?>   
    2. <beans xmlns="http://www.springframework.org/schema/beans"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    4.     xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"  
    5.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
    6.      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd   
    7.      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd   
    8.      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">   
    9.   
    10.     <!-- Spring Annotation配置, 自動搜索組件 -->   
    11.     <context:component-scan base-package="cn.tohot.demo"/>    
    12.     <bean id="buffalo"   class="cn.tohot.common.annotation.BuffaloAnnotationServiceFactoryBean" />    
    13. </beans>  
     

     服務端的Buffalo bean 類:

    Java代碼 復制代碼 收藏代碼
    1. package cn.tohot.demo;   
    2.   
    3. import org.springframework.stereotype.Service;   
    4.   
    5. import cn.tohot.common.annotation.Buffalo;   
    6.   
    7. @Service     //聲明Spring bean,   
    8. @Buffalo("testbean"//聲明一個名為"testbean"的Buffalo service   
    9. public class BuffaloBeanTestService {   
    10.     public String run() {   
    11.         System.out.println("run");   
    12.         return "run";   
    13.     }   
    14. }  

     很簡潔,不是嗎?

    posted @ 2011-08-26 09:21 xzc 閱讀(233) | 評論 (0)編輯 收藏
    轉自:http://www.iteye.com/topic/11738
    前幾天解釋了Spring的抽象事務機制。這次講講Spring中的DataSource 事務。
    DataSource事務相關的類比較多,我們一步步來撥開其中的密團。

    1 如何獲得連接
    看DataSourceUtils代碼
    Java代碼 復制代碼 收藏代碼
    1. protected static Connection doGetConnection(DataSource dataSource, boolean allowSynchronization);   
    2.             throws SQLException {   
    3.            
    4.         ConnectionHolder conHolder = (ConnectionHolder); TransactionSynchronizationManager.getResource(dataSource);;   
    5.         if (conHolder != null); {   
    6.             conHolder.requested();;   
    7.             return conHolder.getConnection();;   
    8.         }   
    9.   
    10.            
    11.         Connection con = dataSource.getConnection();;   
    12.         if (allowSynchronization && TransactionSynchronizationManager.isSynchronizationActive();); {   
    13.                         conHolder = new ConnectionHolder(con);;   
    14.             TransactionSynchronizationManager.bindResource(dataSource, conHolder);;   
    15.             TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(conHolder, dataSource););;   
    16.             conHolder.requested();;   
    17.         }   
    18.   
    19.         return con;   
    20.     }  

    原來連接是從TransactionSynchronizationManager中獲取,如果TransactionSynchronizationManager中已經有了,那么拿過來然后調用conHolder.requested()。否則從原始的DataSource這創建一個連接,放到一個ConnectionHolder,然后再調用TransactionSynchronizationManager.bindResource綁定。
    好,我們又遇到兩個新的類TransactionSynchronizationManager和ConnectionHolder和。繼續跟蹤


    2 TransactionSynchronizationManager
    看其中的一些代碼
    Java代碼 復制代碼 收藏代碼
    1. private static ThreadLocal resources = new ThreadLocal();;   
    2. public static Object getResource(Object key); {   
    3.         Map map = (Map); resources.get();;   
    4.         if (map == null); {   
    5.             return null;   
    6.         }   
    7.         Object value = map.get(key);;   
    8.                 return value;   
    9.     }   
    10. public static void bindResource(Object key, Object value); throws IllegalStateException {   
    11.         Map map = (Map); resources.get();;   
    12.                 if (map == null); {   
    13.             map = new HashMap();;   
    14.             resources.set(map);;   
    15.         }   
    16.         map.put(key, value);;   
    17.             }  
    原來TransactionSynchronizationManager內部建立了一個ThreadLocal的resources,這個resources又是和一個map聯系在一起的,這個map在某個線程第一次調用bindResource時生成。
    聯系前面的DataSourceUtils代碼,我們可以總結出來。
    某個線程使用DataSourceUtils,當第一次要求創建連接將在TransactionSynchronizationManager中創建出一個ThreadLocal的map。然后以DataSource作為鍵,ConnectionHolder為值放到map中。等這個線程下一次再請求的這個DataSource的時候,就從這個map中獲取對應的ConnectionHolder。用map是為了解決同一個線程上多個DataSource。
    然后我們來看看ConnectionHolder又是什么?



    3 對連接進行引用計數
    看ConnectionHolder代碼,這個類很簡單,看不出個所以然,只好再去看父類代碼ResourceHolderSupport,我們感興趣的是這兩個方法
    Java代碼 復制代碼 收藏代碼
    1. public void requested(); {   
    2.         this.referenceCount++;   
    3.     }   
    4.   
    5.     public void released(); {   
    6.         this.referenceCount--;   
    7.     }  

    看得出這是一個引用計數的技巧。原來Spring中對Connection是竟量使用已創建的對象,而不是每次都創建一個新對象。這就是DataSourceUtils中
    Java代碼 復制代碼 收藏代碼
    1. if (conHolder != null); {   
    2.             conHolder.requested();;   
    3.             return conHolder.getConnection();;   
    4.         }  
    的原因


    4 釋放連接
    完成事物后DataSourceTransactionManager有這樣的代碼
    Java代碼 復制代碼 收藏代碼
    1. protected void doCleanupAfterCompletion(Object transaction); {   
    2.         DataSourceTransactionObject txObject = (DataSourceTransactionObject); transaction;   
    3.   
    4.         // Remove the connection holder from the thread.   
    5.         TransactionSynchronizationManager.unbindResource(this.dataSource);;   
    6.         txObject.getConnectionHolder();.clear();;   
    7.   
    8.         //...       DataSourceUtils.closeConnectionIfNecessary(con, this.dataSource);;   
    9.     }  

    DataSourceUtils
    Java代碼 復制代碼 收藏代碼
    1. protected static void doCloseConnectionIfNecessary(Connection con, DataSource dataSource); throws SQLException {   
    2.         if (con == null); {   
    3.             return;   
    4.         }   
    5.   
    6.         ConnectionHolder conHolder = (ConnectionHolder); TransactionSynchronizationManager.getResource(dataSource);;   
    7.         if (conHolder != null && con == conHolder.getConnection();); {   
    8.             // It's the transactional Connection: Don't close it.   
    9.             conHolder.released();;   
    10.             return;   
    11.         }   
    12.            
    13.         // Leave the Connection open only if the DataSource is our   
    14.         // special data source, and it wants the Connection left open.   
    15.         if (!(dataSource instanceof SmartDataSource); || ((SmartDataSource); dataSource);.shouldClose(con);); {   
    16.             logger.debug("Closing JDBC connection");;   
    17.             con.close();;   
    18.         }   
    19.     }  

    恍然大悟。如果事物完成,那么就
    TransactionSynchronizationManager.unbindResource(this.dataSource);將當前的ConnectionHolder
    從TransactionSynchronizationManager上脫離,然后doCloseConnectionIfNecessary。最后會把連接關閉掉。

    5 兩個輔助類JdbcTemplate和TransactionAwareDataSourceProxy
    JdbcTemplate中的execute方法的第一句和最后一句
    Java代碼 復制代碼 收藏代碼
    1. public Object execute(PreparedStatementCreator psc, PreparedStatementCallback action);   
    2.             throws DataAccessException {   
    3.   
    4.         Connection con = DataSourceUtils.getConnection(getDataSource(););;   
    5.         //其他代碼   
    6.     DataSourceUtils.closeConnectionIfNecessary(con, getDataSource(););;   
    7.         }   
    8.     }  

    作用不言自明了吧

    從TransactionAwareDataSourceProxy中獲取的連接是這個樣子的
    Java代碼 復制代碼 收藏代碼
    1. public Connection getConnection(); throws SQLException {   
    2.         Connection con = DataSourceUtils.doGetConnection(getTargetDataSource();, true);;   
    3.         return getTransactionAwareConnectionProxy(con, getTargetDataSource(););;   
    4.     }  

    萬變不離其宗,不過我們還是看看getTransactionAwareConnectionProxy
    Java代碼 復制代碼 收藏代碼
    1. protected Connection getTransactionAwareConnectionProxy(Connection target, DataSource dataSource); {   
    2.         return (Connection); Proxy.newProxyInstance(   
    3.                 ConnectionProxy.class.getClassLoader();,   
    4.                 new Class[] {ConnectionProxy.class},   
    5.                 new TransactionAwareInvocationHandler(target, dataSource););;   
    6.     }  

    原來返回的是jdk的動態代理。繼續看TransactionAwareInvocationHandler
    Java代碼 復制代碼 收藏代碼
    1. public Object invoke(Object proxy, Method method, Object[] args); throws Throwable {   
    2.         //...           if (method.getName();.equals(CONNECTION_CLOSE_METHOD_NAME);); {   
    3.                 if (this.dataSource != null); {   
    4.                     DataSourceUtils.doCloseConnectionIfNecessary(this.target, this.dataSource);;   
    5.                 }   
    6.                 return null;   
    7.             }   
    8.   
    9.                     }  

    TransactionAwareDataSourceProxy會先從DataSourceUtils獲取連接。然后將這個連接用jdk的動態代理包一下返回。外部代碼如果調用的這個冒牌的Connection,就會先調用TransactionAwareInvocationHandler的invoke,在這個invoke 中,完成原來調用DataSourceUtils的功能。

    總結上面的流程
    Spring 對DataSource進行事務管理的關鍵在于ConnectionHolder和TransactionSynchronizationManager。
      0.先從TransactionSynchronizationManager中嘗試獲取連接
      1.如果前一步失敗則在每個線程上,對每個DataSouce只創建一個Connection
       2.這個Connection用ConnectionHolder包裝起來,由TransactionSynchronizationManager管理
      3.再次請求同一個連接的時候,從TransactionSynchronizationManager返回已經創建的ConnectionHolder,然后調用ConnectionHolder的request將引用計數+1
      4.釋放連接時要調用ConnectionHolder的released,將引用計數-1
      5.當事物完成后,將ConnectionHolder從TransactionSynchronizationManager中解除。當誰都不用,這個連接被close

    以上所有都是可以調用DataSourceUtils化簡代碼,而JdbcTemplate又是調用DataSourceUtils的。所以在Spring文檔中要求盡量首先使用JdbcTemplate,其次是用DataSourceUtils來獲取和釋放連接。至于TransactionAwareDataSourceProxy,那是下策的下策。不過可以將Spring事務管理和遺留代碼無縫集成。

    所以如某位朋友說要使用Spring的事務管理,但是又不想用JdbcTemplate,那么可以考慮TransactionAwareDataSourceProxy。這個類是原來DataSource的代理。
    其次,想使用Spring事物,又不想對Spring進行依賴是不可能的。與其試圖自己模擬DataSourceUtils,不如直接使用現成的。
    posted @ 2011-08-09 14:59 xzc 閱讀(4008) | 評論 (1)編輯 收藏
    僅列出標題
    共32頁: First 上一頁 6 7 8 9 10 11 12 13 14 下一頁 Last 
    主站蜘蛛池模板: 曰韩无码AV片免费播放不卡| A国产一区二区免费入口| 成年人在线免费看视频| 亚洲一区二区三区精品视频| 91在线视频免费91| 亚洲综合av一区二区三区| 成人午夜18免费看| 美女被羞羞网站免费下载| 亚洲伊人久久综合中文成人网| 一区二区三区免费视频观看| 亚洲精品卡2卡3卡4卡5卡区| 日韩免费的视频在线观看香蕉| 亚洲综合无码一区二区| 在线观看的免费网站| 久久亚洲AV成人无码国产电影| 波多野结衣中文一区二区免费 | 中文字幕免费在线播放| 亚洲高清国产拍精品26U| 国产成人免费高清激情明星| 国产 亚洲 中文在线 字幕| 免费一级毛片一级毛片aa| 三上悠亚电影全集免费| 亚洲黄色中文字幕| 日韩成人免费视频播放| a级毛片无码免费真人久久| 亚洲国产精品成人综合色在线婷婷| 日韩在线免费播放| a级男女仿爱免费视频| 亚洲av极品无码专区在线观看| 国产精品视_精品国产免费| a级毛片免费播放| 亚洲国产日韩视频观看| 久久综合亚洲色HEZYO国产| 2021精品国产品免费观看| 亚洲爆乳少妇无码激情| 亚洲精品高清无码视频| 日韩亚洲国产高清免费视频| 免费人成大片在线观看播放| 老色鬼久久亚洲AV综合| 国产免费观看青青草原网站| 亚洲a一级免费视频|