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

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

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

    #

    文 字 變 化 效 果 JS事例講解

    源程序講解:
    ? ?

    var thissize=20

    聲明一個變量,定義字符串長度。
    var textfont="隸書" 聲明一個變量,定義字體。
    var textcolor= new Array()
    textcolor[0]="000000"
    textcolor[1]="000000"
    textcolor[2]="000000"
    textcolor[3]="111111"
    textcolor[4]="222222"
    textcolor[5]="333333"
    textcolor[6]="444444"
    textcolor[7]="555555"
    textcolor[8]="666666"
    textcolor[9]="777777"
    textcolor[10]="888888"
    textcolor[11]="999999"
    textcolor[12]="aaaaaa"
    textcolor[13]="bbbbbb"
    textcolor[14]="cccccc"
    textcolor[15]="dddddd"
    textcolor[16]="eeeeee"
    textcolor[17]="ffffff"
    textcolor[18]="ffffff"
    定義一個新數(shù)組,并列出其中的元素。
    var message = new Array()
    message[0]="洪恩在線 求知無限"
    message[1]="十二億人的網(wǎng)上大學(xué)"
    i_message=0
    定義新數(shù)組,并列出其中的元素。
    var i_strength=0
    var i_message=0
    聲明變量,并賦初值。
    var timer 聲明變量。
    function glowtext() { 定義函數(shù)。
    if(document.all)
    如果是IE瀏覽器,執(zhí)行以下語句。
    { if (i_strength <=17)
    如果i_strength <=17,執(zhí)行以下語句。
    { glowdiv.innerText=message[i_message]
    document.all.glowdiv.style.filter=
    "glow(color="+textcolor[i_strength]+", strength=4)"
    i_strength++
    輸出i_message的值,然后i_strength遞加,即亮度增加。
    timer=setTimeout("glowtext()",100) }
    每100毫秒,調(diào)用一次glowtext函數(shù)。
    else { clearTimeout(timer)
    setTimeout("deglowtext()",1500) }
    如果i_strength 大于17了,調(diào)用deglowtext函數(shù),即亮度開始變暗。
    } } function deglowtext()
    { if(document.all)
    { if (i_strength >=0)
    定義deglowtext函數(shù),并當瀏覽器是IE時,i_strength >=0時,執(zhí)行以下語句。
    { glowdiv.innerText=message[i_message]
    document.all.glowdiv.style.filter=
    "glow(color="+textcolor[i_strength]+",
    strength=4)"
    i_strength--
    輸出i_message的值,然后i_strength遞減,即亮度減弱。
    timer=setTimeout("deglowtext()",100) }
    else { clearTimeout(timer)
    i_message++
    每100毫秒,調(diào)用一次glowtext函數(shù),減到最暗,接著執(zhí)行下一個字符串。
    if (i_message>=message.length)
    {i_message=0} i_strength=0 intermezzo() } } }
    如果數(shù)組message中的字符串都執(zhí)行完了,一切恢復(fù)初始設(shè)置,并執(zhí)行intermezzo函數(shù)。
    function intermezzo()
    定義一個函數(shù)intermezzo。
    { glowdiv.innerText=""
    setTimeout("glowtext()",1500) }
    1.5秒后,重新調(diào)用glowtext函數(shù)。

    posted @ 2007-07-08 22:23 金家寶 閱讀(396) | 評論 (0)編輯 收藏

    innerHTML、outerHTML、innerText、outerText的區(qū)別

    運行一下就知道區(qū)別了。

    posted @ 2007-07-08 22:15 金家寶 閱讀(302) | 評論 (0)編輯 收藏

    document 和 document.all

    如果與a,form對象,image對象,applet對象相對應(yīng)的html標記中設(shè)定了name性質(zhì),它的值將被用作document對象的屬性名,用來引用相應(yīng)的對象,其他的對象則不可以。
    另外,input等如果作為form的子元素,則直接用inputName或者document.inputName來引用此對象就是錯誤的,必須使用formName.inputName引用,否則就可以使用inputName來引用.
    另外應(yīng)該注意到有很多平時用的元素都沒有name.
    如果想引用一個有id的元素,只能用Id或者document.getElementById,document.all.id來引用
    但是象這樣的元素,所以象<a href="......" name="linkname" id="linkid">......</a>這樣的
    可以用
    linkid.href;
    linkname.href;
    document.all.linkid.href;
    document.all.linkname.href;
    document.getElementById("linkid").href;
    document.getElementsByName("linkname")[0].href來引用

    all是一個集合,包含所有html對像的集合,寫一個程式,可以存取到所有的對像。像這樣:
    <script language="javascript">
    var obj="";
    for(i=0;i<document.all.length;i++)
    obj+=document.all[i].tagName+";";
    alert(obj);
    </script>
    注意要把程式放到</html>之后哦。

    posted @ 2007-07-08 22:05 金家寶 閱讀(261) | 評論 (0)編輯 收藏

    Java開源遲內(nèi)幕

    對于全球軟件業(yè)人士來說,Java源碼要開放無疑是近期的焦點新聞。Sun公司的首席開源官菲利普澄清,表示Java開源化的工作不會在近期完成,還需要“十幾個月”的時間。許多業(yè)界人士認為,Java是人們最希望Sun開源的技術(shù),而且這件事應(yīng)該在幾年前就完成。Sun公司為何在Java開源上步履謹慎?其背后有何考慮? 日前美國《商業(yè)周刊》雜志撰文進行了解析:

      西蒙?菲利普打開了一個開源的“蠕蟲”之盒。6月的最后一個星期,他不得不澄清人們對于Sun公司一個眾人期待的宏大項目的質(zhì)疑:Sun公司何時才會公開Java編程語言的源代碼?套用業(yè)內(nèi)術(shù)語來說,Sun何時才會把Java“開源化”。

      這個問題已經(jīng)長期困擾了Sun公司的高層,答案搖擺不定。此舉可以讓Java面向數(shù)以百萬計的開發(fā)人員,讓Java進一步融入IT業(yè)界,更不用說它將提高業(yè)界對Sun公司其他產(chǎn)品的興趣,并使一個正在提高業(yè)績的公司甩掉一個大包袱。

      作為Sun公司首席開源官的菲利普表示,Java的開源將在“幾個月”而不是“幾年內(nèi)”完成。他后來表示,“幾個月”的意思是未來10到11個月,不過,與會者迫不及待地在其博客上宣布,Sun將在近期甚至九月份開放Java的源碼。菲利浦不得以再次面對媒體,強調(diào)不會那么早。此舉隨后又引發(fā)了Sun公司在Java開源上是否在自拖后腿的猜疑。

      來來回回的表態(tài)在Sun公司的開源道路上并不鮮見。正如菲利普等高層經(jīng)常掛在嘴邊說的一樣,Sun公司的開源道路根植于1980年代,從Mozilla基金會的火狐瀏覽器到OpenOffice和Aparche WEB服務(wù)器,這些家喻戶曉的開源項目都有Sun的影子。

      這些顯然遠遠不夠,Sun公司現(xiàn)在幾乎是要把所有的產(chǎn)品都開放源碼。即使是作為Linux長期盟友的IBM也走不到那么遠。你參加任何一個有關(guān)開源的大會,總免不了會和Sun公司的頭面人物打照面,比如菲利普、首席信息官比爾?瓦斯,負責(zé)軟件的執(zhí)行副總裁里奇?格林甚至是首席執(zhí)行官喬納森?施瓦茨。

      盡管作出那么多努力,Sun公司卻很少獲得開源業(yè)界的褒獎。一些批評人士指出,Sun公司將Solaris操作系統(tǒng)開源的真實原因是因為它已經(jīng)被Linux擊敗,此外,在其他已經(jīng)開源的項目中,Sun公司也掌握了決定性的控制權(quán),導(dǎo)致無法形成開發(fā)群體共同影響產(chǎn)品戰(zhàn)略的局面。

      事實上,Sun公司的高層也承認在開源業(yè)務(wù)上犯下錯誤。為了捍衛(wèi)自己更加可靠但又價格昂貴的產(chǎn)品,施瓦茨和前任麥克尼利經(jīng)常對Linux和低成本服務(wù)器產(chǎn)品“惡語相加”。這讓IBM和惠普等競爭對手有借口將Sun公司“刻畫”成為一個開源和Linux的敵人,這種形象甚至影響了大多數(shù)開源業(yè)界人士。

      在作為WEB和商業(yè)軟件開發(fā)語言的Java的開源問題上,業(yè)界的看法也不盡和Sun一致。前Sun公司高層、現(xiàn)任開源軟件公司ActiveGrid負責(zé)人的皮特?雅雷德表示:“其實Java是人們最希望Sun公司開放源碼的唯一產(chǎn)品。”另外一個Sun公司前任高層比爾?柯爾曼則表示:“我個人認為他們應(yīng)該幾年前就做這件事?!?

      現(xiàn)在看來,Sun公司終于決定作出妥協(xié)(開放Java源碼)。人們關(guān)心的另外一個問題是:Sun公司可以從中獲得什么利益?最簡單的答案:很多利益??梢钥紤]一下Java在Sun公司的地位。首先,這是一個公認的軟件開發(fā)語言標準,諸如甲骨文和BEA這樣的公司使用Java來開發(fā)應(yīng)用軟件,也包括JBoss這樣的開源軟件項目。此外,Sun公司本身亦提供很多的Java應(yīng)用軟件,并銷售相關(guān)的服務(wù)。雖然Java已經(jīng)成為全球軟件行業(yè)發(fā)展的一個里程碑,不過,Sun公司并未從中獲得很多收入。
    對于柯爾曼這樣的業(yè)內(nèi)人士來說,Sun開源Java還有背后的理由。據(jù)他介紹,在擔任BEA公司CEO的末期,Sun公司雇用了1200名工程師來維護Java,這個開支達到每年幾億美元,但他們帶來的銷售收入只占公司的百分之幾。隨著Sun公司逐步轉(zhuǎn)型,從一個銷售昂貴專有服務(wù)器的廠商逐漸適應(yīng)一個更需要低價而靈活的產(chǎn)品的市場,諸如Java這樣的開支對于Sun來說已經(jīng)成為一個包袱。

      不過,Sun開放Java源碼的道路走得很謹慎。菲利普強調(diào),Java是一個標準和Sun公司的品牌,他們希望開源之后的Java能夠得到很好的維護。如果開源過早,則將會出現(xiàn)多個分裂市場的Java版本,削弱Java作為行業(yè)標準的地位。正如菲利普指出,Java成功的最大原因是任何一個公司都無法在它身上獲得不公平的優(yōu)勢,在任何環(huán)境下,Java的這種特性必須得到保留。菲利普說:“問題是如何讓Java開源的同時保持著兩個價值,答案并不那么簡單。不負責(zé)任的人可能會有一個輕松的答案?!?

      值得慶幸的是,這些爭論在Sun公司內(nèi)部已經(jīng)停止,他們表示在開源Java的問題上已經(jīng)達成了一致。不管它是不是晚了五年,這仍然是一個正確的舉動。還有一個背景,其他逐漸流行的WEB開發(fā)語言,比如PHP和Ruby on Rails等正在蠶食Java的份額。雅雷德的公司ActiveGrid正在使這些開發(fā)語言足夠強勁,以便能夠在商用軟件開發(fā)中取代Java。如果菲利普認為Sun公司對全世界的Java開發(fā)人員有一種責(zé)任,那么,他們就必須保證其他語言不會削弱Java的地位。事實上,許多人認為在開源之后,在眾多開發(fā)人員的參與之下,Java會變得更加強大。

      對于Sun來說,Java開源還有其它好處,公司不會放棄有關(guān)Java的收入來源。隨著這個開發(fā)語言和IT業(yè)界的關(guān)系變得更加緊密,Sun公司也將更容易賣出自己兼容Java良好的WEB服務(wù)器和操作系統(tǒng)。這個舉動將會給軟件開發(fā)群體帶來新的活力,改善Sun公司的公眾形象,并同時證明Sun可以成為一個開源社會的“良民”。

      新官上任的CEO施瓦茨已經(jīng)給人們留下深刻印象,他宣布了一系列“遲到”的大規(guī)模重組計劃。開放Java語言的源碼無疑將成為施瓦茨“后無來者”的“政績”。  



    更多資源:
    參與論壇討論: http://www.java-cn.com/forum/index.jsp
    更多技術(shù)文章: http://www.java-cn.com/technology/index.jsp
    更多JAVA博客: http://www.54bk.com
    JAVA中文站:? 我們要做中國最好的JAVA門戶網(wǎng)站,記住我們的域名: JAVA-CN.COM | JAVA-CN.NET | JAVA-CN.ORG
    本文網(wǎng)址: http://www.java-cn.com/technology/technology_detail.jsp?id=4216
    聲??? 明: 轉(zhuǎn)載此文章,須在顯著位置注明 JAVA中文站 的原文網(wǎng)址;
    ????????? 若是本站的轉(zhuǎn)載文章,請標明原文出處,并保留作者信息

    posted @ 2007-06-19 00:19 金家寶 閱讀(222) | 評論 (0)編輯 收藏

    .javascript.論壇

    http://bbs.javascript.com.cn

    posted @ 2007-05-27 01:02 金家寶 閱讀(1007) | 評論 (2)編輯 收藏

    php+mysql扎實個人基本功

    一. 10句話
    1.不要依賴register_global=ON的環(huán)境,從你剛懂得配置php運行環(huán)境甚至尚不明白register_global的ON/OFF會對自己有什么影響的那天起,就應(yīng)該勇敢地把它設(shè)為OFF.
    2.寫程序前看看怎么用error_reporting.
    3.不懂就問本身沒錯,但你需要在那之前查查手冊。
    4.當然,你需要懂得使用手冊。手冊上找不到答案的時候,應(yīng)該考慮下網(wǎng)絡(luò)上的搜索引擎。
    5.剛學(xué)會php+mysql之后,不要叫嚷著要寫論壇,要寫XXX。要明白,剛學(xué)會寫漢字并不表示你有能力寫詩。
    6.在學(xué)web編程的時候,你應(yīng)該先去認識html這個朋友。
    7.有點能力后,試著回答新手的問題,不要看到自己懂的而別人不懂就沾沾自喜,扔下一名“簡單,那是基本的東西”就走更要不得。
    8.思考是一個好習(xí)慣,不動手去寫就等于空想,什么也沒有。
    9.寫好一段程序,如果覺得很滿意,一周后再看一遍,也許你會認為它應(yīng)該有所改變
    10.有空多看看別人的程序,找出他人的不足或優(yōu)點,自己掂量。

    二. 各取所需

    1.善于使用“引用”,它能直接影響到程序的效率。

    2.善于用三元運算子,可以讓程式較精簡有效率。
    比如:

    PHP代碼:

    if ($data[$i]['nickname'])
    {
    ????$nickname =??$data[$i]['nickname'];
    }
    else
    {
    ????$nickname =??$data[$i]['ip'];
    }


    可以寫成:

    PHP代碼:

    $nickname =??$data[$i]['nickname'] ? $data[$i]['nickname'] : $data[$i]['ip'];



    3.善于組織if...else...回圈
    比如:

    PHP代碼:

    $ext_name = strtolower(str_replace(".", "", strrchr($upfilename, ".")));
    if (!empty($type))
    {
    ????if (!strpos($type, $ext_name))
    ????{
    ????????echo "Please upload the file of $type form.";
    ????????exit();
    ????}
    }


    上面的代碼你應(yīng)該寫成這樣:

    PHP代碼:

    $ext_name = strtolower(str_replace(".", "", strrchr($upfilename, ".")));
    if (!($type==='') && strpos($type, $ext_name)===false)
    {
    ????echo "Please upload the file of $type form.";
    ????exit();
    }



    4.盡量讓你的代碼清淅些
    如果寫成這樣,是比較讓人頭痛的:

    PHP代碼:

    $foo=$_post["foo"];
    ???$username=$_post["user"];
    $group=$_POST["group"];
    if ($group=="wheel"){
    $username=$username."wheel";
    }


    同樣的代碼,這樣就比較讓人看得舒服了:

    PHP代碼:

    $foo??????= $_post["foo"];
    $username = $_post["username"];
    $group????= $_POST["group"];
    if ($group=="wheel")
    {
    ????$username = $username."wheel";
    }


    當然,有一定基礎(chǔ)后,你應(yīng)該要寫成這樣:

    PHP代碼:

    $foo??????= &$_POST['foo'];
    $username =??$_POST["group"]!='wheel' ? $_POST["username"] : $_POST["username"].'wheel';


    5.編寫規(guī)范的mysql 語句。
    字段和表名用"`"引起來,避免保留字的影響。
    如果看到下面這樣的一個sql query,會讓人比較頭痛:

    PHP代碼:

    $query="select `flash_comment`.`content` , `flash_comment`.`nickname` , `flash_comment`.`date` , `flash_comment`.`ip` , `product`.`p_name` , `sgflash`.`fid` from `flash_comment` left join `product` on ( `flash_comment`.`p_no` = `product`.`p_no` ) left join `sgflash` on ( `product`.`p_name` = `sgflash`.`f_name` ) where `flash_comment`.`p_no` != '' order by `flash_comment`.`date`";


    同樣的一個query,寫成這樣就令人看得明白得多了:

    PHP代碼:

    $query = "SELECT `flash_comment`.`content` , `flash_comment`.`nickname` , `flash_comment`.`date` , `flash_comment`.`ip` , `product`.`p_name` , `sgflash`.`fid`
    ??????????FROM `flash_comment`
    ??????????LEFT JOIN `product` ON ( `flash_comment`.`p_no` = `product`.`p_no` )
    ??????????LEFT JOIN `sgflash` ON ( `product`.`p_name` = `sgflash`.`f_name` )
    ??????????WHERE `flash_comment`.`p_no` != ''
    ??????????ORDER BY `flash_comment`.`date`";

    posted @ 2007-04-21 19:45 金家寶 閱讀(307) | 評論 (0)編輯 收藏

    深入剖析Java編程中的中文問題及建議最優(yōu)解決方法

    1、中文問題的來源
    ????計算機最初的操作系統(tǒng)支持的編碼是單字節(jié)的字符編碼,于是,在計算機中一切處理程序最初都是以單字節(jié)編碼的英文為準進行處理。隨著計算機的發(fā)展,為了適應(yīng)世界其它民族的語言(當然包括我們的漢字),人們提出了UNICODE編碼,它采用雙字節(jié)編碼,兼容英文字符和其它民族的雙字節(jié)字符編碼,所以,目前,大多數(shù)國際性的軟件內(nèi)部均采用UNICODE編碼,在軟件運行時,它獲得本地支持系統(tǒng)(多數(shù)時間是操作系統(tǒng))默認支持的編碼格式,然后再將軟件內(nèi)部的UNICODE轉(zhuǎn)化為本地系統(tǒng)默認支持的格式顯示出來。Java的JDK和JVM即是如此,我這里說的JDK是指國際版的JDK,我們大多數(shù)程序員使用的是國際化的JDK版本,以下所有的JDK均指國際化的JDK版本。我們的漢字是雙字節(jié)編碼語言,為了能讓計算機處理中文,我們自己制定的gb2312、GBK、GBK2K等標準以適應(yīng)計算機處理的需求。所以,大部分的操作系統(tǒng)為了適應(yīng)我們處理中文的需求,均定制有中文操作系統(tǒng),它們采用的是GBK,GB2312編碼格式以正確顯示我們的漢字。如:中文Win2K默認采用的是GBK編碼顯示,在中文WIN2k中保存文件時默認采用的保存文件的編碼格式也是GBK的,即,所有在中文WIN2K中保存的文件它的內(nèi)部編碼默認均采用GBK編碼,注意:GBK是在GB2312基礎(chǔ)上擴充來的。
    ????由于Java語言內(nèi)部采用UNICODE編碼,所以在JAVA程序運行時,就存在著一個從UNICODE編碼和對應(yīng)的操作系統(tǒng)及瀏覽器支持的編碼格式轉(zhuǎn)換輸入、輸出的問題,這個轉(zhuǎn)換過程有著一系列的步驟,如果其中任何一步出錯,則顯示出來的漢字就會出是亂碼,這就是我們常見的JAVA中文問題。
    ????同時,Java是一個跨平臺的編程語言,也即我們編寫的程序不僅能在中文windows上運行,也能在中文Linux等系統(tǒng)上運行,同時也要求能在英文等系統(tǒng)上運行(我們經(jīng)??吹接腥税言谥形膚in2k上編寫的JAVA程序,移植到英文Linux上運行)。這種移植操作也會帶來中文問題。
    ????還有,有人使用英文的操作系統(tǒng)和英文的IE等瀏覽器,來運行帶中文字符的程序和瀏覽中文網(wǎng)頁,它們本身就不支持中文,也會帶來中文問題。
    ????有,幾乎所有的瀏覽器默認在傳遞參數(shù)時都是以UTF-8編碼格式來傳遞,而不是按中文編碼傳遞,所以,傳遞中文參數(shù)時也會有問題,從而帶來亂碼現(xiàn)象。
    ????總之,以上幾個方面是JAVA中的中文問題的主要來源,我們把以上原因造成的程序不能正確運行而產(chǎn)生的問題稱作:JAVA中文問題。
    2、JAVA編碼轉(zhuǎn)換的詳細過程
    ????我們常見的JAVA程序包括以下類別:
    ???? *直接在console上運行的類(包括可視化界面的類)
    ???? *JSP代碼類(注:JSP是Servlets類的變型)
    ???? *Servelets類
    ???? *EJB類
    ???? *其它不可以直接運行的支持類
    ????這些類文件中,都有可能含有中文字符串,并且我們常用前三類JAVA程序和用戶直接交互,用于輸出和輸入字符,如:我們在JSP和Servlet中得到客戶端送來的字符,這些字符也包括中文字符。無論這些JAVA類的作用如何,這些JAVA程序的生命周期都是這樣的:
    ????*編程人員在一定的操作系統(tǒng)上選擇一個合適的編輯軟件來實現(xiàn)源程序代碼并以.java擴展名保存在操作系統(tǒng)中,例如我們在中文win2k中用記事本編輯一個java源程序;
    ???? *編程人員用JDK中的javac.exe來編譯這些源代碼,形成.class類(JSP文件是由容器調(diào)用JDK來編譯的);
    ???? *直接運行這些類或?qū)⑦@些類布署到WEB容器中去運行,并輸出結(jié)果。
    ????那么,在這些過程中,JDK和JVM是如何將這些文件如何編碼和解碼并運行的呢?
    ????這里,我們以中文win2k操作系統(tǒng)為例說明JAVA類是如何來編碼和被解碼的。
    ????第一步,我們在中文win2k中用編輯軟件如記事本編寫一個Java源程序文件(包括以上五類JAVA程序),程序文件在保存時默認采用了操作系統(tǒng)默認支持GBK編碼格式(操作系統(tǒng)默認支持的格式為file.encoding格式)形成了一個.java文件,也即,java程序在被編譯前,我們的JAVA源程序文件是采用操作系統(tǒng)默認支持的file.encoding編碼格式保存的,java源程序中含有中文信息字符和英文程序代碼;要查看系統(tǒng)的file.encoding參數(shù),可以用以下代碼:
    public class ShowSystemDefaultEncoding {
    public static void main(String[] args) {
    String encoding = System.getProperty("file.encoding");
    System.out.println(encoding);
    }}
    ????第二步,我們用JDK的javac.exe文件編譯我們的Java源程序,由于JDK是國際版的,在編譯的時候,如果我們沒有用-encoding參數(shù)指定我們的JAVA源程序的編碼格式,則javac.exe首先獲得我們操作系統(tǒng)默認采用的編碼格式,也即在編譯java程序時,若我們不指定源程序文件的編碼格式,JDK首先獲得操作系統(tǒng)的file.encoding參數(shù)(它保存的就是操作系統(tǒng)默認的編碼格式,如WIN2k,它的值為GBK),然后JDK就把我們的java源程序從file.encoding編碼格式轉(zhuǎn)化為JAVA內(nèi)部默認的UNICODE格式放入內(nèi)存中。然后,javac把轉(zhuǎn)換后的unicode格式的文件進行編譯成.class類文件,此時.class文件是UNICODE編碼的,它暫放在內(nèi)存中,緊接著,JDK將此以UNICODE編碼的編譯后的class文件保存到我們的操作系統(tǒng)中形成我們見到的.class文件。對我們來說,我們最終獲得的.class文件是內(nèi)容以UNICODE編碼格式保存的類文件,它內(nèi)部包含我們源程序中的中文字符串,只不過此時它己經(jīng)由file.encoding格式轉(zhuǎn)化為UNICODE格式了。
    ????這一步中,對于JSP源程序文件是不同的,對于JSP,這個過程是這樣的:即WEB容器調(diào)用JSP編譯器,JSP編譯器先查看JSP文件中是否設(shè)置有文件編碼格式,如果JSP文件中沒有設(shè)置JSP文件的編碼格式,則JSP編譯器調(diào)用JDK先把JSP文件用JVM默認的字符編碼格式(也即WEB容器所在的操作系統(tǒng)的默認的file.encoding)轉(zhuǎn)化為臨時的Servlet類,然后再把它編譯成UNICODE格式的class類,并保存在臨時文件夾中。如:在中文win2k上,WEB容器就把JSP文件從GBK編碼格式轉(zhuǎn)化為UNICODE格式,然后編譯成臨時保存的Servlet類,以響應(yīng)用戶的請求。
    ????第三步,運行第二步編譯出來的類,分為三種情況:
    ????A、 直接在console上運行的類
    ????B、 EJB類和不可以直接運行的支持類(如JavaBean類)
    ????C、 JSP代碼和Servlet類
    ????D、 JAVA程序和數(shù)據(jù)庫之間
    ????下面我們分這四種情況來看。
    ????A、直接在console上運行的類
    ????這種情況,運行該類首先需要JVM支持,即操作系統(tǒng)中必須安裝有JRE。運行過程是這樣的:首先java啟動JVM,此時JVM讀出操作系統(tǒng)中保存的class文件并把內(nèi)容讀入內(nèi)存中,此時內(nèi)存中為UNICODE格式的class類,然后JVM運行它,如果此時此類需要接收用戶輸入,則類會默認用file.encoding編碼格式對用戶輸入的串進行編碼并轉(zhuǎn)化為unicode保存入內(nèi)存(用戶可以設(shè)置輸入流的編碼格式)。程序運行后,產(chǎn)生的字符串(UNICODE編碼的)再回交給JVM,最后JRE把此字符串再轉(zhuǎn)化為file.encoding格式(用戶可以設(shè)置輸出流的編碼格式)傳遞給操作系統(tǒng)顯示接口并輸出到界面上。
    ????對于這種直接在console上運行的類,它的轉(zhuǎn)化過程可用圖1更加明確的表示出來:

    圖1
    ????以上每一步的轉(zhuǎn)化都需要正確的編碼格式轉(zhuǎn)化,才能最終不出現(xiàn)亂碼現(xiàn)象。
    ????B、EJB類和不可以直接運行的支持類(如JavaBean類)
    ????由于EJB類和不可以直接運行的支持類,它們一般不與用戶直接交互輸入和輸出,它們常常與其它的類進行交互輸入和輸出,所以它們在第二步被編譯后,就形成了內(nèi)容是UNICODE編碼的類保存在操作系統(tǒng)中了,以后只要它與其它的類之間的交互在參數(shù)傳遞過程中沒有丟失,則它就會正確的運行。
    這種EJB類和不可以直接運行的支持類, 它的轉(zhuǎn)化過程可用圖2更加明確的表示出來:

    圖2
    ????C、JSP代碼和Servlet類
    ????經(jīng)過第二步后,JSP文件也被轉(zhuǎn)化為Servlets類文件,只不過它不像標準的Servlets一校存在于classes目錄中,它存在于WEB容器的臨時目錄中,故這一步中我們也把它做為Servlets來看。
    ????對于Servlets,客戶端請求它時,WEB容器調(diào)用它的JVM來運行Servlet,首先,JVM把Servlet的class類從系統(tǒng)中讀出并裝入內(nèi)存中,內(nèi)存中是以UNICODE編碼的Servlet類的代碼,然后JVM在內(nèi)存中運行該Servlet類,如果Servlet在運行的過程中,需要接受從客戶端傳來的字符如:表單輸入的值和URL中傳入的值,此時如果程序中沒有設(shè)定接受參數(shù)時采用的編碼格式,則WEB容器會默認采用ISO-8859-1編碼格式來接受傳入的值并在JVM中轉(zhuǎn)化為UNICODE格式的保存在WEB容器的內(nèi)存中。Servlet運行后生成輸出,輸出的字符串是UNICODE格式的,緊接著,容器將Servlet運行產(chǎn)生的UNICODE格式的串(如html語法,用戶輸出的串等)直接發(fā)送到客戶端瀏覽器上并輸出給用戶,如果此時指定了發(fā)送時輸出的編碼格式,則按指定的編碼格式輸出到瀏覽器上,如果沒有指定,則默認按ISO-8859-1編碼發(fā)送到客戶的瀏覽器上。這種JSP代碼和Servlet類,它的轉(zhuǎn)化過程可用圖3更加明確地表示出來:

    圖3
    ????D、Java程序和數(shù)據(jù)庫之間
    ????對于幾乎所有數(shù)據(jù)庫的JDBC驅(qū)動程序,默認的在JAVA程序和數(shù)據(jù)庫之間傳遞數(shù)據(jù)都是以ISO-8859-1為默認編碼格式的,所以,我們的程序在向數(shù)據(jù)庫內(nèi)存儲包含中文的數(shù)據(jù)時,JDBC首先是把程序內(nèi)部的UNICODE編碼格式的數(shù)據(jù)轉(zhuǎn)化為ISO-8859-1的格式,然后傳遞到數(shù)據(jù)庫中,在數(shù)據(jù)庫保存數(shù)據(jù)時,它默認即以ISO-8859-1保存,所以,這是為什么我們常常在數(shù)據(jù)庫中讀出的中文數(shù)據(jù)是亂碼。
    ????對于JAVA程序和數(shù)據(jù)庫之間的數(shù)據(jù)傳遞,我們可以用圖4清晰地表示出來

    圖4
    ????3、分析常見的JAVA中文問題幾個必須清楚的原則
    ????首先,經(jīng)過上面的詳細分析,我們可以清晰地看到,任何JAVA程序的生命期中,其編碼轉(zhuǎn)換的關(guān)鍵過程是在于:最初編譯成class文件的轉(zhuǎn)碼和最終向用戶輸出的轉(zhuǎn)碼過程。
    ????其次,我們必須了解JAVA在編譯時支持的、常用的編碼格式有以下幾種:
    ????*ISO-8859-1,8-bit, 同8859_1,ISO-8859-1,ISO_8859_1等編碼
    ????*Cp1252,美國英語編碼,同ANSI標準編碼
    ????*UTF-8,同unicode編碼
    ????*GB2312,同gb2312-80,gb2312-1980等編碼
    ????*GBK , 同MS936,它是gb2312的擴充
    ????及其它的編碼,如韓文、日文、繁體中文等。同時,我們要注意這些編碼間的兼容關(guān)體系如下:
    ????unicode和UTF-8編碼是一一對應(yīng)的關(guān)系。GB2312可以認為是GBK的子集,即GBK編碼是在gb2312上擴展來的。同時,GBK編碼包含了20902個漢字,編碼范圍為:0x8140-0xfefe,所有的字符可以一一對應(yīng)到UNICODE2.0中來。
    ????再次,對于放在操作系統(tǒng)中的.java源程序文件,在編譯時,我們可以指定它內(nèi)容的編碼格式,具體來說用-encoding來指定。注意:如果源程序中含有中文字符,而你用-encoding指定為其它的編碼字符,顯然是要出錯的。用-encoding指定源文件的編碼方式為GBK或gb2312,無論我們在什么系統(tǒng)上編譯含有中文字符的JAVA源程序都不會有問題,它都會正確地將中文轉(zhuǎn)化為UNICODE存儲在class文件中。
    ????
    然后,我們必須清楚,幾乎所有的WEB容器在其內(nèi)部默認的字符編碼格式都是以ISO-8859-1為默認值的,同時,幾乎所有的瀏覽器在傳遞參數(shù)時都是默認以UTF-8的方式來傳遞參數(shù)的。所以,雖然我們的Java源文件在出入口的地方指定了正確的編碼方式,但其在容器內(nèi)部運行時還是以ISO-8859-1來處理的。

    ?




    ???4、中文問題的分類及其建議最優(yōu)解決辦法
    ????了解以上JAVA處理文件的原理之后,我們就可以提出了一套建議最優(yōu)的解決漢字問題的辦法。
    ????我們的目標是:我們在中文系統(tǒng)中編輯的含有中文字符串或進行中文處理的JAVA源程序經(jīng)編譯后可以移值到任何其它的操作系統(tǒng)中正確運行,或拿到其它操作系統(tǒng)中編譯后能正確運行,能正確地傳遞中文和英文參數(shù),能正確地和數(shù)據(jù)庫交流中英文字符串。
    ????我們的具體思路是:在JAVA程序轉(zhuǎn)碼的入口和出口及JAVA程序同用戶有輸入輸出轉(zhuǎn)換的地方限制編碼方法使之正確即可。
    ????具體解決辦法如下:
    ????1、 針對直接在console上運行的類
    ????對于這種情況,我們建議在程序編寫時,如果需要從用戶端接收用戶的可能含有中文的輸入或含有中文的輸出,程序中應(yīng)該采用字符流來處理輸入和輸出,具體來說,應(yīng)用以下面向字符型節(jié)點流類型:
    ????對文件:FileReader,F(xiàn)ileWrieter
    ????????其字節(jié)型節(jié)點流類型為:FileInputStream,F(xiàn)ileOutputStream
    ????對內(nèi)存(數(shù)組):CharArrayReader,CharArrayWriter
    ????????其字節(jié)型節(jié)點流類型為:ByteArrayInputStream,ByteArrayOutputStream
    ????對內(nèi)存(字符串):StringReader,StringWriter
    ????對管道:PipedReader,PipedWriter
    ????????其字節(jié)型節(jié)點流類型為:PipedInputStream,PipedOutputStream
    ????同時,應(yīng)該用以下面向字符型處理流來處理輸入和輸出:
    ????BufferedWriter,BufferedReader
    ????????其字節(jié)型的處理流為:BufferedInputeStream,BufferedOutputStream
    ????InputStreamReader,OutputStreamWriter
    ????其字節(jié)型的處理流為:DataInputStream,DataOutputStream
    ????其中InputStreamReader和InputStreamWriter用于將字節(jié)流按照指定的字符編碼集轉(zhuǎn)換到字符流,如:
    ????InputStreamReader in = new InputStreamReader(System.in,"GB2312");
    ????OutputStreamWriter out = new OutputStreamWriter (System.out,"GB2312");
    ????例如:采用如下的示例JAVA編碼就達到了要求:
    //Read.java
    import java.io.*;
    public class Read {
    public static void main(String[] args) throws IOException {
    String str = "\n中文測試,這是內(nèi)部硬編碼的串"+"\ntest english character";
    String strin= "";
    BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in,"gb2312")); //設(shè)置輸入接口按中文編碼
    BufferedWriter stdout = new BufferedWriter(new OutputStreamWriter(System.out,"gb2312")); //設(shè)置輸出接口按中文編碼
    stdout.write("請輸入:");
    stdout.flush();
    strin = stdin.readLine();
    stdout.write("這是從用戶輸入的串:"+strin);
    stdout.write(str);
    stdout.flush();
    }}
    ????同時,在編譯程序時,我們用以下方式來進行:
    ????javac -encoding gb2312 Read.java
    ????其運行結(jié)果如圖5所示:

    ????圖5
    ????2、 針對EJB類和不可以直接運行的支持類(如JavaBean類)
    ????由于這種類它們本身被其它的類調(diào)用,不直接與用戶交互,故對這種類來說,我們的建議的處理方式是內(nèi)部程序中應(yīng)該采用字符流來處理程序內(nèi)部的中文字符串(具體如上面一節(jié)中一樣),同時,在編譯類時用-encoding gb2312參數(shù)指示源文件是中文格式編碼的即可。
    ????3、 針對Servlet類
    ????針對Servlet,我們建議用以下方法:
    ????在編譯Servlet類的源程序時,用-encoding指定編碼為GBK或GB2312,且在向用戶輸出時的編碼部分用response對象的setContentType("text/html;charset=GBK");或gb2312來設(shè)置輸出編碼格式,同樣在接收用戶輸入時,我們用request.setCharacterEncoding("GB2312");這樣無論我們的servlet類移植到什么操作系統(tǒng)中,只有客戶端的瀏覽器支持中文顯示,就可以正確顯示。如下是一個正確的示例:
    //HelloWorld.java
    package hello;
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    public class HelloWorld extends HttpServlet
    {
    public void init() throws ServletException { }
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
    request.setCharacterEncoding("GB2312"); //設(shè)置輸入編碼格式
    response.setContentType("text/html;charset=GB2312"); //設(shè)置輸出編碼格式
    PrintWriter out = response.getWriter(); //建議使用PrintWriter輸出
    out.println("&lt hr &gt");
    out.println("Hello World! This is created by Servlet!測試中文!");
    out.println("&lt hr &gt");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
    request.setCharacterEncoding("GB2312"); //設(shè)置輸入編碼格式
    response.setContentType("text/html;charset=GB2312"); //設(shè)置輸出編碼格式
    String name = request.getParameter("name");
    String id = request.getParameter("id");
    if(name==null) name="";
    if(id==null) id="";
    PrintWriter out = response.getWriter(); //建議使用PrintWriter輸出
    out.println("&lt hr &gt");
    out.println("你傳入的中文字串是:" + name);
    out.println("&lt hr &gt你輸入的id是:" + id);
    out.println("&lt hr &gt");
    }
    public void destroy() { }
    }
    ??? 請用javac -encoding gb2312 HelloWorld.java來編譯此程序。
    ??? 測試此Servlet的程序如下所示:
    &lt %@page contentType="text/html; charset=gb2312"% &gt
    &lt %request.setCharacterEncoding("GB2312");% &gt
    &lt html &gt&lt head &gt&lt title &gt&lt /title &gt
    &lt Script language="JavaScript" &gt
    function Submit() {
    //通過URL傳遞中文字符串值給Servlet
    document.base.action = "./HelloWorld?name=中文";
    document.base.method = "POST";
    document.base.submit();
    }
    &lt /Script &gt
    &lt /head &gt
    &lt body bgcolor="#FFFFFF" text="#000000" topmargin="5" &gt
    &lt form name="base" method = "POST" target="_self" &gt
    &lt input name="id" type="text" value="" size="30" &gt
    &lt a href = "JavaScript:Submit()" &gt傳給Servlet&lt /a &gt
    &lt /form &gt&lt /body &gt&lt /html &gt
    ??? 其運行結(jié)果如圖6所示:

    ????圖6
    ????4、 JAVA程序和數(shù)據(jù)庫之間
    ????為避免JAVA程序和數(shù)據(jù)庫之間數(shù)據(jù)傳遞出現(xiàn)亂碼現(xiàn)象,我們建議采用以下最優(yōu)方法來處理:
    ????1、 對于JAVA程序的處理方法按我們指定的方法處理。
    ????2、 把數(shù)據(jù)庫默認支持的編碼格式改為GBK或GB2312的。
    ????如:在mysql中,我們可以在配置文件my.ini中加入以下語句實現(xiàn):
    ????在[mysqld]區(qū)增加:
    ????default-character-set=gbk
    ????并增加:
    ????[client]
    ????default-character-set=gbk
    ????在SQL Server2K中,我們可以將數(shù)據(jù)庫默認的語言設(shè)置為Simplified Chinese來達到目的。
    ????5、 針對JSP代碼
    ????由于JSP是在運行時,由WEB容器進行動態(tài)編譯的,如果我們沒有指定JSP源文件的編碼格式,則JSP編譯器會獲得服務(wù)器操作系統(tǒng)的file.encoding值來對JSP文件編譯的,它在移植時最容易出問題,如在中文win2k中可以很好運行的jsp文件拿到英文linux中就不行,盡管客戶端都是一樣的,那是因為容器在編譯JSP文件時獲取的操作系統(tǒng)的編碼不同造成的(在中文wink中的file.encoding和在英文Linux中file.encoding是不同的,且英文Linux的file.encoding對中文不支持,所以編譯出來的JSP類就會有問題)。網(wǎng)絡(luò)上討論的大多數(shù)是此類問題,多是因為JSP文件移植平臺時不能正確顯示的問題,對于這類問題,我們了解了JAVA中程序編碼轉(zhuǎn)換的原理,解決起來就容易多了。我們建議的解決辦法如下:
    ????1、我們要保證JSP向客戶端輸出時是采用中文編碼方式輸出的,即無論如何我們首先在我們的JSP源代編中加入以下一行:

    ? &lt %@page contentType="text/html; charset=gb2312"% &gt
    ??? 2、為了讓JSP能正確獲得傳入的參數(shù),我們在JSP源文件頭加入下面一句:
    ??? &lt %request.setCharacterEncoding("GB2312");% &gt
    ??? 3、為了讓JSP編譯器能正確地解碼我們的含有中文字符的JSP文件,我們需要在JSP源文件中指定我們的JSP源文件的編碼格式,具體來說,我們在JSP源文件頭上加入下面的一句即可:
    ??? &lt %@page pageEncoding="GB2312"% &gt或&lt %@page pageEncoding="GBK"% &gt
    ??? 這是JSP規(guī)范2.0新增加的指令。
    ??? 我們建議使用此方法來解JSP文件中的中文問題,下面的代碼是一個正確做法的JSP文件的測試程序:
    //testchinese.jsp
    &lt %@page pageEncoding="GB2312"% &gt
    &lt %@page contentType="text/html; charset=gb2312"% &gt
    &lt %request.setCharacterEncoding("GB2312");% &gt
    &lt %
    String action = request.getParameter("ACTION");
    String name = "";
    String str = "";
    if(action!=null && action.equals("SENT"))
    {
    name = request.getParameter("name");
    str = request.getParameter("str");
    }
    % &gt
    &lt html &gt
    &lt head &gt
    &lt title &gt&lt /title &gt
    &lt Script language="JavaScript" &gt
    function Submit()
    {
    document.base.action = "?ACTION=SENT&str=傳入的中文";
    document.base.method = "POST";
    document.base.submit();
    }
    &lt /Script &gt
    &lt /head &gt
    &lt body bgcolor="#FFFFFF" text="#000000" topmargin="5" &gt
    &lt form name="base" method = "POST" target="_self" &gt
    &lt input type="text" name="name" value="" size="30" &gt
    &lt a href = "JavaScript:Submit()" &gt提交&lt /a &gt
    &lt /form &gt
    &lt %
    if(action!=null && action.equals("SENT"))
    {
    out.println("&lt br &gt你輸入的字符為:"+name);
    out.println("&lt br &gt你通過URL傳入的字符為:"+str);
    }
    % &gt
    &lt /body &gt
    &lt /html &gt
    ??? 如圖7是此程序運行的結(jié)果示意圖:

    ????圖7
    ????5、總結(jié)
    ????在上面的詳細分析中,我們清晰地給出了JAVA在處理源程序過程中的詳細轉(zhuǎn)換過程,為我們正確解決JAVA編程中的中文問題提供了基礎(chǔ)。同時,我們給出了認為是最優(yōu)的解決JAVA中文問題的辦法。
    ????6、參考資料
    ????1、段明輝.Java 編程技術(shù)中漢字問題的分析及解決.
    ????????http://www-900.ibm.com/developerWorks/cn/java/java_chinese/index.shtml
    ????2、 周競濤.關(guān)于Java中文問題的幾條分析原則
    ????????http://www-900.ibm.com/developerWorks/cn/java/l-javachinese/index.shtml
    ????7、作者介紹
    ????????作者:abnerchai,高級程序員,作者聯(lián)系方法:josserchai@yahoo.com

    ???

    posted @ 2007-04-10 15:55 金家寶 閱讀(594) | 評論 (0)編輯 收藏

    Java/J2EE中文問題終極解決之道

    ?

    Java中文問題一直困擾著很多初學(xué)者,如果了解了Java系統(tǒng)的中文問題原理,我們就可以對中文問題能夠采取根本的解決之道。

      最古老的解決方案是使用String的字節(jié)碼轉(zhuǎn)換,這種方案問題是不方便,我們需要破壞對象封裝性,進行字節(jié)碼轉(zhuǎn)換。

      還有一種方式是對J2EE容器進行編碼設(shè)置,如果J2EE應(yīng)用系統(tǒng)脫離該容器,則會發(fā)生亂碼,而且指定容器配置不符合J2EE應(yīng)用和容器分離的原則。

      在Java內(nèi)部運算中,涉及到的所有字符串都會被轉(zhuǎn)化為UTF-8編碼來進行運算。那么,在被Java轉(zhuǎn)化之前,字符串是什么樣的字符集? Java總是根據(jù)操作系統(tǒng)的默認編碼字符集來決定字符串的初始編碼,而且Java系統(tǒng)的輸入和輸出的都是采取操作系統(tǒng)的默認編碼。

      因此,如果能統(tǒng)一Java系統(tǒng)的輸入、輸出和操作系統(tǒng)3者的編碼字符集合,將能夠使Java系統(tǒng)正確處理和顯示漢字。這是處理Java系統(tǒng)漢字的一個原則,但是在實際項目中,能夠正確抓住和控制住Java系統(tǒng)的輸入和輸出部分是比較難的。J2EE中,由于涉及到外部瀏覽器和數(shù)據(jù)庫等,所以中文問題亂碼顯得非常突出。

      J2EE應(yīng)用程序是運行在J2EE容器中。在這個系統(tǒng)中,輸入途徑有很多種:一種是通過頁面表單打包成請求(request)發(fā)往服務(wù)器的;第二種是通過數(shù)據(jù)庫讀入;還有第3種輸入比較復(fù)雜,JSP在第一次運行時總是被編譯成Servlet,JSP中常常包含中文字符,那么編譯使用javac時,Java將根據(jù)默認的操作系統(tǒng)編碼作為初始編碼。除非特別指定,如在Jbuilder/eclipse中可以指定默認的字符集。

      輸出途徑也有幾種:第一種是JSP頁面的輸出。由于JSP頁面已經(jīng)被編譯成Servlet,那么在輸出時,也將根據(jù)操作系統(tǒng)的默認編碼來選擇輸出編碼,除非指定輸出編碼方式;還有輸出途徑是數(shù)據(jù)庫,將字符串輸出到數(shù)據(jù)庫。

      由此看來,一個J2EE系統(tǒng)的輸入輸出是非常復(fù)雜,而且是動態(tài)變化的,而Java是跨平臺運行的,在實際編譯和運行中,都可能涉及到不同的操作系統(tǒng),如果任由Java自由根據(jù)操作系統(tǒng)來決定輸入輸出的編碼字符集,這將不可控制地出現(xiàn)亂碼。

      正是由于Java的跨平臺特性,使得字符集問題必須由具體系統(tǒng)來統(tǒng)一解決,所以在一個Java應(yīng)用系統(tǒng)中,解決中文亂碼的根本辦法是明確指定整個應(yīng)用系統(tǒng)統(tǒng)一字符集。

      指定統(tǒng)一字符集時,到底是指定ISO8859_1 、GBK還是UTF-8呢?

     ?。?)如統(tǒng)一指定為ISO8859_1,因為目前大多數(shù)軟件都是西方人編制的,他們默認的字符集就是ISO8859_1,包括操作系統(tǒng)Linux和數(shù)據(jù)庫MySQL等。這樣,如果指定Jive統(tǒng)一編碼為ISO8859_1,那么就有下面3個環(huán)節(jié)必須把握:

      開發(fā)和編譯代碼時指定字符集為ISO8859_1。

      運行操作系統(tǒng)的默認編碼必須是ISO8859_1,如Linux。

      在JSP頭部聲明:<%@ page contentType="text/html;charset=ISO8859_1" %>。

      (2)如果統(tǒng)一指定為GBK中文字符集,上述3個環(huán)節(jié)同樣需要做到,不同的是只能運行在默認編碼為GBK的操作系統(tǒng),如中文Windows。

      統(tǒng)一編碼為ISO8859_1和GBK雖然帶來編制代碼的方便,但是各自只能在相應(yīng)的操作系統(tǒng)上運行。但是也破壞了Java跨平臺運行的優(yōu)越性,只在一定范圍內(nèi)行得通。例如,為了使得GBK編碼在linux上運行,設(shè)置Linux編碼為GBK。

      那么有沒有一種除了應(yīng)用系統(tǒng)以外不需要進行任何附加設(shè)置的中文編碼根本解決方案呢?

      將Java/J2EE系統(tǒng)的統(tǒng)一編碼定義為UTF-8。UTF-8編碼是一種兼容所有語言的編碼方式,惟一比較麻煩的就是要找到應(yīng)用系統(tǒng)的所有出入口,然后使用UTF-8去“結(jié)扎”它。

      一個J2EE應(yīng)用系統(tǒng)需要做下列幾步工作:

    1. 開發(fā)和編譯代碼時指定字符集為UTF-8。JBuilder和Eclipse都可以在項目屬性中設(shè)置。
    2. 使用過濾器,如果所有請求都經(jīng)過一個Servlet控制分配器,那么使用Servlet的filter執(zhí)行語句,將所有來自瀏覽器的請求(request)轉(zhuǎn)換為UTF-8,因為瀏覽器發(fā)過來的請求包根據(jù)瀏覽器所在的操作系統(tǒng)編碼,可能是各種形式編碼。關(guān)鍵一句:
      request.setCharacterEncoding("UTF-8")。
      網(wǎng)上有此filter的源碼,Jdon框架源碼中com.jdon.util.SetCharacterEncodingFilter
      需要配置web.xml 激活該Filter。
    3. 在JSP頭部聲明:<%@ page contentType="text/html;charset= UTF-8" %>。
    4. 在Jsp的html代碼中,聲明UTF-8:
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    5. 設(shè)定數(shù)據(jù)庫連接方式是UTF-8。例如連接MYSQL時配置URL如下:
      jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8
      一般數(shù)據(jù)庫都可以通過管理設(shè)置設(shè)定UTF-8
    6. 其他和外界交互時能夠設(shè)定編碼時就設(shè)定UTF-8,例如讀取文件,操作XML等。
           

      以上討論了Java/J2EE的中文問題。如果整個應(yīng)用系統(tǒng)是從開始進行開發(fā),那么統(tǒng)一指定編碼為UTF-8就非常容易做到。如果是在英文源代碼基礎(chǔ)上二次開發(fā),那么首先要將原來的源代碼轉(zhuǎn)換為統(tǒng)一編碼UTF-8,那么這種轉(zhuǎn)換工作會帶來一定的麻煩?! ?

      有了這個解決方案,無論使用什么框架Struts 或JSF或未來出現(xiàn)的Java技術(shù),統(tǒng)一成UTF-8的方案都不會出現(xiàn)亂碼,筆者以前在Jsp/Servlet時就基于這個原則,后來使用Struts等框架,從未被亂碼困擾過,希望本方案公布出來供更多初學(xué)者分享,減少Java/J2EE的第一個攔路虎,也避免采取一些臨時解決方案。

    posted @ 2007-04-10 15:38 金家寶 閱讀(227) | 評論 (0)編輯 收藏

    表現(xiàn)層、持久層、業(yè)務(wù)層

    為了實現(xiàn)web層(struts)和持久層(Hibernate)之間的松散耦合,我們采用業(yè)務(wù)代表(Business Delegate)和DAO(Data Access Object)兩種模式。DAO模式為了減少業(yè)務(wù)邏輯和數(shù)據(jù)訪問邏輯之間的耦合,當一個持久曾框架被應(yīng)用時,該模式將會減少業(yè)務(wù)對象和該框架之間的耦合,這樣我們可以不修改業(yè)務(wù)對象而選擇不同的持久層框架的實現(xiàn)。實際上在DAO模式中包含兩種結(jié)構(gòu)模式:橋(Bridge)模式和適配器(Adaptor)模式。?

    對表現(xiàn)層,我們使用 Struts ;業(yè)務(wù)層使用 Spring ;對于持久層我們使用的是 Hibernate 。你盡可以取代這里的某個框架而使用你喜歡的框架已達到同樣的效果。下圖顯示了框架被整合起來時,從最高層次看到的視圖。

    clip_image001_0007.gif

    應(yīng)用層

    ??? 許多設(shè)計良好的web應(yīng)用,可以被按職責(zé)分為四層。這些層次是表現(xiàn)層、持久層、業(yè)務(wù)層、和領(lǐng)域模型層。每一個層次都有其獨特的職責(zé),不能把各自的功能與其它層次相混合。每一個應(yīng)用層都應(yīng)該和其它層隔離開來,但允許使用接口在層間進行通信。我們開始來看看每個層,并討論一下它們各自都應(yīng)該提供什么和不應(yīng)該提供什么。

    表現(xiàn)層

    ??? 一個典型的web 應(yīng)用的末端是表現(xiàn)層。許多Java 開發(fā)者都知道Struts提供了什么東西。然而,太多時候,耦合代碼比如業(yè)務(wù)邏輯被放進org.apache.struts.Action中。所以,我們先總結(jié)一下Struts之類的框架應(yīng)該提供什么。下面就是Struts 的職責(zé)所在:

    1. 管理用戶的請求和響應(yīng)
    2. 提供一個控制起來將調(diào)用委托到業(yè)務(wù)邏輯和其他上游處理
    3. 將來自于拋出例外的其他層的例外處理到Struts Action 中
    4. 組裝可以在視圖中表現(xiàn)的模型對象
    5. 執(zhí)行UI 校驗

    下面是一些經(jīng)??梢允褂肧truts進行編碼但是不應(yīng)該和表現(xiàn)層關(guān)聯(lián)的事情:

    1. 直接和數(shù)據(jù)庫交互,比如JDBC 調(diào)用
    2. 與應(yīng)用相關(guān)的業(yè)務(wù)邏輯和校驗
    3. 事務(wù)管理

    在表現(xiàn)層中引入這些類型的代碼將導(dǎo)致類型耦合和維護負擔。

    持久層

    ??? 一個典型Web應(yīng)用的另一端是持久層。這也是應(yīng)用中最容易很快失控的地方。開發(fā)者通常低估了自己構(gòu)建自己的持久層框架的挑戰(zhàn)。一個定制的,內(nèi)部開發(fā)的持久層不僅需要大量的開發(fā)時間,并且通常缺乏功能和難以管理。目前有許多解決這些問題的開源對象關(guān)系映射 (ORM) 框架。特別地,Hibernate 框架就允許Java中的對象-關(guān)系的持久性和查詢服務(wù)。Hibernate 對已經(jīng)熟悉了SQL 和JDBC API的Java開發(fā)者來或具有中度的學(xué)習(xí)曲線。Hibernate 的持久對象基于POJO和Java群集(collections)。此外,使用Hibernate 不和你的IDE接口。下面列出了你需要在持久性框架中編寫的代碼類型:

    1. 查詢關(guān)系信息到對象中。Hibernate是通過稱為HQL的OO查詢語言,或者使用更有表現(xiàn)能力的規(guī)則API,來完成這個工作的。除了使用對象而不是表,使用字段而不是列的方式,HQL非常類似于 SQL。也有一些新的特定的HQL 語言特征需要學(xué)習(xí);但是,它們是很容易理解和良好編寫的。HQL是一種用于查詢對象的自然語言,而對象,只需要很少的學(xué)習(xí)曲線吧。.
    2. 存儲、更新和刪除存儲在數(shù)據(jù)庫中的信息
    3. 高級的對象關(guān)系映射框架比如Hibernate支持大部分主流SQL數(shù)據(jù)庫,它們支持父/子關(guān)系,事務(wù),繼承和多態(tài)。

    下面是應(yīng)該在持久層避免的一些事情:

    1. 業(yè)務(wù)邏輯應(yīng)該置于應(yīng)用的更高層中。這里只允許數(shù)據(jù)訪問方法。
    2. 不應(yīng)該使持久邏輯和表現(xiàn)邏輯耦合。避免表現(xiàn)組件如JSP或者基于servlet的類中的邏輯直接和數(shù)據(jù)訪問進行通信。通過將持久性邏輯隔離在其自己的層中,應(yīng)用將具有更加靈活的修改性而不影響到其他層的代碼。例如, Hibernate可以使用其他持久框架和API代替,而不需要修改其它層中的代碼。

    業(yè)務(wù)層應(yīng)該負責(zé)下面的問題:

    1. 處理應(yīng)用的業(yè)務(wù)邏輯和業(yè)務(wù)校驗
    2. 管理事務(wù)
    3. 允許與其他層進行交互的接口
    4. 管理業(yè)務(wù)級對象之間的依賴性
    5. 加入了表現(xiàn)和持久層之間的靈活性,以便它們不需要彼此進行直接通信
    6. 從表現(xiàn)層暴露上下文給業(yè)務(wù)層以獲得業(yè)務(wù)服務(wù)
    7. 管理從業(yè)務(wù)層到表現(xiàn)層的實現(xiàn)

    posted @ 2007-04-08 03:17 金家寶 閱讀(24150) | 評論 (6)編輯 收藏

    關(guān)于POJO及DAO- -

    POJO = pure old Java object POJO有一些private的參數(shù)作為對象的屬性。然后針對每個參數(shù)定義了get和set方法作為訪問的接口。例如: public class User {

    private long id;

    private String name;

    public void setId(long id) {

    this.id = id;

    }

    public void setName(String name) {

    this.name=name;

    }

    public long getId() {

    return id;

    }

    public String getName() {

    return name;

    }

    }

    POJO對象有時也被稱為Data對象,大量應(yīng)用于表現(xiàn)現(xiàn)實中的對象。

    取自"

    ?

    ??????????????????????????????????????

    POJO = pure old java object or plain ordinary java object or what ever.

    PO = persisent object 持久對象

    就是說在一些Object/Relation Mapping工具中,能夠做到維護數(shù)據(jù)庫表記錄的persisent object完全是一個符合Java Bean規(guī)范的純Java對象,沒有增加別的屬性和方法。全都是這樣子的:

    public class User { 
      private long id; 
      private String name;
      public void setId(long id) {
     this.id = id;
    }  
    public void setName(String name) {
    this.name=name;
    } 
     public long getId() {
     return id;
    }  
    public String getName() { 
    return name;
    }
    }  
    

    首先要區(qū)別持久對象和POJO。

    持久對象實際上必須對應(yīng)數(shù)據(jù)庫中的entity,所以和POJO有所區(qū)別。比如說POJO是由new創(chuàng)建,由GC回收。但是持久對象是insert數(shù)據(jù)庫創(chuàng)建,由數(shù)據(jù)庫delete刪除的?;旧铣志脤ο笊芷诤蛿?shù)據(jù)庫密切相關(guān)。另外持久對象往往只能存在一個數(shù)據(jù)庫Connection之中,Connnection關(guān)閉以后,持久對象就不存在了,而POJO只要不被GC回收,總是存在的。

    由于存在諸多差別,因此持久對象PO(Persistent Object)在代碼上肯定和POJO不同,起碼PO相對于POJO會增加一些用來管理數(shù)據(jù)庫entity狀態(tài)的屬性和方法。而ORM追求的目標就是要PO在使用上盡量和POJO一致,對于程序員來說,他們可以把PO當做POJO來用,而感覺不到PO的存在。

    JDO的實現(xiàn)方法是這樣的:

    1、編寫POJO

    2、編譯POJO

    3、使用JDO的一個專門工具,叫做Enhancer,一般是一個命令行程序,手工運行,或者在ant腳本里面運行,對POJO的class文件處理一下,把POJO替換成同名的PO。

    4、在運行期運行的實際上是PO,而不是POJO。

    該方法有點類似于JSP,JSP也是在編譯期被轉(zhuǎn)換成Servlet來運行的,在運行期實際上運行的是Servlet,而不是JSP。

    Hibernate的實現(xiàn)方法比較先進:

    1、編寫POJO

    2、編譯POJO

    3、直接運行,在運行期,由Hibernate的CGLIB動態(tài)把POJO轉(zhuǎn)換為PO。

    由此可以看出Hibernate是在運行期把POJO的字節(jié)碼轉(zhuǎn)換為PO的,而JDO是在編譯期轉(zhuǎn)換的。一般認為JDO的方式效率會稍高,畢竟是編譯期轉(zhuǎn)換嘛。但是Hibernate的作者Gavin King說CGLIB的效率非常之高,運行期的PO的字節(jié)碼生成速度非常之快,效率損失幾乎可以忽略不計。

    實際上運行期生成PO的好處非常大,這樣對于程序員來說,是無法接觸到PO的,PO對他們來說完全透明??梢愿幼杂傻囊訮OJO的概念操縱PO。另外由于是運行期生成PO,所以可以支持增量編譯,增量調(diào)試。而JDO則無法做到這一點。實際上已經(jīng)有很多人在抱怨JDO的編譯期Enhancer問題了,而據(jù)說JBossDO將采用運行期生成PO字節(jié)碼,而不采用編譯期生成PO字節(jié)碼。

    另外一個相關(guān)的問題是,不同的JDO產(chǎn)品的Enhancer生成的PO字節(jié)碼可能會有所不同,可能會影響在JDO產(chǎn)品之間的可移植性,這一點有點類似EJB的可移植性難題。


    由這個問題另外引出一個JDO的缺陷。

    由于JDO的PO狀態(tài)管理方式,所以當你在程序里面get/set的時候,實際上不是從PO的實例中取values,而是從JDO State Manager?中取出來,所以一旦PM關(guān)閉,PO就不能進行存取了。

    在JDO中,也可以通過一些辦法使得PO可以在PM外面使用,比如說定義PO是transient的,但是該PO在PM關(guān)閉后就沒有PO identity了。無法進行跨PM的狀態(tài)管理。

    而Hibernate是從PO實例中取values的,所以即使Session關(guān)閉,也一樣可以get/set,可以進行跨Session的狀態(tài)管理。

    在分多層的應(yīng)用中,由于持久層和業(yè)務(wù)層和web層都是分開的,此時Hibernate的PO完全可以當做一個POJO來用,也就是當做一個VO,在各層間自由傳遞,而不用去管Session是開還是關(guān)。如果你把這個POJO序列化的話,甚至可以用在分布式環(huán)境中。(不適合lazy loading的情況)

    但是JDO的PO在PM關(guān)閉后就不能再用了,所以必須在PM關(guān)閉前把PO拷貝一份VO,把VO傳遞給業(yè)務(wù)層和web層使用。在非分布式環(huán)境中,也可以使用ThreadLocal模式確保PM始終是打開狀態(tài),來避免每次必須進行PO到VO的拷貝操作。但是不管怎么說,這總是權(quán)宜之計,不如Hibernate的功能強。

    辨別一些名詞:
    1。VO:實際上很模糊,通常指ValueObject和ViewObject
    2. ViewObject,界面展現(xiàn)需要的對象,如Struts的FormBean
    3。Value Object,早期被作為ValueObject和Transfer Object的總稱。實際上Value Object的真正意義在于它的內(nèi)容,而不是身份
    4。Transfer Object:數(shù)據(jù)傳輸對象,在應(yīng)用程序不同層次之間傳書對象,在一個分布式應(yīng)用程序中,通??梢蕴岣哒w的性能
    5。PO:也許就是Persistent Object,基本上就是Entity了
    在不同的體系結(jié)構(gòu)和實現(xiàn)方式里面,這些對象有可能重復(fù),也有可能不重疊。如果你要做一個對所有的體系都能夠方便移植的框架,那么每一種對象都需要嚴格區(qū)分。例如JDO的PO不能作為TO,應(yīng)為它不能脫離PM,譬如你可以選擇用ViewObject(如Struts的FOrmBean)直接作為TO,但在tapestry和Webwork里面就不合適了。但在很多時候,能夠方便實用是最重要的,不要過度設(shè)計就是了。

    POJO是這樣一個對象,它是一個普通的Java對象,它不同于EJB這樣的帶有繁重的容器控制功能的對象,它也不是那種被Enhanced過的對象,例如JDO的靜態(tài)Enhance,也不是類似Hibernate那樣被動態(tài)的byte code generation過。

    也就是說POJO的概念是相對于其他那種被人動過手腳的class而言的,它是沒有被動過手腳的。

    其實,為什么要做DAO?無非是:
    1, 管理connection/transaction (hibernate的話就是session/transaction)
    2, 便于進行統(tǒng)計/log操作;
    3, 便于進行權(quán)限控制;

    DAO模式中,有兩類對象,一種是DAO,一種是valueObject。 在我們討論的這個情況中,value object是hibernate對應(yīng)的POJO.

    那么,按照我的理解,DAO就是一個Transaction包裝器,其邏輯結(jié)構(gòu)就是商業(yè)的具體事務(wù)。此處,數(shù)據(jù)庫的transaction和商業(yè)的事務(wù)是統(tǒng)一的。

    posted @ 2007-04-06 22:11 金家寶 閱讀(1947) | 評論 (0)編輯 收藏

    僅列出標題
    共7頁: 上一頁 1 2 3 4 5 6 7 下一頁 
    主站蜘蛛池模板: 国产一卡2卡3卡4卡无卡免费视频 国产一卡二卡3卡四卡免费 | 美腿丝袜亚洲综合| 精品国产日韩亚洲一区91| 97在线观免费视频观看| 亚洲国产品综合人成综合网站| 免费国产黄网站在线观看可以下载| 亚洲欧洲日产国码无码久久99| 岛国岛国免费V片在线观看| 国产成人精品日本亚洲专区 | 114级毛片免费观看| 久久久亚洲AV波多野结衣| 99xxoo视频在线永久免费观看| 亚洲黄色片免费看| 蜜桃视频在线观看免费网址入口| 亚洲日本久久久午夜精品| 狼友av永久网站免费观看| 国产偷国产偷亚洲高清人| 综合亚洲伊人午夜网| 最新国产乱人伦偷精品免费网站| 亚洲国产精品自在在线观看| AV大片在线无码永久免费| 亚洲国产aⅴ成人精品无吗| 亚洲国产成人五月综合网 | 亚洲av激情无码专区在线播放| 91高清免费国产自产拍2021| 2020亚洲男人天堂精品| yy6080亚洲一级理论| 久草视频在线免费看| 亚洲五月综合缴情婷婷| 亚洲 无码 在线 专区| 午夜无码A级毛片免费视频| 亚洲欧美熟妇综合久久久久| 亚洲精品国产成人影院| 在线观看的免费网站无遮挡| 亚洲国产精品成人午夜在线观看| 亚洲欧洲中文日韩久久AV乱码| 免费看又黄又无码的网站| 亚洲爆乳无码专区www| 久久亚洲伊人中字综合精品| 啦啦啦在线免费视频| 久久99久久成人免费播放|