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

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

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

    byterat

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      54 隨筆 :: 0 文章 :: 15 評論 :: 0 Trackbacks

    2007年2月2日 #

    Eclipse及其插件介紹和下載

    0.Eclipse下載
    EMF,GEF - Graphical Editor Framework,UML2,VE - Visual Editor都在這里下載
    http://www.eclipse.org/downloads/index.php

    0.5.lomboz J2EE插件,開發JSP,EJB
    http://forge.objectweb.org/projects/lomboz
    1.MyEclipse J2EE開發插件,支持SERVLET/JSP/EJB/數據庫操縱等
    http://www.myeclipseide.com

    2.Properties Editor 編輯java的屬性文件,并可以自動存盤為Unicode格式
    http://propedit.sourceforge.jp/index_en.html

    3.Colorer Take 為上百種類型的文件按語法著色
    http://colorer.sourceforge.net/

    4.XMLBuddy 編輯xml文件
    http://www.xmlbuddy.com

    5.Code Folding 加入多種代碼折疊功能(比eclipse自帶的更多)
    http://www.coffee-bytes.com/servlet/PlatformSupport

    6.Easy Explorer 從eclipse中訪問選定文件、目錄所在的文件夾
    http://easystruts.sourceforge.net/

    7.Fat Jar 打包插件,可以方便的完成各種打包任務,可以包含外部的包等
    http://fjep.sourceforge.net/

    8.RegEx Test 測試正則表達式
    http://brosinski.com/stephan/archives/000028.php

    9.JasperAssistant 報表插件(強,要錢的)
    http://www.jasperassistant.com/

    10.Jigloo GUI Builder JAVA的GUI編輯插件
    http://cloudgarden.com/jigloo/

    11.Profiler 性能跟蹤、測量工具,能跟蹤、測量BS程序
    http://sourceforge.net/projects/eclipsecolorer/

    12.AdvanQas 提供對if/else等條件語句的提示和快捷幫助(自動更改結構等)
    http://eclipsecolorer.sourceforge.net/advanqas/index.html

    13.Log4E Log4j插件,提供各種和Log4j相關的任務,如為方法、類添加一個logger等
    http://log4e.jayefem.de/index.php/Main_Page

    14.VSSPlugin VSS插件
    http://sourceforge.net/projects/vssplugin

    15.Implementors 提供跳轉到一個方法的實現類,而不是接中的功能(實用!)
    http://eclipse-tools.sourceforge.net/implementors/
    16.Call Hierarchy 顯示一個方法的調用層次(被哪些方法調,調了哪些方法)
    http://eclipse-tools.sourceforge.net/call-hierarchy/index.html

    17.EclipseTidy 檢查和格式化HTML/XML文件
    http://eclipsetidy.sourceforge.net/

    18.Checkclipse 檢查代碼的風格、寫法是否符合規范
    http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm

    19.Hibernate Synchronizer Hibernate插件,自動映射等
    http://www.binamics.com/hibernatesync/

    20.VeloEclipse Velocity插件
    http://propsorter.sourceforge.net/

    21.EditorList 方便的列出所有打開的Editor
    http://editorlist.sourceforge.net/

    22.MemoryManager 內存占用率的監視
    http://cloudgarden.com/memorymanager/

    23.swt-designer java的GUI插件
    http://www.swt-designer.com/

    24.TomcatPlugin 支持Tomcat插件
    http://www.eclipsetotale.com/tomcatPlugin.html

    25.XML Viewer
    http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html

    26.quantum 數據庫插件
    http://quantum.sourceforge.net/

    27.Dbedit 數據庫插件
    http://sourceforge.net/projects/dbedit

    28.clay.core 可視化的數據庫插件
    http://www.azzurri.jp/en/software/index.jsp
    http://www.azzurri.jp/eclipse/plugins

    29.hiberclipse hibernate插件
    http://hiberclipse.sourceforge.net
    http://www.binamics.com/hibernatesync

    30.struts-console Struts插件
    http://www.jamesholmes.com/struts/console/

    31.easystruts Struts插件
    http://easystruts.sourceforge.net

    32.veloedit Velocity插件
    http://veloedit.sourceforge.net/

    33.jalopy 代碼整理插件
    http://jalopy.sourceforge.net/

    34.JDepend 包關系分析
    http://andrei.gmxhome.de/jdepend4eclipse/links.html

    35.Spring IDE Spring插件
    http://springide-eclip.sourceforge.net/updatesite/

    36.doclipse 可以產生xdoclet 的代碼提示
    http://beust.com/doclipse/
    posted @ 2008-06-05 15:44 比特鼠| 編輯 收藏

         摘要: 有這樣一個函數, 它接受一個函數(或者說閉包)作為參數  閱讀全文
    posted @ 2008-05-30 15:19 比特鼠| 編輯 收藏

    當談到表格數據的設計時,沒有太多的網頁設計師會有太大的興趣。今天我們已經收集了20多個功能超大且看上去挺漂亮的Ajax/CSS表格設計,并且教你一些表格設計中所運用的技巧,例如表格數據的排序和過濾等。

    OK,讓我們來看一下這些表格:

    1. Tablecloth

    Tablecloth 由CSS Globe 開發,是一個輕巧易于使用的表格,簡潔的將表格樣式添加到你的HTML 表格元素中。

    21個新奇漂亮的Ajax/CSS表格設計-Tablecloth

    2. Ask the CSS Guy Table

    Ask the CSS Guy Table教給我們要如何去創建能夠清晰顯出去資料之間的相關聯系的表格,例如:點擊一個表格元素時,將突了顯示這個元素,并且在縱列和橫列都顯示出相關的類別關系。

    21個新奇漂亮的Ajax/CSS表格設計-Ask the CSS Guy Table

    #3. A CSS styled table version 2

    Veerle Duoh 為我們展示了一個漂亮的表格設計,并教我們如何使用CSS來吸引用戶的眼球。

    21個新奇漂亮的Ajax/CSS表格設計-A CSS styled table version 2

    #4. Sortable Table

    Sortable Table 演示了如何按升序或降序排列以及如何過濾表格中的數據。

    21個新奇漂亮的Ajax/CSS表格設計-Sortable Table

    5. Row Locking with CSS and JavaScript

    Css Guy再次對表格使用了聚焦高亮的效果,除非用戶再次點擊,否則表單數據將一直保持亮高。

    21個新奇漂亮的Ajax/CSS表格設計-Row Locking with CSS and JavaScript

    他還給了我們另一個示例:another example to Lock rows with radios .

    #6. Vertical scrolling tables

    如果您有大量的表格數據,但卻沒有太大的空間來展示它,這可能是個比較好的方法:一個純CSS的表格與固定的標題和頁腳,以及滾動顯示的內容。

    21個新奇漂亮的Ajax/CSS表格設計-Vertical scrolling tables

    7. Replicating a Tree table

    這是一個使用HTML 和CSS 設計的樹形狀表格。

    21個新奇漂亮的Ajax/CSS表格設計-Replicating a Tree table

    8 ) Paginate, sort and search a table with Ajax and Rails

    這個表格提供了一個動態的界面,而不需要重新刷新整個頁面。

    21個新奇漂亮的Ajax/CSS表格設計-ajax tables

    9. Collapsible tables with DOM and CSS

    此表格加上箭頭形象的腳本提示,用來控制表格的伸展和收縮。

    21個新奇漂亮的Ajax/CSS表格設計-Collapsible tables with DOM and CSS

    10. TableSorter plug-in for jQuery

    它的主要特性包括多列排序,支持<TH>的rowspan和colspan屬性以及許多其他功能。

    21個新奇漂亮的Ajax/CSS表格設計-TableSorter plug-in for jQuery

    11. Stripe your tables the OO way

    使用了Javascript 為表格中的行進行顏色交替,并且添加了onmouseoveronmouseout 事件,當鼠標點擊時,切換背景顏色。

    21個新奇漂亮的Ajax/CSS表格設計-Stripe your tables the OO way

    12. MooTools Table Row & Column highlighting

    基于MooTools 框架,高亮顯示鼠標懸停時的單元格所在的行和列。

    21個新奇漂亮的Ajax/CSS表格設計-MooTools Table Row & Column highlighting

    13. CSS Table Gallery

    93 styled tables是一個專門收集表格樣式的站點,下面是來自一個表格樣式的截圖:

    21個新奇漂亮的Ajax/CSS表格設計-CSS Table Gallery

    14. jQuery Table Filter

    可以對數據進行各種不同的排序、過濾。

    21個新奇漂亮的Ajax/CSS表格設計-jQuery Table Filter

    15. Sortable/Resizable/Editable TableKit

    TableKit基于Prototype框架,專門收集各種HTML表格,可以利用Ajax實時的進行表格欄目大小、排序等編輯。

    21個新奇漂亮的Ajax/CSS表格設計-sortable, resizable, editable

    16. Make all your tables sortable

    21個新奇漂亮的Ajax/CSS表格設計-sortable table

    17. Zebra Tables

    alistapart為我們提供了一個極好的例子,如何使用JavaScript和DOM的改變背景色風格,以突出顯示單元格。

    21個新奇漂亮的Ajax/CSS表格設計-Zebra Tables

    18. Standardista Table Sorting

    Standardista Table Sorting 是一個Javascript模塊,讓您可以對HTML數據表的任何欄目進行排序。

    21個新奇漂亮的Ajax/CSS表格設計-Standardista Table Sorting

    19. GridView3 Example

    21個新奇漂亮的Ajax/CSS表格設計-GridView3 Example

    20. Mootable

    21個新奇漂亮的Ajax/CSS表格設計-Mootable

    21. Drag & Drop Sortable Lists with JavaScript and CSS

    21個新奇漂亮的Ajax/CSS表格設計-Drag & Drop Sortable Lists with JavaScript and CSS

    可能還會有一些你更想尋找的詳細資料,下面是一些相關的資源鏈接:

    如果你知道其它更強大的Ajax/CSS表格,歡迎在此留言。

    posted @ 2008-01-23 17:46 比特鼠 閱讀(3201) | 評論 (0)編輯 收藏

    一個在線調色工具
    posted @ 2008-01-23 17:44 比特鼠 閱讀(392) | 評論 (1)編輯 收藏

    /**
     * 加碼解碼工具
     * @author lwm
     *
     */

    public class Encode {
     
     /*
      * 對應javascript的escape()函數, 加碼后的串可直接使用javascript的unescape()進行解碼
      */
     public static String escape(String src) {
      int i;
      char j;
      StringBuffer tmp = new StringBuffer();
      tmp.ensureCapacity(src.length() * 6);
      for (i = 0; i < src.length(); i++) {
       j = src.charAt(i);
       if (Character.isDigit(j) || Character.isLowerCase(j)
         || Character.isUpperCase(j))
        tmp.append(j);
       else if (j < 256) {
        tmp.append("%");
        if (j < 16)
         tmp.append("0");
        tmp.append(Integer.toString(j, 16));
       } else {
        tmp.append("%u");
        tmp.append(Integer.toString(j, 16));
       }
      }
      return tmp.toString();
     }

     /*
      * 對應javascript的unescape()函數, 可對javascript的escape()進行解碼
      */
     public static String unescape(String src) {
      StringBuffer tmp = new StringBuffer();
      tmp.ensureCapacity(src.length());
      int lastPos = 0, pos = 0;
      char ch;
      while (lastPos < src.length()) {
       pos = src.indexOf("%", lastPos);
       if (pos == lastPos) {
        if (src.charAt(pos + 1) == 'u') {
         ch = (char) Integer.parseInt(src
           .substring(pos + 2, pos + 6), 16);
         tmp.append(ch);
         lastPos = pos + 6;
        } else {
         ch = (char) Integer.parseInt(src
           .substring(pos + 1, pos + 3), 16);
         tmp.append(ch);
         lastPos = pos + 3;
        }
       } else {
        if (pos == -1) {
         tmp.append(src.substring(lastPos));
         lastPos = src.length();
        } else {
         tmp.append(src.substring(lastPos, pos));
         lastPos = pos;
        }
       }
      }
      return tmp.toString();
     }

    }

    posted @ 2008-01-11 17:08 比特鼠 閱讀(1837) | 評論 (0)編輯 收藏

    讀 YUI ,EXT等源碼的時候看JS天旋地轉,那可不是51JS上那種挪挪位置就能理解的,此刻如果沒有JavaScrip的基礎,更是像沒有星光的黑夜…….

    自以為覺得Js對象是很好理解的東東,然而真實踐起來卻一片糊涂。
    通過查閱經典書籍《Professional JavaScript For Web Developers》稍微有些理解了

    JavaScript的基本類型
    原始類型如: Undefined Null Boolean Number String 等 用 typeof方法能辨別之
    引用類型如: Object Function Array Boolean Number String Date等,用insanceof方法辨別之

    嚴格來講,JavaScript沒有對象(Object),但是由于和OO術語對應,所以也稱之為對象。所以Array,Function,基本類型,引用類型,函數,以及函數的屬性 等等這些都是對象。

    而對象分類,則可以分為內置對象(Built-in Object) 和宿主對象(host object)。
    內置對象如 Math,Data啊。
    宿主對象則如 BOM,DOM之類.

    重新回顧了下這些基本概念之后,在做簡單實踐就有些理解了。
    因此對象的使用,創建方式不盡相同,最簡單的歸類如下:

    1 基本創建方式

    function Class() {
    window.alert("Hello Class!");
    }
    var clz= new Class();

    2 訪問對象成員

    function Class(){
    this.x = " this is x";
    this.y = "this is y";
    this.z = viewXY;
    function viewXY(){
    alert("x+","+y);
    }
    }
    var clz= new Class();
    clz.viewXY();

    3 對象繼承

    function Parent() {
    this.type= "human!";
    }
    function Child(){
    this.age = "26";
    this.sex ="male";
    this.say= myInfo;
    function myInfo(msg){
    alert(msg+this.type+ ","+this.age+","+this.sex);
    }
    }
    Child.prototype = new Parent();
    var clild = new Child();
    clild.say("I'm ");

    4.重用原對象 (書上的例子太好了,搬來了)

    Funcion.prototype.toString() = function(){
    return "Function code hidden";
    }
    function sayHi(){
    alert("hi");
    }
    alert(sayHi.toString());
    posted @ 2008-01-02 11:06 比特鼠 閱讀(273) | 評論 (0)編輯 收藏

    希望能做到以下幾點:

    1. 在Java服務端架構的設計, 選型, 方案等方面有所突破! -- 這是最主要的!
    2. 也想玩一玩Web前端的AJAX編程, RIA(富互聯網應用)等等
    3. 熟悉Linux/Unix系統的命令行操作
    4. 在Java中跑腳本語言Python, JRuby等等
    5. 項目管理

    暫時就這么多吧!

    posted @ 2007-12-28 09:41 比特鼠 閱讀(209) | 評論 (0)編輯 收藏

    為 Ajax 安全性所提出的經驗法則:
    1. 如果你使用身份驗證, 確定你在請求頁上檢查!
    2. 為 SQL 注入檢查。
    3. 為 JavaScript 注入檢查。
    4. 保留商務邏輯在服務器上!
    5. 不要假設每個請求是真正的!
    6. 確認檢查數據!
    7. 審查請求的數據而且確定它是正確的。
    posted @ 2007-12-19 17:10 比特鼠 閱讀(280) | 評論 (0)編輯 收藏

    1. jvm內部分為主工作區和線程工作區。主工作區是實例的所有線程共有,線程工作區是實例的每個線程專有的工作區,其中包括一些主工作區的一些實例字段數據的拷貝。

    2. 服務器一般都有線程池,線程資源是可以重復利用的。你2000個用戶在線,不見得能又200個用戶同時(或者說并發)訪問。再說,只要對象不是太大,我寧愿用200個拷貝,也不想讓用戶在這個200個任務的隊列里等待。

    3. 兩個DB之間的復制數據,每個DB各自使用自己的Sequane來生成id。復制數據時,如果DB中的外鍵是由DB維護的,則不會產生id沖突,如果外鍵是由外部程序維護的,則可能會產生錯誤!

    4. 對于非static的類的數據成員來說,在該類產生的實例中都有一份,并且相互獨立(修改后并不影響其他實例), 但static的數據成員則變成了每個類只有一份,即在該類產生的所有實例共享這一個數據成員, 該數據成員的改變會影響到其他的實例. 而static的方法則是讓你不用創建對象及能調用這個方法.

    5. ThreadLocal的作用就是將經常要用到的對象的引用放到屬于線程自己的一個存儲空間中,在該線程的執行過程中,可以通過類的靜態的ThreadLocal來方便的獲取到這個對象,而不用通過參數的形式傳來傳去。
    posted @ 2007-12-19 14:54 比特鼠 閱讀(255) | 評論 (0)編輯 收藏

    很多高分辨率的圖像真的能夠扮靚一個Web網站。但是它們也可能會降低網站的(響應)速度——圖像都是文件,文件就要占用帶寬,而帶寬與等待時間直接相關。現在是你進行自我學習,了解如何利用一種叫做圖像預加載的小技巧給網站提速的時候了。

    圖像的預加載

           瀏覽器通常的工作方式是:只有當要求加載圖像的HTTP請求被發送的時候,圖像才會被加載,而不論它是被動地通過<img>標記加載,還是主動地通過方法調用加載。所以,如果你有一段JavaScript,需要在鼠標懸停的時候切換圖像,或者在超時之后自動地更換圖像,那么你就可能會在從服務器取回圖像的時候隨時碰到等待,時間會從數秒鐘到幾分鐘不等。當你以較慢的速度連接到Internet上的時候,或者被取回的圖像非常巨大的時候,這種狀況尤其顯著,而這種數據延遲通常都會毀掉你所期望的效果。

            有些瀏覽器會試圖轉嫁這一問題,比如把圖像保存在本地緩沖區里,這樣以后對它的調用就能夠很快進行了,但是需要第一次調用圖像的時候仍然會產生延遲。預加載是一項在需要圖像之前就把它下載到緩沖區里的技術。通過這種方式,當真的需要圖像的時候,它可以被從緩沖區里取出來,并立即顯示出來。

    Image()對象
            預加載圖像最簡單的方法用JavaScript將一個新的Image()對象實例化,并把你想要預加載的圖像的URL傳遞給它。假設我們有一個叫做
    http://www.host01.com/Get/jsp/00040004/heavyimagefile.jpg的圖像,我們希望,當用戶把鼠標放在一個已經顯示過的圖像上的時,系統能夠顯示出這個圖像。為了預加載這個圖像,以便實現更快的響應時間,我們只用創建一個新的Image()對象,將其命名為heavyImage,并使用onLoad()事件處理程序把它同時加載到頁面上。

    1 < html >< head >< script  language  = "JavaScript" > function  preloader()  {heavyImage  =   new  Image(); heavyImage.src = " http://www.host01.com/Get/jsp/00040004/heavyimagefile.jpg " ;} </ script ></ head >< body  onLoad ="javascript:preloader()" >< href ="#"  onMouseOver ="javascript:document.img01.src='http://www.host01.com/Get/jsp/00040004/heavyimagefile.jpg'" >< img  name ="img01"  src =http://www.host01.com/Get/jsp/00040004/"justanotherfile.jpg" ></ a ></ body ></ html >
    2

     

              要注意的是,圖像標記自身并不會處理onMouseOver()和onMouseOut()事件,這就是為什么上面例子里的<img>標記被放在一個<a>標記里,后者的確加入了對這些事件類型的支持。
    用數組加載多個圖像


               在實際操作中,你可能需要預加載一幅以上的圖像;例如,在包含有多個圖像翻滾(rollover)的菜單條里,或者如果你正在嘗試創建平滑的動態效果。這并不困難;你所需要做的就是使用JavaScript的數組,就像下面例子里的一樣:

     

    1 < script language = " JavaScript " > function  preloader()  //  counter var i = 0; // create object imageObj = new Image(); // set image list images = new Array(); images[0]="image1.jpg" images[1]="image2.jpg" images[2]="image3.jpg" images[3]="image4.jpg" // start preloading for(i=0; i<=3; i++) { imageObj.src=images[i]; }
    2 }
      </ script >


             在上面的例子里,你先定義變量i和叫做imageObj的Image()對象。然后定義一個叫做images[]的新數組,在這個數組里,每個數組元素都保存著需要預加載的圖像來源。最后,創建一個for()循環,讓它在數組里循環,并將它們中的每一個都指派給Image()對象,這樣就能夠把它預加載到緩沖區里。
    onLoad()事件處理程序
            就和JavaScript里的其它很多對象一樣,Image()對象也帶有多個事件處理程序。這其中最有用的毫無疑問的就是onLoad()處理程序了,它會在完成圖像加載的時候被調用。這個處理程序可以與自定義的函數一起使用,以便在完成圖像加載之后進行特定的任務。下面的例子通過在圖像加載的時候顯示“請等待(please wait)”提示信息來說明這個問題,然后在圖像完成加載之后就向瀏覽器發送一個新的URL。

     

    < html >< head >< script  language ="JavaScript" > //  create an image objectobjImage = new Image(); // set what happens once the image has loaded objImage.onLoad=imagesLoaded(); // preload the image fileobjImage.src='http://www.host01.com/Get/jsp/00040004/images/image1n.gif';// function invoked on image loadfunction imagesLoaded(){ document.location.href='index2.html';}</script></head><body>Please wait, loading images</body></html>

     


           當然,你還可以創建一個圖像數組,對它進行循環,預加載每個圖像,并在每個階段對已加載圖像的數量保持跟蹤。一旦加載了所有的圖像,事件處理程序就能夠按照設定把瀏覽器帶到下一個頁面(或者進行其他的任務)。

    預加載與多狀態菜單

              現在,把你剛剛學到的理論付諸真正的實踐怎么樣?下面一部分內容就是我碰巧編寫的一段代碼——一個由多個按鈕(圖像鏈接)組成的菜單條——其中每個按鈕都可能處于三種狀態中的一種:正常(normal)、hover(懸停)和點擊(click)。由于所有的按鈕都有多個狀態,所以就有必要使用圖像預加載來確保菜單能夠根據其切換到的狀態進行快速的響應。列表A里的代碼就說了這一點。

               列表A里的HTML代碼會建立一個由四個按鈕組成的菜單條,每個按鈕都有三種狀態:正常、懸停和點擊。其要求如下:

              但鼠標移動到處于正常狀態的按鈕上時,按鈕會變為懸停狀態。當鼠標移開的時候,按鈕又會恢復到正常狀態。當鼠標點擊按鈕的時候,按鈕就會變為點擊狀態。它會一直保持這個狀態,直到另外一個按鈕被點擊。如果有一個按鈕被點擊,那么其他的按鈕就都不能處于點擊狀態。其他的按鈕只能夠處于懸停或者正常狀態。一次只能有一個按鈕可以被點擊。一次只能有一個按鈕處于懸停狀態。
            第一項任務是建立保存有菜單每個狀態的圖像的數組。與這些數組元素相對應的<img>元素也都在HTML文檔的主體里被創建,并按順序命名。要注意的是,對數組值的索引是從0開始的,而相應的<img>元素是從1開始命名的——這就需要在腳本后面的一段里進行某種計算上的調整。

            PreloadImages()函數會負責把所有的圖像都加載到緩沖區里,這樣的話對鼠標移動的響應時間會被減到最小。一個for()循環被用在第一步里創建的圖像里進行迭代,并預加載每一個圖像。

                ResetAll()函數是把所有圖像恢復都到它們正常狀態的方便方法。這是有必要的,因為當菜單的項目被點擊的時候,菜單里其他所有的項目都必須在被點擊項目能夠切換到點擊狀態之前恢復到正常狀態。

            SetNormal()、setHover()和setClick()函數負責把特定圖像(圖像的編號被作為函數的自變量進行傳遞)的來源分別改為正常、懸停或者點擊狀態。由于被點擊的圖像必須一直保持點擊狀態,直到另外一個圖像被點擊(見第二項要求),所以它們暫時不會對鼠標移動作出反應;這樣的話,如果按鈕還不是處在點擊狀態,那么setNormal()和setHover()函數所包括的代碼就只能用來改變按鈕的狀態。

             上面所提到的預加載只是提高你JavaScript效果響應時間的多種方法之一。就在你的網站上使用上面列出的技巧,并根據你的要求在需要的地方更改它們吧。祝你好運!

    posted @ 2007-12-19 10:40 比特鼠 閱讀(255) | 評論 (0)編輯 收藏

    這些東西都是Java Script大部分都是由老外寫的,并且封裝得很好,在運用上也很方便,而且也都兼容FF與OPERA,檔案中少部分是由中國的高手寫的。

     

      一、多樣化摺疊菜單:下載

      一個由老外寫的折疊式垂直菜單,多樣化,多功能,可自訂,使用容易,支持FF。

    國內外 Java Script 經典封裝
    圖1

      二、CSS圓角邊框:下載

      以CSS為主要,用Java Script封裝的相當完整,也是老外寫的,支持多瀏覽器,可以自訂樣式,目前有十多種可以運用。

    國內外 Java Script 經典封裝
    圖2

    國內外 Java Script 經典封裝
    圖3

      三、模擬視窗:下載

      用層模擬的視窗,是一個中國高手寫的,Java Script封裝的相當好,使用上也很容易

    國內外 Java Script 經典封裝
    圖4
      

      四、支持FF的省略符:下載

      說到省略符,那非CSS莫屬,有個老外用Java Script來實現,并且是批量處理的,重點是支持FF。

    國內外 Java Script 經典封裝
    圖5

      五、TAB選項卡:下載

      用Java Script模仿各種作業系統的選項卡,老外就是牛,不僅支援多樣式的即時切換,同時也支援每個選項卡是否附帶圖示的切換選項,選項卡也可以上下切換。

    國內外 Java Script 經典封裝
    圖6
      

      六、最佳化多樣式Windows:下載

      用層模擬視窗的最佳代表作,這是我看過功能最多的模擬式窗,內附多達74項功能與樣式,你完完全全可以把它當成是一個真正的視窗來應用,可以根據你的需求來應用,快丟掉你那認為好用的層視窗,這套封裝非常完整的視窗絕對可以滿足你的各種需求。

    國內外 Java Script 經典封裝
    圖7

    國內外 Java Script 經典封裝
    圖8

      七、多樣化的垂直菜單:附件

      別具風格的方塊式垂直折疊菜單,目前有8種風格可以運用,如果你已經厭煩WEB上平凡的菜單,這套在國外頗受歡迎的菜單肯定是你的最佳首選。

    國內外 Java Script 經典封裝
    圖9
      

      八、多樣化的連結提示效果:下載

      這個連結提示樣式允許你直接寫入css與html,共有14項功能可以讓你自訂。

    國內外 Java Script 經典封裝
    圖10

      九、側欄式折疊菜單:下載

      這是一個側欄式的折疊菜單,它允許你設置它是否有過渡效果、側欄菜單是否自動伸縮、菜單項切換是否允許動畫過渡、是否輪替切換等多項設置,并且也有多種樣式可以運用。

      這個腳本有個很好玩的東東,下載并且解壓後,請進入samples的目錄并打show.html看看效果,我不知道這效果容不容易實現,但是這效果很牛,菜單全自動運行的~

    國內外 Java Script 經典封裝
    圖11
      

      十、圖形滾動條:下載

      老外寫的圖形滾動條,有多種樣式,在ie里頭還支持滾輪滾動。

    國內外 Java Script 經典封裝
    圖12

      十一、圖片倒影效果:下載
      說到圖片倒影,不外乎就是直接作成圖片跟css濾鏡來實現,但是這個是用Java Script實現的,值得借鏡。

    國內外 Java Script 經典封裝
    圖13

      十二、代碼自動高亮:下載

      雖說這不是什麼新東西,但總是會有人需要吧,而且想學正則表達的人,這肯定是最佳借鏡的作品。

    國內外 Java Script 經典封裝
    圖14
      
      

      十三、酷似flash效果的圖片展示:下載

      這個老外牛到有點變態,這圖片展示效果已經跟FLASH沒什麼兩樣,用Java Script寫的耶。

    國內外 Java Script 經典封裝
    圖15

      十四、讓ie6支援png圖檔:下載

    國內外 Java Script 經典封裝
    圖16

      這個問題之前被很多人討論過,我就不多說什麼了,有需要下吧。

    posted @ 2007-12-13 17:29 比特鼠 閱讀(5341) | 評論 (5)編輯 收藏

    在一個老外的Blog上看到了這個網站,發現原來是一個以C語言為基準的性能比較網站!

    Java還算不錯,Ruby就不怎么樣了, 在腳本語言中居然排在了最后!

    看來,解析性的語言玩起來是簡單方便了,可是卻是以損失性能為代價的!
    posted @ 2007-12-13 16:34 比特鼠 閱讀(468) | 評論 (0)編輯 收藏

    BIG-ENDIAN(大字節序、高字節序)
    LITTLE-ENDIAN(小字節序、低字節序)
    主機字節序
    網絡字節順序
    JAVA字節序

    1.BIG-ENDIAN、LITTLE-ENDIAN跟多字節類型的數據有關的比如int,short,long型,而對單字節數據byte卻沒有影響。BIG-ENDIAN就是低位字節排放在內存的低端,高位字節排放在內存的高端。而LITTLE-ENDIAN正好相反。
    比如 int a = 0x05060708
    在BIG-ENDIAN的情況下存放為:
    字節號 0 1 2 3
    數據 05 06 07 08
    在LITTLE-ENDIAN的情況下存放為:
    字節號 0 1 2 3
    數據 08 07 06 05

    2.BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有關的,每一種CPU不是BIG-ENDIAN就是LITTLE-ENDIAN、。IA架構的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola處理器。這其實就是所謂的主機字節序。而網絡字節序是指數據在網絡上傳輸時是大頭還是小頭的,在Internet的網絡字節序是BIG-ENDIAN。所謂的JAVA字節序指的是在JAVA虛擬機中多字節類型數據的存放順序,JAVA字節序也是BIG-ENDIAN。

    3.所以在用C/C++寫通信程序時,在發送數據前務必用htonl和htons去把整型和短整型的數據進行從主機字節序到網絡字節序的轉換,而接收數據后對于整型和短整型數據則必須調用ntohl和ntohs實現從網絡字節序到主機字節序的轉換。如果通信的一方是JAVA程序、一方是C/C++程序時,則需要在C/C++一側使用以上幾個方法進行字節序的轉換,而JAVA一側,則不需要做任何處理,因為JAVA字節序與網絡字節序都是BIG-ENDIAN,只要C/C++一側能正確進行轉換即可(發送前從主機序到網絡序,接收時反變換)。如果通信的雙方都是JAVA,則根本不用考慮字節序的問題了。

    4.如果網絡上全部是PowerPC,SPARC和Motorola CPU的主機那么不會出現任何問題,但由于實際存在大量的IA架構的CPU,所以經常出現數據傳輸錯誤。

    5.文章開頭所提出的問題,就是因為程序運行在X86架構的PC SERVER上,發送數據的一端用C實現的,接收一端是用JAVA實現的,而發送端在發送數據前未進行從主機字節序到網絡字節序的轉換,這樣接收端接收到的是LITTLE-ENDIAN的數據,數據解釋自然出錯。
    具體數據如下,實際發送的數據為23578
    發送端發送數據: 1A 5C
    接收端接收到數據后,按BIG-ENDIAN進行解釋具體數據是多少?你們自己去計算并比較吧!


    ===============================================================================================

    Big Endian and Little Endian

        談到字節序的問題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存儲數據,而x86系列則采用little endian方式存儲數據。那么究竟什么是big endian,什么又是little endian呢?

        其實big endian是指低地址存放最高有效字節(MSB),而little endian則是低地址存放最低有效字節(LSB),即常說的低位在先,高位在后。
        用文字說明可能比較抽象,下面用圖像加以說明。比如數字0x12345678在兩種不同字節序CPU中的存儲順序如下所示:

    Big Endian

      低地址                           高地址
      ----------------------------------------->
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |     12     |      34    |     56      |     78    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    Little Endian

      低地址                           高地址
      ----------------------------------------->
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |     78     |      56    |     34      |     12    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

        從上面兩圖可以看出,采用big endian方式存儲數據是符合我們人類的思維習慣的。而little endian,!@#$%^&*,見鬼去吧 -_-|||

        為什么要注意字節序的問題呢?你可能這么問。當然,如果你寫的程序只在單機環境下面運行,并且不和別人的程序打交道,那么你完全可以忽略字節序的存在。但是,如果你的程序要跟別人的程序產生交互呢?尤其是當你把你在微機上運算的結果運用到計算機群上去的話。在這里我想說說兩種語言。C/C++語言編寫的程序里數據存儲順序是跟編譯平臺所在的CPU相關的,而JAVA編寫的程序則唯一采用big endian方式來存儲數據。試想,如果你用C/C++語言在x86平臺下編寫的程序跟別人的JAVA程序互通時會產生什么結果?就拿上面的 0x12345678來說,你的程序傳遞給別人的一個數據,將指向0x12345678的指針傳給了JAVA程序,由于JAVA采取big endian方式存儲數據,很自然的它會將你的數據翻譯為0x78563412。什么?竟然變成另外一個數字了?是的,就是這種后果。因此,在你的C程序傳給JAVA程序之前有必要進行字節序的轉換工作。

        無獨有偶,所有網絡協議也都是采用big endian的方式來傳輸數據的。所以有時我們也會把big endian方式稱之為網絡字節序。當兩臺采用不同字節序的主機通信時,在發送數據之前都必須經過字節序的轉換成為網絡字節序后再進行傳輸。ANSI C中提供了四個轉換字節序的宏。


    ========================================================================================================

    /**
    * 通信格式轉換
    *
    * Java和一些windows編程語言如c、c++、delphi所寫的網絡程序進行通訊時,需要進行相應的轉換
    * 高、低字節之間的轉換
    * windows的字節序為低字節開頭
    * linux,unix的字節序為高字節開頭
    * java則無論平臺變化,都是高字節開頭
    */

    public class FormatTransfer {
    /**
      * 將int轉為低字節在前,高字節在后的byte數組
      * @param n int
      * @return byte[]
      */
    public static byte[] toLH(int n) {
      byte[] b = new byte[4];
      b[0] = (byte) (n & 0xff);
      b[1] = (byte) (n >> 8 & 0xff);
      b[2] = (byte) (n >> 16 & 0xff);
      b[3] = (byte) (n >> 24 & 0xff);
      return b;
    }

    /**
      * 將int轉為高字節在前,低字節在后的byte數組
      * @param n int
      * @return byte[]
      */
    public static byte[] toHH(int n) {
      byte[] b = new byte[4];
      b[3] = (byte) (n & 0xff);
      b[2] = (byte) (n >> 8 & 0xff);
      b[1] = (byte) (n >> 16 & 0xff);
      b[0] = (byte) (n >> 24 & 0xff);
      return b;
    }

    /**
      * 將short轉為低字節在前,高字節在后的byte數組
      * @param n short
      * @return byte[]
      */
    public static byte[] toLH(short n) {
      byte[] b = new byte[2];
      b[0] = (byte) (n & 0xff);
      b[1] = (byte) (n >> 8 & 0xff);
      return b;
    }

    /**
      * 將short轉為高字節在前,低字節在后的byte數組
      * @param n short
      * @return byte[]
      */
    public static byte[] toHH(short n) {
      byte[] b = new byte[2];
      b[1] = (byte) (n & 0xff);
      b[0] = (byte) (n >> 8 & 0xff);
      return b;
    }

     

    /**
      * 將將int轉為高字節在前,低字節在后的byte數組

    public static byte[] toHH(int number) {
      int temp = number;
      byte[] b = new byte[4];
      for (int i = b.length - 1; i > -1; i--) {
        b = new Integer(temp & 0xff).byteValue();
        temp = temp >> 8;
      }
      return b;
    }

    public static byte[] IntToByteArray(int i) {
        byte[] abyte0 = new byte[4];
        abyte0[3] = (byte) (0xff & i);
        abyte0[2] = (byte) ((0xff00 & i) >> 8);
        abyte0[1] = (byte) ((0xff0000 & i) >> 16);
        abyte0[0] = (byte) ((0xff000000 & i) >> 24);
        return abyte0;
    }


    */

    /**
      * 將float轉為低字節在前,高字節在后的byte數組
      */
    public static byte[] toLH(float f) {
      return toLH(Float.floatToRawIntBits(f));
    }

    /**
      * 將float轉為高字節在前,低字節在后的byte數組
      */
    public static byte[] toHH(float f) {
      return toHH(Float.floatToRawIntBits(f));
    }

    /**
      * 將String轉為byte數組
      */
    public static byte[] stringToBytes(String s, int length) {
      while (s.getBytes().length < length) {
        s += " ";
      }
      return s.getBytes();
    }


    /**
      * 將字節數組轉換為String
      * @param b byte[]
      * @return String
      */
    public static String bytesToString(byte[] b) {
      StringBuffer result = new StringBuffer("");
      int length = b.length;
      for (int i=0; i<length; i++) {
        result.append((char)(b & 0xff));
      }
      return result.toString();
    }

    /**
      * 將字符串轉換為byte數組
      * @param s String
      * @return byte[]
      */
    public static byte[] stringToBytes(String s) {
      return s.getBytes();
    }

    /**
      * 將高字節數組轉換為int
      * @param b byte[]
      * @return int
      */
    public static int hBytesToInt(byte[] b) {
      int s = 0;
      for (int i = 0; i < 3; i++) {
        if (b >= 0) {
        s = s + b;
        } else {
        s = s + 256 + b;
        }
        s = s * 256;
      }
      if (b[3] >= 0) {
        s = s + b[3];
      } else {
        s = s + 256 + b[3];
      }
      return s;
    }

    /**
      * 將低字節數組轉換為int
      * @param b byte[]
      * @return int
      */
    public static int lBytesToInt(byte[] b) {
      int s = 0;
      for (int i = 0; i < 3; i++) {
        if (b[3-i] >= 0) {
        s = s + b[3-i];
        } else {
        s = s + 256 + b[3-i];
        }
        s = s * 256;
      }
      if (b[0] >= 0) {
        s = s + b[0];
      } else {
        s = s + 256 + b[0];
      }
      return s;
    }


    /**
      * 高字節數組到short的轉換
      * @param b byte[]
      * @return short
      */
    public static short hBytesToShort(byte[] b) {
      int s = 0;
      if (b[0] >= 0) {
        s = s + b[0];
        } else {
        s = s + 256 + b[0];
        }
        s = s * 256;
      if (b[1] >= 0) {
        s = s + b[1];
      } else {
        s = s + 256 + b[1];
      }
      short result = (short)s;
      return result;
    }

    /**
      * 低字節數組到short的轉換
      * @param b byte[]
      * @return short
      */
    public static short lBytesToShort(byte[] b) {
      int s = 0;
      if (b[1] >= 0) {
        s = s + b[1];
        } else {
        s = s + 256 + b[1];
        }
        s = s * 256;
      if (b[0] >= 0) {
        s = s + b[0];
      } else {
        s = s + 256 + b[0];
      }
      short result = (short)s;
      return result;
    }

    /**
      * 高字節數組轉換為float
      * @param b byte[]
      * @return float
      */
    public static float hBytesToFloat(byte[] b) {
      int i = 0;
      Float F = new Float(0.0);
      i = ((((b[0]&0xff)<<8 | (b[1]&0xff))<<8) | (b[2]&0xff))<<8 | (b[3]&0xff);
      return F.intBitsToFloat(i);
    }

    /**
      * 低字節數組轉換為float
      * @param b byte[]
      * @return float
      */
    public static float lBytesToFloat(byte[] b) {
      int i = 0;
      Float F = new Float(0.0);
      i = ((((b[3]&0xff)<<8 | (b[2]&0xff))<<8) | (b[1]&0xff))<<8 | (b[0]&0xff);
      return F.intBitsToFloat(i);
    }

    /**
      * 將byte數組中的元素倒序排列
      */
    public static byte[] bytesReverseOrder(byte[] b) {
      int length = b.length;
      byte[] result = new byte[length];
      for(int i=0; i<length; i++) {
        result[length-i-1] = b;
      }
      return result;
    }

    /**
      * 打印byte數組
      */
    public static void printBytes(byte[] bb) {
      int length = bb.length;
      for (int i=0; i<length; i++) {
        System.out.print(bb + " ");
      }
      System.out.println("");
    }

    public static void logBytes(byte[] bb) {
      int length = bb.length;
      String ut = "";
      for (int i=0; i<length; i++) {
        ut = out + bb + " ";
      }

    }

    /**
      * 將int類型的值轉換為字節序顛倒過來對應的int值
      * @param i int
      * @return int
      */
    public static int reverseInt(int i) {
      int result = FormatTransfer.hBytesToInt(FormatTransfer.toLH(i));
      return result;
    }

    /**
      * 將short類型的值轉換為字節序顛倒過來對應的short值
      * @param s short
      * @return short
      */
    public static short reverseShort(short s) {
      short result = FormatTransfer.hBytesToShort(FormatTransfer.toLH(s));
      return result;
    }

    /**
      * 將float類型的值轉換為字節序顛倒過來對應的float值
      * @param f float
      * @return float
      */
    public static float reverseFloat(float f) {
      float result = FormatTransfer.hBytesToFloat(FormatTransfer.toLH(f));
      return result;
    }

    }

    posted @ 2007-10-24 09:57 比特鼠 閱讀(3407) | 評論 (0)編輯 收藏

    實現Leader/Fellows模式的項目--CAJ, 地址是:http://caj.cosylab.com/
    posted @ 2007-10-23 14:57 比特鼠 閱讀(198) | 評論 (0)編輯 收藏

    網址:http://httpd.apache.org/docs/2.0/programs/ab.html
    posted @ 2007-10-23 14:53 比特鼠 閱讀(273) | 評論 (0)編輯 收藏

    緩沖區基礎

    抽象類Buffer是java.nio包支持緩沖區的基礎。 Buffer 的工作方式就象內存中用于讀寫基本數據類型的 RandomAccessFile 。象 RandomAccessFile 一樣,使用 Buffer ,所執行的下一個操作(讀/寫)在當前某個位置發生。執行讀/寫操作中的任一個都會改變那個位置,所以在寫操作之后進行讀操作不會讀到剛才所寫的內容,而會讀到剛才所寫內容之后的數據。 Buffer 提供了四個指示方法,用于訪問線性結構(從最高值到最低值):

    capacity() :表明緩沖區的容量大小, 一旦確定了大小, 將不能再改變;
    limit() :告訴您到目前為止已經往緩沖區填了多少字節,或者讓您用 :limit(int newLimit) 來改變這個限制
    position() :告訴您當前的位置,以執行下一個讀/寫操作
    mark() :為了稍后用 reset() 進行重新設置而記住某個位置
    flip() :交換限制指針和位置指針,然后將位置置為 0,并廢棄已經做的mark標記

    緩沖區的基本操作是讀 get() 和寫 put() ;然而,這些方法在子類中都是針對每種數據類型的特定方法。為了說明這一情況,讓我們研究一個簡單示例,該示例演示了從同一個緩沖區讀和寫一個字符。在清單 1 中, flip() 方法交換限制和位置,然后將位置置為 0,并廢棄標記,讓您讀剛才所寫的數據:


    清單 1. 讀/寫示例
    import java.nio.*;
    ...
    CharBuffer buff = ...;
    buff.put('A');
    buff.flip();
    char c = buff.get();
    System.out.println("An A: " + c);
     


    現在讓我們研究一些具體的 Buffer 子類。

     

    緩沖區類型

    Merlin 具有 7 種特定的 Buffer 類型,每種類型對應著一個基本數據類型(不包括 boolean):

    ByteBuffer       //存放任何除boolean類型外的其他基本類型
    CharBuffer       //存放char
    DoubleBuffer     //存放double
    FloatBuffer      //存放float
    IntBuffer        //存放int
    LongBuffer       //存放long
    ShortBuffer      //存放short

    在本文后面,我將討論第 8 種類型 MappedByteBuffer ,它用于內存映射文件。如果您必須使用的類型不是這些基本類型,則可以先從 ByteBuffer 獲得字節類型,然后將其轉換成 Object 或其它任何類型。


    創建緩沖區
    一共有兩種類型的緩沖區,直接緩沖區和非直接緩沖區。

    在創建緩沖區時,可以要求創建直接緩沖區,創建直接緩沖區的成本要比創建間接緩沖區高,但這可以使運行時環境直接在該緩沖區上進行較快的本機 I/O 操作。因為創建直接緩沖區所增加的成本,所以直接緩沖區只用于長生存期的緩沖區,而不用于短生存期、一次性且用完就丟棄的緩沖區。而且,只能在 ByteBuffer 這個級別上創建直接緩沖區,如果希望使用其它類型,則必須將 Buffer 轉換成更具體的類型。

    判斷一個緩沖區是否是直接緩沖區,可以調用isDirect()方法。

    有三種方式來獲取一個緩沖區的對象:
    a. 調用allocate()或者allocateDirect()方法直接分配,其中allocateDirect()返回的是直接緩沖區。
    b. 包裝一個數組,如:
          byte[] b = new byte[1024];
          ByteBuffer bb = ByteBuffer.wrap(b);
    c. 內存映射,即調用FileChannel的map()方法。

    緩沖區基本屬性
    這幾個屬性是每個緩沖區都有的并且是常用的操作。
    a. 容量(capacity),緩沖區大小
    b. 限制(limit),第一個不應被讀取或寫入的字節的索引,總是小于容量。
    c. 位置(position),下一個被讀取或寫入的字節的索引,總是小于限制。
    d. clear()方法:設置limit為capacity,position為0。
    e. filp()方法:設置limit為當前position,然后設置position為0。
    f. rewind()方法:保持limit不變,設置position為0。

    緩沖區數據操作
    操作包括了讀取和寫入數據兩種。
    讀取數據使用get()及其系列方法,除boolean外,每一種類型包括了對應的get()方法,如getInt(),getChar()等,get()方法用來讀取字節,支持相對和絕對索引兩種方式。
    寫入數據使用put()及其系列方法,和get()方法是對應的。

    package nio;

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;

    public class BufferDemo ...{

        
        public static void main(String[] args) throws Exception...{
            //分配一個非直接緩沖區
            ByteBuffer bb = ByteBuffer.allocate(100);
            //向緩沖區寫入0到100的字節制
            for(int i = 0; i <100; i++)...{
                byte b = (byte) (Math.random() * 100);
                bb.put(b);
            }
            
            System.out.println("寫入文件前的緩沖區數據");
            bb.flip();
            while(bb.hasRemaining())
                System.out.print(bb.get() + " ");
            System.out.println();
            
            //獲取一個關聯到文件buffer.txt的信道
            FileChannel fc = new FileOutputStream("buffer.txt").getChannel();
            //將緩沖區數據寫到文件中
            bb.flip();
            fc.write(bb);
            //防止緩存
            fc.force(true);
            //關閉信道
            fc.close();
            bb = null;
            fc = null;
            
            //下面從文件中讀取數據
            fc = new FileInputStream("buffer.txt").getChannel();
            ByteBuffer bb2 = ByteBuffer.allocate((int) fc.size());
            fc.read(bb2);
            System.out.println("從文件讀取的緩沖區數據");
            bb2.flip();
            while(bb2.hasRemaining())
                System.out.print(bb2.get() + " ");
            System.out.println();
            fc.close();
            bb2 = null;
            fc = null;
            

        }

    }

    內存映射文件

    第 8 種 Buffer 類型 MappedByteBuffer 只是一種特殊的 ByteBuffer 。 MappedByteBuffer 將文件所在區域直接映射到內存。通常,該區域包含整個文件,但也可以只映射部分文件。所以,必須指定要映射文件的哪部分。而且,與其它 Buffer 對象一樣,這里沒有構造函數;必須讓 java.nio.channels.FileChannel 的 map() 方法來獲取 MappedByteBuffer 。此外,無需過多涉及通道就可以用 getChannel() 方法從 FileInputStream 或 FileOutputStream 獲取 FileChannel 。通過從命令行傳入文件名來讀取文本文件的內容,清單 4 顯示了 MappedByteBuffer :


    清單 4. 讀取內存映射文本文件
    import java.io.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.charset.*;
    public class ReadFileBuff {
      public static void main(String args[]) throws IOException {
         if (args.length != 0) {
          String filename = args[0];
          FileInputStream fis = new FileInputStream(filename);
          FileChannel channel = fis.getChannel();
          int length = (int)channel.size();
          MappedByteBuffer byteBuffer =
            channel.map(FileChannel.MapMode.READ_ONLY, 0, length);
          Charset charset = Charset.forName("ISO-8859-1");
          CharsetDecoder decoder = charset.newDecoder();
          CharBuffer charBuffer = decoder.decode(byteBuffer);
          for (int i=0, n=charBuffer.length(); i<n; i++) {
            System.out.print(charBuffer.get());
          }
        }
      }
    }

    posted @ 2007-08-01 11:13 比特鼠 閱讀(3826) | 評論 (0)編輯 收藏

    1. 左移操作: x << n
      x可以是byte, short, char, int, long基本類型, n(位移量)只能是int型

      編譯器的執行步驟:
      1) 如果x是byte, short, char類型, 則將x提升為int;
      2) 如果x是byte, short, char, int類型, 則n被重新賦值(過程是:取n的補碼的低5位再轉成十進制的int值,相當對n取32模: n=n%32);
         如果x是long型, 則n被重新賦值(過程是:取n的補碼的低6位再轉成十進制的int值,相當對n取64模: n=n%64);
         (因為int類型為4個字節,即32位,移動32位將沒有任何意義.對于long則是模64)
      3) 對x左移n個位數, 整個表達式產生一個新值(x的值不變);
    2. <<是左移符號,列x<<1,就是x的內容左移一位(x的內容并不改變)
    3. >>是帶符號位的右移符號,x>>1就是x的內容右移一位,如果開頭是1則補1,是0責補0,(x的內容并不改變).
    4. >>>是不帶符號位的右移,x>>>1就是x的內容右移一位,開頭補0(x的內容并不改變)
    posted @ 2007-08-01 10:12 比特鼠 閱讀(2804) | 評論 (0)編輯 收藏

    原文地址 http://www.programbbs.com/doc/2433.htm
    為什么會排隊等待?

    下面的這個簡單的 Java 程序完成四項不相關的任務。這樣的程序有單個控制線程,控制在這四個任務之間線性地移動。此外,因為所需的資源 — 打印機、磁盤、數據庫和顯示屏 -- 由于硬件和軟件的限制都有內在的潛伏時間,所以每項任務都包含明顯的等待時間。因此,程序在訪問數據庫之前必須等待打印機完成打印文件的任務,等等。如果您正在等待程序的完成,則這是對計算資源和您的時間的一種拙劣使用。改進此程序的一種方法是使它成為多線程的。
     
    四項不相關的任務
     

    class myclass {
        static public void main(String args[]) {
            print_a_file();
            manipulate_another_file();
            access_database();
            draw_picture_on_screen();
        }
    }

    在本例中,每項任務在開始之前必須等待前一項任務完成,即使所涉及的任務毫不相關也是這樣。但是,在現實生活中,我們經常使用多線程模型。我們在處理某些任務的同時也可以讓孩子、配偶和父母完成別的任務。例如,我在寫信的同時可能打發我的兒子去郵局買郵票。用軟件術語來說,這稱為多個控制(或執行)線程。

    可以用兩種不同的方法來獲得多個控制線程:

    多個進程
    在大多數操作系統中都可以創建多個進程。當一個程序啟動時,它可以為即將開始的每項任務創建一個進程,并允許它們同時運行。當一個程序因等待網絡訪問或用戶輸入而被阻塞時,另一個程序還可以運行,這樣就增加了資源利用率。但是,按照這種方式創建每個進程要付出一定的代價:設置一個進程要占用相當一部分處理器時間和內存資源。而且,大多數操作系統不允許進程訪問其他進程的內存空間。因此,進程間的通信很不方便,并且也不會將它自己提供給容易的編程模型。


    線程
    線程也稱為輕型進程 (LWP)。因為線程只能在單個進程的作用域內活動,所以創建線程比創建進程要廉價得多。這樣,因為線程允許協作和數據交換,并且在計算資源方面非常廉價,所以線程比進程更可取。線程需要操作系統的支持,因此不是所有的機器都提供線程。Java 編程語言,作為相當新的一種語言,已將線程支持與語言本身合為一體,這樣就對線程提供了強健的支持。


    使用 Java 編程語言實現線程
    Java 編程語言使多線程如此簡單有效,以致于某些程序員說它實際上是自然的。盡管在 Java 中使用線程比在其他語言中要容易得多,仍然有一些概念需要掌握。要記住的一件重要的事情是 main() 函數也是一個線程,并可用來做有用的工作。程序員只有在需要多個線程時才需要創建新的線程。

    Thread 類
    Thread 類是一個具體的類,即不是抽象類,該類封裝了線程的行為。要創建一個線程,程序員必須創建一個從 Thread 類導出的新類。程序員必須覆蓋 Thread 的 run() 函數來完成有用的工作。用戶并不直接調用此函數;而是必須調用 Thread 的 start() 函數,該函數再調用 run()。下面的代碼說明了它的用法:

    創建兩個新線程

    import java.util.*;

    class TimePrinter extends Thread {
        int pauseTime;

        String name;

        public TimePrinter(int x, String n) {
            pauseTime = x;
            name = n;
        }

        public void run() {
            while (true) {
                try {
                    System.out.println(name + ":"
                            + new Date(System.currentTimeMillis()));
                    Thread.sleep(pauseTime);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }

        static public void main(String args[]) {
            TimePrinter tp1 = new TimePrinter(1000, "Fast Guy");
            tp1.start();
            TimePrinter tp2 = new TimePrinter(3000, "Slow Guy");
            tp2.start();

        }
    }

    在本例中,我們可以看到一個簡單的程序,它按兩個不同的時間間隔(1 秒和 3 秒)在屏幕上顯示當前時間。這是通過創建兩個新線程來完成的,包括 main() 共三個線程。但是,因為有時要作為線程運行的類可能已經是某個類層次的一部分,所以就不能再按這種機制創建線程。雖然在同一個類中可以實現任意數量的接口,但 Java 編程語言只允許一個類有一個父類。同時,某些程序員避免從 Thread 類導出,因為它強加了類層次。對于這種情況,就要 runnable 接口。

    Runnable 接口
    此接口只有一個函數,run(),此函數必須由實現了此接口的類實現。但是,就運行這個類而論,其語義與前一個示例稍有不同。我們可以用 runnable 接口改寫前一個示例。(不同的部分用黑體表示。)

    創建兩個新線程而不強加類層次

    import java.util.*;

    class TimePrinter implements Runnable {
        int pauseTime;

        String name;

        public TimePrinter(int x, String n) {
            pauseTime = x;
            name = n;
        }

        public void run() {
            while (true) {
                try {
                    System.out.println(name + ":"
                            + new Date(System.currentTimeMillis()));
                    Thread.sleep(pauseTime);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }

        static public void main(String args[]) {
            Thread t1 = new Thread(new TimePrinter(1000, "Fast Guy"));
            t1.start();
            Thread t2 = new Thread(new TimePrinter(3000, "Slow Guy"));
            t2.start();

        }
    }

    請注意,當使用 runnable 接口時,您不能直接創建所需類的對象并運行它;必須從 Thread 類的一個實例內部運行它。許多程序員更喜歡 runnable 接口,因為從 Thread 類繼承會強加類層次。

    synchronized 關鍵字
    到目前為止,我們看到的示例都只是以非常簡單的方式來利用線程。只有最小的數據流,而且不會出現兩個線程訪問同一個對象的情況。但是,在大多數有用的程序中,線程之間通常有信息流。試考慮一個金融應用程序,它有一個 Account 對象,如下例中所示:

    一個銀行中的多項活動

    public class Account {
        String holderName;

        float amount;

        public Account(String name, float amt) {
            holderName = name;
            amount = amt;
        }

        public void deposit(float amt) {
            amount += amt;
        }

        public void withdraw(float amt) {
            amount -= amt;
        }

        public float checkBalance() {
            return amount;
        }
    }

    在此代碼樣例中潛伏著一個錯誤。如果此類用于單線程應用程序,不會有任何問題。但是,在多線程應用程序的情況中,不同的線程就有可能同時訪問同一個 Account 對象,比如說一個聯合帳戶的所有者在不同的 ATM 上同時進行訪問。在這種情況下,存入和支出就可能以這樣的方式發生:一個事務被另一個事務覆蓋。這種情況將是災難性的。但是,Java 編程語言提供了一種簡單的機制來防止發生這種覆蓋。每個對象在運行時都有一個關聯的鎖。這個鎖可通過為方法添加關鍵字 synchronized 來獲得。這樣,修訂過的 Account 對象(如下所示)將不會遭受像數據損壞這樣的錯誤:

    對一個銀行中的多項活動進行同步處理

    public class Account {
        String holderName;

        float amount;

        public Account(String name, float amt) {
            holderName = name;
            amount = amt;
        }

        public synchronized void deposit(float amt) {
            amount += amt;
        }

        public synchronized void withdraw(float amt) {
            amount -= amt;
        }

        public float checkBalance() {
            return amount;
        }
    }

    deposit() 和 withdraw() 函數都需要這個鎖來進行操作,所以當一個函數運行時,另一個函數就被阻塞。請注意,checkBalance() 未作更改,它嚴格是一個讀函數。因為 checkBalance() 未作同步處理,所以任何其他方法都不會阻塞它,它也不會阻塞任何其他方法,不管那些方法是否進行了同步處理。

    Java 編程語言中的高級多線程支持

    線程組
    線程是被個別創建的,但可以將它們歸類到線程組中,以便于調試和監視。只能在創建線程的同時將它與一個線程組相關聯。在使用大量線程的程序中,使用線程組組織線程可能很有幫助。可以將它們看作是計算機上的目錄和文件結構。

    線程間發信
    當線程在繼續執行前需要等待一個條件時,僅有 synchronized 關鍵字是不夠的。雖然 synchronized 關鍵字阻止并發更新一個對象,但它沒有實現線程間發信。Object 類為此提供了三個函數:wait()、notify() 和 notifyAll()。以全球氣候預測程序為例。這些程序通過將地球分為許多單元,在每個循環中,每個單元的計算都是隔離進行的,直到這些值趨于穩定,然后相鄰單元之間就會交換一些數據。所以,從本質上講,在每個循環中各個線程都必須等待所有線程完成各自的任務以后才能進入下一個循環。這個模型稱為屏蔽同步,下例說明了這個模型:

    屏蔽同步

    public class BSync {
        int totalThreads;

        int currentThreads;

        public BSync(int x) {
            totalThreads = x;
            currentThreads = 0;
        }

        public synchronized void waitForAll() {
            currentThreads++;
            if (currentThreads < totalThreads) {
                try {
                    wait();
                } catch (Exception e) {
                }
            } else {
                currentThreads = 0;
                notifyAll();
            }
        }
    }

    當對一個線程調用 wait() 時,該線程就被有效阻塞,只到另一個線程對同一個對象調用 notify() 或 notifyAll() 為止。因此,在前一個示例中,不同的線程在完成它們的工作以后將調用 waitForAll() 函數,最后一個線程將觸發 notifyAll() 函數,該函數將釋放所有的線程。第三個函數 notify() 只通知一個正在等待的線程,當對每次只能由一個線程使用的資源進行訪問限制時,這個函數很有用。但是,不可能預知哪個線程會獲得這個通知,因為這取決于 Java 虛擬機 (JVM) 調度算法。

    將 CPU 讓給另一個線程
    當線程放棄某個稀有的資源(如數據庫連接或網絡端口)時,它可能調用 yield() 函數臨時降低自己的優先級,以便某個其他線程能夠運行。

    守護線程
    有兩類線程:用戶線程和守護線程。用戶線程是那些完成有用工作的線程。守護線程是那些僅提供輔助功能的線程。Thread 類提供了 setDaemon() 函數。Java 程序將運行到所有用戶線程終止,然后它將破壞所有的守護線程。在 Java 虛擬機 (JVM) 中,即使在 main 結束以后,如果另一個用戶線程仍在運行,則程序仍然可以繼續運行。

    避免不提倡使用的方法
    不提倡使用的方法是為支持向后兼容性而保留的那些方法,它們在以后的版本中可能出現,也可能不出現。Java 多線程支持在版本 1.1 和版本 1.2 中做了重大修訂,stop()、suspend() 和 resume() 函數已不提倡使用。這些函數在 JVM 中可能引入微妙的錯誤。雖然函數名可能聽起來很誘人,但請抵制誘惑不要使用它們。

    調試線程化的程序
    在線程化的程序中,可能發生的某些常見而討厭的情況是死鎖、活鎖、內存損壞和資源耗盡。

    死鎖
    死鎖可能是多線程程序最常見的問題。當一個線程需要一個資源而另一個線程持有該資源的鎖時,就會發生死鎖。這種情況通常很難檢測。但是,解決方案卻相當好:在所有的線程中按相同的次序獲取所有資源鎖。例如,如果有四個資源 —A、B、C 和 D — 并且一個線程可能要獲取四個資源中任何一個資源的鎖,則請確保在獲取對 B 的鎖之前首先獲取對 A 的鎖,依此類推。如果“線程 1”希望獲取對 B 和 C 的鎖,而“線程 2”獲取了 A、C 和 D 的鎖,則這一技術可能導致阻塞,但它永遠不會在這四個鎖上造成死鎖。

    活鎖
    當一個線程忙于接受新任務以致它永遠沒有機會完成任何任務時,就會發生活鎖。這個線程最終將超出緩沖區并導致程序崩潰。試想一個秘書需要錄入一封信,但她一直在忙于接電話,所以這封信永遠不會被錄入。

    內存損壞
    如果明智地使用 synchronized 關鍵字,則完全可以避免內存錯誤這種氣死人的問題。

    資源耗盡
    某些系統資源是有限的,如文件描述符。多線程程序可能耗盡資源,因為每個線程都可能希望有一個這樣的資源。如果線程數相當大,或者某個資源的侯選線程數遠遠超過了可用的資源數,則最好使用資源池。一個最好的示例是數據庫連接池。只要線程需要使用一個數據庫連接,它就從池中取出一個,使用以后再將它返回池中。資源池也稱為資源庫。

    調試大量的線程
    有時一個程序因為有大量的線程在運行而極難調試。在這種情況下,下面的這個類可能會派上用場:

    public class Probe extends Thread {
        public Probe() {
        }

        public void run() {

            while (true) {
                Thread[] x = new Thread[100];
                Thread.enumerate(x);

                for (int i = 0; i < 100; i++) {
                    Thread t = x[i];
                    if (t == null)
                        break;
                    else
                        System.out.println(t.getName() + "\t" + t.getPriority()
                                + "\t" + t.isAlive() + "\t" + t.isDaemon());
                }
            }
        }
    }

    限制線程優先級和調度
    Java 線程模型涉及可以動態更改的線程優先級。本質上,線程的優先級是從 1 到 10 之間的一個數字,數字越大表明任務越緊急。JVM 標準首先調用優先級較高的線程,然后才調用優先級較低的線程。但是,該標準對具有相同優先級的線程的處理是隨機的。如何處理這些線程取決于基層的操作系統策略。在某些情況下,優先級相同的線程分時運行;在另一些情況下,線程將一直運行到結束。請記住,Java 支持 10 個優先級,基層操作系統支持的優先級可能要少得多,這樣會造成一些混亂。因此,只能將優先級作為一種很粗略的工具使用。最后的控制可以通過明智地使用 yield() 函數來完成。通常情況下,請不要依靠線程優先級來控制線程的狀態。

    小結
    本文說明了在 Java 程序中如何使用線程。像是否應該使用線程這樣的更重要的問題在很大程序上取決于手頭的應用程序。決定是否在應用程序中使用多線程的一種方法是,估計可以并行運行的代碼量。并記住以下幾點:

    使用多線程不會增加 CPU 的能力。但是如果使用 JVM 的本地線程實現,則不同的線程可以在不同的處理器上同時運行(在多 CPU 的機器中),從而使多 CPU 機器得到充分利用。
    如果應用程序是計算密集型的,并受 CPU 功能的制約,則只有多 CPU 機器能夠從更多的線程中受益。
    當應用程序必須等待緩慢的資源(如網絡連接或數據庫連接)時,或者當應用程序是非交互式的時,多線程通常是有利的。
    基于 Internet 的軟件有必要是多線程的;否則,用戶將感覺應用程序反映遲鈍。例如,當開發要支持大量客戶機的服務器時,多線程可以使編程較為容易。在這種情況下,每個線程可以為不同的客戶或客戶組服務,從而縮短了響應時間。

    某些程序員可能在 C 和其他語言中使用過線程,在那些語言中對線程沒有語言支持。這些程序員可能通常都被搞得對線程失去了信心。

    posted @ 2007-07-30 09:36 比特鼠 閱讀(209) | 評論 (0)編輯 收藏

    眾所周知, Java在從XML文件中裝載內容到內存過程中,不論用何種方式,IO操作的開銷都無可避免。本文嘗試比較dom4j中的XPP3和SAX兩種方式裝載XML文件的性能,以便將IO操作的開銷降到最小!

    package gz.lwm;

    import java.io.File;
    import org.apache.log4j.Logger;
    import org.dom4j.Document;
    import org.dom4j.DocumentHelper;
    import org.dom4j.io.SAXReader;
    import org.dom4j.io.XPP3Reader;

    public class TestDom4j {
     private static final Logger log = Logger.getLogger(TestDom4j.class);
     private static long bt; 
     
     public static void main(String[] args) {
      Document doc = DocumentHelper.createDocument();   
      //先運行getXmlSAX()
      bt = System.currentTimeMillis();
      String strXml = getXmlSAX("xml/test.xml");
      if(log.isDebugEnabled()){
       log.debug("\ngetXmlSAX() use time: " + (System.currentTimeMillis() - bt) + " millis\n");
      }

      //再運行getXmlXPP3()
      bt = System.currentTimeMillis();
      String s1 =getXmlXPP3("xml/test.xml");
      if(log.isDebugEnabled()){
       log.debug("\ngetXmlXPP3() use time: " + (System.currentTimeMillis() - bt) + " millis\n");
      }
      
      
     }
     
     public static String getXmlSAX(String xmlFile){
      String result = "";
      try {
       SAXReader reader = new SAXReader();
       Document document = reader.read(new File(xmlFile));
       result = document.asXML();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return result;
     }
     
     public static String getXmlXPP3(String xmlFile){
      String result = "";
      try {
       XPP3Reader reader = new XPP3Reader();
       Document document = reader.read(new File(xmlFile));
       result = document.asXML();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return result;
     }


     
    }

    有沒有這一句"Document doc = DocumentHelper.createDocument()",對性能的影響很大,特別是對大xml文件(盡管并沒有使用doc)

    另外, getXmlXSAX()和getXmlXPP3()運行的先后次序對性能的影響也很大!

    測試:
        在我的機器上,對一個100k左右的XML文件進行多次測試后的均值結果為:

        getXmlXPP3() use time: 265 millis
        ...
        getXmlXSAX() use time: 359 millis
        ...

    結論:
        通過比較,在讀取XML文件上,XPP3略為優于SAX!


    注意:

    要運行例子,classpath需包含:
    dom4j-1.6.1.jar
    jaxen-1.1-beta-10.jar
    log4j-1.2.9.jar
    pull-parser-2.1.10.jar
    xpp3-1.1.4c.jar


    參考:
    dom4j :  http://www.dom4j.org/
    XPP   :  http://www.extreme.indiana.edu/xgws/xsoap/xpp/

    posted @ 2007-05-19 00:39 比特鼠 閱讀(2509) | 評論 (0)編輯 收藏

       Namespace namespace ...

       //第一種方法
       Document doc = DocumentHelper.createDocument();
       Element root = doc.addElement("Root", namespace.getURI());
       Element eResultMessage = root.addElement("ResultMessage");

       結果為:
       <Root xmlns="http://aaaaaa"><ResultMessage>...</ResultMessage></Root>



       //第二種方法
       Document doc = DocumentHelper.createDocument();
       Element root = doc.addElement(("Root");
       root.add(namespace);
       Element eResultMessage = root.addElement("ResultMessage");
       
       結果為:
       <Root xmlns="
    http://aaaaaa"><ResultMessage xmlns="">...</ResultMessage></Root>

    posted @ 2007-05-17 21:08 比特鼠 閱讀(2659) | 評論 (0)編輯 收藏

    正則表達式語法 
     

    正則表達式是一種文本模式,包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱為“元字符”)。模式描述在搜索文本時要匹配的一個或多個字符串。

    正則表達式示例
     
    表達式  匹配 
    /^\s*$/
     匹配空行。
     
    /\d{2}-\d{5}/
     驗證由兩位數字、一個連字符再加 5 位數字組成的 ID 號。
     
    /<\s*(\S+)(\s[^>]*)?>[\s\S]*<\s*\/\1\s*>/
     匹配 HTML 標記。
     

    下表包含了元字符的完整列表以及它們在正則表達式上下文中的行為:

     
    字符  說明 
    \
     將下一字符標記為特殊字符、文本、反向引用或八進制轉義符。例如,“n”匹配字符“n”。“\n”匹配換行符。序列“\\”匹配“\”,“\(”匹配“(”。
     
    ^
     匹配輸入字符串開始的位置。如果設置了 RegExp 對象的 Multiline 屬性,^ 還會與“\n”或“\r”之后的位置匹配。
     
    $
     匹配輸入字符串結尾的位置。如果設置了 RegExp 對象的 Multiline 屬性,$ 還會與“\n”或“\r”之前的位置匹配。
     
    *
     零次或多次匹配前面的字符或子表達式。例如,zo* 匹配“z”和“zoo”。* 等效于 {0,}。
     
    +
     一次或多次匹配前面的字符或子表達式。例如,“zo+”與“zo”和“zoo”匹配,但與“z”不匹配。+ 等效于 {1,}。
     
    ?
     零次或一次匹配前面的字符或子表達式。例如,“do(es)?”匹配“do”或“does”中的“do”。? 等效于 {0,1}。
     
    {n}
     n 是非負整數。正好匹配 n 次。例如,“o{2}”與“Bob”中的“o”不匹配,但與“food”中的兩個“o”匹配。
     
    {n,}
     n 是非負整數。至少匹配 n 次。例如,“o{2,}”不匹配“Bob”中的“o”,而匹配“foooood”中的所有 o。“o{1,}”等效于“o+”。“o{0,}”等效于“o*”。
     
    {n,m}
     M 和 n 是非負整數,其中 n <= m。匹配至少 n 次,至多 m 次。例如,“o{1,3}”匹配“fooooood”中的頭三個 o。'o{0,1}' 等效于 'o?'。注意:您不能將空格插入逗號和數字之間。
     
    ?
     當此字符緊隨任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后時,匹配模式是“非貪心的”。“非貪心的”模式匹配搜索到的、盡可能短的字符串,而默認的“貪心的”模式匹配搜索到的、盡可能長的字符串。例如,在字符串“oooo”中,“o+?”只匹配單個“o”,而“o+”匹配所有“o”。
     
    .
     匹配除“\n”之外的任何單個字符。若要匹配包括“\n”在內的任意字符,請使用諸如“[\s\S]”之類的模式。
     
    (pattern)
     匹配 pattern 并捕獲該匹配的子表達式。可以使用 $0…$9 屬性從結果“匹配”集合中檢索捕獲的匹配。若要匹配括號字符 ( ),請使用“\(”或者“\)”。
     
    (?:pattern)
     匹配 pattern 但不捕獲該匹配的子表達式,即它是一個非捕獲匹配,不存儲供以后使用的匹配。這對于用“or”字符 (|) 組合模式部件的情況很有用。例如,'industr(?:y|ies) 是比 'industry|industries' 更經濟的表達式。
     
    (?=pattern)
     執行正向預測先行搜索的子表達式,該表達式匹配處于匹配 pattern 的字符串的起始點的字符串。它是一個非捕獲匹配,即不能捕獲供以后使用的匹配。例如,'Windows (?=95|98|NT|2000)' 匹配“Windows 2000”中的“Windows”,但不匹配“Windows 3.1”中的“Windows”。預測先行不占用字符,即發生匹配后,下一匹配的搜索緊隨上一匹配之后,而不是在組成預測先行的字符后。
     
    (?!pattern)
     執行反向預測先行搜索的子表達式,該表達式匹配不處于匹配 pattern 的字符串的起始點的搜索字符串。它是一個非捕獲匹配,即不能捕獲供以后使用的匹配。例如,'Windows (?!95|98|NT|2000)' 匹配“Windows 3.1”中的 “Windows”,但不匹配“Windows 2000”中的“Windows”。預測先行不占用字符,即發生匹配后,下一匹配的搜索緊隨上一匹配之后,而不是在組成預測先行的字符后。
     
    x|y
     匹配 x 或 y。例如,'z|food' 匹配“z”或“food”。'(z|f)ood' 匹配“zood”或“food”。
     
    [xyz]
     字符集。匹配包含的任一字符。例如,“[abc]”匹配“plain”中的“a”。
     
    [^xyz]
     反向字符集。匹配未包含的任何字符。例如,“[^abc]”匹配“plain”中的“p”。
     
    [a-z]
     字符范圍。匹配指定范圍內的任何字符。例如,“[a-z]”匹配“a”到“z”范圍內的任何小寫字母。
     
    [^a-z]
     反向范圍字符。匹配不在指定的范圍內的任何字符。例如,“[^a-z]”匹配任何不在“a”到“z”范圍內的任何字符。
     
    \b
     匹配一個字邊界,即字與空格間的位置。例如,“er\b”匹配“never”中的“er”,但不匹配“verb”中的“er”。
     
    \B
     非字邊界匹配。“er\B”匹配“verb”中的“er”,但不匹配“never”中的“er”。
     
    \cx
     匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回車符。x 的值必須在 A-Z 或 a-z 之間。如果不是這樣,則假定 c 就是“c”字符本身。
     
    \d
     數字字符匹配。等效于 [0-9]。
     
    \D
     非數字字符匹配。等效于 [^0-9]。
     
    \f
     換頁符匹配。等效于 \x0c 和 \cL。
     
    \n
     換行符匹配。等效于 \x0a 和 \cJ。
     
    \r
     匹配一個回車符。等效于 \x0d 和 \cM。
     
    \s
     匹配任何空白字符,包括空格、制表符、換頁符等。與 [ \f\n\r\t\v] 等效。
     
    \S
     匹配任何非空白字符。與 [^ \f\n\r\t\v] 等效。
     
    \t
     制表符匹配。與 \x09 和 \cI 等效。
     
    \v
     垂直制表符匹配。與 \x0b 和 \cK 等效。
     
    \w
     匹配任何字類字符,包括下劃線。與“[A-Za-z0-9_]”等效。
     
    \W
     與任何非單詞字符匹配。與“[^A-Za-z0-9_]”等效。
     
    \xn
     匹配 n,此處的 n 是一個十六進制轉義碼。十六進制轉義碼必須正好是兩位數長。例如,“\x41”匹配“A”。“\x041”與“\x04”&“1”等效。允許在正則表達式中使用 ASCII 代碼。
     
    \num
     匹配 num,此處的 num 是一個正整數。到捕獲匹配的反向引用。例如,“(.)\1”匹配兩個連續的相同字符。
     
    \n
     標識一個八進制轉義碼或反向引用。如果 \n 前面至少有 n 個捕獲子表達式,那么 n 是反向引用。否則,如果 n 是八進制數 (0-7),那么 n 是八進制轉義碼。
     
    \nm
     標識一個八進制轉義碼或反向引用。如果 \nm 前面至少有 nm 個捕獲子表達式,那么 nm 是反向引用。如果 \nm 前面至少有 n 個捕獲,則 n 是反向引用,后面跟有字符 m。如果兩種前面的情況都不存在,則 \nm 匹配八進制值 nm,其中 n 和 m 是八進制數字 (0-7)。
     
    \nml
     當 n 是八進制數 (0-3),m 和 l 是八進制數 (0-7) 時,匹配八進制轉義碼 nml。
     
    \un
     匹配 n,其中 n 是以四位十六進制數表示的 Unicode 字符。例如,\u00A9 匹配版權符號 (?)。
     

    posted @ 2007-05-17 10:48 比特鼠 閱讀(7536) | 評論 (0)編輯 收藏

    package com.sunrise.ocs.webservice.unicom.test;

    import java.io.File;
    import java.io.StringWriter;
    import java.util.HashMap;
    import java.util.Iterator;

    import javax.xml.parsers.DocumentBuilderFactory;

    import org.apache.log4j.Logger;
    import org.dom4j.Document;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    import org.dom4j.XPath;
    import org.dom4j.io.SAXReader;

    import com.sun.org.apache.xml.internal.serialize.OutputFormat;
    import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

    public class TestDom4j {
     private static final Logger log = Logger.getLogger(TestDom4j.class);

     private static long bt;

     public static void main(String[] args) {
      String strXml = "";
      int b = 0;
      String file1 = "xml/CreateUserRequest.xml";
      String file2 = "xml/CancelUserRequest.xml";
      if(b==0){
       bt = System.currentTimeMillis();
       strXml = xmlFile2String(file1);
       if (log.isDebugEnabled()) {
        log.debug("\nxmlFile2String() use time: "
          + (System.currentTimeMillis() - bt) + " millis\n");
       }
      }else{
       bt = System.currentTimeMillis();
       strXml = xmlFile2String2(file1);
       if (log.isDebugEnabled()) {
        log.debug("\nxmlFile2String2() use time: "
          + (System.currentTimeMillis() - bt) + " millis\n");
       }
      }

      if(b==0){
       bt = System.currentTimeMillis();
       findElement4XPath1(strXml);
       if (log.isDebugEnabled()) {
        log.debug("\nfindElement4XPath1() use time: "
          + (System.currentTimeMillis() - bt) + " millis\n");
       }
      }else{
       bt = System.currentTimeMillis();
       findElement4XPath2(strXml);
       if (log.isDebugEnabled()) {
        log.debug("\nfindElement4XPath2() use time: "
          + (System.currentTimeMillis() - bt) + " millis\n");
       } 
       
      }
     }

     public static void findElement4XPath1(String xml) {
      try {
       String str = delNamespace4Pattern(xml);
       Document doc = DocumentHelper.parseText(str);
       Element e = (Element) doc.selectSingleNode("http://CreateUserRequest/RequestMessage/MessageHeader");
       if (e != null) {
        Iterator iter = e.elementIterator();
        while (iter.hasNext()) {
         Element sub = (Element) iter.next();
         log.debug("\n" + sub.getText() + "\n");
        }
       }
       
       /* 讀取屬性的例子
       List childNodes = doc.selectNodes("http://Config/Child/ChildNode");
             for(Object obj:childNodes) {
                 Node childNode = (Node)obj;
                 String name = childNode.valueOf("@name"); //讀取屬性
                 String text = childNode.getText();
             }
             */

       
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
     public static void findElement4XPath2(String xml) {
      try {
       Document doc = DocumentHelper.parseText(xml);
       Element root = doc.getRootElement();
       
       HashMap map = new HashMap();
       map.put("tns", "   XPath x = doc.createXPath("http://tns:CreateUserRequest/tns:RequestMessage/tns:MessageHeader");
       x.setNamespaceURIs(map);
       
       Element e = (Element) x.selectSingleNode(doc);
       if (e != null) {
        Iterator iter = e.elementIterator();
        while (iter.hasNext()) {
         Element sub = (Element) iter.next();
         if (log.isDebugEnabled()) {
          log.debug("\n" + sub.getText() + "\n");
         }
        }
       }
      } catch (Exception e) {
       e.printStackTrace();
      }
     }

     public static Document xml2Document(String xml) {
      try {
       return DocumentHelper.parseText(xml);
      } catch (Exception e) {
       e.printStackTrace();
      }
      return null;
     }

     public static String xmlFile2String(String xmlFile) {
      try {
       return new SAXReader().read(new File(xmlFile)).asXML();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return null;
     }
     
     //讀取xml文件為xml串
     public static String xmlFile2String2(String xmlFile) {
      try {
       org.w3c.dom.Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile); 
       OutputFormat format = new OutputFormat(document);
       //format.setEncoding("UTF-8");
       StringWriter stringOut = new StringWriter();
       XMLSerializer serial = new XMLSerializer(stringOut, format);
       serial.asDOMSerializer();
       serial.serialize(document.getDocumentElement());
       return stringOut.toString();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return "";
     }
     
     
     public static String delNamespace4Pattern(String xml){
      String result = "";
      try {
       result = xml.replaceFirst("xmlns([^ ]*)=([^ ]*)http([^>^\"]*)\"", "");
      } catch (Exception e) {
       e.printStackTrace();
      }
      return result;
      
     }

     

    }

    posted @ 2007-05-17 10:46 比特鼠 閱讀(208) | 評論 (0)編輯 收藏

    package com.sunrise.ocs.webservice.unicom.test;

    import java.io.File;
    import java.io.StringReader;
    import java.io.StringWriter;

    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;

    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.xml.sax.InputSource;

    import com.sun.org.apache.xml.internal.serialize.OutputFormat;
    import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

    public class TestDom {
     
     //將xml串轉換為document
     public static Document xml2Document(String xml) {
      Document doc = null;
      try {
       DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
       doc = builder.parse(new InputSource(new StringReader(xml)));
      } catch (Exception e) {
       e.printStackTrace();
      }
      return doc;
     }
     
     //將xml文件串轉換為document
     public static Document xmlFile2Document(String xmlFile) {
      Document doc = null;
      try {
       DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
       doc = builder.parse(new File(xmlFile));
      } catch (Exception e) {
       e.printStackTrace();
      }
      return doc;
     }
     
     //刪除命名空間: xmlns="..."
     public static String delNamespace(String xml) {
      String result = xml;
      try {
       Document doc = xml2Document(xml);
       Element root = doc.getDocumentElement();
       root.removeAttribute("xmlns");
       result = asXml(doc);
      } catch (Exception e) {
       e.printStackTrace();
      }
      return result;
     }
     
     //將doc轉換為xml串
     public static String asXml(Document doc) {
      String strxml = "";
      try {
       OutputFormat format = new OutputFormat(doc);
       // format.setEncoding("UTF-8");
       StringWriter stringOut = new StringWriter();
       XMLSerializer serial = new XMLSerializer(stringOut, format);
       serial.asDOMSerializer();
       serial.serialize(doc.getDocumentElement());
       strxml = stringOut.toString();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return strxml;
     }
     
     //將node轉換為xml串
     public static String asXml(Node node, Document doc) {
      String strxml = "";
      try {
       OutputFormat format = new OutputFormat(doc);
       // format.setEncoding("UTF-8");
       StringWriter stringOut = new StringWriter();
       XMLSerializer serial = new XMLSerializer(stringOut, format);
       serial.asDOMSerializer();
       serial.serialize((Element)node);
       strxml = stringOut.toString();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return strxml;
     }
    }

    posted @ 2007-05-17 10:10 比特鼠 閱讀(283) | 評論 (0)編輯 收藏

    vi 是visual edit 的縮寫
    文本編輯器是所有計算機系統中最常用的一種工具。UNIX下的編輯器有ex,sed和vi等,其中,使用最為廣泛的是vi,而vi命令繁多,論壇里好像這方面的總結不多,以下稍做總結,以資共享!渴望更正和補充!

    進入vi的命令
    vi filename :打開或新建文件,并將光標置于第一行首
    vi +n filename :打開文件,并將光標置于第n行首
    vi + filename :打開文件,并將光標置于最后一行首
    vi +/pattern filename:打開文件,并將光標置于第一個與pattern匹配的串處
    vi -r filename :在上次正用vi編輯時發生系統崩潰,恢復filename
    vi filename....filename :打開多個文件,依次進行編輯

    移動光標類命令
    h :光標左移一個字符
    l :光標右移一個字符
    space:光標右移一個字符
    Backspace:光標左移一個字符
    k或Ctrl+p:光標上移一行
    j或Ctrl+n :光標下移一行
    Enter :光標下移一行
    w或W :光標右移一個字至字首
    b或B :光標左移一個字至字首
    e或E :光標右移一個字至字尾
    ) :光標移至句尾
    ( :光標移至句首
    }:光標移至段落開頭
    { :光標移至段落結尾
    nG:光標移至第n行首
    n+:光標下移n行
    n-:光標上移n行
    n$:光標移至第n行尾
    H :光標移至屏幕頂行
    M :光標移至屏幕中間行
    L :光標移至屏幕最后行
    0:(注意是數字零)光標移至當前行首
    $:光標移至當前行尾

    屏幕翻滾類命令
    Ctrl+u:向文件首翻半屏
    Ctrl+d:向文件尾翻半屏
    Ctrl+f:向文件尾翻一屏
    Ctrl+b;向文件首翻一屏
    nz:將第n行滾至屏幕頂部,不指定n時將當前行滾至屏幕頂部。

    插入文本類命令
    i :在光標前
    I :在當前行首
    a:光標后
    A:在當前行尾
    o:在當前行之下新開一行
    O:在當前行之上新開一行
    r:替換當前字符
    R:替換當前字符及其后的字符,直至按ESC鍵
    s:從當前光標位置處開始,以輸入的文本替代指定數目的字符
    S:刪除指定數目的行,并以所輸入文本代替之
    ncw或nCW:修改指定數目的字
    nCC:修改指定數目的行

    刪除命令
    ndw或ndW:刪除光標處開始及其后的n-1個字
    do:刪至行首
    d$:刪至行尾
    ndd:刪除當前行及其后n-1行
    x或X:刪除一個字符,x刪除光標后的,而X刪除光標前的
    Ctrl+u:刪除輸入方式下所輸入的文本

    搜索及替換命令
    /pattern:從光標開始處向文件尾搜索pattern
    ?pattern:從光標開始處向文件首搜索pattern
    n:在同一方向重復上一次搜索命令
    N:在反方向上重復上一次搜索命令
    :s/p1/p2/g:將當前行中所有p1均用p2替代
    :n1,n2s/p1/p2/g:將第n1至n2行中所有p1均用p2替代
    :g/p1/s//p2/g:將文件中所有p1均用p2替換

    選項設置
    all:列出所有選項設置情況
    term:設置終端類型
    ignorance:在搜索中忽略大小寫
    list:顯示制表位(Ctrl+I)和行尾標志($)
    number:顯示行號
    report:顯示由面向行的命令修改過的數目
    terse:顯示簡短的警告信息
    warn:在轉到別的文件時若沒保存當前文件則顯示NO write信息
    nomagic:允許在搜索模式中,使用前面不帶“\”的特殊字符
    nowrapscan:禁止vi在搜索到達文件兩端時,又從另一端開始
    mesg:允許vi顯示其他用戶用write寫到自己終端上的信息

    最后行方式命令
    :n1,n2 co n3:將n1行到n2行之間的內容拷貝到第n3行下
    :n1,n2 m n3:將n1行到n2行之間的內容移至到第n3行下
    :n1,n2 d :將n1行到n2行之間的內容刪除
    :w :保存當前文件
    :e filename:打開文件filename進行編輯
    :x:保存當前文件并退出
    :q:退出vi
    :q!:不保存文件并退出vi
    :!command:執行shell命令command
    :n1,n2 w!command:將文件中n1行至n2行的內容作為command的輸入并執行之,若不指定n1,n2,則表示將整個文件內容作為command的輸入
    :r!command:將命令command的輸出結果放到當前行

    寄存器操作
    "?nyy:將當前行及其下n行的內容保存到寄存器?中,其中?為一個字母,n為一個數字
    "?nyw:將當前行及其下n個字保存到寄存器?中,其中?為一個字母,n為一個數字
    "?nyl:將當前行及其下n個字符保存到寄存器?中,其中?為一個字母,n為一個數字
    "?p:取出寄存器?中的內容并將其放到光標位置處。這里?可以是一個字母,也可以是一個數字
    ndd:將當前行及其下共n行文本刪除,并將所刪內容放到1號刪除寄存器中。


    進入vi
    vi test
    離開vi
    :q! 離開vi,并放棄剛在緩沖區內編輯的內容。
       :wq 將緩沖區內的資料寫入磁盤中,并離開vi。
       :ZZ 同wq
    同wq
    :w 將緩沖區內的資料寫入磁盤中,但并不離開vi。
      :q 離開vi,若文件被修改過,則會被要求確認是否放棄修改的內容,此指令可與: w 配合使用。
    Vi 的操作模式
    Vi 提供兩種操作模式:
    輸入模式(insert mode)
    指令模式(command mode)
    當使用者進入vi后,既處于指令模式下,此刻鍵入任何字元皆被視為指令。

    輸入模式:a(append) 游標之后加入資料。
    A 該行之末加入資料
    i (insert) 游標之前加入資料
    I 該行之首加入資料
    o (open) 新增一行與該行之下供輸入資料
    O 新增一行與該行之上供輸入資料

    指令模式:B      移至該行第一個字符,若光標在該行第一字符則光標移至上一行第一字符。
       b    由游標所在位置之前一個字串的第一個字元
         cc 刪除整行,修改整行的內容。
         D      以行為單位,刪除游標在內后面的所有字符。
    db 刪除該行光標前字符
         dd 刪除該行
         de 刪除自光標開始后面的字符
         d加字符   刪除光標所在位置至字符之間的單
         E      移至該行最后字符,若光標在該行最后字符則光標移至下一行最后字符
     e      由游標所在位置至該字串的最后一個字元
         G 移至該檔案的最后一行 
         h 向前移一個字元
    j 向下移一個字元
    k 向上移一個字元
    0 移至該行之首
    M 移至視窗的中間那行
    L 移至視窗的最后一行
         l 向后移一個字符
    0 由游標所在位置該行的第一個字元
    nG 移至該檔案的第n行
    n+ 自游標所在位置向后移n行至該行的第一字符
    n- 自游標所在位置向前移n行至該行的第一字符
    R 進入取代狀態,直到《ESC》為止
    s 刪除游標所在字元,并進入取代模式直到《ESC》
    S 刪除游標所在之該行資料,并進入輸入模式直到《ESC》
    w 由游標所在位置之下一個字串的第一個字元
    x 刪除游標所在該字元。
    X 刪除游標所在之前一字元。
    r 用接于此指令之后的字元取代(replace)游標所在字元
    yy yank整行,使游標所在該行復制到記憶體緩沖區
    顯示該行之行號、檔案名稱、檔案中最末之行號、游標所在行號占
    總行號之百分比
    $ 由游標所在位置至該行的最后一個字元。
    ) 由游標所在位置至下一個句子的第一個字元。
    ( 由游標所在位置至該句子的第一個字元。
    {  由游標所在位置至該段落的最后一個字元。
    } 由游標所在位置至該段落的第一個字元

    yank和delete可將指定的資料復制到記憶體緩沖區,而藉有put指令可將緩沖區內的資料復制到熒幕上
    例如:搬移一行 :在該行執行dd
    游標移至目的地
    執行p
    復制一行 :在該行執行yy
    游標移至目的地
    執行p
    視窗移動:
    視窗往下卷一頁
    視窗往上卷一頁
    視窗往下卷半頁
    視窗往上卷半頁
    視窗往下卷一行
    視窗往上卷一行
    刪除、復制及修改指令介紹:
    d(delete)、c(change)和y(yank)這一類的指令在vi 中的指令格式為:
    operation+scope=command
    (運算子)(范圍)
    運算子:
    d 刪除指令。刪除資料,但會將刪除資料復制到記憶體緩沖區。
    y 將資料(字組、行列、句子或段落)復制到緩沖區。
    p 放置(put)指令,與d和y配合使用。可將最后delete或yank的資料放置于游標所在位置之行列下。
    c 修改(change)指令,類似delete于insert的組合。刪除一個字組、句子等資料,并插入新鍵入的




    posted @ 2007-05-15 11:33 比特鼠 閱讀(247) | 評論 (0)編輯 收藏

    1、使用JdbcTemplate的execute()方法執行SQL語句

    代碼

    2、如果是UPDATE或INSERT,可以用update()方法。
    代碼

    3、帶參數的更新
    代碼

    代碼

    4、使用JdbcTemplate進行查詢時,使用queryForXXX()等方法
    代碼

    代碼

    代碼

    代碼

    JdbcTemplate將我們使用的JDBC的流程封裝起來,包括了異常的捕捉、SQL的執行、查詢結果的轉換等等。spring大量使用Template Method模式來封裝固定流程的動作,XXXTemplate等類別都是基于這種方式的實現。
    除了大量使用Template Method來封裝一些底層的操作細節,spring也大量使用callback方式類回調相關類別的方法以提供JDBC相關類別的功能,使傳統的JDBC的使用者也能清楚了解spring所提供的相關封裝類別方法的使用。

    JDBC的PreparedStatement

    代碼

    代碼

    代碼

    在getUser(id)里面使用UserRowMapper

    代碼

    網上收集
    org.springframework.jdbc.core.PreparedStatementCreator 返回預編譯SQL 不能于Object[]一起用

    代碼

    1.增刪改
    org.springframework.jdbc.core.JdbcTemplate 類(必須指定數據源dataSource)
    代碼


    代碼

    org.springframework.jdbc.core.PreparedStatementSetter 接口 處理預編譯SQL
    代碼

    2.查詢JdbcTemplate.query(String,[Object[]/PreparedStatementSetter],RowMapper/RowCallbackHandler)
    org.springframework.jdbc.core.RowMapper 記錄映射接口 處理結果集
    代碼

    org.springframework.jdbc.core.RowCallbackHandler 記錄回調管理器接口 處理結果集
    代碼

    posted @ 2007-04-11 18:48 比特鼠 閱讀(516) | 評論 (0)編輯 收藏

    制作可執行的JAR文件包及jar命令詳解


    常常在網上看到有人詢問:如何把 java 程序編譯成 .exe 文件。通常回答只有兩種,一種是制作一個可執行的 JAR 文件包,然后就可以像.chm 文檔一樣雙擊運行了;而另一種是使用 JET 來進行 編譯。但是 JET 是要用錢買的,而且據說 JET 也不是能把所有的 Java 程序都編譯成執行文件,性能也要打些折扣。所以,使用制作可執行 JAR 文件包的方法就是最佳選擇了,何況它還能保持 Java 的跨平臺特性。 

    下面就來看看什么是 JAR 文件包吧: 

    1. JAR 文件包 

    JAR 文件就是 Java Archive File,顧名思意,它的應用是與 Java 息息相關的,是 Java 的一種文檔格式。JAR 文件非常類似 ZIP 文件——準確的說,它就是 ZIP 文件,所以叫它文件包。JAR 文件與 ZIP 文件唯一的區別就是在 JAR 文件的內容中,包含了一個 META-INF/MANIFEST.MF 文件,這個文件是在生成 JAR 文件的時候自動創建的。舉個例子,如果我們具有如下目錄結構的一些文件: 

      == 

      `-- test 

        `-- Test.class 

    把它壓縮成 ZIP 文件 test.zip,則這個 ZIP 文件的內部目錄結構為: 

      test.zip 

      `-- test 

        `-- Test.class 

    如果我們使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar,則這個 JAR 文件的內部目錄結構為: 

      test.jar 

      |-- META-INF 

      |  `-- MANIFEST.MF 

      `-- test 

        `--Test.class 

    2. 創建可執行的 JAR 文件包 

    制作一個可執行的 JAR 文件包來發布你的程序是 JAR 文件包最典型的用法。 

    Java 程序是由若干個 .class 文件組成的。這些 .class 文件必須根據它們所屬的包不同而分級分目錄存放;運行前需要把所有用到的包的根目錄指定給 CLASSPATH 環境變量或者 java 命令的 -cp 參數;運行時還要到控制臺下去使用 java 命令來運行,如果需要直接雙擊運行必須寫 Windows 的批處理文件 (.bat) 或者 Linux 的 Shell 程序。因此,許多人說,Java 是一種方便開發者苦了用戶的程序設計語言。 

    其實不然,如果開發者能夠制作一個可執行的 JAR 文件包交給用戶,那么用戶使用起來就方便了。在 Windows 下安裝 JRE (Java Runtime Environment) 的時候,安裝文件會將 .jar 文件映射給 javaw.exe 打開。那么,對于一個可執行的 JAR 文件包,用戶只需要雙擊它就可以運行程序了,和閱讀 .chm 文檔一樣方便 (.chm 文檔默認是由 hh.exe 打開的)。那么,現在的關鍵,就是如何來創建這個可執行的 JAR 文件包。 

    創建可執行的 JAR 文件包,需要使用帶 cvfm 參數的 jar 命令,同樣以上述 test 目錄為例,命令如下: 

    jar cvfm test.jar manifest.mf test 

    這里 test.jar 和 manifest.mf 兩個文件,分別是對應的參數 f 和 m,其重頭戲在 manifest.mf。因為要創建可執行的 JAR 文件包,光靠指定一個 manifest.mf 文件是不夠的,因為 MANIFEST 是 JAR 文件包的特征,可執行的 JAR 文件包和不可執行的 JAR 文件包都包含 MANIFEST。關鍵在于可執行 JAR 文件包的 MANIFEST,其內容包含了 Main-Class 一項。這在 MANIFEST 中書寫格式如下: 

    Main-Class: 可執行主類全名(包含包名) 

    例如,假設上例中的 Test.class 是屬于 test 包的,而且是可執行的類 (定義了 public static void main(String[]) 方法),那么這個 manifest.mf 可以編輯如下: 

    Main-Class: test.Test <回車>; 

    這個 manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且該行以一個回車符結束即可。創建了 manifest.mf 文件之后,我們的目錄結構變為: 

      == 

      |-- test 

      |  `-- Test.class 

      `-- manifest.mf 

    這時候,需要到 test 目錄的上級目錄中去使用 jar 命令來創建 JAR 文件包。也就是在目錄樹中使用“==”表示的那個目錄中,使用如下命令: 

    jar cvfm test.jar manifest.mf test 

    之后在“==”目錄中創建了 test.jar,這個 test.jar 就是執行的 JAR 文件包。運行時只需要使用 java -jar test.jar 命令即可。 

    需要注意的是,創建的 JAR 文件包中需要包含完整的、與 Java 程序的包結構對應的目錄結構,就像上例一樣。而 Main-Class 指定的類,也必須是完整的、包含包路徑的類名,如上例的 test.Test;而且在沒有打成 JAR 文件包之前可以使用 java <類名>; 來運行這個類,即在上例中 java test.Test 是可以正確運行的 (當然要在 CLASSPATH 正確的情況下)。 

    3. jar 命令詳解 

    jar 是隨 JDK 安裝的,在 JDK 安裝目錄下的 bin 目錄中,Windows 下文件名為 jar.exe,Linux 下文件名為 jar。它的運行需要用到 JDK 安裝目錄下 lib 目錄中的 tools.jar 文件。不過我們除了安裝 JDK 什么也不需要做,因為 SUN 已經幫我們做好了。我們甚至不需要將 tools.jar 放到 CLASSPATH 中。 

    使用不帶任何的 jar 命令我們可以看到 jar 命令的用法如下: 

    jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目錄] 文件名 ... 

    其中 {ctxu} 是 jar 命令的子命令,每次 jar 命令只能包含 ctxu 中的一個,它們分別表示: 

    -c 創建新的 JAR 文件包 

    -t 列出 JAR 文件包的內容列表 

    -x 展開 JAR 文件包的指定文件或者所有文件 

    -u 更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中) 

    [vfm0M] 中的選項可以任選,也可以不選,它們是 jar 命令的選項參數 

    -v 生成詳細報告并打印到標準輸出 

    -f 指定 JAR 文件名,通常這個參數是必須的 

    -m 指定需要包含的 MANIFEST 清單文件 

    -0 只存儲,不壓縮,這樣產生的 JAR 文件包會比不用該參數產生的體積大,但速度更快 

    -M 不產生所有項的清單(MANIFEST〕文件,此參數會忽略 -m 參數 

    [jar-文件] 即需要生成、查看、更新或者解開的 JAR 文件包,它是 -f 參數的附屬參數 

    [manifest-文件] 即 MANIFEST 清單文件,它是 -m 參數的附屬參數 

    [-C 目錄] 表示轉到指定目錄下去執行這個 jar 命令的操作。它相當于先使用 cd 命令轉該目錄下再執行不帶 -C 參數的 jar 命令,它只能在創建和更新 JAR 文件包的時候可用。   

    文件名 ... 指定一個文件/目錄列表,這些文件/目錄就是要添加到 JAR 文件包中的文件/目錄。如果指定了目錄,那么 jar 命令打包的時候會自動把該目錄中的所有文件和子目錄打入包中。 

    下面舉一些例子來說明 jar 命令的用法: 

    1) jar cf test.jar test 

    該命令沒有執行過程的顯示,執行結果是在當前目錄生成了 test.jar 文件。如果當前目錄已經存在 test.jar,那么該文件將被覆蓋。 

    2) jar cvf test.jar test 

    該命令與上例中的結果相同,但是由于 v 參數的作用,顯示出了打包過程,如下: 

    標明清單(manifest) 

    增加:test/(讀入= 0) (寫出= 0)(存儲了 0%) 

    增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%) 

    3) jar cvfM test.jar test 

    該命令與 2) 結果類似,但在生成的 test.jar 中沒有包含 META-INF/MANIFEST 文件,打包過程的信息也略有差別: 

    增加:test/(讀入= 0) (寫出= 0)(存儲了 0%) 

    增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%) 

    4) jar cvfm test.jar manifest.mf test 

    運行結果與 2) 相似,顯示信息也相同,只是生成 JAR 包中的 META-INF/MANIFEST 內容不同,是包含了 manifest.mf 的內容 

    5) jar tf test.jar 

    在 test.jar 已經存在的情況下,可以查看 test.jar 中的內容,如對于 2) 和 3) 生成的 test.jar 分別應該此命令,結果如下; 

    對于 2) 

    META-INF/ 

    META-INF/MANIFEST.MF 

    test/ 

    test/Test.class 

    對于 3) 

    test/ 

    test/Test.class 

    6) jar tvf test.jar 

    除顯示 5) 中顯示的內容外,還包括包內文件的詳細信息,如: 

    0 Wed Jun 19 15:39:06 GMT 2002 META-INF/ 

    86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF 

    0 Wed Jun 19 15:33:04 GMT 2002 test/ 

    7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class 

    7) jar xf test.jar 

    解開 test.jar 到當前目錄,不顯示任何信息,對于 2) 生成的 test.jar,解開后的目錄結構如下: 

      == 

      |-- META-INF 

      |  `-- MANIFEST 

      `-- test 

        `--Test.class 

    8) jar xvf test.jar 

    運行結果與 7) 相同,對于解壓過程有詳細信息顯示,如: 

    創建:META-INF/ 

    展開:META-INF/MANIFEST.MF 

    創建:test/ 

    展開:test/Test.class 

    9) jar uf test.jar manifest.mf 

    在 test.jar 中添加了文件 manifest.mf,此使用 jar tf 來查看 test.jar 可以發現 test.jar 中比原來多了一個 manifest。這里順便提一下,如果使用 -m 參數并指定 manifest.mf 文件,那么 manifest.mf 是作為清單文件 MANIFEST 來使用的,它的內容會被添加到 MANIFEST 中;但是,如果作為一般文件添加到 JAR 文件包中,它跟一般文件無異。 

    10) jar uvf test.jar manifest.mf 

    與 9) 結果相同,同時有詳細信息顯示,如: 

    增加:manifest.mf(讀入= 17) (寫出= 19)(壓縮了 -11%) 

    4. 關于 JAR 文件包的一些技巧 

    1) 使用 unzip 來解壓 JAR 文件 

    在介紹 JAR 文件的時候就已經說過了,JAR 文件實際上就是 ZIP 文件,所以可以使用常見的一些解壓 ZIP 文件的工具來解壓 JAR 文件,如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等來解壓是因為它們解壓比較直觀,方便。而使用 unzip,則是因為它解壓時可以使用 -d 參數指定目標目錄。 

    在解壓一個 JAR 文件的時候是不能使用 jar 的 -C 參數來指定解壓的目標的,因為 -C 參數只在創建或者更新包的時候可用。那么需要將文件解壓到某個指定目錄下的時候就需要先將這具 JAR 文件拷貝到目標目錄下,再進行解壓,比較麻煩。如果使用 unzip,就不需要這么麻煩了,只需要指定一個 -d 參數即可。如: 

    unzip test.jar -d dest/ 

    2) 使用 WinZip 或者 WinRAR 等工具創建 JAR 文件 

    上面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件,所以,只需要使用 WinZip、WinRAR 等工具創建所需要 ZIP 壓縮包,再往這個 ZIP 壓縮包中添加一個包含 MANIFEST 文件的 META-INF 目錄即可。對于使用 jar 命令的 -m 參數指定清單文件的情況,只需要將這個 MANIFEST 按需要修改即可。 

    3) 使用 jar 命令創建 ZIP 文件 

    有些 Linux 下提供了 unzip 命令,但沒有 zip 命令,所以需要可以對 ZIP 文件進行解壓,即不能創建 ZIP 文件。如要創建一個 ZIP 文件,使用帶 -M 參數的 jar 命令即可,因為 -M 參數表示制作 JAR 包的時候不添加 MANIFEST 清單,那么只需要在指定目標 JAR 文件的地方將 .jar 擴展名改為 .zip 擴展名,創建的就是一個不折不扣的 ZIP 文件了,如將上一節的第 3) 個例子略作改動: 

    jar cvfM test.zip test
    posted @ 2007-04-11 18:19 比特鼠 閱讀(327) | 評論 (1)編輯 收藏

     

    import java.io.File;

    public class Test {
        
    public static void main(String[] args) {
             System.out.println(
    "1:"+Thread.currentThread().getContextClassLoader().getResource(""));     

              System.out.println(
    "2:"+Test.class.getClassLoader().getResource(""));        

              System.out.println(
    "3:"+ClassLoader.getSystemResource(""));        
              System.out.println(
    "4:"+Test.class.getResource(""));        
              System.out.println(
    "5:"+Test.class.getResource("/")); //Class文件所在路徑  
              System.out.println("6:"+new File("").getAbsolutePath());        
              System.out.println(
    "7:"+System.getProperty("user.dir"));  
              
              String s 
    = ClassLoader.getSystemResource("").getPath();
              System.out.println(s.substring(
    1));
              System.out.println(s.substring(
    1).substring(0, s.lastIndexOf("/classes")));

        }

    }
    posted @ 2007-04-04 16:49 比特鼠 閱讀(170) | 評論 (0)編輯 收藏

    dom4j 直接往Element中加入符合格式的xml串!

    下面的代碼直接往root元素插入符合格式的xml串:

    String strXml = "<aaa><bbb></bbb><ccc></ccc></aaa>";
    Document doc = DocumentHelper.createDocument();
    Element??root = doc.getRootElement();
    root.add(DocumentHelper.parseText(strXml).getRootElement());
    posted @ 2007-03-27 16:20 比特鼠 閱讀(485) | 評論 (1)編輯 收藏

    ?public long algo(){
    ????int a = 0;
    ????String b = null;
    ????long st = System.currentTimeMillis();
    ????for (int i = 0; i < 2000000; i++){
    ??????b = Integer.toString(a);
    ????}
    ????long et = System.currentTimeMillis();
    ????return (et - st);
    ??}
    posted @ 2007-03-27 15:11 比特鼠 閱讀(1423) | 評論 (1)編輯 收藏

    玩轉 XPath 和缺省命名空間(Default Namespaces)

    原文出自:http://www.edankert.com/defaultnamespaces.html
    翻譯文出自:http://wakan.blog.51cto.com/blog/59583/7220



    諸如“為什么用 XPath 的表達式進行查詢,卻沒有返回所期望的結果?”的問題通常都與命名空間(NameSpace)有關,而且絕大多數是與缺省命名空間(Default Namespace)有關。本文試圖解釋這個問題并針對三種流行的 XPath 實現給出解決方法:Jaxen、JAXP XPPathFactory 以及 XSLT。
    內容列表
    問題描述
    “前綴-命名空間”映射
    Jaxen 和 Dom4J
    Jaxen 和 XOM
    Jaxen 和 JDOM
    JAXP XPathFactory
    XSLT
    結束語
    資源


    問題描述
    看下述 XML:
    <catalog>
    ? <cd>
    ??? <artist>Sufjan Stevens</artist>
    ??? <title>Illinois</title>
    ??? <src>http://www.sufjan.com/</src>
    ? </cd>
    ? <cd>
    ??? <artist>Stoat</artist>
    ??? <title>Future come and get me</title>
    ??? <src>http://www.stoatmusic.com/</src>
    ? </cd>
    ? <cd>
    ??? <artist>The White Stripes</artist>
    ??? <title>Get behind me satan</title>
    ??? <src>http://www.whitestripes.com/</src>
    ? </cd>
    </catalog>

    ??? 你可以使用“//cd”來得到沒有在任何命名空間中定義的“cd”節點。?


    ??? 現在讓我們來改造這個 XML,讓它的所有元素都屬于 'http://www.edankert.com/examples/' 命名空間中。
    ?
    ??? 為了避免在每個不同的元素前都要加個前綴,我們在根元素上定義通常所說的缺省命名空間。改造后的 XML 如下:
    ?
    <catalog xmlns="
    http://www.edankert.com/examples/ ">
    ? <cd>
    ??? <artist>Sufjan Stevens</artist>
    ??? <title>Illinois</title>
    ??? <src>http://www.sufjan.com/</src>
    ? </cd>
    ? <cd>
    ??? <artist>Stoat</artist>
    ??? <title>Future come and get me</title>
    ??? <src>http://www.stoatmusic.com/</src>
    ? </cd>
    ? <cd>
    ??? <artist>The White Stripes</artist>
    ??? <title>Get behind me satan</title>
    ??? <src>http://www.whitestripes.com/</src>
    ? </cd>
    </catalog>

    ??? 當我們使用與上文相同的 XPath “//cd”,將得不到任何元素。這是因為指定的 XPath 返回的是所有不屬于任何命名空間的“cd”節點,而本例中,所有的“cd”元素都屬于缺省的命名空間“http://www.edankert.com/examples/”。


    “前綴-命名空間”映射
    ??? 為了取出命名空間“http://www.edankert.com/examples/”中的所有“cd”元素,我們需要對 XPath 表達式做一些額外的工作。
    ?
    ??? 為了解決這個問題,XPath 規范允許我們使用 QName 來指定元素或者屬性。QName 可以是元素的直接名稱(形如“element”),或者包含一個前綴(形如“pre:element”)。這個前綴需要映射到一個命名空間的 URI 上。例如,如果把“pre”前綴映射到“http://www.edankert.com/test”上,則通過“pre:element”可以查找出屬于命名空間“http://www.edankert.com/test”的所有 “element”元素。
    ?
    ??? 在本例中,我們把“edx”映射到“'http://www.edankert.com/examples/”命名空間上。通過 XPath“//edx:cd”就可以查找出屬于“'http://www.edankert.com/examples/”命名空間的所有“cd”元素。?
    ?
    ??? XPath 處理器允許設置“前綴-命名空間”的映射,但是,如何去映射,卻要依賴于具體的實現。下文舉例說明 Jaxen (JDOM/dom4j/XOM)、JAXP 以及 XSLT 中是如何進行“前綴-命名空間”的映射的。

    Jaxen 和 Dom4J
    ??? 下述代碼從文件系統讀入一個 XML 文件到 org.dom4j.Document 對象中,并且在 Document 中查找屬于“http://www.edankert.com/examples/”命名空間的所有“cd”元素。
    ?
    try {
    ? SAXReader reader = new SAXReader();
    ? Document document = reader.read( "file:catalog.xml");
    ?
    ? HashMap map = new HashMap();
    ? map.put( "edx", "
    http://www.edankert.com/examples/ ");
    ?
    ? XPath xpath = new Dom4jXPath( "http://edx:cd");
    ? xpath.setNamespaceContext( new SimpleNamespaceContext( map));
    ?
    ? List nodes = xpath.selectNodes( document);
    ?
    ? ...
    ?
    } catch ( JaxenException e) { // An error occurred parsing or executing the XPath ... } catch ( DocumentException e) {
    ? // the document is not well-formed.
    ? ...
    }
    ??? 第一步,創建一個 SAXReader,用來從文件系統中讀取“catalog.xml”并創建一個特定于 Dom4j 的 Document 對象。

    ??? 第二步,對于所有 Jaxen 實現都一樣,就是創建一個 HashMap 對象,用于保存“前綴-命名空間的 URI”的映射。
    ?
    ??? 為了能通過 Dom4j 使用 Jaxen 的 XPath 功能,需要創建一個與 Dom4j 相關的 XPath 對象:Dom4jXPath。創建方法是把 XPath 的表達式(即“//edx:cd”)傳給 Dom4jXPath 的構造方法。
    ?
    ??? 現在,我們已經創建了 XPath 對象,接下來可以把“前綴-命名空間”的映射表傳遞給 XPath 引擎:把這個 HashMap 映射表用 SimpleNamespaceContext 包裝起來。SimpleNamespaceContext 是 Jaxen 的 NamespaceContext 接口的默認實現類。
    ?
    ??? 最后一步就是調用 XPath 對象的 selectNodes() 方法進行查找。并把完整的 Dom4j? Document 對象作為參數傳遞進去。實際上,Document 中的任何結點都可以作為參數。

    Jaxen 和 XOM
    ??? XOM 是基于簡單的 Java DOM APIs 之上的最新工具,它的設計初衷是提供簡單和易學易用的接口。
    ?
    try {
    ? Builder builder = new Builder();
    ? Document document = builder.build( "file:catalog.xml");
    ?
    ? HashMap map = new HashMap();
    ? map.put( "edx", "
    http://www.edankert.com/examples/ ");
    ?
    ? XPath xpath = new XOMXPath( "http://edx:cd");
    ? xpath.setNamespaceContext( new SimpleNamespaceContext( map));
    ?
    ? List nodes = xpath.selectNodes( document);
    ?
    ? ...
    ?
    } catch ( JaxenException e) { // An error occurred parsing or executing the XPath ... } catch ( IOException e) {
    ? // An error occurred opening the document
    ? ...
    } catch ( ParsingException e) {
    ? // An error occurred parsing the document
    ? ...
    }

    ?
    ??? 我們需要創建一個 Builder 對象,從文件系統中讀取“catalog.xml”文件,并創建出與 XOM 相關的 Document 對象。
    ?
    ??? 下一步創建出包含了“前綴-命名空間”映射關系的 HashMap 對象。
    ?
    ??? 我們需要創建一個特定于 XOM 的 XPath 對象:XOMXPath。創建方法是把 XPath 表達式傳遞給構造方法,然后就可以通過 XOM 使用 Jaxen 的 XPath 功能了。
    ?
    ??? 創建完 XPath 對象后,同樣,我們把“前綴-命名空間”的映射表用 SimpleNamespaceContext 對象封裝后,傳遞給 XPath 引擎。
    ?
    ??? 最后調用 XPath 對象的“selectNodes()”方法進行查找,把 XOM Document 對象作為本方法的參數。
    Jaxen 和 JDOM
    ??? JDOM 是第一個提供簡單的 XML 訪問 API 的工具。
    ?
    try {
    ? SAXBuilder builder = new SAXBuilder();
    ? Document document = builder.build( "file:catalog.xml");
    ?
    ? HashMap map = new HashMap();
    ? map.put( "edx", "
    http://www.edankert.com/examples/ ");
    ?
    ? XPath xpath = new JDOMXPath( "http://edx:cd");
    ? xpath.setNamespaceContext( new SimpleNamespaceContext( map));
    ?
    ? List nodes = xpath.selectNodes( document);
    ?
    ? ...
    ?
    } catch ( JaxenException e) { // An error occurred parsing or executing the XPath ... } catch ( IOException e) {
    ? // An error occurred opening the document
    ? ...
    } catch ( JDOMException e) {
    ? // An error occurred parsing the document
    ? ...
    }

    ?
    ??? 首先,通過 SAXBuilder 創建了一個特定于 JDom 的 Document 對象。
    ?
    ??? 接著創建一個特定于 JDOM 的 XPath 對象:JDOMXPath。
    ?
    ??? 然后,把“前綴-命名空間”的映射表(HashMap)用 SimpleNamespaceContext 對象封裝起來,傳遞給 XPath 引擎。
    ?
    ??? 最后調用 XPath 對象的“selectNodes()”方法來進行查找,并把 JDOM 的 Document 對象作為本方法的輸入參數。
    JAXP XPathFactory
    ??? 從 1.3 版起, JAXP 還提供了一種在 XML Object Models 上進行查詢的通用機制。
    ?
    try {
    ?DocumentBuilderFactory domFactory =DocumentBuilderFactory.newInstance();
    ? domFactory.setNamespaceAware( true);
    ?
    ?DocumentBuilder builder = domFactory.newDocumentBuilder();Document document = builder.parse( new InputSource( "file:catalog.xml"));
    ?
    ?XPathFactory factory =XPathFactory.newInstance();
    ?XPath xpath = factory.newXPath();
    ? xpath.setNamespaceContext( new NamespaceContext() {
    ??? public String getNamespaceURI(String prefix) {
    ????? if ( prefix.equals( "edx")) {
    ??????? return "
    http://www.edankert.com/examples/ ";
    ????? } else if ...
    ??????? ...
    ????? }
    ?????
    ????? return XPathConstants.NULL_NS_URI;
    ??? }
    ?
    ??? public String getPrefix(String namespaceURI) {
    ????? if ( namespaceURI.equals( "
    http://www.edankert.com/examples/ ")) {
    ??????? return "edx";
    ????? } else if ...
    ??????? ...
    ????? }?
    ???
    ????? return null;
    ??? }
    ?
    ??? public Iterator getPrefixes(String namespaceURI) {
    ???? ArrayList list = new ArrayList();
    ???
    ????? if ( namespaceURI.equals( "
    http://www.edankert.com/examples/ ")) {
    ??????? list.add( "edx");
    ????? } else if ...
    ??????? ...
    ????? }
    ???
    ????? return list.iterator();
    ??? }
    ? });
    ?
    ?Object nodes = xpath.evaluate( "http://edx:cd", document.getDocumentElement(),
    ??????????????????????????????? XPathConstants.NODESET);
    ?
    ? ...
    ?
    } catch (ParserConfigurationException e) {
    ? ...
    } catch (XPathExpressionException e) {
    ? ...
    } catch (SAXException e) {
    ? ...
    } catch (IOException e) {
    ? ...
    }

    ??? 首先用 JAXP 的 DocumentBuilderFactory 創建一個org.w3c.dom.Document 對象,確保啟用了 namespace 處理功能。
    ?
    ??? 現在可以通過 XPathFactory 來創建 XPath 對象,并通過 XPath 對象對文檔進行查詢。
    ?
    ??? 為了創建“前綴-命名空間”映射并傳遞給 XPath 引擎,我們需要實現 NamespaceContext 接口,該接口目前還沒有默認實現類。這就意味著要實現 getNamespaceURI、getPrefix 和getPrefixes 方法,并確保這些方法能返回正確的值,包括“xmlns”和“xml”前綴所對應的命名空間的 URI 值。
    ?
    ??? 把我們自己實現的 NamespaceContext 對象傳遞給 XPath 引擎后,就可以通過 evaluate 方法來查詢 XPath 表達式所對應的元素:使用上文中提到的 XPath 表達式,并使用 Document 的根節點作為輸入入參數,并接收一個 NodeList 對象作為返回結果。
    XSLT
    ??? XPath 設計的初衷是用于 XSLT。這也許能解釋“為什么在 XSLT 中定義命名空間的前綴是一件很平常的事”(也許因為 XSLT 也是一個 XML 名詞的緣故吧)。
    ?
    <xsl:stylesheet version="1.1" xmlns:xsl="
    http://www.w3.org/1999/XSL/Transform ">
    ? <xsl:template match="http://edx:cd" xmlns:edx="
    http://www.edankert.com/examples/ ">
    ??? <xsl:apply-templates/>
    ? </xsl:template>
    </xsl:stylesheet>
    ?
    ??? 只需要使用 XML 本身的機制,簡單地為 edx 前綴賦予一個命名空間的 URI 值。
    ?
    ??? 通過與我們的 XPath 表達式“//edx:cd”相匹配的 xsl:template,能得到與上文其他例子相同的輸出結果。

    結束語
    ??? 為了在(缺省)命名空間上使用 XPath 表達式,我們需要指定一個“前綴-命名空間”映射。正如我們所看到的,具體使用什么樣的前綴名稱,是無關緊要的。
    ?
    ??? 同樣的方法,也可以用于查詢那些用其他前綴修飾的元素。這意味著上面的例子對下述 XML 也有效。下述 XML 沒有使用缺省命名空間,而是使用了 examples 作命名空間的前綴:
    ?
    <examples:catalog xmlns:examples="
    http://www.edankert.com/examples/ ">
    ? <examples:cd>
    ??? <examples:artist>Sufjan Stevens</examples:artist>
    ??? <examples:title>Illinois</examples:title>
    ??? <examples:src>http://www.sufjan.com/</examples:src>
    ? </examples:cd>
    ? <examples:cd>
    ??? <examples:artist>Stoat</examples:artist>
    ??? <examples:title>Future come and get me</examples:title>
    ??? <examples:src>http://www.stoatmusic.com/</examples:src>
    ? </examples:cd>
    ? <examples:cd>
    ??? <examples:artist>The White Stripes</examples:artist>
    ??? <examples:title>Get behind me satan</examples:title>
    ??? <examples:src>http://www.whitestripes.com/</examples:src>
    ? </examples:cd>
    </examples:catalog>

    ?
    ??? 使用“//edx:cd”作為 XPath 表達式,使用與前文例子相同的“前綴-命名空間”映射,在這個 XML 上同樣能查詢出屬于“http://www.edankert.com/examples/”命名空間的所有“cd”元素。
    資源
    Extensible Markup Language (XML) 1.0 (Third Edition)
    http://www.w3.org/TR/REC-xml/
    Namespaces in XML
    http://www.w3.org/TR/REC-xml-names/
    XML Path Language (XPath) Version 1.0
    http://www.w3.org/TR/xpath
    XSL Transformations (XSLT) Version 1.0
    http://www.w3.org/TR/xslt
    dom4j
    http://www.dom4j.org/
    XOM
    http://www.xom.nu/
    JDOM
    http://www.jdom.org/
    Jaxen
    http://www.jaxen.org/
    Java 5.0
    http://java.sun.com/j2se/1.5.0/

    posted @ 2007-03-21 10:13 比特鼠 閱讀(1722) | 評論 (1)編輯 收藏

    spring事務探索

    原文出處:
    http://www.javaeye.com/topic/11190

    spring自建事務管理模塊。而且這個事務管理是一個抽象設計,可以應用到很多場合,包括普通的DataSource,jta,jms和hibernate上。

    要正確使用spring的事務,首先需要了解spring在事務設計上的一些概念
    統觀spring事務,圍繞著兩個核心PlatformTransactionManager和TransactionStatus

    PlatformTransactionManager直譯過來就是平臺相關事務,這里的平臺指的是“事務源”,包括剛才我說的DataSource,jta等等。這些無一不是一個事務源。廣義的說,凡是可以完成事務性操作的對象,都可以設計出相對應的PlatformTransactionManager,只要這個事務源支持commit,rollback和getTransaction語意。

    查看spring代碼,可以發現這些manager實現事務,就是調用事務源的事務操作方法

    比如

    HibernateTransactionManager

    代碼

    ?

    1. protected ? void ?doCommit(DefaultTransactionStatus?status)?{ ??
    2. ????????HibernateTransactionObject?txObject?=?(HibernateTransactionObject)?status.getTransaction(); ??
    3. ???????? if ?(status.isDebug())?{ ??
    4. ????????????logger.debug( "Committing?Hibernate?transaction?on?session?[" ?+ ??
    5. ????????????????????txObject.getSessionHolder().getSession()?+? "]" ); ??
    6. ????????} ??
    7. ???????? try ?{ ??
    8. ????????????txObject.getSessionHolder().getTransaction().commit(); ??
    9. ????????} ??
    10. ... ??
    11. ??
    12. ????}??

    jdbc 的DataSourceTransactionManager

    代碼

    ?

    1. protected ? void ?doCommit(DefaultTransactionStatus?status)?{ ??
    2. ????????DataSourceTransactionObject?txObject?=?(DataSourceTransactionObject)?status.getTransaction(); ??
    3. ????????Connection?con?=?txObject.getConnectionHolder().getConnection(); ??
    4. ???????? if ?(status.isDebug())?{ ??
    5. ????????????logger.debug( "Committing?JDBC?transaction?on?connection?[" ?+?con?+? "]" ); ??
    6. ????????} ??
    7. ???????? try ?{ ??
    8. ????????????con.commit(); ??
    9. ????????} ??
    10. ????????... ??
    11. ????}??

    那么PlatformTransactionManager以什么依據處理事務呢?
    是TransactionStatus
    查看api發現這個接口有三個方法
    isNewTransaction() ,isRollbackOnly(),setRollbackOnly()
    PlatformTransactionManager就是根據前兩個方法決定是否要創建一個新事務,是要遞交還是回滾。至于第三個方法是改變事務當前狀態的,很多地方都要用到,偏偏PlatformTransactionManager自身好像不怎么用,畢竟事務狀態的改變是由程序員代碼決定的,不需要一個manager多管閑事。

    總結上面所說的,spring的事務由PlatformTransactionManager管理,manager最后調用事務源的方法來實現一個事務過程。而manager通過TransactionStatus 來決定如何實現。

    接下去說spring事務中的TransactionTemplate和TransactionInterceptor

    TransactionTemplate其實和spring中其他的template的作用類似,起到化簡代碼的作用,不要被它那么長的名字嚇倒了,事實上這個template并不是什么非常核心的對象。如果比較學究派的,可以去看看template設計模式,在此就不再對此贅述了。
    為什么要有TransactionTemplate?先來看看如果沒有TransactionTemplate,我們的代碼該怎么寫

    先來看看spring reference中的一段代碼

    代碼

    ?

    1. DefaultTransactionDefinition?def?=? new ?DefaultTransactionDefinition() ??
    2. def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); ??
    3. ??
    4. TransactionStatus?status?=?transactionManager.getTransaction(def); ??
    5. ??
    6. try ?{ ??
    7. ???? //?execute?your?business?logic?here ??
    8. }? catch ?(MyException?ex)?{ ??
    9. ????transactionManager.rollback(status); ??
    10. ???? throw ?ex; ??
    11. } ??
    12. transactionManager.commit(status);??


    這是直接使用transactionManager的例子,可以看到真正執行business logic 的地方是在try當中那段,前后的代碼都是為了完成事務管理的。如果每個business logic都要寫上那么一段,我肯定是瘋了。我們翻出TransactionTemplate的代碼看看他怎么化簡了我們的代碼

    代碼

    ?

    1. public ?Object?execute(TransactionCallback?action)? throws ?TransactionException?{ ??
    2. ????????TransactionStatus?status?=? this .transactionManager.getTransaction( this ); ??
    3. ????????Object?result?=? null ; ??
    4. ???????? try ?{ ??
    5. ????????????result?=?action.doInTransaction(status); ??
    6. ????????} ??
    7. ???????? catch ?(RuntimeException?ex)?{ ??
    8. ???????????? //?transactional?code?threw?application?exception?->?rollback ??
    9. ????????????rollbackOnException(status,?ex); ??
    10. ???????????? throw ?ex; ??
    11. ????????} ??
    12. ???????? catch ?(Error?err)?{ ??
    13. ???????????? //?transactional?code?threw?error?->?rollback ??
    14. ????????????rollbackOnException(status,?err); ??
    15. ???????????? throw ?err; ??
    16. ????????} ??
    17. ???????? this .transactionManager.commit(status); ??
    18. ???????? return ?result; ??
    19. ????}??

    同上面的代碼如出一轍,前后是事務處理代碼,當中那段result = action.doInTransaction(status);是我們的應用代碼。至于action是什么,全看各位的需要了。但是有一點要主要,如果利用TransactionTemplate,那么他不管你扔出什么異常都會回滾事務,但是回滾的是哪個事務呢?繼續挖代碼

    代碼

    ?

    1. private ? void ?rollbackOnException(TransactionStatus?status,?Throwable?ex)? throws ?TransactionException?{ ??
    2. ???????? if ?(logger.isDebugEnabled())?{ ??
    3. ????????????logger.debug( "Initiating?transaction?rollback?on?application?exception" ,?ex); ??
    4. ????????} ??
    5. ???????? try ?{ ??
    6. ???????????? this .transactionManager.rollback(status); ??
    7. ????????} ??
    8. ???????? catch ?(RuntimeException?ex2)?{ ??
    9. ????????????logger.error( "Application?exception?overridden?by?rollback?exception" ,?ex); ??
    10. ???????????? throw ?ex2; ??
    11. ????????} ??
    12. ???????? catch ?(Error?err)?{ ??
    13. ????????????logger.error( "Application?exception?overridden?by?rollback?error" ,?ex); ??
    14. ???????????? throw ?err; ??
    15. ????????} ??
    16. ????}??


    真相大白,是對template所持有的某個transactionManager進行回滾。所以如果你的應用代碼用的是事務源a的一些資源,比如到服務器a的一個datasource,但是你的transactionManager管理的是另一些資源,比如服務器b的一個datasource,代碼鐵定不會正常運行

    特別是在一些多事務源的程序里,這點千萬不能搞錯。如果多個事務源之間要完成全局事務,還是老老實實用分布式事務管理服務吧(jta)

    那么TransactionInterceptor是干什么的?這個是spring 的聲明式事務的支持方式。因為用TransactionTemplate要硬編碼,而且調整事務策略很麻煩(不是說不能調。舉個例子原來程序拋出異常A需要回滾,現在不需要要,我就可以把a catch吃掉。這時候template就不會回滾了。但是每次調整都要重寫編碼。)而用TransactionInterceptor就可以將這些調整寫在配置中。我們再來挖TransactionInterceptor的代碼

    代碼

    ?

    1. public ?Object?invoke(MethodInvocation?invocation)? throws ?Throwable?{ ??
    2. ???????? //?Work?out?the?target?class:?may?be?null. ??
    3. ???????? //?The?TransactionAttributeSource?should?be?passed?the?target?class ??
    4. ???????? //?as?well?as?the?method,?which?may?be?from?an?interface ??
    5. ????????Class?targetClass?=?(invocation.getThis()?!=? null )???invocation.getThis().getClass()?:? null ; ??
    6. ???????? ??
    7. ???????? //?Create?transaction?if?necessary ??
    8. ????????TransactionInfo?txInfo?=?createTransactionIfNecessary(invocation.getMethod(),?targetClass); ??
    9. ??
    10. ????????Object?retVal?=? null ; ??
    11. ???????? try ?{ ??
    12. ???????????? //?This?is?an?around?advice. ??
    13. ???????????? //?Invoke?the?next?interceptor?in?the?chain. ??
    14. ???????????? //?This?will?normally?result?in?a?target?object?being?invoked. ??
    15. ????????????retVal?=?invocation.proceed(); ??
    16. ????????} ??
    17. ???????? catch ?(Throwable?ex)?{ ??
    18. ???????????? //?target?invocation?exception ??
    19. ????????????doCloseTransactionAfterThrowing(txInfo,?ex); ??
    20. ???????????? throw ?ex; ??
    21. ????????} ??
    22. ???????? finally ?{ ??
    23. ????????????doFinally(txInfo); ??
    24. ????????} ??
    25. ????????doCommitTransactionAfterReturning(txInfo); ??
    26. ??
    27. ???????? return ?retVal; ??
    28. ????}??


    萬變不離其宗。

    所以使用spring的事務管理需要作這些事
    1,設置好事務源,比如DataSource,hibernate的session。如果有多個事務源要考慮他們之間是否有全局事務,如果有,老老實實用jta,否則就需要自己寫一個manager了
    2,設置manager,根據你的事務源選擇對應的PlatformTransactionManager
    3,選擇實現事物的方式,用template還是interceptor。用template代碼直觀點,但是template所管轄的manager和你應用代碼所用的事務源要一致。如果用interceptor千萬注意,一定要調用interceptor那個bean,而不是原始的那個target。在壇子上我已經看到至少有兩個朋友說spring事物不起作用,從配置和代碼上看都正確,這時要好好查查,調用的bean是哪一個。
    4,這個是設計問題了,推薦事務處于一個較高層次,比如service上的某個函數,而底層的dao可以不考慮事務,否則可能會出現事務嵌套,增加程序復雜度。

    posted @ 2007-03-05 14:45 比特鼠 閱讀(244) | 評論 (0)編輯 收藏

    2007年已經過去一個月了, 還沒有制定今年的規劃, 現在是時候了!

    爭取掌握以下技術:

    1. Ruby On Rails?
    進一步學習ruby的語法和語義,最好能深入到解釋器一層看看有些特性是怎么實現的。

    2、Spring AOP 及 AspectJ
    個人覺得Spring 2.0和AspectJ的結合,有很多潛力,值得深入挖掘。

    3. Web Service

    4. Java JPA

    5. Role-Based Access Control , Acegi
    buaawhl推薦的,
    http://csrc.nist.gov/rbac/
    http://www.amazon.com/Role-Based-Access-Control-David-Ferraiolo/dp/1580533701/sr=1-1/qid=1161828835/ref=pd_bbs_1/002-1138304-7372032?ie=UTF8&s=books

    下一個項目的權限管理會比較復雜,以前沒學過這方面的知識。從Acegi開始吧,如果夠用最好。

    6. JBoss JBoss的Cache,AppServer的cluster方面是我比較感興趣的地方,想嘗試一下JBoss應用服務器

    7. 滿足一定條件(比如: 并發達1000個請求)框架Web Application群集部署

    posted @ 2007-02-02 15:28 比特鼠 閱讀(234) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 中文在线观看免费网站| EEUSS影院WWW在线观看免费| 亚洲色少妇熟女11p| 亚洲av日韩综合一区二区三区| 美女被艹免费视频| 国产免费黄色无码视频| 久久午夜夜伦鲁鲁片免费无码| 亚洲免费观看网站| 日韩成人免费视频播放| 亚洲人成人网站在线观看| 久久亚洲AV午夜福利精品一区| 亚洲一区在线观看视频| 羞羞视频免费观看| 国产免费一区二区视频| 欧美好看的免费电影在线观看| 亚洲AV无码一区二三区| 亚洲中文字幕第一页在线| 4480yy私人影院亚洲| 国产精品无码亚洲精品2021 | 久久精品毛片免费观看| 毛片免费视频播放| 国产成人精品曰本亚洲79ren| 亚洲综合在线观看视频| 亚洲国产成人综合精品| 拍拍拍无挡免费视频网站| 国产1024精品视频专区免费| 亚洲国产成人爱av在线播放| 久久精品亚洲一区二区三区浴池| 欧美色欧美亚洲另类二区| 免费人成毛片动漫在线播放| 成人免费无码精品国产电影| 亚洲AV无码码潮喷在线观看 | 亚洲精品无码不卡在线播放| 中国一级全黄的免费观看| 91免费资源网站入口| 国产精品亚洲mnbav网站| 日本亚洲色大成网站www久久| 国产在线精品观看免费观看| 成年女人免费视频播放体验区 | 成人亚洲网站www在线观看| 亚洲首页在线观看|