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

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

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

    菠蘿三國(guó)

    大江東去,浪淘盡...
    隨筆 - 34, 文章 - 47, 評(píng)論 - 22, 引用 - 0
    數(shù)據(jù)加載中……

    2007年10月9日

    用instsrv與srvany在windows 建立服務(wù)

    用instsrv與srvany在windows 建立服務(wù)

    instsrv.exe  srvany.exe

    這兩個(gè)文件是MS批量生產(chǎn)的,網(wǎng)上應(yīng)該能爛下載。

    首先將這兩個(gè)文件放到自定的路徑中。例如放在C:\根目錄下

    在CMD對(duì)話框中輸入 c:\instsrv.exe  servername c:\ srvany.exe 回車

    其中servername是你所需要的服務(wù)名。

    之后你需要進(jìn)入注冊(cè)表進(jìn)行相應(yīng)的設(shè)置,在注冊(cè)表的:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\servername

    中簡(jiǎn)歷Parameters子項(xiàng),然后在其中建立一個(gè)字符串Application,雙擊該字符串,輸入如下格式的語句:

    C:\ABC\DEF\XXX.exe +Xms256M +Xmx256M -nodbcheck -minspan60 -retry1000

    其中的256M與服務(wù)占用內(nèi)存大小有關(guān),這就要看機(jī)器的配置了。

    修改結(jié)束后推出,使用命令services.msc進(jìn)入服務(wù)界面,找到你剛剛定制的服務(wù),雙擊進(jìn)入,之后選擇“登陸”,再選中“本地登陸”并確定。之后手動(dòng)啟動(dòng)服務(wù)即可。

    C:\service\instsrv.exe adslSrv "C:\service\srvany.exe"

    posted @ 2009-04-19 14:44 菠蘿 閱讀(1145) | 評(píng)論 (0)編輯 收藏

    網(wǎng)上在線字典詞典大全

    翻譯類字典詞典

    posted @ 2008-04-07 12:26 菠蘿 閱讀(528) | 評(píng)論 (0)編輯 收藏

    XP/2003訪問XP的用戶驗(yàn)證問題


      首先關(guān)于啟用Guest為什么不能訪問的問題:  
       
      1、默認(rèn)情況下,XP   禁用Guest帳戶  
      2、默認(rèn)情況下,XP的本地安全策略禁止Guest用戶從網(wǎng)絡(luò)訪問  
      3、默認(rèn)情況下,XP的   本地安全策略   ->   安全選項(xiàng)   里,"帳戶:使用空密碼用戶只能進(jìn)行控制臺(tái)登陸"是啟用的,也就是說,空密碼的任何帳戶都不能從網(wǎng)絡(luò)訪問只能本地登陸,Guest默認(rèn)空密碼......  
       
      所以,如果需要使用Guest用戶訪問XP的話,要進(jìn)行上面的三個(gè)設(shè)置:?jiǎn)⒂肎uest、修改安全策略允許Guest從網(wǎng)絡(luò)訪問、禁用3里面的安全策略或者給Guest加個(gè)密碼。  
       
      有時(shí)還會(huì)遇到另外一種情況:訪問XP的時(shí)候,登錄對(duì)話框中的用戶名是灰的,始終是Guest用戶,不能輸入別的用戶帳號(hào)。  
       
      原因是這個(gè)安全策略在作怪。默認(rèn)情況下,XP的訪問方式是"僅來賓"的方式,那么你訪問它,當(dāng)然就固定為Guest不能輸入其他用戶帳號(hào)了。  
       
      所以,訪問XP最簡(jiǎn)單的方法就是:不用啟用Guest,僅修改上面的安全策略為"經(jīng)典"就行了。別的系統(tǒng)訪問XP就可以自己輸入帳戶信息。  
       
      至于訪問2003,默認(rèn)情況下2003禁用Guest,但是沒有   XP   那個(gè)討厭的默認(rèn)自相矛盾的來賓方式共享,所以可以直接輸入用戶名密碼訪問。

    posted @ 2008-03-07 20:43 菠蘿 閱讀(399) | 評(píng)論 (0)編輯 收藏

    RSS的格式及解釋(轉(zhuǎn))

         摘要:   閱讀全文

    posted @ 2008-01-30 09:27 菠蘿 閱讀(2153) | 評(píng)論 (1)編輯 收藏

    AJAX讀取rss的代碼(轉(zhuǎn))

     
    2007-02-02 15:48

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
      " <html xmlns=" <head>
    <title>this is test</title>

    <script type="text/javascript">
    var xmlHttp;

    function createXMLHttpRequest() {
        if (window.ActiveXObject) {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        } 
        else if (window.XMLHttpRequest) {
            xmlHttp = new XMLHttpRequest();
        }
    }

    function readRSS(url) {
        createXMLHttpRequest();
        xmlHttp.onreadystatechange = handleStateChange;
        xmlHttp.open("GET", url, true);
        xmlHttp.send(null);
      
      
    }
        
    function handleStateChange() {
        if(xmlHttp.readyState == 4) {
            if(xmlHttp.status == 200) {
                ResultSet();
            }
        }
    }

    function ResultSet() {
        var results = xmlHttp.responseXML;
        var title = null;
        var item = null;
        var link=null;
        //得到channel
        var ccc=results.getElementsByTagName("channel");
         var headtitle=ccc[0].getElementsByTagName("title")[0].firstChild.nodeValue;
         var headlink=ccc[0].getElementsByTagName("link")[0].firstChild.nodeValue;
         var cell = document.createElement("div");
            cell.innerHTML="<h1><a href="+headlink+" target=_blank>"+headtitle+"</a></h1><br>";
            document.getElementById("result").appendChild(cell);
           //得到items
        var items = results.getElementsByTagName("item");
        for(var i = 0; i < items.length; i++) {
            item = items[i];
            link=item.getElementsByTagName("link")[0].firstChild.nodeValue;
            title = item.getElementsByTagName("title")[0].firstChild.nodeValue;
            var cell = document.createElement("div");
            cell.innerHTML="<a href="+link+" target=_blank>"+title+"</a><br>";
           document.getElementById("result").appendChild(cell);
        }

    }
    function readrss1()
    {
        var url=document.getElementById("txturl").value;
        if(url=="")
        {
            alert("請(qǐng)輸入RSS地址");
            }
        else
            {
                readRSS(url);
                }
        }

    </script>
    </head>

    <body">
      <h1>ajax讀rss示例</h1>
      <form >
          
      <a href="javascript:readRSS('http://m.tkk7.com/rss.aspx')">blogjava原創(chuàng)區(qū) </a>&nbsp     
       <a href="javascript:readRSS('http://beginner.blogjava.net/rss.aspx')">blogjava新手區(qū) </a> &nbsp 
        <a href="javascript:readRSS('http://life.blogjava.net/rss.aspx')">blogjava非技術(shù)區(qū) </a> &nbsp 
         <a href="javascript:readRSS('http://general.blogjava.net/rss.aspx')">綜合區(qū) </a>
         <br>
         輸入一個(gè)RSS地址:<input type="text" value="
    http://m.tkk7.com/wujun/rss.aspx" size=50 id="txturl">
         <input type="button" value="查 看" onclick="readrss1()">
         
      </form>
        <div id="result"></div>
    </body>
    </html>

    posted @ 2008-01-29 22:49 菠蘿 閱讀(354) | 評(píng)論 (0)編輯 收藏

    Session機(jī)制

    摘要:

    雖然session機(jī)制在web應(yīng)用程序中被采用已經(jīng)很長(zhǎng)時(shí)間了,但是仍然有很多人不清楚session機(jī)制的本質(zhì),以至不能正確的應(yīng)用這一技術(shù)。本文將詳細(xì)討論session的工作機(jī)制并且對(duì)在Java web application中應(yīng)用session機(jī)制時(shí)常見的問題作出解答。
     
    一、術(shù)語session
    在我的經(jīng)驗(yàn)里,session這個(gè)詞被濫用的程度大概僅次于transaction,更加有趣的是transaction與session在某些語境下的含義是相同的。

    session,中文經(jīng)常翻譯為會(huì)話,其本來的含義是指有始有終的一系列動(dòng)作/消息,比如打電話時(shí)從拿起電話撥號(hào)到掛斷電話這中間的一系列過程可以稱之為一個(gè) session。有時(shí)候我們可以看到這樣的話“在一個(gè)瀏覽器會(huì)話期間,...”,這里的會(huì)話一詞用的就是其本義,是指從一個(gè)瀏覽器窗口打開到關(guān)閉這個(gè)期間 ①。最混亂的是“用戶(客戶端)在一次會(huì)話期間”這樣一句話,它可能指用戶的一系列動(dòng)作(一般情況下是同某個(gè)具體目的相關(guān)的一系列動(dòng)作,比如從登錄到選購商品到結(jié)賬登出這樣一個(gè)網(wǎng)上購物的過程,有時(shí)候也被稱為一個(gè)transaction),然而有時(shí)候也可能僅僅是指一次連接,也有可能是指含義①,其中的差別只能靠上下文來推斷②。

    然而當(dāng)session一詞與網(wǎng)絡(luò)協(xié)議相關(guān)聯(lián)時(shí),它又往往隱含了“面向連接”和/或“保持狀態(tài)”這樣兩個(gè)含義, “面向連接”指的是在通信雙方在通信之前要先建立一個(gè)通信的渠道,比如打電話,直到對(duì)方接了電話通信才能開始,與此相對(duì)的是寫信,在你把信發(fā)出去的時(shí)候你并不能確認(rèn)對(duì)方的地址是否正確,通信渠道不一定能建立,但對(duì)發(fā)信人來說,通信已經(jīng)開始了。“保持狀態(tài)”則是指通信的一方能夠把一系列的消息關(guān)聯(lián)起來,使得消息之間可以互相依賴,比如一個(gè)服務(wù)員能夠認(rèn)出再次光臨的老顧客并且記得上次這個(gè)顧客還欠店里一塊錢。這一類的例子有“一個(gè)TCP session”或者 “一個(gè)POP3 session”③。

    而到了web服務(wù)器蓬勃發(fā)展的時(shí)代,session在web開發(fā)語境下的語義又有了新的擴(kuò)展,它的含義是指一類用來在客戶端與服務(wù)器之間保持狀態(tài)的解決方案④。有時(shí)候session也用來指這種解決方案的存儲(chǔ)結(jié)構(gòu),如“把xxx保存在session 里”⑤。由于各種用于web開發(fā)的語言在一定程度上都提供了對(duì)這種解決方案的支持,所以在某種特定語言的語境下,session也被用來指代該語言的解決方案,比如經(jīng)常把Java里提供的javax.servlet.http.HttpSession簡(jiǎn)稱為session⑥。

    鑒于這種混亂已不可改變,本文中session一詞的運(yùn)用也會(huì)根據(jù)上下文有不同的含義,請(qǐng)大家注意分辨。
    在本文中,使用中文“瀏覽器會(huì)話期間”來表達(dá)含義①,使用“session機(jī)制”來表達(dá)含義④,使用“session”表達(dá)含義⑤,使用具體的“HttpSession”來表達(dá)含義⑥

    二、HTTP協(xié)議與狀態(tài)保持
    HTTP 協(xié)議本身是無狀態(tài)的,這與HTTP協(xié)議本來的目的是相符的,客戶端只需要簡(jiǎn)單的向服務(wù)器請(qǐng)求下載某些文件,無論是客戶端還是服務(wù)器都沒有必要紀(jì)錄彼此過去的行為,每一次請(qǐng)求之間都是獨(dú)立的,好比一個(gè)顧客和一個(gè)自動(dòng)售貨機(jī)或者一個(gè)普通的(非會(huì)員制)大賣場(chǎng)之間的關(guān)系一樣。

    然而聰明(或者貪心?)的人們很快發(fā)現(xiàn)如果能夠提供一些按需生成的動(dòng)態(tài)信息會(huì)使web變得更加有用,就像給有線電視加上點(diǎn)播功能一樣。這種需求一方面迫使HTML逐步添加了表單、腳本、DOM等客戶端行為,另一方面在服務(wù)器端則出現(xiàn)了CGI規(guī)范以響應(yīng)客戶端的動(dòng)態(tài)請(qǐng)求,作為傳輸載體的HTTP協(xié)議也添加了文件上載、 cookie這些特性。其中cookie的作用就是為了解決HTTP協(xié)議無狀態(tài)的缺陷所作出的努力。至于后來出現(xiàn)的session機(jī)制則是又一種在客戶端與服務(wù)器之間保持狀態(tài)的解決方案。

    讓我們用幾個(gè)例子來描述一下cookie和session機(jī)制之間的區(qū)別與聯(lián)系。筆者曾經(jīng)常去的一家咖啡店有喝5杯咖啡免費(fèi)贈(zèng)一杯咖啡的優(yōu)惠,然而一次性消費(fèi)5杯咖啡的機(jī)會(huì)微乎其微,這時(shí)就需要某種方式來紀(jì)錄某位顧客的消費(fèi)數(shù)量。想象一下其實(shí)也無外乎下面的幾種方案:
    1、該店的店員很厲害,能記住每位顧客的消費(fèi)數(shù)量,只要顧客一走進(jìn)咖啡店,店員就知道該怎么對(duì)待了。這種做法就是協(xié)議本身支持狀態(tài)。
    2、發(fā)給顧客一張卡片,上面記錄著消費(fèi)的數(shù)量,一般還有個(gè)有效期限。每次消費(fèi)時(shí),如果顧客出示這張卡片,則此次消費(fèi)就會(huì)與以前或以后的消費(fèi)相聯(lián)系起來。這種做法就是在客戶端保持狀態(tài)。
    3、發(fā)給顧客一張會(huì)員卡,除了卡號(hào)之外什么信息也不紀(jì)錄,每次消費(fèi)時(shí),如果顧客出示該卡片,則店員在店里的紀(jì)錄本上找到這個(gè)卡號(hào)對(duì)應(yīng)的紀(jì)錄添加一些消費(fèi)信息。這種做法就是在服務(wù)器端保持狀態(tài)。

    由于HTTP協(xié)議是無狀態(tài)的,而出于種種考慮也不希望使之成為有狀態(tài)的,因此,后面兩種方案就成為現(xiàn)實(shí)的選擇。具體來說cookie機(jī)制采用的是在客戶端保持狀態(tài)的方案,而session機(jī)制采用的是在服務(wù)器端保持狀態(tài)的方案。同時(shí)我們也看到,由于采用服務(wù)器端保持狀態(tài)的方案在客戶端也需要保存一個(gè)標(biāo)識(shí),所以session機(jī)制可能需要借助于cookie機(jī)制來達(dá)到保存標(biāo)識(shí)的目的,但實(shí)際上它還有其他選擇。

    三、理解cookie機(jī)制
    cookie機(jī)制的基本原理就如上面的例子一樣簡(jiǎn)單,但是還有幾個(gè)問題需要解決:“會(huì)員卡”如何分發(fā);“會(huì)員卡”的內(nèi)容;以及客戶如何使用“會(huì)員卡”。

    正統(tǒng)的cookie分發(fā)是通過擴(kuò)展HTTP協(xié)議來實(shí)現(xiàn)的,服務(wù)器通過在HTTP的響應(yīng)頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應(yīng)的cookie。然而純粹的客戶端腳本如JavaScript或者VBScript也可以生成cookie。

    而cookie 的使用是由瀏覽器按照一定的原則在后臺(tái)自動(dòng)發(fā)送給服務(wù)器的。瀏覽器檢查所有存儲(chǔ)的cookie,如果某個(gè)cookie所聲明的作用范圍大于等于將要請(qǐng)求的資源所在的位置,則把該cookie附在請(qǐng)求資源的HTTP請(qǐng)求頭上發(fā)送給服務(wù)器。意思是麥當(dāng)勞的會(huì)員卡只能在麥當(dāng)勞的店里出示,如果某家分店還發(fā)行了自己的會(huì)員卡,那么進(jìn)這家店的時(shí)候除了要出示麥當(dāng)勞的會(huì)員卡,還要出示這家店的會(huì)員卡。

    cookie的內(nèi)容主要包括:名字,值,過期時(shí)間,路徑和域。
    其中域可以指定某一個(gè)域比如.google.com,相當(dāng)于總店招牌,比如寶潔公司,也可以指定一個(gè)域下的具體某臺(tái)機(jī)器比如www.google.com或者froogle.google.com,可以用飄柔來做比。
    路徑就是跟在域名后面的URL路徑,比如/或者/foo等等,可以用某飄柔專柜做比。
    路徑與域合在一起就構(gòu)成了cookie的作用范圍。
    如果不設(shè)置過期時(shí)間,則表示這個(gè)cookie的生命期為瀏覽器會(huì)話期間,只要關(guān)閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽器會(huì)話期的 cookie被稱為會(huì)話cookie。會(huì)話cookie一般不存儲(chǔ)在硬盤上而是保存在內(nèi)存里,當(dāng)然這種行為并不是規(guī)范規(guī)定的。如果設(shè)置了過期時(shí)間,瀏覽器就會(huì)把cookie保存到硬盤上,關(guān)閉后再次打開瀏覽器,這些cookie仍然有效直到超過設(shè)定的過期時(shí)間。

    存儲(chǔ)在硬盤上的cookie 可以在不同的瀏覽器進(jìn)程間共享,比如兩個(gè)IE窗口。而對(duì)于保存在內(nèi)存里的cookie,不同的瀏覽器有不同的處理方式。對(duì)于IE,在一個(gè)打開的窗口上按 Ctrl-N(或者從文件菜單)打開的窗口可以與原窗口共享,而使用其他方式新開的IE進(jìn)程則不能共享已經(jīng)打開的窗口的內(nèi)存cookie;對(duì)于 Mozilla Firefox0.8,所有的進(jìn)程和標(biāo)簽頁都可以共享同樣的cookie。一般來說是用javascript的window.open打開的窗口會(huì)與原窗口共享內(nèi)存cookie。瀏覽器對(duì)于會(huì)話cookie的這種只認(rèn)cookie不認(rèn)人的處理方式經(jīng)常給采用session機(jī)制的web應(yīng)用程序開發(fā)者造成很大的困擾。

    下面就是一個(gè)goolge設(shè)置cookie的響應(yīng)頭的例子
    HTTP/1.1 302 Found
    Location: http://www.google.com/intl/zh-CN/
    Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
    Content-Type: text/html


    image
    這是使用HTTPLook這個(gè)HTTP Sniffer軟件來俘獲的HTTP通訊紀(jì)錄的一部分

    image
    瀏覽器在再次訪問goolge的資源時(shí)自動(dòng)向外發(fā)送cookie

    image
    用Firefox可以很容易的觀察現(xiàn)有的cookie的值
    使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理。

    image
    IE也可以設(shè)置在接受cookie前詢問

    四、理解session機(jī)制

    session機(jī)制是一種服務(wù)器端的機(jī)制,服務(wù)器使用一種類似于散列表的結(jié)構(gòu)(也可能就是使用散列表)來保存信息。

    當(dāng)程序需要為某個(gè)客戶端的請(qǐng)求創(chuàng)建一個(gè)session的時(shí)候,服務(wù)器首先檢查這個(gè)客戶端的請(qǐng)求里是否已包含了一個(gè)session標(biāo)識(shí) - 稱為 session id,如果已包含一個(gè)session id則說明以前已經(jīng)為此客戶端創(chuàng)建過session,服務(wù)器就按照session id把這個(gè) session檢索出來使用(如果檢索不到,可能會(huì)新建一個(gè)),如果客戶端請(qǐng)求不包含session id,則為此客戶端創(chuàng)建一個(gè)session并且生成一個(gè)與此session相關(guān)聯(lián)的session id,session id的值應(yīng)該是一個(gè)既不會(huì)重復(fù),又不容易被找到規(guī)律以仿造的字符串,這個(gè) session id將被在本次響應(yīng)中返回給客戶端保存。

    保存這個(gè)session id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動(dòng)的按照規(guī)則把這個(gè)標(biāo)識(shí)發(fā)揮給服務(wù)器。一般這個(gè)cookie的名字都是類似于SEEESIONID,而。比如weblogic對(duì)于web應(yīng)用程序生成的cookie,JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是 JSESSIONID。

    由于cookie可以被人為的禁止,必須有其他機(jī)制以便在cookie被禁止時(shí)仍然能夠把session id傳遞回服務(wù)器。經(jīng)常被使用的一種技術(shù)叫做URL重寫,就是把session id直接附加在URL路徑的后面,附加方式也有兩種,一種是作為URL路徑的附加信息,表現(xiàn)形式為http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
    另一種是作為查詢字符串附加在URL后面,表現(xiàn)形式為http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
    這兩種方式對(duì)于用戶來說是沒有區(qū)別的,只是服務(wù)器在解析的時(shí)候處理的方式不同,采用第一種方式也有利于把session id的信息和正常程序參數(shù)區(qū)分開來。
    為了在整個(gè)交互過程中始終保持狀態(tài),就必須在每個(gè)客戶端可能請(qǐng)求的路徑后面都包含這個(gè)session id。

    另一種技術(shù)叫做表單隱藏字段。就是服務(wù)器會(huì)自動(dòng)修改表單,添加一個(gè)隱藏字段,以便在表單提交時(shí)能夠把session id傳遞回服務(wù)器。比如下面的表單
    <form name="testform" action="/xxx">
    <input type="text">
    </form>


    在被傳遞給客戶端之前將被改寫成
    <form name="testform" action="/xxx">
    <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
    <input type="text">
    </form>


    這種技術(shù)現(xiàn)在已較少應(yīng)用,筆者接觸過的很古老的iPlanet6(SunONE應(yīng)用服務(wù)器的前身)就使用了這種技術(shù)。
    實(shí)際上這種技術(shù)可以簡(jiǎn)單的用對(duì)action應(yīng)用URL重寫來代替。

    在談?wù)搒ession機(jī)制的時(shí)候,常常聽到這樣一種誤解“只要關(guān)閉瀏覽器,session就消失了”。其實(shí)可以想象一下會(huì)員卡的例子,除非顧客主動(dòng)對(duì)店家提出銷卡,否則店家絕對(duì)不會(huì)輕易刪除顧客的資料。對(duì)session來說也是一樣的,除非程序通知服務(wù)器刪除一個(gè)session,否則服務(wù)器會(huì)一直保留,程序一般都是在用戶做log off的時(shí)候發(fā)個(gè)指令去刪除session。然而瀏覽器從來不會(huì)主動(dòng)在關(guān)閉之前通知服務(wù)器它將要關(guān)閉,因此服務(wù)器根本不會(huì)有機(jī)會(huì)知道瀏覽器已經(jīng)關(guān)閉,之所以會(huì)有這種錯(cuò)覺,是大部分session機(jī)制都使用會(huì)話cookie來保存session id,而關(guān)閉瀏覽器后這個(gè) session id就消失了,再次連接服務(wù)器時(shí)也就無法找到原來的session。如果服務(wù)器設(shè)置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發(fā)出的HTTP請(qǐng)求頭,把原來的session id發(fā)送給服務(wù)器,則再次打開瀏覽器仍然能夠找到原來的session。

    恰恰是由于關(guān)閉瀏覽器不會(huì)導(dǎo)致session被刪除,迫使服務(wù)器為seesion設(shè)置了一個(gè)失效時(shí)間,當(dāng)距離客戶端上一次使用session的時(shí)間超過這個(gè)失效時(shí)間時(shí),服務(wù)器就可以認(rèn)為客戶端已經(jīng)停止了活動(dòng),才會(huì)把session刪除以節(jié)省存儲(chǔ)空間。

    五、理解javax.servlet.http.HttpSession
    HttpSession是Java平臺(tái)對(duì)session機(jī)制的實(shí)現(xiàn)規(guī)范,因?yàn)樗鼉H僅是個(gè)接口,具體到每個(gè)web應(yīng)用服務(wù)器的提供商,除了對(duì)規(guī)范支持之外,仍然會(huì)有一些規(guī)范里沒有規(guī)定的細(xì)微差異。這里我們以BEA的Weblogic Server8.1作為例子來演示。

    首先,Weblogic Server提供了一系列的參數(shù)來控制它的HttpSession的實(shí)現(xiàn),包括使用cookie的開關(guān)選項(xiàng),使用URL重寫的開關(guān)選項(xiàng),session持久化的設(shè)置,session失效時(shí)間的設(shè)置,以及針對(duì)cookie的各種設(shè)置,比如設(shè)置cookie的名字、路徑、域, cookie的生存時(shí)間等。

    一般情況下,session都是存儲(chǔ)在內(nèi)存里,當(dāng)服務(wù)器進(jìn)程被停止或者重啟的時(shí)候,內(nèi)存里的session也會(huì)被清空,如果設(shè)置了session的持久化特性,服務(wù)器就會(huì)把session保存到硬盤上,當(dāng)服務(wù)器進(jìn)程重新啟動(dòng)或這些信息將能夠被再次使用, Weblogic Server支持的持久性方式包括文件、數(shù)據(jù)庫、客戶端cookie保存和復(fù)制。

    復(fù)制嚴(yán)格說來不算持久化保存,因?yàn)閟ession實(shí)際上還是保存在內(nèi)存里,不過同樣的信息被復(fù)制到各個(gè)cluster內(nèi)的服務(wù)器進(jìn)程中,這樣即使某個(gè)服務(wù)器進(jìn)程停止工作也仍然可以從其他進(jìn)程中取得session。

    cookie生存時(shí)間的設(shè)置則會(huì)影響瀏覽器生成的cookie是否是一個(gè)會(huì)話cookie。默認(rèn)是使用會(huì)話cookie。有興趣的可以用它來試驗(yàn)我們?cè)诘谒墓?jié)里提到的那個(gè)誤解。

    cookie的路徑對(duì)于web應(yīng)用程序來說是一個(gè)非常重要的選項(xiàng),Weblogic Server對(duì)這個(gè)選項(xiàng)的默認(rèn)處理方式使得它與其他服務(wù)器有明顯的區(qū)別。后面我們會(huì)專題討論。

    關(guān)于session的設(shè)置參考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869

    六、HttpSession常見問題
    (在本小節(jié)中session的含義為⑤和⑥的混合)

    1、session在何時(shí)被創(chuàng)建
    一個(gè)常見的誤解是以為session在有客戶端訪問時(shí)就被創(chuàng)建,然而事實(shí)是直到某server端程序調(diào)用 HttpServletRequest.getSession(true)這樣的語句時(shí)才被創(chuàng)建,注意如果JSP沒有顯示的使用 <% @page session="false"%> 關(guān)閉session,則JSP文件在編譯成Servlet時(shí)將會(huì)自動(dòng)加上這樣一條語句 HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的 session對(duì)象的來歷。

    由于session會(huì)消耗內(nèi)存資源,因此,如果不打算使用session,應(yīng)該在所有的JSP中關(guān)閉它。

    2、session何時(shí)被刪除
    綜合前面的討論,session在下列情況下被刪除a.程序調(diào)用HttpSession.invalidate();或b.距離上一次收到客戶端發(fā)送的session id時(shí)間間隔超過了session的超時(shí)設(shè)置;或c.服務(wù)器進(jìn)程被停止(非持久session)

    3、如何做到在瀏覽器關(guān)閉時(shí)刪除session
    嚴(yán)格的講,做不到這一點(diǎn)。可以做一點(diǎn)努力的辦法是在所有的客戶端頁面里使用javascript代碼window.oncolose來監(jiān)視瀏覽器的關(guān)閉動(dòng)作,然后向服務(wù)器發(fā)送一個(gè)請(qǐng)求來刪除session。但是對(duì)于瀏覽器崩潰或者強(qiáng)行殺死進(jìn)程這些非常規(guī)手段仍然無能為力。

    4、有個(gè)HttpSessionListener是怎么回事
    你可以創(chuàng)建這樣的listener去監(jiān)控session的創(chuàng)建和銷毀事件,使得在發(fā)生這樣的事件時(shí)你可以做一些相應(yīng)的工作。注意是session的創(chuàng)建和銷毀動(dòng)作觸發(fā)listener,而不是相反。類似的與HttpSession有關(guān)的listener還有 HttpSessionBindingListener,HttpSessionActivationListener和 HttpSessionAttributeListener。

    5、存放在session中的對(duì)象必須是可序列化的嗎
    不是必需的。要求對(duì)象可序列化只是為了session能夠在集群中被復(fù)制或者能夠持久保存或者在必要時(shí)server能夠暫時(shí)把session交換出內(nèi)存。在 Weblogic Server的session中放置一個(gè)不可序列化的對(duì)象在控制臺(tái)上會(huì)收到一個(gè)警告。我所用過的某個(gè)iPlanet版本如果 session中有不可序列化的對(duì)象,在session銷毀時(shí)會(huì)有一個(gè)Exception,很奇怪。

    6、如何才能正確的應(yīng)付客戶端禁止cookie的可能性
    對(duì)所有的URL使用URL重寫,包括超鏈接,form的action,和重定向的URL,具體做法參見[6]
    http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

    7、開兩個(gè)瀏覽器窗口訪問應(yīng)用程序會(huì)使用同一個(gè)session還是不同的session
    參見第三小節(jié)對(duì)cookie的討論,對(duì)session來說是只認(rèn)id不認(rèn)人,因此不同的瀏覽器,不同的窗口打開方式以及不同的cookie存儲(chǔ)方式都會(huì)對(duì)這個(gè)問題的答案有影響。

    8、如何防止用戶打開兩個(gè)瀏覽器窗口操作導(dǎo)致的session混亂
    這個(gè)問題與防止表單多次提交是類似的,可以通過設(shè)置客戶端的令牌來解決。就是在服務(wù)器每次生成一個(gè)不同的id返回給客戶端,同時(shí)保存在session里,客戶端提交表單時(shí)必須把這個(gè)id也返回服務(wù)器,程序首先比較返回的id與保存在session里的值是否一致,如果不一致則說明本次操作已經(jīng)被提交過了??梢詤⒖础禞2EE核心模式》關(guān)于表示層模式的部分。需要注意的是對(duì)于使用javascript window.open打開的窗口,一般不設(shè)置這個(gè)id,或者使用單獨(dú)的id,以防主窗口無法操作,建議不要再window.open打開的窗口里做修改操作,這樣就可以不用設(shè)置。

    9、為什么在Weblogic Server中改變session的值后要重新調(diào)用一次session.setValue
    做這個(gè)動(dòng)作主要是為了在集群環(huán)境中提示W(wǎng)eblogic Server session中的值發(fā)生了改變,需要向其他服務(wù)器進(jìn)程復(fù)制新的session值。

    10、為什么session不見了
    排除session正常失效的因素之外,服務(wù)器本身的可能性應(yīng)該是微乎其微的,雖然筆者在iPlanet6SP1加若干補(bǔ)丁的Solaris版本上倒也遇到過;瀏覽器插件的可能性次之,筆者也遇到過3721插件造成的問題;理論上防火墻或者代理服務(wù)器在cookie處理上也有可能會(huì)出現(xiàn)問題。
    出現(xiàn)這一問題的大部分原因都是程序的錯(cuò)誤,最常見的就是在一個(gè)應(yīng)用程序中去訪問另外一個(gè)應(yīng)用程序。我們?cè)谙乱还?jié)討論這個(gè)問題。

    七、跨應(yīng)用程序的session共享

    常常有這樣的情況,一個(gè)大項(xiàng)目被分割成若干小項(xiàng)目開發(fā),為了能夠互不干擾,要求每個(gè)小項(xiàng)目作為一個(gè)單獨(dú)的web應(yīng)用程序開發(fā),可是到了最后突然發(fā)現(xiàn)某幾個(gè)小項(xiàng)目之間需要共享一些信息,或者想使用session來實(shí)現(xiàn)SSO(single sign on),在session中保存login的用戶信息,最自然的要求是應(yīng)用程序間能夠訪問彼此的session。

    然而按照Servlet規(guī)范,session的作用范圍應(yīng)該僅僅限于當(dāng)前應(yīng)用程序下,不同的應(yīng)用程序之間是不能夠互相訪問對(duì)方的session的。各個(gè)應(yīng)用服務(wù)器從實(shí)際效果上都遵守了這一規(guī)范,但是實(shí)現(xiàn)的細(xì)節(jié)卻可能各有不同,因此解決跨應(yīng)用程序session共享的方法也各不相同。

    首先來看一下Tomcat是如何實(shí)現(xiàn)web應(yīng)用程序之間session的隔離的,從 Tomcat設(shè)置的cookie路徑來看,它對(duì)不同的應(yīng)用程序設(shè)置的cookie路徑是不同的,這樣不同的應(yīng)用程序所用的session id是不同的,因此即使在同一個(gè)瀏覽器窗口里訪問不同的應(yīng)用程序,發(fā)送給服務(wù)器的session id也可以是不同的。

    image
    image

    根據(jù)這個(gè)特性,我們可以推測(cè)Tomcat中session的內(nèi)存結(jié)構(gòu)大致如下。
    image

    筆者以前用過的iPlanet也采用的是同樣的方式,估計(jì)SunONE與iPlanet之間不會(huì)有太大的差別。對(duì)于這種方式的服務(wù)器,解決的思路很簡(jiǎn)單,實(shí)際實(shí)行起來也不難。要么讓所有的應(yīng)用程序共享一個(gè)session id,要么讓應(yīng)用程序能夠獲得其他應(yīng)用程序的session id。

    iPlanet中有一種很簡(jiǎn)單的方法來實(shí)現(xiàn)共享一個(gè)session id,那就是把各個(gè)應(yīng)用程序的cookie路徑都設(shè)為/(實(shí)際上應(yīng)該是/NASApp,對(duì)于應(yīng)用程序來講它的作用相當(dāng)于根)。
    <session-info>
    <path>/NASApp</path>
    </session-info>


    需要注意的是,操作共享的session應(yīng)該遵循一些編程約定,比如在session attribute名字的前面加上應(yīng)用程序的前綴,使得 setAttribute("name", "neo")變成setAttribute("app1.name", "neo"),以防止命名空間沖突,導(dǎo)致互相覆蓋。

    在Tomcat中則沒有這么方便的選擇。在Tomcat版本3上,我們還可以有一些手段來共享session。對(duì)于版本4以上的Tomcat,目前筆者尚未發(fā)現(xiàn)簡(jiǎn)單的辦法。只能借助于第三方的力量,比如使用文件、數(shù)據(jù)庫、JMS或者客戶端cookie,URL參數(shù)或者隱藏字段等手段。

    我們?cè)倏匆幌耊eblogic Server是如何處理session的。
    image
    image

    從截屏畫面上可以看到Weblogic Server對(duì)所有的應(yīng)用程序設(shè)置的cookie的路徑都是/,這是不是意味著在Weblogic Server中默認(rèn)的就可以共享session了呢?然而一個(gè)小實(shí)驗(yàn)即可證明即使不同的應(yīng)用程序使用的是同一個(gè)session,各個(gè)應(yīng)用程序仍然只能訪問自己所設(shè)置的那些屬性。這說明Weblogic Server中的session的內(nèi)存結(jié)構(gòu)可能如下
    image

    對(duì)于這樣一種結(jié)構(gòu),在 session機(jī)制本身上來解決session共享的問題應(yīng)該是不可能的了。除了借助于第三方的力量,比如使用文件、數(shù)據(jù)庫、JMS或者客戶端 cookie,URL參數(shù)或者隱藏字段等手段,還有一種較為方便的做法,就是把一個(gè)應(yīng)用程序的session放到ServletContext中,這樣另外一個(gè)應(yīng)用程序就可以從ServletContext中取得前一個(gè)應(yīng)用程序的引用。示例代碼如下,

    應(yīng)用程序A
    context.setAttribute("appA", session);
    


    應(yīng)用程序B
    contextA = context.getContext("/appA");
    HttpSession sessionA = (HttpSession)contextA.getAttribute("appA");


    值得注意的是這種用法不可移植,因?yàn)楦鶕?jù)ServletContext的JavaDoc,應(yīng)用服務(wù)器可以處于安全的原因?qū)τ赾ontext.getContext("/appA");返回空值,以上做法在Weblogic Server 8.1中通過。

    那么Weblogic Server為什么要把所有的應(yīng)用程序的cookie路徑都設(shè)為/呢?原來是為了SSO,凡是共享這個(gè)session的應(yīng)用程序都可以共享認(rèn)證的信息。一個(gè)簡(jiǎn)單的實(shí)驗(yàn)就可以證明這一點(diǎn),修改首先登錄的那個(gè)應(yīng)用程序的描述符weblogic.xml,把cookie路徑修改為/appA 訪問另外一個(gè)應(yīng)用程序會(huì)重新要求登錄,即使是反過來,先訪問cookie路徑為/的應(yīng)用程序,再訪問修改過路徑的這個(gè),雖然不再提示登錄,但是登錄的用戶信息也會(huì)丟失。注意做這個(gè)實(shí)驗(yàn)時(shí)認(rèn)證方式應(yīng)該使用FORM,因?yàn)闉g覽器和web服務(wù)器對(duì)basic認(rèn)證方式有其他的處理方式,第二次請(qǐng)求的認(rèn)證不是通過 session來實(shí)現(xiàn)的。具體請(qǐng)參看[7] secion 14.8 Authorization,你可以修改所附的示例程序來做這些試驗(yàn)。

    八、總結(jié)
    session機(jī)制本身并不復(fù)雜,然而其實(shí)現(xiàn)和配置上的靈活性卻使得具體情況復(fù)雜多變。這也要求我們不能把僅僅某一次的經(jīng)驗(yàn)或者某一個(gè)瀏覽器,服務(wù)器的經(jīng)驗(yàn)當(dāng)作普遍適用的經(jīng)驗(yàn),而是始終需要具體情況具體分析。
    摘要:雖然session機(jī)制在web應(yīng)用程序中被采用已經(jīng)很長(zhǎng)時(shí)間了,但是仍然有很多人不清楚session機(jī)制的本質(zhì),以至不能正確的應(yīng)用這一技術(shù)。本文將詳細(xì)討論session的工作機(jī)制并且對(duì)在Java web application中應(yīng)用session機(jī)制時(shí)常見的問題作出解答。

    posted @ 2008-01-26 09:53 菠蘿 閱讀(336) | 評(píng)論 (0)編輯 收藏

    URLClassLoader加載class到當(dāng)前線程類加載器(轉(zhuǎn))

    我們知道,Java利用ClassLoader將類載入內(nèi)存,并且在同一應(yīng)用中,可以有很多個(gè)ClassLoader,通過委派機(jī)制,把裝載的任務(wù)傳遞給上級(jí)的裝載器的,依次類推,直到啟動(dòng)類裝載器(沒有上級(jí)類裝載器)。如果啟動(dòng)類裝載器能夠裝載這個(gè)類,那么它會(huì)首先裝載。如果不能,則往下傳遞。當(dāng)父類為null時(shí),JVM內(nèi)置的類(稱為:bootstrap class loader)就會(huì)充當(dāng)父類。想想眼下的越來越多用XML文件做配置文件或者是描述符、部署符。其實(shí)這些通過XML文檔描述的配置信息最終都要變成Java類,基實(shí)都是通過ClassLoader來完成的。URLClassLoader是ClassLoader的子類,它用于從指向 JAR 文件和目錄的 URL 的搜索路徑加載類和資源。也就是說,通過URLClassLoader就可以加載指定jar中的class到內(nèi)存中。
    下面來看一個(gè)例子,在該例子中,我們要完成的工作是利用URLClassLoader加載jar并運(yùn)行其中的類的某個(gè)方法。

    首先我們定義一個(gè)接口,使所有繼承它的類都必須實(shí)現(xiàn)action方法,如下:

      public   interface  ActionInterface  {
         public  String action();
    }
    完成后將其打包為testInterface.jar文件。

    接下來新建一工程,為了編譯通過,引入之前打好的testInterface.jar包。并創(chuàng)建TestAction類,使它實(shí)現(xiàn)ActionInterface接口。如下:


      public   class  TestAction  implements  ActionInterface  {
         public  String action()  {
             return   " com.mxjava.TestAction.action " ;
        }
    }
     
    完成后將其打包為test.jar,放在c盤根目錄下。下面要做的就是利用URLClassLoader加載并運(yùn)行TestAction的action方法,并將返回的值打印在控制臺(tái)上。

    新建一工程,引入testInterface.jar包。并創(chuàng)建一可執(zhí)行類(main方法),在其中加入如下代碼:

     URL url  =   new  URL(“file:C: / test.jar”);
    URLClassLoader myClassLoader  =   new  URLClassLoader( new  URL[]  { url } );
    Class myClass  =  myClassLoader.loadClass(“com.mxjava.TestAction”);
    ActionInterface action  =  (ActionInterface)myClass.newInstance();
    System.out.println(action.action());
      在上面的例子中,首先利用URLClassLoader加載了C:\test.jar包,將其中的com.mxjava.TestAction類載入內(nèi)存,將其強(qiáng)制轉(zhuǎn)型為testInterface包中的ActionInterface類型,最后調(diào)用其action方法,并打印到控制臺(tái)中。

      執(zhí)行程序后,在控制臺(tái)上如期打印出我們想要的內(nèi)容。但是,事情并沒有那么簡(jiǎn)單,當(dāng)我們將該代碼移動(dòng)web應(yīng)用中時(shí),就會(huì)拋出異常。原來,Java為我們提供了三種可選擇的ClassLoader:
    1. 系統(tǒng)類加載器或叫作應(yīng)用類加載器 (system classloader or application classloader)
    2. 當(dāng)前類加載器
    3. 當(dāng)前線程類加載器

      在上例中我們使用javac命令來運(yùn)行該程序,這時(shí)候使用的是系統(tǒng)類加載器 (system classloader)。這個(gè)類加載器處理 -classpath下的類加載工作,可以通過ClassLoader.getSystemClassLoader()方法調(diào)用。 ClassLoader 下所有的 getSystemXXX()的靜態(tài)方法都是通過這個(gè)方法定義的。在代碼中,應(yīng)該盡量少地調(diào)用這個(gè)方法,以其它的類加載器作為代理。否則代碼將只能工作在簡(jiǎn)單的命令行應(yīng)用中。當(dāng)在web應(yīng)用中時(shí),服務(wù)器也是利用ClassLoader來加載class的,由于ClassLoader的不同,所以在強(qiáng)制轉(zhuǎn)型時(shí)JVM認(rèn)定不是同一類型。(在JAVA中,一個(gè)類用其完全匹配類名(fully qualified class name)作為標(biāo)識(shí),這里指的完全匹配類名包括包名和類名。但在JVM中一個(gè)類用其全名和一個(gè)加載類ClassLoader的實(shí)例作為唯一標(biāo)識(shí)。因此,如果一個(gè)名為Pg的包中,有一個(gè)名為Cl的類,被類加載器KlassLoader的一個(gè)實(shí)例kl1加載,Cl的實(shí)例,即C1.class在JVM中表示為(Cl, Pg, kl1)。這意味著兩個(gè)類加載器的實(shí)例(Cl, Pg, kl1) 和 (Cl, Pg, kl2)是不同的,被它們所加載的類也因此完全不同,互不兼容的。)為了能夠使程序正確運(yùn)行,我們首要解決的問題就是,如何將URLClassLoader加載的類,同當(dāng)前ClassLoader保持在同一類加載器中。解決方法很簡(jiǎn)單,利用java提供的第三種ClassLoader—當(dāng)前線程類加載器即可。jdk api文檔就會(huì)發(fā)現(xiàn),URLClassLoader提供了三種構(gòu)造方式:

     // 使用默認(rèn)的委托父 ClassLoader 為指定的 URL 構(gòu)造一個(gè)新 URLClassLoader。 
     URLClassLoader(URL[] urls)
    // 為給定的 URL 構(gòu)造新 URLClassLoader。 
    URLClassLoader(URL[] urls, ClassLoader parent)
    // 為指定的 URL、父類加載器和 URLStreamHandlerFactory 創(chuàng)建新 URLClassLoader。
     URLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) 
    接下來要做的就是,在構(gòu)造URLClassLoader時(shí),將當(dāng)前線程類加載器置入即可。如下:

    URLClassLoader myClassLoader  =   new  URLClassLoader( new  URL[]  { url } , Thread.currentThread().getContextClassLoader());
    總結(jié):
      Java是利用ClassLoader來加載類到內(nèi)存的,ClassLoader本身是用java語言寫的,所以我們可以擴(kuò)展自己的ClassLoader。利用URLClassLoader可以加載指定jar包中的類到內(nèi)存。在命行上利用URLClassLoader加載jar時(shí),是使用系統(tǒng)類加載器來加載class的,所以在web環(huán)境下,就會(huì)出錯(cuò)。這是因?yàn)镴VM中一個(gè)類用其全名和一個(gè)加載類ClassLoader的實(shí)例作為唯一標(biāo)識(shí)的。我們只要利用URLClassLoader的第二種構(gòu)造方法并傳入當(dāng)前線程類加載器即可解決。

    posted @ 2008-01-26 09:51 菠蘿 閱讀(457) | 評(píng)論 (0)編輯 收藏

    了解Java ClassLoader

     

    【原文地址:https://www6.software.ibm.com/developerworks/cn/education/java/j-classloader/tutorial/】
    1.介紹
    2.ClassLoader的結(jié)構(gòu)
    3.Compiling ClassLoader
    4.java2 中ClassLoader的變動(dòng)
    5.源代碼
    ---------------------------------------------------------------------------

    第一章 介紹

    什么是 ClassLoader

    在流行的商業(yè)化編程語言中,Java 語言由于在 Java 虛擬機(jī) (JVM) 上運(yùn)行而顯得與眾不同。這意味著已編譯的程序是一種特殊的、獨(dú)立于平臺(tái)的格式,并非依賴于它們所運(yùn)行的機(jī)器。在很大程度上,這種格式不同于傳統(tǒng)的可執(zhí)行程序格式。

    與 C 或 C++ 編寫的程序不同,Java 程序并不是一個(gè)可執(zhí)行文件,而是由許多獨(dú)立的類文件組成,每一個(gè)文件對(duì)應(yīng)于一個(gè) Java 類。

    此外,這些類文件并非立即全部都裝入內(nèi)存,而是根據(jù)程序需要裝入內(nèi)存。ClassLoader 是 JVM 中將類裝入內(nèi)存的那部分。

    而且,Java ClassLoader 就是用 Java 語言編寫的。這意味著創(chuàng)建您自己的 ClassLoader 非常容易,不必了解 JVM 的微小細(xì)節(jié)。

    為什么編寫 ClassLoader?

    如果 JVM 已經(jīng)有一個(gè) ClassLoader,那么為什么還要編寫另一個(gè)呢?問得好。缺省的 ClassLoader 只知道如何從本地文件系統(tǒng)裝入類文件。不過這只適合于常規(guī)情況,即已全部編譯完 Java 程序,并且計(jì)算機(jī)處于等待狀態(tài)。

    但 Java 語言最具新意的事就是 JVM 可以非常容易地從那些非本地硬盤或從網(wǎng)絡(luò)上獲取類。例如,瀏覽者可以使用定制的 ClassLoader 從 Web 站點(diǎn)裝入可執(zhí)行內(nèi)容。

    有許多其它方式可以獲取類文件。除了簡(jiǎn)單地從本地或網(wǎng)絡(luò)裝入文件以外,可以使用定制的 ClassLoader 完成以下任務(wù):

    • 在執(zhí)行非置信代碼之前,自動(dòng)驗(yàn)證數(shù)字簽名
    • 使用用戶提供的密碼透明地解密代碼
    • 動(dòng)態(tài)地創(chuàng)建符合用戶特定需要的定制化構(gòu)建類
    任何您認(rèn)為可以生成 Java 字節(jié)碼的內(nèi)容都可以集成到應(yīng)用程序中。

    定制 ClassLoader 示例

    如果使用過 JDK 或任何基于 Java 瀏覽器中的 Applet 查看器,那么您差不多肯定使用過定制的 ClassLoader。

    Sun 最初發(fā)布 Java 語言時(shí),其中最令人興奮的一件事是觀看這項(xiàng)新技術(shù)是如何執(zhí)行在運(yùn)行時(shí)從遠(yuǎn)程的 Web 服務(wù)器裝入的代碼。(此外,還有更令人興奮的事 -- Java 技術(shù)提供了一種便于編寫代碼的強(qiáng)大語言。)更一些令人激動(dòng)的是它可以執(zhí)行從遠(yuǎn)程 Web 服務(wù)器通過 HTTP 連接發(fā)送過來的字節(jié)碼。

    此項(xiàng)功能歸功于 Java 語言可以安裝定制 ClassLoader。Applet 查看器包含一個(gè) ClassLoader,它不在本地文件系統(tǒng)中尋找類,而是訪問遠(yuǎn)程服務(wù)器上的 Web 站點(diǎn),經(jīng)過 HTTP 裝入原始的字節(jié)碼文件,并把它們轉(zhuǎn)換成 JVM 內(nèi)的類。

    瀏覽器和 Applet 查看器中的 ClassLoaders 還可以做其它事情:它們支持安全性以及使不同的 Applet 在不同的頁面上運(yùn)行而互不干擾。

    Luke Gorrie 編寫的 Echidna 是一個(gè)開放源碼包,它可以使您在單個(gè)虛擬機(jī)上運(yùn)行多個(gè) Java 應(yīng)用程序。(請(qǐng)參閱進(jìn)一步了解和參考資料。)它使用定制的 ClassLoader,通過向每個(gè)應(yīng)用程序提供該類文件的自身副本,以防止應(yīng)用程序互相干擾。


    我們的 ClassLoader 示例

    了解了 ClassLoader 如何工作以及如何編寫 ClassLoader 之后,我們將創(chuàng)建稱作 CompilingClassLoader (CCL) 的 Classloader。CCL 為我們編譯 Java 代碼,而無需要我們干涉這個(gè)過程。它基本上就類似于直接構(gòu)建到運(yùn)行時(shí)系統(tǒng)中的 "make" 程序。

    注:進(jìn)一步了解之前,應(yīng)注意在 JDK 版本 1.2 中已改進(jìn)了 ClassLoader 系統(tǒng)的某些方面(即 Java 2 平臺(tái))。本教程是按 JDK 版本 1.0 和 1.1 寫的,但也可以在以后的版本中運(yùn)行。

    Java 2 中 ClassLoader 的變動(dòng)描述了 Java 版本 1.2 中的變動(dòng),并提供了一些詳細(xì)信息,以便修改 ClassLoader 來利用這些變動(dòng)。

     


     

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

    第二章.ClassLoader的結(jié)構(gòu)



    ClassLoader 的基本目標(biāo)是對(duì)類的請(qǐng)求提供服務(wù)。當(dāng) JVM 需要使用類時(shí),它根據(jù)名稱向 ClassLoader 請(qǐng)求這個(gè)類,然后 ClassLoader 試圖返回一個(gè)表示這個(gè)類的 Class 對(duì)象。

    通過覆蓋對(duì)應(yīng)于這個(gè)過程不同階段的方法,可以創(chuàng)建定制的 ClassLoader。

    在本章的其余部分,您會(huì)學(xué)習(xí) Java ClassLoader 的關(guān)鍵方法。您將了解每一個(gè)方法的作用以及它是如何適合裝入類文件這個(gè)過程的。您也會(huì)知道,創(chuàng)建自己的 ClassLoader 時(shí),需要編寫什么代碼。

    在下一章中,您將會(huì)利用這些知識(shí)來使用我們的 ClassLoader 示例 -- CompilingClassLoader。


    方法 loadClass


    ClassLoader.loadClass() 是 ClassLoader 的入口點(diǎn)。其特征如下:

     

    Class loadClass( String name, boolean resolve );

    name 參數(shù)指定了 JVM 需要的類的名稱,該名稱以包表示法表示,如 Foojava.lang.Object。

    resolve 參數(shù)告訴方法是否需要解析類。在準(zhǔn)備執(zhí)行類之前,應(yīng)考慮類解析。并不總是需要解析。如果 JVM 只需要知道該類是否存在或找出該類的超類,那么就不需要解析。

    在 Java 版本 1.1 和以前的版本中,loadClass 方法是創(chuàng)建定制的 ClassLoader 時(shí)唯一需要覆蓋的方法。(Java 2 中 ClassLoader 的變動(dòng)提供了關(guān)于 Java 1.2 中 findClass() 方法的信息。)


    方法 defineClass

    defineClass 方法是 ClassLoader 的主要訣竅。該方法接受由原始字節(jié)組成的數(shù)組并把它轉(zhuǎn)換成 Class 對(duì)象。原始數(shù)組包含如從文件系統(tǒng)或網(wǎng)絡(luò)裝入的數(shù)據(jù)。

    defineClass 管理 JVM 的許多復(fù)雜、神秘和倚賴于實(shí)現(xiàn)的方面 -- 它把字節(jié)碼分析成運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)、校驗(yàn)有效性等等。不必?fù)?dān)心,您無需親自編寫它。事實(shí)上,即使您想要這么做也不能覆蓋它,因?yàn)樗驯粯?biāo)記成最終的。


    方法 findSystemClass

    findSystemClass 方法從本地文件系統(tǒng)裝入文件。它在本地文件系統(tǒng)中尋找類文件,如果存在,就使用 defineClass 將原始字節(jié)轉(zhuǎn)換成 Class 對(duì)象,以將該文件轉(zhuǎn)換成類。當(dāng)運(yùn)行 Java 應(yīng)用程序時(shí),這是 JVM 正常裝入類的缺省機(jī)制。(Java 2 中 ClassLoader 的變動(dòng)提供了關(guān)于 Java 版本 1.2 這個(gè)過程變動(dòng)的詳細(xì)信息。)

    對(duì)于定制的 ClassLoader,只有在嘗試其它方法裝入類之后,再使用 findSystemClass。原因很簡(jiǎn)單:ClassLoader 是負(fù)責(zé)執(zhí)行裝入類的特殊步驟,不是負(fù)責(zé)所有類。例如,即使 ClassLoader 從遠(yuǎn)程的 Web 站點(diǎn)裝入了某些類,仍然需要在本地機(jī)器上裝入大量的基本 Java 庫。而這些類不是我們所關(guān)心的,所以要 JVM 以缺省方式裝入它們:從本地文件系統(tǒng)。這就是 findSystemClass 的用途。

    其工作流程如下:

     

    • 請(qǐng)求定制的 ClassLoader 裝入類。
    • 檢查遠(yuǎn)程 Web 站點(diǎn),查看是否有所需要的類。
    • 如果有,那么好;抓取這個(gè)類,完成任務(wù)。
    • 如果沒有,假定這個(gè)類是在基本 Java 庫中,那么調(diào)用 findSystemClass,使它從文件系統(tǒng)裝入該類。

    在大多數(shù)定制 ClassLoaders 中,首先調(diào)用 findSystemClass 以節(jié)省在本地就可以裝入的許多 Java 庫類而要在遠(yuǎn)程 Web 站點(diǎn)上查找所花的時(shí)間。然而,正如,在下一章節(jié)所看到的,直到確信能自動(dòng)編譯我們的應(yīng)用程序代碼時(shí),才讓 JVM 從本地文件系統(tǒng)裝入類。


    方法 resolveClass

    正如前面所提到的,可以不完全地(不帶解析)裝入類,也可以完全地(帶解析)裝入類。當(dāng)編寫我們自己的 loadClass 時(shí),可以調(diào)用 resolveClass,這取決于 loadClassresolve 參數(shù)的值。

    方法 findLoadedClass

    findLoadedClass 充當(dāng)一個(gè)緩存:當(dāng)請(qǐng)求 loadClass 裝入類時(shí),它調(diào)用該方法來查看 ClassLoader 是否已裝入這個(gè)類,這樣可以避免重新裝入已存在類所造成的麻煩。應(yīng)首先調(diào)用該方法。

    組裝

     

     

     

    讓我們看一下如何組裝所有方法。

    我們的 loadClass 實(shí)現(xiàn)示例執(zhí)行以下步驟。(這里,我們沒有指定生成類文件是采用了哪種技術(shù) -- 它可以是從 Net 上裝入、或者從歸檔文件中提取、或者實(shí)時(shí)編譯。無論是哪一種,那是種特殊的神奇方式,使我們獲得了原始類文件字節(jié)。)

     

    • 調(diào)用 findLoadedClass 來查看是否存在已裝入的類。

    • 如果沒有,那么采用那種特殊的神奇方式來獲取原始字節(jié)。

    • 如果已有原始字節(jié),調(diào)用 defineClass 將它們轉(zhuǎn)換成 Class 對(duì)象。

    • 如果沒有原始字節(jié),然后調(diào)用 findSystemClass 查看是否從本地文件系統(tǒng)獲取類。

    • 如果 resolve 參數(shù)是 true,那么調(diào)用 resolveClass 解析 Class 對(duì)象。

    • 如果還沒有類,返回 ClassNotFoundException

    • 否則,將類返回給調(diào)用程序。
    推想

    現(xiàn)在您已經(jīng)了解了 ClassLoader 的工作原理,現(xiàn)在該構(gòu)建一個(gè)了。在下一章中,我們將討論 CCL。

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

    第三章:Compiling ClassLoader

    CCL 揭密

    我們的 ClassLoader (CCL) 的任務(wù)是確保代碼被編譯和更新。

    下面描述了它的工作方式:

     

    • 當(dāng)請(qǐng)求一個(gè)類時(shí),先查看它是否在磁盤的當(dāng)前目錄或相應(yīng)的子目錄。

    • 如果該類不存在,但源碼中有,那么調(diào)用 Java 編譯器來生成類文件。

    • 如果該類已存在,檢查它是否比源碼舊。如果是,調(diào)用 Java 編譯器來重新生成類文件。

    • 如果編譯失敗,或者由于其它原因不能從現(xiàn)有的源碼中生成類文件,返回 ClassNotFoundException。

    • 如果仍然沒有該類,也許它在其它庫中,所以調(diào)用 findSystemClass 來尋找該類。

    • 如果還是沒有,則返回 ClassNotFoundException。

    • 否則,返回該類。
    Java 編譯的工作方式

     

    在深入討論之前,應(yīng)該先退一步,討論 Java 編譯。通常,Java 編譯器不只是編譯您要求它編譯的類。它還會(huì)編譯其它類,如果這些類是您要求編譯的類所需要的類。

    CCL 逐個(gè)編譯應(yīng)用程序中的需要編譯的每一個(gè)類。但一般來說,在編譯器編譯完第一個(gè)類后,CCL 會(huì)查找所有需要編譯的類,然后編譯它。為什么?Java 編譯器類似于我們正在使用的規(guī)則:如果類不存在,或者與它的源碼相比,它比較舊,那么它需要編譯。其實(shí),Java 編譯器在 CCL 之前的一個(gè)步驟,它會(huì)做大部分的工作。

    當(dāng) CCL 編譯它們時(shí),會(huì)報(bào)告它正在編譯哪個(gè)應(yīng)用程序上的類。在大多數(shù)的情況下,CCL 會(huì)在程序中的主類上調(diào)用編譯器,它會(huì)做完所有要做的 -- 編譯器的單一調(diào)用已足夠了。

    然而,有一種情形,在第一步時(shí)不會(huì)編譯某些類。如果使用 Class.forName 方法,通過名稱來裝入類,Java 編譯器會(huì)不知道這個(gè)類時(shí)所需要的。在這種情況下,您會(huì)看到 CCL 再次運(yùn)行 Java 編譯器來編譯這個(gè)類。在源代碼中演示了這個(gè)過程。

    使用 CompilationClassLoader

    要使用 CCL,必須以特殊方式調(diào)用程序。不能直接運(yùn)行該程序,如:

     

    % java Foo arg1 arg2

    應(yīng)以下列方式運(yùn)行它:

     

    % java CCLRun Foo arg1 arg2

    CCLRun 是一個(gè)特殊的存根程序,它創(chuàng)建 CompilingClassLoader 并用它來裝入程序的主類,以確保通過 CompilingClassLoader 來裝入整個(gè)程序。CCLRun 使用 Java Reflection API 來調(diào)用特定類的主方法并把參數(shù)傳遞給它。有關(guān)詳細(xì)信息,請(qǐng)參閱源代碼。

    運(yùn)行示例

    源碼包括了一組小類,它們演示了工作方式。主程序是 Foo 類,它創(chuàng)建類 Bar 的實(shí)例。類 Bar 創(chuàng)建另一個(gè)類 Baz 的實(shí)例,它在 baz 包內(nèi),這是為了展示 CCL 是如何處理子包里的代碼。Bar 也是通過名稱裝入的,其名稱為 Boo,這用來展示它也能與 CCL 工作。

    每個(gè)類都聲明已被裝入并運(yùn)行?,F(xiàn)在用源代碼來試一下。編譯 CCLRun 和 CompilingClassLoader。確保不要編譯其它類(FooBarBazBoo),否則將不會(huì)使用 CCL,因?yàn)檫@些類已經(jīng)編譯過了。

     


    % java CCLRun Foo arg1 arg2
    CCL: Compiling Foo.java...
    foo! arg1 arg2
    bar! arg1 arg2
    baz! arg1 arg2
    CCL: Compiling Boo.java...
    Boo!

    請(qǐng)注意,首先調(diào)用編譯器,Foo.java 管理 Barbaz.Baz。直到 Bar 通過名稱來裝入 Boo 時(shí),被調(diào)用它,這時(shí) CCL 會(huì)再次調(diào)用編譯器來編譯它。

     

     

     

     

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

    第四章:java2 中ClassLoader的變動(dòng)


    概述

    在 Java 版本 1.2 和以后的版本中,對(duì) ClassLoader 做了一些改進(jìn)。任何為老系統(tǒng)編寫的代碼可以在新版本中運(yùn)行,但新系統(tǒng)為您提供了一些便利。

    新模型是委托模型,這意味著如果 ClassLoader 不能找到類,它會(huì)請(qǐng)求父代 ClassLoader 來執(zhí)行此項(xiàng)任務(wù)。所有 ClassLoaders 的根是系統(tǒng) ClassLoader,它會(huì)以缺省方式裝入類 -- 即,從本地文件系統(tǒng)。

    loadClass 的缺省實(shí)現(xiàn)

    定制編寫的 loadClass 方法一般嘗試幾種方式來裝入所請(qǐng)求的類,如果您編寫許多類,會(huì)發(fā)現(xiàn)一次次地在相同的、很復(fù)雜的方法上編寫變量。

    在 Java 1.2 中 loadClass 的實(shí)現(xiàn)嵌入了大多數(shù)查找類的一般方法,并使您通過覆蓋 findClass 方法來定制它,在適當(dāng)?shù)臅r(shí)候 findClass 會(huì)調(diào)用 loadClass。

    這種方式的好處是您可能不一定要覆蓋 loadClass;只要覆蓋 findClass 就行了,這減少了工作量。

    新方法:findClass

    loadClass 的缺省實(shí)現(xiàn)調(diào)用這個(gè)新方法。findClass 的用途包含您的 ClassLoader 的所有特殊代碼,而無需要復(fù)制其它代碼(例如,當(dāng)專門的方法失敗時(shí),調(diào)用系統(tǒng) ClassLoader)。

    新方法:getSystemClassLoader

    如果覆蓋 findClassloadClassgetSystemClassLoader 使您能以實(shí)際 ClassLoader 對(duì)象來訪問系統(tǒng) ClassLoader(而不是固定的從 findSystemClass 調(diào)用它)。

    新方法:getParent

    為了將類請(qǐng)求委托給父代 ClassLoader,這個(gè)新方法允許 ClassLoader 獲取它的父代 ClassLoader。當(dāng)使用特殊方法,定制的 ClassLoader 不能找到類時(shí),可以使用這種方法。

    父代 ClassLoader 被定義成創(chuàng)建該 ClassLoader 所包含代碼的對(duì)象的 ClassLoader。

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

     

     

     

    第五章.源代碼

     

    CompilingClassLoader.java

    以下是 CompilingClassLoader.java 的源代碼

    // $Id$
    import java.io.*;
    /*
    A CompilingClassLoader compiles your Java source on-the-fly. It checks
    for nonexistent .class files, or .class files that are older than their
    corresponding source code.*/
    public class CompilingClassLoader extends ClassLoader
    {
    // Given a filename, read the entirety of that file from disk
    // and return it as a byte array.
    private byte[] getBytes( String filename ) throws IOException {
    // Find out the length of the file
    File file = new File( filename );
    long len = file.length();
    // Create an array that's just the right size for the file's
    // contents
    byte raw[] = new byte[(int)len];
    // Open the file
    FileInputStream fin = new FileInputStream( file );
    // Read all of it into the array; if we don't get all,
    // then it's an error.
    int r = fin.read( raw );
    if (r != len)
    throw new IOException( "Can't read all, "+r+" != "+len );
    // Don't forget to close the file!
    fin.close();
    // And finally return the file contents as an array
    return raw;
    }
    // Spawn a process to compile the java source code file
    // specified in the 'javaFile' parameter. Return a true if
    // the compilation worked, false otherwise.
    private boolean compile( String javaFile ) throws IOException {
    // Let the user know what's going on
    System.out.println( "CCL: Compiling "+javaFile+"..." );
    // Start up the compiler
    Process p = Runtime.getRuntime().exec( "javac "+javaFile );
    // Wait for it to finish running
    try {
    p.waitFor();
    } catch( InterruptedException ie ) { System.out.println( ie ); }
    // Check the return code, in case of a compilation error
    int ret = p.exitValue();
    // Tell whether the compilation worked
    return ret==0;
    }
    // The heart of the ClassLoader -- automatically compile
    // source as necessary when looking for class files
    public Class loadClass( String name, boolean resolve )
    throws ClassNotFoundException {

    // Our goal is to get a Class object
    Class clas = null;

    // First, see if we've already dealt with this one
    clas = findLoadedClass( name );

    //System.out.println( "findLoadedClass: "+clas );

    // Create a pathname from the class name
    // E.g. java.lang.Object => java/lang/Object
    String fileStub = name.replace( '.', '/' );

    // Build objects pointing to the source code (.java) and object
    // code (.class)
    String javaFilename = fileStub+".java";
    String classFilename = fileStub+".class";

    File javaFile = new File( javaFilename );
    File classFile = new File( classFilename );

    //System.out.println( "j "+javaFile.lastModified()+" c "+
    // classFile.lastModified() );

    // First, see if we want to try compiling. We do if (a) there
    // is source code, and either (b0) there is no object code,
    // or (b1) there is object code, but it's older than the source
    if (javaFile.exists() &&
    (!classFile.exists() ||
    javaFile.lastModified() > classFile.lastModified())) {

    try {
    // Try to compile it. If this doesn't work, then
    // we must declare failure. (It's not good enough to use
    // and already-existing, but out-of-date, classfile)
    if (!compile( javaFilename ) || !classFile.exists()) {
    throw new ClassNotFoundException( "Compile failed: "+javaFilename );
    }
    } catch( IOException ie ) {

    // Another place where we might come to if we fail
    // to compile
    throw new ClassNotFoundException( ie.toString() );
    }
    }

    // Let's try to load up the raw bytes, assuming they were
    // properly compiled, or didn't need to be compiled
    try {

    // read the bytes
    byte raw[] = getBytes( classFilename );

    // try to turn them into a class
    clas = defineClass( name, raw, 0, raw.length );
    } catch( IOException ie ) {
    // This is not a failure! If we reach here, it might
    // mean that we are dealing with a class in a library,
    // such as java.lang.Object
    }

    //System.out.println( "defineClass: "+clas );

    // Maybe the class is in a library -- try loading
    // the normal way
    if (clas==null) {
    clas = findSystemClass( name );
    }

    //System.out.println( "findSystemClass: "+clas );

    // Resolve the class, if any, but only if the "resolve"
    // flag is set to true
    if (resolve && clas != null)
    resolveClass( clas );

    // If we still don't have a class, it's an error
    if (clas == null)
    throw new ClassNotFoundException( name );

    // Otherwise, return the class
    return clas;
    }
     }
    CCRun.java


    以下是 CCRun.java 的源代碼


    // $Id$

    import java.lang.reflect.*;

    /*

    CCLRun executes a Java program by loading it through a
    CompilingClassLoader.

    */

    public class CCLRun
    {
    static public void main( String args[] ) throws Exception {

    // The first argument is the Java program (class) the user
    // wants to run
    String progClass = args[0];

    // And the arguments to that program are just
    // arguments 1..n, so separate those out into
    // their own array
    String progArgs[] = new String[args.length-1];
    System.arraycopy( args, 1, progArgs, 0, progArgs.length );

    // Create a CompilingClassLoader
    CompilingClassLoader ccl = new CompilingClassLoader();

    // Load the main class through our CCL
    Class clas = ccl.loadClass( progClass );

    // Use reflection to call its main() method, and to
    // pass the arguments in.

    // Get a class representing the type of the main method's argument
    Class mainArgType[] = { (new String[0]).getClass() };

    // Find the standard main method in the class
    Method main = clas.getMethod( "main", mainArgType );

    // Create a list containing the arguments -- in this case,
    // an array of strings
    Object argsArray[] = { progArgs };

    // Call the method
    main.invoke( null, argsArray );
    }
    }
    Foo.java


    以下是 Foo.java 的源代碼



    // $Id$

    public class Foo
    {
    static public void main( String args[] ) throws Exception {
    System.out.println( "foo! "+args[0]+" "+args[1] );
    new Bar( args[0], args[1] );
    }
    }
    Bar.java


    以下是 Bar.java 的源代碼


    // $Id$

    import baz.*;

    public class Bar
    {
    public Bar( String a, String b ) {
    System.out.println( "bar! "+a+" "+b );
    new Baz( a, b );

    try {
    Class booClass = Class.forName( "Boo" );
    Object boo = booClass.newInstance();
    } catch( Exception e ) {
    e.printStackTrace();
    }
    }
    }
    baz/Baz.java


    以下是 baz/Baz.java 的源代碼


    // $Id$

    package baz;

    public class Baz
    {
    public Baz( String a, String b ) {
    System.out.println( "baz! "+a+" "+b );
    }
    }

    Boo.java


    以下是 Boo.java 的源代碼


    // $Id$

    public class Boo
    {
    public Boo() {
    System.out.println( "Boo!" );
    }
    }

    posted @ 2008-01-25 13:52 菠蘿 閱讀(326) | 評(píng)論 (0)編輯 收藏

    eclipse配置weblogic(轉(zhuǎn))

    安裝WebLogic8.1
    安裝WebLogic比較容易,在這里就不再累述了,大家可以參閱相關(guān)文檔?,F(xiàn)在著重講一下WebLogic的配置,因?yàn)楹竺嬖谂渲肕yEclipse時(shí)將用到這里的有關(guān)信息。
    (1)運(yùn)行開始\程序\BEA WebLogic PlatFORM 8.1\Configuration Wizard。
    (2)選擇Create a new WebLogic configuration,下一步。
    (3)選擇Basic WebLogic Server Domain,下一步。
    (4)選擇Custom,下一步。
    (5)在Name處輸入admin,Listen Address處選擇localhost,以下兩個(gè)Port均采用默認(rèn)值,下一步。
    (6)選擇Skip跳過Multiple Servers,Clusters,and Machines Options,下一步。
    (7)選擇Skip跳過JDBC連接池的配置(注:JDBC連接池的配置可以在啟動(dòng)WebLogic后到控制臺(tái)上進(jìn)行,大家可以參閱相關(guān)文檔),下一步。
    (選擇Skip跳過JMS的配置(同樣留到控制臺(tái)上做),下一步。
    (9)繼續(xù)跳過,下一步。
    (10)選擇Yes,下一步。
    (11)在User頁點(diǎn)擊Add,隨意添加一個(gè)用戶user,密碼12345678,下一步。
    (12)將用戶user分配到Administrators組(還可以同時(shí)分配到其它組,方法是選中待加入的組,然后勾中user前的復(fù)選框即可),下一步。
    (13)直接點(diǎn)擊下一步跳過。
    (14)設(shè)置用戶user的權(quán)限,選中Admin,勾中user前的復(fù)選框(要指定其它權(quán)限依次類推),下一步。
    (15)采用默認(rèn)設(shè)置,直接點(diǎn)擊下一步跳過。
    (16)同樣采用默認(rèn)設(shè)置,直接點(diǎn)擊下一步跳過。
    (17)配置JDK,采用WebLogic的默認(rèn)值,直接點(diǎn)擊下一步跳過。
    (1最后在Configuration Name處輸入dev,然后點(diǎn)擊Create生成配置,完畢點(diǎn)擊Done關(guān)閉Configuration Wizard對(duì)話框。
    5.配置MyEclipse的WebLogic服務(wù)器
    MyEclipse默認(rèn)的應(yīng)用服務(wù)器為JBoss3,這里我們使用WebLogic8.1。啟動(dòng)Eclipse,選擇“窗口\首選項(xiàng)”菜單,打開首選項(xiàng)對(duì)話框。展開MyEclipse下的Application Servers結(jié)點(diǎn),點(diǎn)擊JBoss 3,選中右面的Disable單選按鈕,停用JBoss 3。然后點(diǎn)擊WebLogic 8,選中右邊的Enable單選按鈕,啟用WebLogic服務(wù)器。同時(shí)下面的配置如下:
    (1)BEA home directory:D:\BEA。假定WebLogic安裝在D:\BEA文件夾中。
    (2)WebLogic installation directory:D:\BEA\weblogic81。
    (3)Admin username:user。
    (4)Admin password:12345678。
    (5)Execution domain root:D:\BEA\user_projects\dev。
    (6)Execution domain name:dev。
    (7)Execution server name:admin。
    (8)Hostname:PortNumber:localhost:7001。
    (9)Security policy file:D:\BEA\weblogic81\server\lib\weblogic.policy。
    (10)JAAS login configuration file:省略。
    接著展開WebLogic 8結(jié)點(diǎn),點(diǎn)擊JDK,在右邊的WLS JDK name處選擇WebLogic 8的默認(rèn)JDK。這里組合框中缺省為j2re1.4.2_03,即之前單獨(dú)安裝的jre。單擊Add按鈕,彈出WebLogic > Add JVM對(duì)話框,在JRE名稱處隨便輸入一個(gè)名字,如jre1.4.1_02。然后在JRE主目錄處選擇WebLogic安裝文件夾中的JDK文件夾,如D:\BEA\jdk141_02,程序會(huì)自動(dòng)填充Javadoc URL文本框和JRE系統(tǒng)庫列表框。單擊確定按鈕關(guān)閉對(duì)話框。這時(shí)候就可以在WLS JDK name組合框中選擇jre1.4.1_02了。之后還要在下面的Optional Java VM arguments,如-ms64m -mx64m -Djava.library.path="D:/BEA/weblogic81/server/bin" -Dweblogic.management.discover=false -Dweblogic.ProductionModeEnabled=false
    最后點(diǎn)擊Paths,在右邊的Prepend to classpath列表框中,通過Add JAR/ZIP按鈕,加入D:\BEA\weblogic81\server\lib\weblogic.jar、D:\BEA\weblogic81\server\lib\webservices.jar。如果用到數(shù)據(jù)庫,還需把數(shù)據(jù)庫的驅(qū)動(dòng)類庫加進(jìn)來,這里我們用WebLogic自帶的SQL Server數(shù)據(jù)庫驅(qū)動(dòng)庫D:\BEA\weblogic81\server\lib\mssqlserver4v65.jar。
    至此,MyEclipse中WebLogic8的配置工作就算完成了。下面可以看看在Eclipse中能否啟動(dòng)WebLogic了?自從安裝了MyEclipse之后,Eclipse工具欄中就會(huì)有一個(gè)Run/Stop Servers下拉按鈕。點(diǎn)擊該按鈕的下拉部分,選擇“WebLogic 8\Start”菜單,即開始啟動(dòng)WebLogic了。通過查看下面的控制臺(tái)消息,就可以知道啟動(dòng)是否成功,或有什么異常發(fā)生。停止WebLogic可選擇“WebLogic\Stop”菜單。 

    posted @ 2008-01-24 15:33 菠蘿 閱讀(991) | 評(píng)論 (0)編輯 收藏

    J2EE配置WebLogic-Eclipse插件(轉(zhuǎn))

    Eclipse插件設(shè)計(jì)用于從Eclipse IDE運(yùn)行 WebLogic Server.借助WebLogic Server插件,可以從Eclipse中啟動(dòng)和停止WebLogic Server,可以通過 Eclipse調(diào)試WebLogic Server中部署的應(yīng)用程序。在Eclipse中安裝WebLogic插件,并在Eclipse中設(shè)置服務(wù)器類路徑和JVM選項(xiàng)后,即可通過Eclipse IDE配置和管理WebLogic Server.

      概述

      J2EE開發(fā)人員經(jīng)常需要管理WebLogic Server并調(diào)試WebLogic Server上部署的應(yīng)用程序。 WebLogic Server管理控制臺(tái)雖然能夠啟動(dòng)和停止WebLogic Server,卻不能設(shè)置JVM選項(xiàng)和服務(wù)器類路徑。必須使用startWebLogic腳本來設(shè)置JVM選項(xiàng)和服務(wù)器類路徑。而要調(diào)試WebLogic Server上部署的應(yīng)用程序,則需要帶遠(yuǎn)程調(diào)試器的IDE.有了WebLogic插件后,就可以通過Eclipse IDE管理WebLogic Server. 在文本中,我們將開發(fā)一個(gè)包括會(huì)話EJB和servlet的J2EE應(yīng)用程序、通過Eclipse IDE在WebLogic Server中部署應(yīng)用程序、在Eclipse中調(diào)試應(yīng)用程序。

      安裝準(zhǔn)備

      下載并安裝Eclipse 3.0 IDE:www.eclipse.org

      下載并安裝WebLogic Server 8.1:

      www.bea.com/framework.jsp?CNT=index.htm&FP=/content/products/weblogic/server

      安裝WebLogic-Eclipse插件

      現(xiàn)在安裝WebLogic-Eclipse IDE.在Eclipse IDE上,選擇Help>Software Updates>Find and Install,將顯示Install/Update窗體。選擇Search for new features to install,然后單擊Next按鈕。在顯示的Install窗體中,單擊New Remote Site按鈕指定要從其安裝插件的更新Web站點(diǎn)。在New Update Site窗體中,指定名稱和安裝WebLogic-Eclipse插件的URL.WebLogic-Eclipse插件的URL是

      選擇許可條款并單擊Next按鈕。在Install location窗體中指定將安裝WebLogic-Eclipse插件的目錄。單擊Finish按鈕完成WebLogic插件的配置。在顯示的JAR Verification窗體中,單擊Install按鈕安裝WebLogic-Eclipse插件。重啟Eclipse工作臺(tái)完成插件安裝。現(xiàn)在WebLogic-Eclipse插件便安裝在 Eclipse IDE中了。Eclipse中新添了Run>Start WebLogic和Run>Stop WebLogic兩個(gè)功能。

      配置WebLogic-Eclipse插件

      安裝了WebLogic-Eclipse插件后,我們將在Eclipse IDE中配置該插件。首先,創(chuàng)建一個(gè)用于配置WebLogic插件的項(xiàng)目。選擇File>New>Project.在New Project窗體中選擇Java>Java Project,然后單擊Next按鈕。在Create a Java project窗體中指定項(xiàng)目名稱,然后單擊Next按鈕。在Java Settings窗體中為項(xiàng)目添加源文件夾。單擊Add Folder按鈕。在New Source Folder窗體中指定文件夾名稱。出現(xiàn)一個(gè)消息窗體提示設(shè)置bin文件夾作為構(gòu)建輸出文件夾。接下來,添加項(xiàng)目所需的庫。示例應(yīng)用程序需要在類路徑中添加J2EE JAR.選擇Libraries選項(xiàng)卡,然后單擊Add External JARs按鈕。

      為項(xiàng)目添加J2EE 1.4 j2ee.jar文件。1.4 j2ee.jar將在項(xiàng)目庫中列出。單擊Finish按鈕完成項(xiàng)目配置。這樣便將一個(gè)項(xiàng)目添加到Eclipse IDE Package Explorer視圖中。

      接下來指定WebLogic Server配置。選擇Window>Preferences.在出現(xiàn)的Preferences窗體中,選擇WebLogic節(jié)點(diǎn)。在WebLogic preference頁面,選擇要配置的WebLogic Server版本。指定不同的字段值,如 表1 所示。由于安裝服務(wù)器和配置域的目錄不同,值也有所不同。單擊Apply按鈕應(yīng)用指定的值。

      字段描述值

      表1 WebLogic-Eclipse插件

      如果必須向服務(wù)器類路徑添加JAR文件,請(qǐng)選擇WebLogic>Classpath節(jié)點(diǎn)。可以在添加WebLogic庫之前或之后添加JAR/Zip文件或目錄。選擇WebLogic>JavaVM Options節(jié)點(diǎn)指定JavaVM選項(xiàng)。例如,修改weblogic.ProductionModeEnabled屬性。將屬性值設(shè)置為false可使用開發(fā)模式啟動(dòng)服務(wù)器。單擊Apply按鈕應(yīng)用JavaVM選項(xiàng)。

      接下來,指定要使用WebLogic Server配置進(jìn)行調(diào)試的項(xiàng)目。單擊Add按鈕,選擇要添加到插件配置的項(xiàng)目。若要調(diào)試某個(gè)項(xiàng)目,該項(xiàng)目必須位于插件配置中。單擊OK按鈕。

      這樣便將選擇的項(xiàng)目添加到項(xiàng)目列表中了。單擊Apply按鈕,然后單擊OK按鈕,使用項(xiàng)目和WebLogic Server完成WebLogic插件的配置。

      開發(fā)和調(diào)試WebLogic應(yīng)用程序

      配置了WebLogic插件后,將開發(fā)一個(gè)J2EE應(yīng)用程序在WebLogic Server中進(jìn)行部署和調(diào)試。示例J2EE應(yīng)用程序由Session EJB和客戶端servlet組成??蓮馁Y源zip文件中獲取該 J2EE應(yīng)用程序(關(guān)于本文的源代碼,可在線查看WLDJ歸檔文件中的文章 http://wldj.sys-con.com/read/issue/archives/,Vol. 5,iss. 2)。將資源zip文件提取到目錄。在上文中配置的Eclipse項(xiàng)目EclipseWebLogic中,選擇File>Import導(dǎo)入J2EE應(yīng)用程序的src目錄。在Import窗體中,選擇File System節(jié)點(diǎn),然后單擊Next按鈕。在File system窗體中,選擇directories/files添加項(xiàng)目,然后單擊Finish按鈕(見圖1)。

    配置WebLogic-Eclipse插件 圖-1

      圖1

      這樣便將示例J2EE應(yīng)用程序文件添加到項(xiàng)目中。使用Ant build.xml文件構(gòu)建項(xiàng)目。右鍵單擊build.xml,選擇Run>Ant Build即可構(gòu)建J2EE應(yīng)用程序并將其部署在WebLogic Server應(yīng)用程序目錄中。接下來,選擇Run>Start WebLogic在Eclipse IDE中啟動(dòng)WebLogic Server.這樣便將Session EJB/Servlet應(yīng)用程序部署在 WebLogic Server中,如應(yīng)用程序節(jié)點(diǎn)所示。

      在瀏覽器中輸入U(xiǎn)RL http://localhost:7001/weblogic/webLogicPlug-in運(yùn)行WebLogicServlet. servlet的輸出將在瀏覽器中顯示。接下來向客戶端servlet添加一個(gè)異常(NullPointerException),以驗(yàn)證WebLogic插件的調(diào)試功能。在WebLogicServlet servlet中將:

      out.println(sessionEJB.getEclipsePlug-in());

      替換為:

      String str=null;

      out.println(str.toString());

      選擇Run>Add Java Exception Breakpoint向servlet添加一個(gè)斷點(diǎn)。在Add Java Exception Breakpoint窗體中,選擇NullPointerException.刪除之前構(gòu)建的目錄并使用build.xml構(gòu)建應(yīng)用程序。選擇Debug perspective.在Debug perspective可以看到WebLogic Server正運(yùn)行在localhost主機(jī)中。

      在瀏覽器中運(yùn)行示例servlet(帶NullPointerException)。因?yàn)閟ervlet帶有異常,所以服務(wù)器被中斷,并且Debug perspective顯示NullPointerException.使用Run菜單項(xiàng)中的調(diào)試功能可以調(diào)試應(yīng)用程序。

      結(jié)束語

      綜上所述,使用WebLogic插件可以通過Eclipse IDE管理WebLogic Server,還可通過Eclipse IDE調(diào)試服務(wù)器中部署的應(yīng)用程序。WebLogic插件的局限性在于不支持JSP調(diào)試。該插件的2.0版本將有更多功能。

    J2EE配置WebLogic-Eclipse插件

    posted @ 2008-01-24 15:32 菠蘿 閱讀(452) | 評(píng)論 (0)編輯 收藏

    C3P0連接池詳細(xì)配置(轉(zhuǎn))

    <c3p0-config>
    <default-config>
    <!--當(dāng)連接池中的連接耗盡的時(shí)候c3p0一次同時(shí)獲取的連接數(shù)。Default: 3 -->
    <property name="acquireIncrement">3</property>

    <!--定義在從數(shù)據(jù)庫獲取新連接失敗后重復(fù)嘗試的次數(shù)。Default: 30 -->
    <property name="acquireRetryAttempts">30</property>

    <!--兩次連接中間隔時(shí)間,單位毫秒。Default: 1000 -->
    <property name="acquireRetryDelay">1000</property>

    <!--連接關(guān)閉時(shí)默認(rèn)將所有未提交的操作回滾。Default: false -->
    <property name="autoCommitOnClose">false</property>

    <!--c3p0將建一張名為Test的空表,并使用其自帶的查詢語句進(jìn)行測(cè)試。如果定義了這個(gè)參數(shù)那么
    屬性preferredTestQuery將被忽略。你不能在這張Test表上進(jìn)行任何操作,它將只供c3p0測(cè)試
    使用。Default: null-->
    <property name="automaticTestTable">Test</property>

    <!--獲取連接失敗將會(huì)引起所有等待連接池來獲取連接的線程拋出異常。但是數(shù)據(jù)源仍有效
    保留,并在下次調(diào)用getConnection()的時(shí)候繼續(xù)嘗試獲取連接。如果設(shè)為true,那么在嘗試
    獲取連接失敗后該數(shù)據(jù)源將申明已斷開并永久關(guān)閉。Default: false-->
    <property name="breakAfterAcquireFailure">false</property>

    <!--當(dāng)連接池用完時(shí)客戶端調(diào)用getConnection()后等待獲取新連接的時(shí)間,超時(shí)后將拋出
    SQLException,如設(shè)為0則無限期等待。單位毫秒。Default: 0 -->
    <property name="checkoutTimeout">100</property>

    <!--通過實(shí)現(xiàn)ConnectionTester或QueryConnectionTester的類來測(cè)試連接。類名需制定全路徑。
    Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->
    <property name="connectionTesterClassName"></property>

    <!--指定c3p0 libraries的路徑,如果(通常都是這樣)在本地即可獲得那么無需設(shè)置,默認(rèn)null即可
    Default: null-->
    <property name="factoryClassLocation">null</property>

    <!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs.
    (文檔原文)作者強(qiáng)烈建議不使用的一個(gè)屬性-->
    <property name="forceIgnoreUnresolvedTransactions">false</property>

    <!--每60秒檢查所有連接池中的空閑連接。Default: 0 -->
    <property name="idleConnectionTestPeriod">60</property>

    <!--初始化時(shí)獲取三個(gè)連接,取值應(yīng)在minPoolSize與maxPoolSize之間。Default: 3 -->
    <property name="initialPoolSize">3</property>

    <!--最大空閑時(shí)間,60秒內(nèi)未使用則連接被丟棄。若為0則永不丟棄。Default: 0 -->
    <property name="maxIdleTime">60</property>

    <!--連接池中保留的最大連接數(shù)。Default: 15 -->
    <property name="maxPoolSize">15</property>

    <!--JDBC的標(biāo)準(zhǔn)參數(shù),用以控制數(shù)據(jù)源內(nèi)加載的PreparedStatements數(shù)量。但由于預(yù)緩存的statements
    屬于單個(gè)connection而不是整個(gè)連接池。所以設(shè)置這個(gè)參數(shù)需要考慮到多方面的因素。
    如果maxStatements與maxStatementsPerConnection均為0,則緩存被關(guān)閉。Default: 0-->
    <property name="maxStatements">100</property>

    <!--maxStatementsPerConnection定義了連接池內(nèi)單個(gè)連接所擁有的最大緩存statements數(shù)。Default: 0 -->
    <property name="maxStatementsPerConnection"></property>

    <!--c3p0是異步操作的,緩慢的JDBC操作通過幫助進(jìn)程完成。擴(kuò)展這些操作可以有效的提升性能
    通過多線程實(shí)現(xiàn)多個(gè)操作同時(shí)被執(zhí)行。Default: 3-->
    <property name="numHelperThreads">3</property>

    <!--當(dāng)用戶調(diào)用getConnection()時(shí)使root用戶成為去獲取連接的用戶。主要用于連接池連接非c3p0
    的數(shù)據(jù)源時(shí)。Default: null-->
    <property name="overrideDefaultUser">root</property>

    <!--與overrideDefaultUser參數(shù)對(duì)應(yīng)使用的一個(gè)參數(shù)。Default: null-->
    <property name="overrideDefaultPassword">password</property>

    <!--密碼。Default: null-->
    <property name="password"></property>

    <!--定義所有連接測(cè)試都執(zhí)行的測(cè)試語句。在使用連接測(cè)試的情況下這個(gè)一顯著提高測(cè)試速度。注意:
    測(cè)試的表必須在初始數(shù)據(jù)源的時(shí)候就存在。Default: null-->
    <property name="preferredTestQuery">select id from test where id=1</property>

    <!--用戶修改系統(tǒng)配置參數(shù)執(zhí)行前最多等待300秒。Default: 300 -->
    <property name="propertyCycle">300</property>

    <!--因性能消耗大請(qǐng)只在需要的時(shí)候使用它。如果設(shè)為true那么在每個(gè)connection提交的
    時(shí)候都將校驗(yàn)其有效性。建議使用idleConnectionTestPeriod或automaticTestTable
    等方法來提升連接測(cè)試的性能。Default: false -->
    <property name="testConnectionOnCheckout">false</property>

    <!--如果設(shè)為true那么在取得連接的同時(shí)將校驗(yàn)連接的有效性。Default: false -->
    <property name="testConnectionOnCheckin">true</property>

    <!--用戶名。Default: null-->
    <property name="user">root</property>

    <!--早期的c3p0版本對(duì)JDBC接口采用動(dòng)態(tài)反射代理。在早期版本用途廣泛的情況下這個(gè)參數(shù)
    允許用戶恢復(fù)到動(dòng)態(tài)反射代理以解決不穩(wěn)定的故障。最新的非反射代理更快并且已經(jīng)開始
    廣泛的被使用,所以這個(gè)參數(shù)未必有用。現(xiàn)在原先的動(dòng)態(tài)反射與新的非反射代理同時(shí)受到
    支持,但今后可能的版本可能不支持動(dòng)態(tài)反射代理。Default: false-->
    <property name="usesTraditionalReflectiveProxies">false</property>

    <property name="automaticTestTable">con_test</property>
    <property name="checkoutTimeout">30000</property>
    <property name="idleConnectionTestPeriod">30</property>
    <property name="initialPoolSize">10</property>
    <property name="maxIdleTime">30</property>
    <property name="maxPoolSize">25</property>
    <property name="minPoolSize">10</property>
    <property name="maxStatements">0</property>
    <user-overrides user="swaldman">
    </user-overrides>
    </default-config>
    <named-config name="dumbTestConfig">
    <property name="maxStatements">200</property>
    <user-overrides user="poop">
    <property name="maxStatements">300</property>
    </user-overrides>
    </named-config>
    </c3p0-config>

    posted @ 2008-01-18 11:58 菠蘿 閱讀(242) | 評(píng)論 (0)編輯 收藏

    修改jfreechart中的默認(rèn)字體

    生成圖表后自動(dòng)生成chart表的問題:

    我測(cè)試生成圖表中的中文問題都解決了,但是每次生成chart圖時(shí)會(huì)報(bào)UTF編碼錯(cuò)誤,從錯(cuò)誤判斷應(yīng)該是某個(gè)文件的編碼錯(cuò)誤,起初根據(jù)錯(cuò)誤判斷是filter的問題,可是filter那點(diǎn)代碼中根本不涉及編碼的問題.我將很多配置文件的編碼都改了也不行.因?yàn)槟莻€(gè)英文例子沒問題,我查看了JFreechart的一個(gè)servlet(org.jfree.chart.servlet.DisplayChart),因?yàn)閖pviot就是調(diào)用這個(gè)servlet實(shí)現(xiàn)繪圖的,分析這個(gè)servlet我知道它會(huì)在一個(gè)臨時(shí)目錄生成png文件,然后交給servlet寫到瀏覽器的響應(yīng)中去,我找到那個(gè)臨時(shí)目錄(tomcattemp),發(fā)現(xiàn)里面已經(jīng)生成了正確的中文圖形.從而判斷圖形生成正確,但是寫到瀏覽器中時(shí)出了問題.最后我查看能生成英文圖表的那個(gè)例子,發(fā)覺不僅僅在html中生成圖形,而且生成map.而這個(gè)map的生成全是在程序中做的,程序生成一個(gè)xml文件,通過chart.xsl解析生成map的最終html代碼.但是在程序中生成時(shí)并沒有加入編碼設(shè)置,因此問題出在生成map這兒.

    最終修改代碼如下:

    com.tonbeller.jpivot.chart.ChartComponent:

    在render函數(shù)中修改如下:

    String desc="<?xml version="1.0" encoding="gb2312"?>";
    String xchart =desc+"n"+ "<xchart>" + writeImageMap(filename, info, false) + "</xchart>";
    這樣就為xchart設(shè)置了編碼.

    修改jfreechart中的默認(rèn)字體:

    com.tonbeller.jpivot.chart.ChartComponent中定義了幾種字體,但是這幾種字體都是英文字體,我將其修改為宋體:
    把所有的字體定義都改為"SimSun"
    注意到這兒并沒有玩,如果你僅僅修改程序,仍舊會(huì)出現(xiàn)問題,報(bào)錯(cuò)說沒有適合"SimSun"的item
    同時(shí)要修改一個(gè)配置文件:WEB-INFjpivotchartchartpropertiesform.xml
    在這個(gè)配置文件中將SimSun加入其中,形式如下:

    <listBox1 type="string" modelReference="fontName" label="Title font">
    <listItem value="SansSerif" label="SansSerif"/>
    <listItem value="Serif" label="Serif"/>
    <listItem value="SimSun" label="SimSun"/>
    <listItem value="Monospaced" label="Monospaced"/>
    </listBox1>

    posted @ 2008-01-14 12:20 菠蘿 閱讀(1251) | 評(píng)論 (0)編輯 收藏

    jfreechart在aix unix上的中文顯示問題

     

     

    今天開始搭建新的平臺(tái),要把原來windows的應(yīng)用遷移到Aix上,結(jié)果由于jfreechart的中文字體顯示耗了整個(gè)下午,好不郁悶,不過還好最后解決問題了:)
         
    主機(jī)環(huán)境:
     AIX Version 5.2 + Jboss4.03sp1 + J2RE 1.4.2 IBM AIX build ca142ifx-20050119
     使用jfreechart1.0rc

    添加啟動(dòng)參數(shù) -Djava.awt.headless=true才能正常顯示jfreechart的圖.

    讓jre使用中文字體的過程如下:

    1.解包字體文件
    TrueType_zhCN_GBK.tar,列表如下:
    fangsongti.ttf
    heiti.ttf
    kaiti.ttf
    songti.ttf
    注:字體包是我以前在solaris上整出來的.

    2.copy字體到j(luò)re的字體目錄${JAVA_HOME}/jre/lib/fonts


    3.修改JRE的字體配置
    3.1 修改fonts.scale文件[${JAVA_HOME}/jre/lib/fonts/fonts.scale]
    把一行的數(shù)字加4
    在文件尾添加
    fangsongti.ttf -zhongyi-fangsong-medium-r-normal--0-0-0-0-m-0-gbk-0
    heiti.ttf -zhongyi-hei-medium-r-normal--0-0-0-0-m-0-gbk-0
    kaiti.ttf -zhongyi-kai-medium-r-normal--0-0-0-0-m-0-gbk-0
    songti.ttf -zhongyi-song-medium-r-normal--0-0-0-0-m-0-gbk-0
    3.2 修改fonts.dir文件[${JAVA_HOME}/jre/lib/fonts/fonts.dir]
    把一行的數(shù)字加4
    在文件尾添加
    fangsongti.ttf -zhongyi-fangsong-medium-r-normal--0-0-0-0-m-0-gbk-0
    heiti.ttf -zhongyi-hei-medium-r-normal--0-0-0-0-m-0-gbk-0
    kaiti.ttf -zhongyi-kai-medium-r-normal--0-0-0-0-m-0-gbk-0
    songti.ttf -zhongyi-song-medium-r-normal--0-0-0-0-m-0-gbk-0
    3.3 修改font.properties.zh文件[${JAVA_HOME}/jre/lib/font.properties.zh]
    把所有的serif.1的值 進(jìn)行如下替換
    -zhongyi-song-medium-r-normal--0-0-0-0-m-0-gbk-0


    4.重新啟動(dòng)就可以了.

     

    其他的unix上我試了一下hp-unix,可以通過,其他的沒有試過,或許也可以吧:)

    posted @ 2008-01-14 12:18 菠蘿 閱讀(1120) | 評(píng)論 (9)編輯 收藏

    修改字體

    //X軸下標(biāo)字體大小及顏色
    Axis axis1 = plot.getDomainAxis();
    axis1.setLabelFont(new Font("sansserf",Font.PLAIN,30));//字體
    axis1.setLabelPaint(Color.white);//顏色
     
    //X軸的字體顏色
    Axis axis = plot.getDomainAxis();
    axis.setTickLabelFont(new Font("Serif", Font.PLAIN,25));//字體
    axis.setTickLabelPaint(Color.white);//顏色 
     
    //Y軸字下標(biāo)字體大小及顏色
    Axis axis2 = plot.getRangeAxis();
    axis2.setLabelFont(new Font("Serif", Font.PLAIN, 30));//字體  
    axis2.setLabelPaint(Color.white); //顏色
     
    //Y軸字體及顏色
    Axis axis3 = plot.getRangeAxis();
    axis3.setTickLabelFont(new Font("Serif", Font.PLAIN, 25));//字體  
    axis3.setTickLabelPaint(Color.white);//顏色
    

    posted @ 2008-01-14 12:10 菠蘿 閱讀(248) | 評(píng)論 (0)編輯 收藏

    WebBrowser.ExecWB方法

    WebBrowser.ExecWB(1,1) 打開
    WebBrowser.ExecWB(2,1) 關(guān)閉現(xiàn)在所有的IE窗口,并打開一個(gè)新窗口
    WebBrowser.ExecWB(4,1) 保存網(wǎng)頁
    WebBrowser.ExecWB(6,1) 打印
    WebBrowser.ExecWB(7,1) 打印預(yù)覽
    WebBrowser.ExecWB(8,1) 打印頁面設(shè)置
    WebBrowser.ExecWB(10,1) 查看頁面屬性
    WebBrowser.ExecWB(15,1) 好像是撤銷,有待確認(rèn)
    WebBrowser.ExecWB(17,1) 全選
    WebBrowser.ExecWB(22,1) 刷新
    WebBrowser.ExecWB(45,1) 關(guān)閉窗體無提示

     

    其中最后一項(xiàng)WebBrowser.ExecWB(45,1)可以有效解決IE7下,使用

    WebBrowser.ExecWB(7,1)執(zhí)行打印預(yù)覽后返回到原窗口時(shí),window.close()方法失效的問題

    posted @ 2008-01-03 13:08 菠蘿 閱讀(1515) | 評(píng)論 (1)編輯 收藏

    iframe高度自適應(yīng)(轉(zhuǎn))

    <iframe name="src" width="100%" frameborder=0 scrolling=no src='admin.htm?catId=<c:out value="${model.l}" />'
            onload="this.height =   document.frames['src'].document.body.scrollHeight" />

    例子:
    1,創(chuàng)建頁面 test.html 。 頁面中含有一個(gè) iframe,name為 ifrname ,id為 ifrid, src 為 iframe.html頁面。
    <iframe src="ifarme.html" name="ifrname" height="" style="" onload="" id="ifrid"   scrolling=""> </iframe>

    2,創(chuàng)建 iframe.html 頁面,里面含有一些內(nèi)容。
    <p>
    這是iframe頁面,通過在父窗口頁面或子頁面添加JS來自動(dòng)更改寬高,以適應(yīng)內(nèi)容的多少。
    </p>
    要想使iframe自動(dòng)適應(yīng)寬和高,可以在 test.html 頁面iframe onload處增加一些JS代碼。如:
       <iframe src="ifarme.html" name="ifrname" height="" style="" onload="this.height =   document.frames["ifrname"].document.body.scrollHeight" id="ifrid"   scrolling=""></iframe>

    這樣iframe即可以自動(dòng)適應(yīng)高度了。如果不在onload處增加js,那也可以放到頁面上來調(diào)用。比如寫個(gè)函數(shù)。
    <script>
    function setAutoHeight(iframeElement,   iframeWindow) {
    iframeElement.style.height = iframeWindow.document.body.scrollHeight;
    iframeElement.style.width   =   iframeWindow.document.body.scrollWidth   ;
    // 或者
    // iframeElement.height = iframeWindow.document.body.offsetHeight ;
    // iframeElement.width   =   iframeWindow.document.body.offsetWidth;

    }
    //調(diào)用函數(shù)setAutoHeight();
    setAutoHeight( document.getElementById("iframeid"), window.frames[0]   );
    </script>
    這樣也可以達(dá)到自適應(yīng)高寬的目的,在這里要注意的是,iframeElement參數(shù)必須是 document.getElementById("iframeid"), iframeWindow參數(shù)是 window.frames[0] 或document.frames["ifrname"]。 這是因?yàn)橥ㄟ^name得到的對(duì)象是窗口(window)對(duì)象,非窗口里的iframe對(duì)象。同時(shí)document.getElementById("iframeid)不能像window對(duì)象可以得到window.document。
    所以這里最好給iframe分別加上name和id,id用來更改寬高樣式屬性,name用來執(zhí)行window相關(guān)事件如location.href,document.write。bgColor例外,元素對(duì)象和窗口對(duì)象都可以得到,這是因?yàn)樗麄兌加羞@個(gè)屬性。
    如果要隱藏iframe滾動(dòng)條,可以設(shè)置iframeWindow.scrolling = "no";但這不能兼容多個(gè)瀏覽器,用iframeElement.document.body.style.overflow = "hidden";這種或直接在iframe處增加scrolling="no" html代碼就可以很好地兼容了。
    3,如果不能修改父頁面,而只能把代碼增加在iframe頁面里呢?
    可以寫個(gè)類似函數(shù),放在iframe頁面里:
    <script>
    function setAutoHeight( parentIframeElement, slefDocument ){
    slefDocument.style.overflow = "hidden";           // 隱藏全部滾動(dòng)條
    // document.body.style.overflowY = "hidden";   // 沒有豎滾動(dòng)條
    parentIframeElement.style.height = slefDocument.scrollHeight;
    parentIframeElement.style.width   =   slefDocument.scrollWidth;
    }
    // 在頁面最后執(zhí)行
    setAutoHeight(parent.document.getElementById("ifrid"), document.body);
    // 或onload時(shí)執(zhí)行
    //window.onload = function() {
    //    setAutoHeight(parent.document.getElementById("ifrid"), document.body);
    //}
    // 或者超時(shí)執(zhí)行
    // setTimeout(
    //    function() {
    //      setAutoHeight(parent.document.getElementById("ifrid"), document.body);
    //   },
    // 200 );
    </script>

    4,在線通過iframe更改父窗口里iframe的寬高,因?yàn)榘踩驎?huì)有跨域的問題,若是不在同一域名,那是被禁止的。如果同在一個(gè)域名下,但2級(jí)域名不同,比如a.yourcompany.com 和b.yourcompany.com。
    這時(shí)可以通過重新設(shè)置document.domain 來跨越2級(jí)域名。
    var domain = "yourcompany.com";
    try {
        if( document.domain.indexOf(domain)   != -1 ) {
          document.domain = domain;                   // set new document.domain;
        }
    } catch (ex) {
        alert("error: " + ex.toString() );
    }
    如果域名含有yourcompany.com,則改將document.domain改為yourcompany.com

    posted @ 2007-12-03 12:28 菠蘿 閱讀(286) | 評(píng)論 (0)編輯 收藏

    高校ftp,密碼一百年不變

    高校ftp,密碼一百年不變.好東東不少~~
    高校ftp,密碼一百年不變.好東東不少,速度狂快(夸張點(diǎn)說是一百年,但現(xiàn)在還可以用的)
    ftp://smu:smc@218.5.241.10  主機(jī):218.5.241.10 用戶名:smu 密碼: smc
    是教育網(wǎng)的,電信的可能很快,大家都來看看,里面很多軟件和電影
       
          看了,不要忘記跟貼哦。。。
    友情提示:下載后,請(qǐng)自行查毒!

    posted @ 2007-12-02 21:43 菠蘿 閱讀(353) | 評(píng)論 (0)編輯 收藏

    我的鏈接

    Tomcat專題
    http://www.chinaitlab.com/www/techspecial/tomcat/

    EXT
    http://www.dojochina.com/

    posted @ 2007-11-28 22:01 菠蘿 閱讀(144) | 評(píng)論 (0)編輯 收藏

    Aptana 插件

    Plugging Aptana into an existing Eclipse configuration

    From Aptana

    This page describes how to install into an existing Eclipse configuration.

    Contents

    [hide]

    Introduction

    If you are already an Eclipse user, you can install Aptana as a plug-in directly into your current Eclipse configuration.

    Instructions

    To plug Aptana (Milestone 8+) into an existing Eclipse (v3.2) configuration:

       

    1. From the Help menu in Eclipse, select Software Updates > Find and Install... to open an Install/Update pop-up window (shown below).

      Image:installUpdate.png

    2. On the Install/Update pop-up window, choose the Search for new features to install option, and click the Next button.
    3. Add a new remote site to add the Aptana plug-in:
      1. Click the New Remote Site... button to open a New Update Site pop-up window.
      2. On the New Update Site pop-up window, type Aptana in the site Name text box.
      3. In the URL text box, type the URL for the Aptana update site: http://update.aptana.com/install/3.2/ (shown below) and click OK.

        Image:updateAptana.png

      4. Click the Finish button to switch to the Updates window.
    4. On the Updates window, check the Aptana box (shown below), and click the Finish button.

      Image:includeAptana.png

    5. On the next screen, check the Aptana box, and click the Next button.
    6. Choose the option to accept the terms of the license agreement, and click the Next button.
    7. Click the Finish button.
    8. Click the Install All button.

       

     

    Eclipse installs the Aptana plug-in. To finish the installation process, follow the prompts to shut down and re-start Eclipse.

    To access all of Aptana's features as they are described in the Aptana documentation, you will need to change your Eclipse Perspective to the Aptana perspective. See Changing your Eclipse Perspective for instructions on how to change your Eclipse Perspective.


    Installing manually

    Download the latest release from http://update.aptana.com/install/3.2/ and follow the manual installation instructions on the page.

    Note: You may need to start Eclipse from the command-line with the "clean" option: eclipse -clean if the update didn't seem to work correctly.

    Related Topics

    Retrieved from "

    posted @ 2007-11-19 22:32 菠蘿 閱讀(1094) | 評(píng)論 (0)編輯 收藏

    vsftp500錯(cuò)誤簡(jiǎn)單解決方法

     

    cannot change directory:/home/***

    ftp服務(wù)器連接失敗,錯(cuò)誤提示:
    500 OOPS: cannot change directory:/home/*******
    500 OOPS: child died
    解決方法:
     # setsebool ftpd_disable_trans 1
      # service vsftpd restart


    為避免每次開機(jī)都要作這個(gè)操作,可在setsebool命令后面加上-P選項(xiàng),使改動(dòng)永久有效。

    posted @ 2007-11-07 22:59 菠蘿 閱讀(600) | 評(píng)論 (0)編輯 收藏

    To install JSEclipse

    1. Open the Eclipse workbench.
    2. To install new software with the Update manager, in the main Eclipse menu, go to Help > Software Updates ->Find and Install.
    3. In the user interface that opens, select the Search for new features to install.
    4. In the next step you choose what locations will be searched. If this is the first time installing JSEclipse, you have to add a New remote site. If you already have it defined, skip to step 7.
    5. To define a new site to be searched for available plugins, in the user interface click the New Remote Site button.
    6. The New Update Site dialog box opens. It contains two fields that must be completed:
    7. Check the newly added entry's checkbox. This will set it as active for the software search. You can disable or enable sites on which the software search is performed by checking, respectively un-checking them in the user interface
    8. Click Finish to start searching for software. A new window will appear showing the search progress.
    9. Once the search completes, a list of the features available on the remote site will be displayed, with their respective version, using an hierarchical display
    10. Select the feature to install by checking its checkbox. Click Next to continue.
    11. The license agreement for each selected feature is displayed next. You must accept the licence agreement in order to continue with the install process. Click the I accept the terms in the license agreement radio button, then Next to move on.
    12. Next select where to install the plugin. By default, it is the current folder. Use the default and click Finish to install.
    13. If your configuration is set to check plugins for a digital signature, a confirmation window is displayed, warning if the plugin is not digitally signed. Simply click Install to close the window and install the plugin
    14. After the installation is completed, and all features have been copied to the desired location, a dialog box will ask for a restart of the workbench. Although some features can be enabled without restarting the workbench, a restart is recommended. Select Yes.
    15. JSEclipse has been installed.

    posted @ 2007-10-31 22:16 菠蘿 閱讀(263) | 評(píng)論 (0)編輯 收藏

    JSTL簡(jiǎn)介

         摘要: JSTL簡(jiǎn)介
    JSTL是一個(gè)不斷完善的開放源代碼的JSP標(biāo)簽庫,是由apache的jakarta小組來維護(hù)的。JSTL只能運(yùn)行在支持JSP1.2和Servlet2.3規(guī)范的容器上,如tomcat 4.x。但是在即將推出的JSP 2.0中是作為標(biāo)準(zhǔn)支持的。  閱讀全文

    posted @ 2007-10-24 12:32 菠蘿 閱讀(281) | 評(píng)論 (0)編輯 收藏

    Eclipse支持PHP自動(dòng)提示

    其實(shí)如果你已經(jīng)安裝好了php環(huán)境(安裝過程見)的話,只需要下面2步就可以了。hoho,很簡(jiǎn)單的。

    1,下載eclipse中php的插件
    地址:http://www.phpeclipse.de/tiki-view_articles.php
    http://prdownloads.sourceforge.n ... ip?use_mirror=jaist

    2,解壓縮。plugins文件夾下內(nèi)容copy至eclipseplugins文件夾下,features文件夾下內(nèi)容copy至eclipsefeatures文件夾下。

    使用Eclipse環(huán)境來編寫PHP程序,以下是詳細(xì)說明。有基礎(chǔ)的朋友可以不看。

    簡(jiǎn)單介紹:
    Eclipse,著名開源軟件,IDE,廣泛用于Java開發(fā)等。
    加上相應(yīng)插件后,可支持大部分編程語言。

    使用前提:
    已正確搭建安裝了AMP(A=Apache, M=Mysql, P=PHP)環(huán)境,操作系統(tǒng)平臺(tái)不限

    下載:
    Eclipse3.0.1: http://www.eclipse.org/downloads/index.php
    (選擇適合你系統(tǒng)的相應(yīng)版本,支持windows,linux,max等,建議選擇最新版本3.0.1)

    PHPeclipse插件: http://sourceforge.net/project/ showfiles.php?group_id=57621
    (同上,最新版本1.1.2)

    安裝:
    均為綠色軟件,無須安裝
    將下載回來的Eclipse壓縮包解開,放到常用安裝軟件文件夾即可(請(qǐng)勿急著馬上啟動(dòng)Eclipse)
    將PHPeclipse插件(下載的壓縮包內(nèi)有features及plugins兩個(gè)文件夾,跟Eclipse目錄下的一樣,應(yīng)該是對(duì)應(yīng)的)解壓到Eclipse相應(yīng)目錄下即可
    注意:
    如果已經(jīng)事先安裝過Eclipse或者在未解壓插件之前已經(jīng)啟動(dòng)過,因?yàn)樗谝淮螁?dòng)會(huì)掃描全部xml文件并緩存以加快啟動(dòng)速度,所以PHP插件不會(huì)被馬上識(shí)別。需要用選項(xiàng)-clean來強(qiáng)行啟動(dòng)一次。(win下直接cmd到Eclipse目錄再Eclipse.exe –clean即可,其他平臺(tái)類似)

    配置:
    1、Eclipse啟動(dòng)比較慢,在硬件配置比較好的機(jī)器上也需要好幾秒鐘,請(qǐng)耐心等待。首次啟動(dòng)會(huì)讓你選擇工作目錄(workspace),制定后打個(gè)勾下次就不會(huì)再問。
    2、另外指定一個(gè)用來放置PHP項(xiàng)目的目錄,如果不指定默認(rèn)就在workspace的子目錄下,最好事先想好名字,比如我的:workspace/phpeclipse
    3、修改httpd.conf文件,新建一個(gè)指向workspace/phpeclipse的別名(Alias)---PHP安裝的問題,恕不多述。我這里還是叫phpeclipse。當(dāng)然如果你把PHP項(xiàng)目放在DocumentRoot下的話這步就可以省略了。
    4、本次啟動(dòng)后會(huì)發(fā)現(xiàn)菜單和工具欄上多了一些東西(如果你之前用過Eclipse的話,呵呵)
    到Window - Preferences – PHPeclipse Web Development – PHP中指定一下你的PHP環(huán)境中Apache,php,mysql三個(gè)執(zhí)行文件的相應(yīng)位置,至于參數(shù)似乎默認(rèn)的就可以了,我用的是Apache2,修改了一下,啟動(dòng)用:-w -n "Apache2" -k start ;停止用:-w -n "Apache2" -k stop;重啟用-w -n "Apache2" -k restart
    這樣工具欄上的那幾個(gè)apache和mysql的按鈕就可以用了。

    使用:
    菜單->new->Project->PHP->PHP Project,指定一個(gè)名字,然后就可以用了,不過要注意跟前面的別名部分對(duì)應(yīng),否則無法訪問
    在Navigator欄的項(xiàng)目名稱上右擊,new一個(gè)php file,然后保存,Eclipse就自動(dòng)打開web browser顯示結(jié)果了。相當(dāng)不錯(cuò)。主要是看中它集成開發(fā)的方便性,代碼塊伸縮,自動(dòng)完成等眾多特性。

    關(guān)于在Eclipse中加入PHP插件的更詳細(xì)內(nèi)容可以參考這篇文章(英文):
    http://www.phpbuilder.com/columns/c...921.php3?page=1
    PHPeclipse插件的主頁在 http://phpeclipse.de/ ,安裝中如果有問題或者需要更詳細(xì)的文檔可以到上面去找尋。

    posted @ 2007-10-22 12:51 菠蘿 閱讀(288) | 評(píng)論 (0)編輯 收藏

    Total Commander雙擊*.lnk彈出“在執(zhí)行程序時(shí)出錯(cuò)”的問題

     注冊(cè)項(xiàng)HKEY_CLASSES_ROOT\lnkfile ,新建名為IsShortcut的字符串值,內(nèi)容為空。
        重啟TC后問題解決。

    posted @ 2007-10-20 16:53 菠蘿 閱讀(1071) | 評(píng)論 (2)編輯 收藏

    我的鏈接

    EXT:
        Eclipse插件:http://www.spket.com/ 
        http://extjs.com/blog/2007/06/29/building-a-desktop-application-with-ext-air-aptana-and-red-bull/

    posted @ 2007-10-17 21:51 菠蘿 閱讀(141) | 評(píng)論 (0)編輯 收藏

    解決WinXP網(wǎng)絡(luò)不能互相訪問

         摘要: 由WIN XP構(gòu)成的網(wǎng)絡(luò)所有設(shè)置和由WIN 2000構(gòu)成的完全一樣,但還是出現(xiàn)了根本不能訪問的情況,筆者認(rèn)為這主要是因?yàn)閄P的安全設(shè)置和2000不一樣所導(dǎo)致。針對(duì)這個(gè)問題筆者在網(wǎng)上查了一些資料,并將各種網(wǎng)上提供的常見解決方法做了相應(yīng)測(cè)試,現(xiàn)在整理介紹給大家,希望能對(duì)遇到此問題的網(wǎng)友有所幫助,并請(qǐng)高手繼續(xù)指點(diǎn)。部分內(nèi)容摘自網(wǎng)絡(luò),請(qǐng)?jiān)彶灰灰蛔⒚鞒鎏帯?  首先,這里不考慮物理聯(lián)接和其它問題,只談及策略問題。此外,請(qǐng)安裝相應(yīng)的協(xié)議并正確的設(shè)置IP地址,同時(shí)盡量把計(jì)算機(jī)設(shè)置在一個(gè)工作組內(nèi)且具有相同網(wǎng)段的IP地址。
      閱讀全文

    posted @ 2007-10-09 20:34 菠蘿 閱讀(267) | 評(píng)論 (0)編輯 收藏

    主站蜘蛛池模板: 免费看国产成年无码AV片| 亚洲精品在线电影| 亚洲1区2区3区精华液| 亚洲黄色三级网站| 国产精品美女久久久免费| 日本视频免费在线| 亚洲精品午夜国产va久久| 1000部羞羞禁止免费观看视频| 亚洲精品乱码久久久久久按摩 | 国产午夜亚洲精品午夜鲁丝片| 久久久久亚洲av无码专区导航| 亚洲精品视频免费观看| 免费少妇a级毛片人成网| 亚洲人成色4444在线观看| 青娱乐免费在线视频| 中文字幕在线观看亚洲| 日韩在线永久免费播放| 亚洲国产精品无码专区影院| 亚洲免费无码在线| 亚洲一本大道无码av天堂| 免费看一级一级人妻片| 四虎永久精品免费观看| 久久亚洲欧美国产精品| 日本免费一区二区三区最新| 亚洲午夜精品一区二区麻豆| 毛片在线免费视频| 在线观看亚洲AV日韩AV| 成全影视免费观看大全二| 中文字幕在线观看亚洲日韩| 丁香花免费高清视频完整版| 亚洲一级毛片免费观看| 69天堂人成无码麻豆免费视频| 亚洲天堂一区二区三区四区| 免费A级毛片无码A∨免费| 国产综合亚洲专区在线| 亚洲精品无码成人片在线观看| 免费人成网站永久| 亚洲一区二区三区乱码A| www在线观看免费视频| 亚洲自偷自偷图片| 全黄大全大色全免费大片|