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

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

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

    Java Votary

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      48 隨筆 :: 1 文章 :: 80 評(píng)論 :: 0 Trackbacks

    #

    原文:http://m.tkk7.com/eamoi/archive/2005/11/01/17639.html

    有網(wǎng)友反映說《AJAX開發(fā)簡(jiǎn)略》配文代碼不全。其實(shí)應(yīng)該是全的,只是要把包括框架和兩個(gè)示例的程序都整合起來看。這里把全部的代碼貼出來,需要的朋友可以看看。
    sample1_1.jsp:
    <%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>無標(biāo)題文檔</title>
    <script language="javascript">
     var http_request = false;
     function send_request(url) {//初始化、指定處理函數(shù)、發(fā)送請(qǐng)求的函數(shù)
      http_request = false;
      //開始初始化XMLHttpRequest對(duì)象
      if(window.XMLHttpRequest) { //Mozilla 瀏覽器
       http_request = new XMLHttpRequest();
       if (http_request.overrideMimeType) {//設(shè)置MiME類別
        http_request.overrideMimeType('text/xml');
       }
      }
      else if (window.ActiveXObject) { // IE瀏覽器
       try {
        http_request = new ActiveXObject("Msxml2.XMLHTTP");
       } catch (e) {
        try {
         http_request = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {}
       }
      }
      if (!http_request) { // 異常,創(chuàng)建對(duì)象實(shí)例失敗
       window.alert("不能創(chuàng)建XMLHttpRequest對(duì)象實(shí)例.");
       return false;
      }
      http_request.onreadystatechange = processRequest;
      // 確定發(fā)送請(qǐng)求的方式和URL以及是否同步執(zhí)行下段代碼
      http_request.open("GET", url, true);
      http_request.send(null);
     }
     // 處理返回信息的函數(shù)
        function processRequest() {
            if (http_request.readyState == 4) { // 判斷對(duì)象狀態(tài)
                if (http_request.status == 200) { // 信息已經(jīng)成功返回,開始處理信息
                    alert(http_request.responseText);
                } else { //頁面不正常
                    alert("您所請(qǐng)求的頁面有異常。");
                }
            }
        }
     function userCheck() {
      var f = document.form1;
      var username = f.username.value;
      if(username=="") {
       window.alert("用戶名不能為空。");
       f.username.focus();
       return false;
      }
      else {
       send_request('sample1_2.jsp?username='+username);
      }
     }
    </script>
    <link href="css/style.css" rel="stylesheet" type="text/css">
    </head>

    <body>
    <form name="form1" action="" method="post">
    用戶名:<input type="text" name="username" value="">&nbsp;
    <input type="button" name="check" value="唯一性檢查" onClick="userCheck()">
    <input type="submit" name="submit" value="提交">
    </form>
    <!--span style="cursor: pointer; text-decoration: underline" onclick="send_request('2.jsp?username=educhina')">Send a request</span-->
    </body>
    </html>

    sample1_2.jsp:
    <%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>
    <%
    String playPos = request.getParameter("playPos");
    if("pos_1".equals(playPos)) out.print("用戶名已經(jīng)被注冊(cè),請(qǐng)更換一個(gè)用戶名。");
    else out.print("用戶名尚未被使用,您可以繼續(xù)。");
    %>

    sample2_1.jsp:
    <%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>無標(biāo)題文檔</title>
    <script language="javascript">
     var http_request = false;
     var currentPos = null;
     function send_request(url) {//初始化、指定處理函數(shù)、發(fā)送請(qǐng)求的函數(shù)
      http_request = false;
      //開始初始化XMLHttpRequest對(duì)象
      if(window.XMLHttpRequest) { //Mozilla 瀏覽器
       http_request = new XMLHttpRequest();
       if (http_request.overrideMimeType) {//設(shè)置MiME類別
        http_request.overrideMimeType('text/xml');
       }
      }
      else if (window.ActiveXObject) { // IE瀏覽器
       try {
        http_request = new ActiveXObject("Msxml2.XMLHTTP");
       } catch (e) {
        try {
         http_request = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {}
       }
      }
      if (!http_request) { // 異常,創(chuàng)建對(duì)象實(shí)例失敗
       window.alert("不能創(chuàng)建XMLHttpRequest對(duì)象實(shí)例.");
       return false;
      }
      http_request.onreadystatechange = processRequest;
      // 確定發(fā)送請(qǐng)求的方式和URL以及是否同步執(zhí)行下段代碼
      http_request.open("GET", url, true);
      http_request.send(null);
     }
     // 處理返回信息的函數(shù)
        function processRequest() {
            if (http_request.readyState == 4) { // 判斷對(duì)象狀態(tài)
                if (http_request.status == 200) { // 信息已經(jīng)成功返回,開始處理信息
                    //alert(http_request.responseText);
        document.getElementById(currentPos).innerHTML = http_request.responseText;
                } else { //頁面不正常
                    alert("您所請(qǐng)求的頁面有異常。");
                }
            }
        }
     //顯示部門下的崗位
     function showRoles(obj) {
      document.getElementById(obj).parentNode.style.display = "";
      document.getElementById(obj).innerHTML = "正在讀取數(shù)據(jù)..."
      currentPos = obj;
      send_request("sample2_2.jsp?playPos="+obj);
     }
    </script>
    <link href="css/style.css" rel="stylesheet" type="text/css">
    </head>

    <body>
    <table width="200" border="0" cellspacing="0" cellpadding="0">
        <tr>
            <td height="20"><a href="javascript:void(0)" onClick="showRoles('pos_1')">經(jīng)理室</a></td>
        </tr>
        <tr style="display:none">
            <td height="20" id="pos_1">&nbsp;</td>
        </tr>
        <tr>
            <td height="20"><a href="javascript:void(0)" onClick="showRoles('pos_2')">開發(fā)部</a></td>
        </tr>
        <tr style="display:none ">
            <td id="pos_2" height="20">&nbsp;</td>
        </tr>
    </table>
    <!--a href="javascript:void(0)" onClick="showRoles('pos_1')">測(cè)試</a-->
    <!--span style="cursor: pointer; text-decoration: underline" onclick="send_request('2.jsp?username=educhina')">Send a request</span-->
    </body>
    </html>

    sample2_2.jsp:
    <%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>
    <%
    String playPos = request.getParameter("playPos");
    if("pos_1".equals(playPos)) out.print("&nbsp;&nbsp;總經(jīng)理<br>&nbsp;&nbsp;副總經(jīng)理");
    else if("pos_2".equals(playPos)) out.println("&nbsp;&nbsp;總工程師<br>&nbsp;&nbsp;軟件工程師");
    %>

    posted @ 2005-11-23 20:26 Dion 閱讀(784) | 評(píng)論 (0)編輯 收藏

         摘要: http://m.tkk7.com/eamoi/archive/2005/10/31/17489.html AJAX開發(fā)簡(jiǎn)略   文檔說明   參與人員:   作者 網(wǎng)名 聯(lián)絡(luò) 柯自聰 eamoi   educhina ...  閱讀全文
    posted @ 2005-11-23 20:25 Dion 閱讀(587) | 評(píng)論 (0)編輯 收藏

         摘要: ASP服務(wù) ASP是英文Application Service Provider的縮寫,通常中文譯為應(yīng)用服務(wù)提供商,它是指配置、租賃和管理應(yīng)用解決方案,為商業(yè)、個(gè)人提供服務(wù)的專業(yè)化服務(wù)公司。通俗地說,ASP是一種業(yè)務(wù)租賃模式,企業(yè)用戶可以直接租用ASP的計(jì)算機(jī)及軟件系統(tǒng)進(jìn)行自己的業(yè)務(wù)管理,從而節(jié)省一大筆用于IT產(chǎn)品技術(shù)購(gòu)買和運(yùn)行的資金。 在國(guó)外,ASP最早出現(xiàn)于1998年,是伴隨著互聯(lián)...  閱讀全文
    posted @ 2005-11-23 20:23 Dion 閱讀(628) | 評(píng)論 (0)編輯 收藏

         摘要: (轉(zhuǎn))ASP的行業(yè)介紹   一、ASP的概念     1、 幾個(gè)比喻    想吃雞蛋,用不著買只母雞回家,想喝牛奶,也不需要牽一頭奶牛回家。同理,在互聯(lián)網(wǎng)時(shí)代,通過互聯(lián)網(wǎng),企業(yè)日常的生產(chǎn)、經(jīng)營(yíng)、管理過程中使用的應(yīng)用服務(wù)都可以讓別人幫你打點(diǎn),你可以節(jié)省時(shí)間和人力,他們向你收取租金,他們就是ASP...  閱讀全文
    posted @ 2005-11-23 20:22 Dion 閱讀(703) | 評(píng)論 (0)編輯 收藏

    ASP英文全稱為Application Service Provider,中文譯為應(yīng)用服務(wù)供應(yīng)商。 這是隨著Internet革命將人類從工業(yè)經(jīng)濟(jì)時(shí)代推向電子商務(wù)時(shí)代,并重塑信息技術(shù)(Information Technology,簡(jiǎn)稱IT)產(chǎn)業(yè)的未來發(fā)展方向所應(yīng)運(yùn)而生的一種嶄新的產(chǎn)品及服務(wù)模式。

    ASP的本質(zhì)在于:這種應(yīng)用,從所需的硬件平臺(tái)到應(yīng)用軟件、企業(yè)內(nèi)部資源管理和業(yè)務(wù)流程的處理,不是發(fā)生在企業(yè)本地的實(shí)施上,而是由特定的供應(yīng)商提供,并由供應(yīng)商進(jìn)行維護(hù)、管理及更新,企業(yè)(ASP的用戶)通過租賃、承包等方式獲得服務(wù)。

    因此,ASP產(chǎn)生和發(fā)展的前提條件主要基于以下IT技術(shù)的成熟:
     
    Internet
    的普及:Internet逐步深入人們生活,大量的基于Web的解決方案不斷涌現(xiàn),這些都使得遠(yuǎn)程的基于主機(jī)的應(yīng)用方案成為可能。
     
    帶寬不斷增大和價(jià)格不斷下降:增長(zhǎng)的通信性能和持續(xù)減少的帶寬費(fèi)用,使主機(jī)上的應(yīng)用程序可以通過Internet和瘦客戶機(jī)來訪問。
     
    客戶機(jī)/服務(wù)器環(huán)境下的可共享應(yīng)用:在ASP概念中的遠(yuǎn)程訪問,用戶早已經(jīng)在客戶機(jī)/服務(wù)器環(huán)境下習(xí)以為常,這使得遠(yuǎn)程訪問和共享應(yīng)用成為可接受的一種業(yè)務(wù)模式
     
    瀏覽器成為廣泛接受的圖形界面應(yīng)用程序:瀏覽器技術(shù)的的廣泛應(yīng)用及開發(fā)為基于Web的計(jì)算和瘦客戶機(jī)的計(jì)算聚集了足夠的技術(shù)及人力資源,以及良好的用戶基礎(chǔ)。
     
    電子商務(wù)解決方案的潛力:先進(jìn)的電子商務(wù)解決方案,與ASP的概念一起分享了許多棘手的業(yè)務(wù)和技術(shù)問題,例如系統(tǒng)的安全性和可靠性。所以,電子商務(wù)的巨大動(dòng)力也在推動(dòng)ASP的前進(jìn)。

    幾年前,當(dāng)應(yīng)用服務(wù)提供商(ASP)剛剛出現(xiàn)時(shí),它似乎是幫助企業(yè)投身數(shù)字時(shí)代的最佳選擇:ASP們開發(fā)、運(yùn)行和維護(hù)商用軟件,企業(yè)只需按月或按年繳納租費(fèi),就可以獲得需要的應(yīng)用軟件。然而,互聯(lián)網(wǎng)泡沫的破裂使ASP的成功如曇花一現(xiàn),當(dāng)大多數(shù)Start-up公司倒下后,ASP們似乎也偃旗息鼓了。

    究其原因,技術(shù)不成熟是關(guān)鍵因素。Yankee Group的分析家認(rèn)為,“5年前,ASP技術(shù)還不成熟,它不能定制、不具備離線能力、不能與其他系統(tǒng)集成、缺少這樣或那樣的功能,因此ASP們難以逃生也就成為必然。”但現(xiàn)在情況不同了,一方面是技術(shù)的進(jìn)步使客戶通過Internet訪問商用軟件變得更安全和容易;另一方面是全球經(jīng)濟(jì)的不景氣促使企業(yè)再次把目光投向ASP,畢竟,與購(gòu)買許可證和高昂的維護(hù)費(fèi)用相比,按月或按年付費(fèi)的軟件使用方式更能節(jié)省成本,至少在短時(shí)間內(nèi)是如此。通常情況下,諸如OracleSAP等公司的大型軟件系統(tǒng)都需要有相當(dāng)大的初期投資,用于軟件的購(gòu)買、安裝和培訓(xùn),一旦投入使用,還必須支付維護(hù)和軟件升級(jí)費(fèi)用。與此相反,如果向ASP租用軟件,所有這些投資都可以節(jié)省下來,企業(yè)所需要付出的不過是每月數(shù)百美元的租金而已,況且這筆錢完全可以納入企業(yè)的日常開支。

    目前的ASP主要針對(duì)企業(yè)市場(chǎng),采用遠(yuǎn)程租用的方式,所提供的服務(wù)可以是集成硬件、軟件和網(wǎng)絡(luò)技術(shù)來為大中小各類企業(yè)提供應(yīng)用解決方案;也可以是安裝、配置、定做和管理定制的封裝應(yīng)用軟件;有些ASP甚至可以提供商務(wù)處理咨詢和外包服務(wù)。  
    ASP
    不再試圖通過Internet提供為企業(yè)網(wǎng)設(shè)計(jì)的傳統(tǒng)客戶機(jī)/服務(wù)器應(yīng)用,而是創(chuàng)建適合Internet傳送的應(yīng)用。因此它能夠更好地提供可伸縮和定制的應(yīng)用,更容易與其他系統(tǒng)集成。除了最初的標(biāo)準(zhǔn)軟件以一對(duì)多的方式租賃使用之外,新的ASP應(yīng)用模式還增加了個(gè)性化的服務(wù)。個(gè)性化服務(wù)從某種意義上說更接近于傳統(tǒng)的應(yīng)用軟件系統(tǒng)開發(fā),用戶仍然要為軟件開發(fā)支付一筆可觀的開發(fā)費(fèi)用,所不同的是系統(tǒng)賴以傳輸數(shù)據(jù)的載體是開放的Internet。目前國(guó)外有觀點(diǎn)認(rèn)為,ASP最適合的應(yīng)用領(lǐng)域是財(cái)務(wù)、電子商務(wù)和客戶關(guān)系管理;國(guó)內(nèi)專家則認(rèn)為,在人力資源管理上ASP也可以有所發(fā)揮。此外,新的信息傳輸技術(shù)的應(yīng)用也為ASP彌補(bǔ)了Internet帶來的一些不足,比如VPN可以保證數(shù)據(jù)的安全性,有利于吸引一些對(duì)安全性有更高要求的用戶;寬帶技術(shù)則使更快的速度和更豐富的功能成為可能。
    從未來發(fā)展來看,影響ASP發(fā)展的主要有以下幾個(gè)因素
       
    1
    )通訊頻寬的限制
       
    ASP
    商業(yè)模式需要有充足的帶寬資源支持,目前我國(guó)的通訊基礎(chǔ)設(shè)施有了很大的發(fā)展,但是帶寬資源還沒到富余的程度,因此,頻寬資源可能會(huì)成為制約ASP發(fā)展的一個(gè)重要因素。
       
    2
    )網(wǎng)絡(luò)安全性
       
    網(wǎng)絡(luò)的安全性包括了兩層含義:一是技術(shù)上能夠抵御黑客的非法侵入,另一層更重要的含義是ASP商本身的職業(yè)操守達(dá)到一定的層次,顧客的商業(yè)秘密不會(huì)因ASP自身的原因而泄露。
       
    3
    )社會(huì)信用體系
       
    我們看到美國(guó)的ASP業(yè)發(fā)展迅速,應(yīng)該看到他們多年積累的信用體系其實(shí)是ASP發(fā)展的關(guān)鍵動(dòng)力。然而,反觀國(guó)內(nèi)的企業(yè),普遍缺乏信用觀念,這極大地增加了ASP用戶的交易成本和投資風(fēng)險(xiǎn)。
       
    4
    )品牌因素
      
    由于ASP這一商業(yè)模式本身需要很高的技術(shù)要求、安全要求和信用要求,ASP商的品牌因素也特別重要。 

    雖然技術(shù)是ASP成功的原動(dòng)力之一,但是ASP的成功關(guān)鍵不僅在于先進(jìn)技術(shù)和人力資源的掌握,也依賴于對(duì)相關(guān)業(yè)務(wù)流程和信息管理的行業(yè)經(jīng)驗(yàn),因此目前的少數(shù)ASP所提供的功能遠(yuǎn)不能滿足企業(yè)用戶的需要,無法達(dá)到真正的ASP所提供的功能。

    從市場(chǎng)前景來看,ASP已經(jīng)占有了一席之地,它從根本上降低了客戶的TCO。對(duì)客戶來說,向ASP租用軟件的風(fēng)險(xiǎn)很小,按照Enterprise Applications Consulting公司的分析家的話來說“你不必購(gòu)買永久許可而只在某些時(shí)候才使用軟件,你所買的就是你所需要的”。除此之外,租用軟件可以減少企業(yè)內(nèi)部對(duì)IT人員的需求,甚至有可能取消企業(yè)的IT部門,因?yàn)橛?/font>ASP替您維護(hù)和升級(jí)應(yīng)用程序。盡管如此,仍然有相當(dāng)?shù)臐撛诳蛻魰?huì)擔(dān)心租用軟件可能面臨的問題:諸如無法讓第三方來替它處理有價(jià)值的數(shù)據(jù);或者是擔(dān)心托管系統(tǒng)的安全問題以及被托管的系統(tǒng)能否與來自其他廠商的應(yīng)用系統(tǒng)協(xié)同工作。這些技術(shù)上的問題都需要被妥善解決,同時(shí)也會(huì)成ASP技術(shù)繼續(xù)發(fā)展的原動(dòng)力。但無論怎樣,隨著商用軟件復(fù)雜度的增加以及企業(yè)降低成本的需求,ASP模式將成為企業(yè)IT應(yīng)用發(fā)展的大趨勢(shì)。

    以下是軟件公司為某電器有限公司定制的分銷體系解決方案,也許可以從中更深的了解到基于ASP的解決方案的魅力。  

    (1)信息化動(dòng)因分析  
       
    公司成立于1994年,現(xiàn)有員工近千名,目前的產(chǎn)品主要有食品攪拌機(jī)、榨汁機(jī)、全自動(dòng)豆?jié){機(jī)等,2000年其銷售額達(dá)1億元。作為一家制造型的企業(yè),產(chǎn)品技術(shù)和研發(fā)是基礎(chǔ),產(chǎn)品銷售則是最終目標(biāo),所以企業(yè)信息化的核心目標(biāo)是:理順企業(yè)管理流程為銷售服務(wù)。  
       
    目前公司在全國(guó)有近1000個(gè) 銷售網(wǎng)點(diǎn)。以前在銷售環(huán)節(jié)上出的問題比較多,給公司造成了很大的損失。因此,公司制訂出一套規(guī)范的業(yè)務(wù)流程,來監(jiān)督管理下屬的各地辦事處。改進(jìn)流程的結(jié)果 是實(shí)行“兩級(jí)管理一級(jí)核算”的體制,總公司進(jìn)行獨(dú)立核算。在各地的辦事處只負(fù)責(zé)銷售,記錄銷售費(fèi)用,客戶與總公司直接結(jié)算。  
       
    這 種方式堵住了管理上漏洞,只是手工重復(fù)的勞動(dòng)比較多。總公司和辦事處之間的信息交流,以前是通過電話、傳真、電子郵件方式實(shí)現(xiàn)的,各辦事處手工錄入的大量 數(shù)據(jù)傳到總公司后,匯總處理時(shí)仍然需要再次重復(fù)錄入,工作量極其繁重,處理效率非常低。同時(shí),由于人工匯總存在較大的計(jì)算出錯(cuò)可能性,因此上報(bào)給企業(yè)管理 層的銷售匯總數(shù)據(jù)的可靠性和及時(shí)性都比較差。而且在手工管理模式下,每周只能進(jìn)行12次銷售匯總數(shù)據(jù)的統(tǒng)計(jì)和報(bào)告,無法實(shí)現(xiàn)對(duì)辦事處存貨、客戶應(yīng)收帳款等明細(xì)數(shù)據(jù)的實(shí)時(shí)額度控制。  
     
    (2)
    分銷管理系統(tǒng)解決方案  
       
    針對(duì)目前存在的問題,軟件公司提出分銷系統(tǒng)的ASP模 式,即所有數(shù)據(jù)都集中在總公司的數(shù)據(jù)庫中,而辦事處只需要登錄進(jìn)系統(tǒng),在客戶端將所發(fā)生的數(shù)據(jù)按照系統(tǒng)模塊的要求輸入進(jìn)去,系統(tǒng)將自動(dòng)生成各種數(shù)據(jù),并允 許相應(yīng)級(jí)別的人實(shí)時(shí)查詢其相應(yīng)權(quán)限下的所有相關(guān)數(shù)據(jù)。這種模式正好滿足其對(duì)眾多分子公司和辦事處的管理要求。同時(shí)在實(shí)施整個(gè)系統(tǒng)時(shí),先將數(shù)據(jù)存放在軟件公 司的服務(wù)器上。在實(shí)施完成后,可以選擇兩種方式:一是自己建服務(wù)器和數(shù)據(jù)中心并承擔(dān)系統(tǒng)維護(hù)工作;二是租用軟件公司提供的網(wǎng)站和數(shù)據(jù)庫維護(hù)增值服務(wù),完全 不再投入硬件和人員。  
      
    實(shí) 施系統(tǒng)管理之后,該公司的整體業(yè)務(wù)流程系統(tǒng)由業(yè)務(wù)管理子系統(tǒng)和財(cái)務(wù)管理子系統(tǒng)兩部分構(gòu)成。業(yè)務(wù)管理子系統(tǒng)主要功能包括:客戶端電子商務(wù)功能、銷售過程管 理、庫存管理、應(yīng)收帳款管理、各類計(jì)劃管理、商品檔案管理、客戶檔案管理、統(tǒng)計(jì)查詢、系統(tǒng)管理等;財(cái)務(wù)管理子系統(tǒng)主要功能為日常費(fèi)用管理。該分銷管理系統(tǒng) 在 “用友偉庫企業(yè)分銷管理軟件”的基礎(chǔ)上進(jìn)行了適量的二次開發(fā)。  
     
    (3)
    分銷管理系統(tǒng)效果評(píng)析  
      
    實(shí) 施了這套系統(tǒng)以后,以往許多無法解決的問題就迎刃而解。各地辦事處只要正確輸入貨物出入庫數(shù)據(jù),系統(tǒng)平臺(tái)的總數(shù)據(jù)累計(jì)自動(dòng)生成,與以往用手工合計(jì)的速度相 比有了很大的提升。各辦事處可以進(jìn)入公司網(wǎng)站,在分銷系統(tǒng)平臺(tái)中本辦事處的界面進(jìn)行操作,減少了運(yùn)營(yíng)費(fèi)用。各地分公司和辦事處均可通過系統(tǒng)提供的業(yè)務(wù)處理 平臺(tái)將每日訂單、銷售、存貨等數(shù)據(jù)輸入系統(tǒng),自動(dòng)處理/生成各類銷售統(tǒng)計(jì)報(bào)表;管理層可根據(jù)不同的權(quán)限隨時(shí)了解銷售、產(chǎn)品庫存及資金情況,瀏覽系統(tǒng)提供的部分?jǐn)?shù)據(jù)分析報(bào)告,為管理決策層提供更準(zhǔn)確和及時(shí)的量化依據(jù)。  
       
    由于采用ASP運(yùn)行模式,實(shí)現(xiàn)了異地商務(wù)集中管理。海菱公司不需要單獨(dú)構(gòu)建昂貴的數(shù)據(jù)處理中心;分支機(jī)構(gòu)無需安裝專用的客戶端軟件,采用標(biāo)準(zhǔn)瀏覽器上網(wǎng)即可使用該系統(tǒng)的全部功能,數(shù)據(jù)處理全部在數(shù)據(jù)中心完成和存儲(chǔ),數(shù)據(jù)安全性高,操作簡(jiǎn)單,系統(tǒng)維護(hù)成本低。

    posted @ 2005-11-23 20:22 Dion 閱讀(603) | 評(píng)論 (0)編輯 收藏

    轉(zhuǎn)自http://dev2dev.bea.com.cn/techdoc/2005110103.html


    Ajax簡(jiǎn)介

    時(shí)間:2005-11-01
    作者:David Teare
    瀏覽次數(shù): 1786
    本文關(guān)鍵字:ajaxdhtmldwr javascript
    文章工具
    推薦給朋友 推薦給朋友
    打印文章 打印文章

      作為J2EE開發(fā)人員,我們似乎經(jīng)常關(guān)注“后端機(jī)制(backend mechanics)”。我們通常會(huì)忘記,J2EE的主要成功之處在Web應(yīng)用程序方面;許多原因使得人們喜歡利用Web開發(fā)應(yīng)用程序,但主要還是因?yàn)槠? 易于部署的特點(diǎn)允許站點(diǎn)以盡可能低的成本擁有上百萬的用戶。遺憾的是,在過去幾年中,我們?cè)诤蠖送度肓颂嗟臅r(shí)間,而在使我們的Web用戶界面對(duì)用戶自然 和響應(yīng)靈敏方面卻投入不足。

      本文介紹一種方法,Ajax,使用它可以構(gòu)建更為動(dòng)態(tài)和響應(yīng)更靈敏的Web應(yīng)用程序。該方法的關(guān)鍵在于對(duì)瀏覽器端的JavaScript、 DHTML和與服務(wù)器異步通信的組合。本文也演示了啟用這種方法是多么簡(jiǎn)單:利用一個(gè)Ajax框架(指DWR)構(gòu)造一個(gè)應(yīng)用程序,它直接從瀏覽器與后端服 務(wù)進(jìn)行通信。如果使用得當(dāng),這種強(qiáng)大的力量可以使應(yīng)用程序更加自然和響應(yīng)靈敏,從而提升用戶的瀏覽體驗(yàn)。

      該應(yīng)用程序中所使用的示例代碼已打包為單獨(dú)的WAR文件,可供下載。

    簡(jiǎn)介

      術(shù)語Ajax用來描述一組技術(shù),它使瀏覽器可以為用戶提供更為自然的瀏覽體驗(yàn)。在Ajax之前,Web站點(diǎn)強(qiáng)制用戶進(jìn)入提交/等待/重新顯示范 例,用戶的動(dòng)作總是與服務(wù)器的“思考時(shí)間”同步。Ajax提供與服務(wù)器異步通信的能力,從而使用戶從請(qǐng)求/響應(yīng)的循環(huán)中解脫出來。借助于Ajax,可以在 用戶單擊按鈕時(shí),使用JavaScript和DHTML立即更新UI,并向服務(wù)器發(fā)出異步請(qǐng)求,以執(zhí)行更新或查詢數(shù)據(jù)庫。當(dāng)請(qǐng)求返回時(shí),就可以使用 JavaScript和CSS來相應(yīng)地更新UI,而不是刷新整個(gè)頁面。最重要的是,用戶甚至不知道瀏覽器正在與服務(wù)器通信:Web站點(diǎn)看起來是即時(shí)響應(yīng) 的。

      雖然Ajax所需的基礎(chǔ)架構(gòu)已經(jīng)出現(xiàn)了一段時(shí)間,但直到最近異步請(qǐng)求的真正威力才得到利用。能夠擁有一個(gè)響應(yīng)極其靈敏的Web站點(diǎn)確實(shí)激動(dòng)人 心,因?yàn)樗罱K允許開發(fā)人員和設(shè)計(jì)人員使用標(biāo)準(zhǔn)的HTML/CSS/JavaScript堆棧創(chuàng)建“桌面風(fēng)格的(desktop-like)”可用性。

      通常,在J2EE中,開發(fā)人員過于關(guān)注服務(wù)和持久性層的開發(fā),以至于用戶界面的可用性已經(jīng)落后。在一個(gè)典型的J2EE開發(fā)周期中,常常會(huì)聽到這樣的話,“我們沒有可投入U(xiǎn)I的時(shí)間”或“不能用HTML實(shí)現(xiàn)”。但是,以下Web站點(diǎn)證明,這些理由再也站不住腳了:

      所有這些Web站點(diǎn)都告訴我們,Web應(yīng)用程序不必完全依賴于從服務(wù)器重新載入頁面來向用戶呈現(xiàn)更改。一切似乎就在瞬間發(fā)生。簡(jiǎn)而言之,在涉及到用戶界面的響應(yīng)靈敏度時(shí),基準(zhǔn)設(shè)得更高了。

    定義Ajax

      Adaptive Path公司的Jesse James Garrett這樣定義Ajax

      Ajax不是一種技術(shù)。實(shí)際上,它由幾種蓬勃發(fā)展的技術(shù)以新的強(qiáng)大方式組合而成。Ajax包含:

    • 基于XHTMLCSS標(biāo)準(zhǔn)的表示;
    • 使用Document Object Model進(jìn)行動(dòng)態(tài)顯示和交互;
    • 使用XMLHttpRequest與服務(wù)器進(jìn)行異步通信;
    • 使用JavaScript綁定一切。

      這非常好,但為什么要以Ajax命名呢?其實(shí)術(shù)語Ajax是由Jesse James Garrett創(chuàng)造的,他說它是“Asynchronous JavaScript + XML的簡(jiǎn)寫”。

    Ajax的工作原理

      Ajax的核心是JavaScript對(duì)象XmlHttpRequest。該對(duì)象在Internet Explorer 5中首次引入,它是一種支持異步請(qǐng)求的技術(shù)。簡(jiǎn)而言之,XmlHttpRequest使您可以使用JavaScript向服務(wù)器提出請(qǐng)求并處理響應(yīng),而不 阻塞用戶。

      在創(chuàng)建Web站點(diǎn)時(shí),在客戶端執(zhí)行屏幕更新為用戶提供了很大的靈活性。下面是使用Ajax可以完成的功能:

    • 動(dòng)態(tài)更新購(gòu)物車的物品總數(shù),無需用戶單擊Update并等待服務(wù)器重新發(fā)送整個(gè)頁面。
    • 提升站點(diǎn)的性 能,這是通過減少?gòu)姆?wù)器下載的數(shù)據(jù)量而實(shí)現(xiàn)的。例如,在Amazon的購(gòu)物車頁面,當(dāng)更新籃子中的一項(xiàng)物品的數(shù)量時(shí),會(huì)重新載入整個(gè)頁面,這必須下載 32K的數(shù)據(jù)。如果使用Ajax計(jì)算新的總量,服務(wù)器只會(huì)返回新的總量值,因此所需的帶寬僅為原來的百分之一。
    • 消除了每次用戶輸入時(shí)的頁面刷新。例如,在Ajax中,如果用戶在分頁列表上單擊Next,則服務(wù)器數(shù)據(jù)只刷新列表而不是整個(gè)頁面。
    • 直接編輯表格數(shù)據(jù),而不是要求用戶導(dǎo)航到新的頁面來編輯數(shù)據(jù)。對(duì)于Ajax,當(dāng)用戶單擊Edit時(shí),可以將靜態(tài)表格刷新為內(nèi)容可編輯的表格。用戶單擊Done之后,就可以發(fā)出一個(gè)Ajax請(qǐng)求來更新服務(wù)器,并刷新表格,使其包含靜態(tài)、只讀的數(shù)據(jù)。

      一切皆有可能!但愿它能夠激發(fā)您開始開發(fā)自己的基于Ajax的站點(diǎn)。然而,在開始之前,讓我們介紹一個(gè)現(xiàn)有的Web站點(diǎn),它遵循傳統(tǒng)的提交/等待/重新顯示的范例,我們還將討論Ajax如何提升用戶體驗(yàn)。

    Ajax可用于那些場(chǎng)景?——一個(gè)例子:MSN Money頁面

      前幾天,在瀏覽MSN Money頁面的時(shí)候,有一篇關(guān)于房地產(chǎn)投資的文章引起了我的好奇心。我決定使用站點(diǎn)的“Rate this article”(評(píng)價(jià)本文)功能,鼓勵(lì)其他的用戶花一點(diǎn)時(shí)間來閱讀這篇文章。在我單擊vote按鈕并等待了一會(huì)兒之后,整個(gè)頁面被刷新,在原來投票問題所在的地方出現(xiàn)了一個(gè)漂亮的感謝畫面。

      而Ajax能夠使用戶的體驗(yàn)更加愉快,它可以提供響應(yīng)更加靈敏的UI,并消除頁面刷新所帶來的閃爍。目前,由于要刷新整個(gè)頁面,需要傳送大量的 數(shù)據(jù),因?yàn)楸仨氈匦掳l(fā)送整個(gè)頁面。如果使用Ajax,服務(wù)器可以返回一個(gè)包含了感謝信息的500字節(jié)的消息,而不是發(fā)送26,813字節(jié)的消息來刷新整個(gè) 頁面。即使使用的是高速Internet,傳送26K和1/2K的差別也非常大。同樣重要的是,只需要刷新與投票相關(guān)的一小節(jié),而不是刷新整個(gè)屏幕。

      讓我們利用Ajax實(shí)現(xiàn)自己的基本投票系統(tǒng)。

    原始的Ajax:直接使用XmlHttpRequest

      如上所述,Ajax的核心是JavaScript對(duì)象XmlHttpRequest。下面的示例文章評(píng)價(jià)系統(tǒng)將帶您熟悉Ajax的底層基本知識(shí):http://tearesolutions.com/ajax-demo/raw-ajax.html。注:如果您已經(jīng)在本地WebLogic容器中安裝了ajax-demo.war,可以導(dǎo)航到http://localhost:7001/ajax-demo/raw-ajax.html

      瀏覽應(yīng)用程序,參與投票,并親眼看它如何運(yùn)轉(zhuǎn)。熟悉了該應(yīng)用程序之后,繼續(xù)閱讀,進(jìn)一步了解其工作原理細(xì)節(jié)。

      首先,您擁有一些簡(jiǎn)單的定位點(diǎn)標(biāo)記,它連接到一個(gè)JavaScriptcastVote(rank)函數(shù)。
    function castVote(rank) {
    var url = "/ajax-demo/static-article-ranking.html";
    var callback = processAjaxResponse;
    executeXhr(callback, url);
    }

      該函數(shù)為您想要與之通信的服務(wù)器資源創(chuàng)建一個(gè)URL并調(diào)用內(nèi)部函數(shù)executeXhr,提供一個(gè)回調(diào)JavaScript函數(shù),一旦服務(wù)器響 應(yīng)可用,該函數(shù)就被執(zhí)行。由于我希望它運(yùn)行在一個(gè)簡(jiǎn)單的Apache環(huán)境中,“cast vote URL”只是一個(gè)簡(jiǎn)單的HTML頁面。在實(shí)際情況中,被調(diào)用的URL將記錄票數(shù)并動(dòng)態(tài)地呈現(xiàn)包含投票總數(shù)的響應(yīng)。

      下一步是發(fā)出一個(gè)XmlHttpRequest請(qǐng)求:
    function executeXhr(callback, url) {
    // branch for native XMLHttpRequest object
    if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
    req.onreadystatechange = callback;
    req.open("GET", url, true);
    req.send(null);
    } // branch for IE/Windows ActiveX version
    else if (window.ActiveXObject) {
    req = new ActiveXObject("Microsoft.XMLHTTP");
    if (req) {
    req.onreadystatechange = callback;
    req.open("GET", url, true);
    req.send();
    }
    }
    }

      如您所見,執(zhí)行一個(gè)XmlHttpRequest并不簡(jiǎn)單,但非常直觀。和平常一樣,在JavaScript領(lǐng)域,大部分的工作量都花在確保瀏 覽器兼容方面。在這種情況下,首先要確定XmlHttpRequest是否可用。如果不能用,很可能要使用Internet Explorer,這樣就要使用所提供的ActiveX實(shí)現(xiàn)。

    executeXhr()方法中最關(guān)鍵的部分是這兩行:

    req.onreadystatechange = callback;
    req.open("GET", url, true);

      第一行定義了JavaScript回調(diào)函數(shù),您希望一旦響應(yīng)就緒它就自動(dòng)執(zhí)行,而req.open()方法中所指定的“true”標(biāo)志說明您想要異步執(zhí)行該請(qǐng)求。

      一旦服務(wù)器處理完XmlHttpRequest并返回給瀏覽器,使用req.onreadystatechange指派所設(shè)置的回調(diào)方法將被自動(dòng)調(diào)用。
    function processAjaxResponse() {
    // only if req shows "loaded"
    if (req.readyState == 4) {
    // only if "OK"
    if (req.status == 200) {
    502 502'votes').innerHTML = req.responseText;
    } else {
    alert("There was a problem retrieving the XML data:
    " +
    req.statusText);
    }
    }
    }

      該代碼相當(dāng)簡(jiǎn)潔,并且使用了幾個(gè)幻數(shù),這使得難以一下子看出發(fā)生了什么。為了弄清楚這一點(diǎn),下面的表格(引用自http://developer.apple.com/internet/webcontent/xmlhttpreq.html)列舉了常用的XmlHttpRequest對(duì)象屬性。

    屬性

    描述

    onreadystatechange

    每次狀態(tài)改變所觸發(fā)事件的事件處理程序

    readyState

    對(duì)象狀態(tài)值:

    • 0 = 未初始化(uninitialized)
    • 1 = 正在加載(loading)
    • 2 = 加載完畢(loaded)
    • 3 = 交互(interactive)
    • 4 = 完成(complete)

    responseText

    從服務(wù)器進(jìn)程返回的數(shù)據(jù)的字符串形式

    responseXML

    從服務(wù)器進(jìn)程返回的DOM兼容的文檔數(shù)據(jù)對(duì)象

    status

    從服務(wù)器返回的數(shù)字代碼,比如404(未找到)或200(就緒)

    statusText

    伴隨狀態(tài)碼的字符串信息

      現(xiàn)在processVoteResponse()函數(shù)開始顯示出其意義了。它首先檢查XmlHttpRequest的整體狀態(tài)以保證它已經(jīng)完成 (readyStatus == 4),然后根據(jù)服務(wù)器的設(shè)定詢問請(qǐng)求狀態(tài)。如果一切正常(status == 200),就使用innerHTML屬性重寫DOM的“votes”節(jié)點(diǎn)的內(nèi)容。

      既然您親眼看到了XmlHttpRequest對(duì)象是如何工作的,就讓我們利用一個(gè)旨在簡(jiǎn)化JavaScript與Java應(yīng)用程序之間的異步通信的框架來對(duì)具體的細(xì)節(jié)進(jìn)行抽象。

    Ajax: DWR方式

      按照與文章評(píng)價(jià)系統(tǒng)相同的流程,我們將使用Direct Web Remoting(DWR)框架實(shí)現(xiàn)同樣的功能。

      假定文章和投票結(jié)果存儲(chǔ)在一個(gè)數(shù)據(jù)庫中,使用某種對(duì)象/關(guān)系映射技術(shù)來完成抽取工作。為了部署起來盡可能地簡(jiǎn)單,我們不會(huì)使用數(shù)據(jù)庫進(jìn)行持久性 存儲(chǔ)。此外,為使應(yīng)用程序盡可能通用,也不使用Web框架。相反,應(yīng)用程序?qū)囊粋€(gè)靜態(tài)HTML文件開始,可以認(rèn)為它由服務(wù)器動(dòng)態(tài)地呈現(xiàn)。除了這些簡(jiǎn)化措 施,應(yīng)用程序還應(yīng)該使用Spring Framework關(guān)聯(lián)一切,以便輕松看出如何在一個(gè)“真實(shí)的”應(yīng)用程序中使用DWR。

      現(xiàn)在應(yīng)該下載示例應(yīng)用程序并熟悉它。該應(yīng)用程序被壓縮為標(biāo)準(zhǔn)的WAR文件,因此您可以把它放置到任何一個(gè)Web容器中——無需進(jìn)行配置。部署完畢之后,就可以導(dǎo)航到http://localhost:7001/ajax_demo/dwr-ajax.html來運(yùn)行程序。

      可以查看HTML 源代碼,了解它如何工作。給人印象最深的是,代碼如此簡(jiǎn)單——所有與服務(wù)器的交互都隱藏在JavaScript對(duì)象ajaxSampleSvc的后面。更加令人驚訝的是,ajaxSampleSvc服務(wù)不是由手工編寫而是完全自動(dòng)生成的!讓我們繼續(xù),看看這是如何做到的。

    引入DWR

      如同在“原始的Ajax”一節(jié)所演示的那樣,直接使用XmlHttpRequest創(chuàng)建異步請(qǐng)求非常麻煩。不僅JavaScript代碼冗長(zhǎng),而且必須考慮服務(wù)器端為定位Ajax請(qǐng)求到適當(dāng)?shù)姆?wù)所需做的工作,并將結(jié)果封送到瀏覽器。

      設(shè)計(jì)DWR的目的是要處理將Web頁面安裝到后端服務(wù)上所需的所有信息管道。它是一個(gè)Java框架,可以很輕松地將它插入到Web應(yīng)用程序中, 以便JavaScript代碼可以調(diào)用服務(wù)器上的服務(wù)。它甚至直接與Spring Framework集成,從而允許用戶直接向Web客戶機(jī)公開bean。

      DWR真正的巧妙之處是,在用戶配置了要向客戶機(jī)公開的服務(wù)之后,它使用反射來生成JavaScript對(duì)象,以便Web頁面能夠使用這些對(duì)象 來訪問該服務(wù)。然后Web頁面只需接合到生成的JavaScript對(duì)象,就像它們是直接使用服務(wù)一樣;DWR無縫地處理所有有關(guān)Ajax和請(qǐng)求定位的瑣 碎細(xì)節(jié)。

      讓我們仔細(xì)分析一下示例代碼,弄清它是如何工作的。

    應(yīng)用程序細(xì)節(jié):DWR分析

      關(guān)于應(yīng)用程序,首先要注意的是,它是一個(gè)標(biāo)準(zhǔn)的Java應(yīng)用程序,使用分層架構(gòu)(Layered Architecture)設(shè)計(jì)模式。使用DWR通過JavaScript公開一些服務(wù)并不影響您的設(shè)計(jì)。

      下面是一個(gè)簡(jiǎn)單的Java服務(wù),我們將使用DWR框架直接將其向JavaScript代碼公開:

    package com.tearesolutions.service;

    public interface AjaxSampleSvc {
    Article castVote(int rank);
    }

      這是一個(gè)被簡(jiǎn)化到幾乎不可能的程度的例子,其中只有一篇文章可以投票。該服務(wù)由Spring管理,它使用的bean名是ajaxSampleSvc,它的持久性需求則依賴于ArticleDao。詳情請(qǐng)參見applicationContext.xml。

      為了把該服務(wù)公開為JavaScript對(duì)象,需要配置DWR,添加dwr.xml文件到WEB-INF目錄下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 0.4//EN"
    "http://www.getahead.ltd.uk/dwr/dwr.dtd">

    <dwr>
    <allow>
    <create creator="spring" javascript="ajaxSampleSvc">
    <param name="beanName" value="ajaxSampleSvc" />
    </create>
    <convert converter="bean" match="com.tearesolutions.model.Article"/>
    <exclude method="toString"/>
    <exclude method="setArticleDao"/>
    </allow>
    </dwr>

      dwr.xml文件告訴DWR哪些服務(wù)是要直接向JavaScript代碼公開的。注意,已經(jīng)要求公開Spring bean ajaxSampleSvc。DWR將自動(dòng)找到由應(yīng)用程序設(shè)置的SpringApplicationContext。為此,必須使用標(biāo)準(zhǔn)的servlet 過濾器ContextLoaderListener來初始化Spring ApplicationContext。

      DWR被設(shè)置為一個(gè)servlet,所以把它的定義添加到web.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD
    Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

    <web-app>
    <display-name>Ajax Examples</display-name>

    <listener>
    <listener-class>
    org.springframework.web.context.ContextLoaderListener
    </listener-class>
    </listener>

    <servlet>
    <servlet-name>ajax_sample</servlet-name>
    <servlet-class>com.tearesolutions.web.AjaxSampleServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
    <servlet-name>dwr-invoker</servlet-name>
    <display-name>DWR Servlet</display-name>
    <description>Direct Web Remoter Servlet</description>
    <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
    <init-param>
    <param-name>debug</param-name>
    <param-value>true</param-value>
    </init-param>
    </servlet>

    <servlet-mapping>
    <servlet-name>ajax_sample</servlet-name>
    <url-pattern>/ajax_sample</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
    <servlet-name>dwr-invoker</servlet-name>
    <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>
    </web-app>

      做完這些之后,可以加載http://localhost:7001/ajax-demo/dwr,看看哪些服務(wù)可用。結(jié)果如下:

    圖3. 可用的服務(wù)

      單擊ajaxSampleSvc鏈接,查看有關(guān)如何在HTML頁面內(nèi)直接使用服務(wù)的示例實(shí)現(xiàn)。其中包含的兩個(gè)JavaScript文件完成了大部分的功能:
    <script type='text/javascript' 
    src='/ajax-demo/dwr/interface/ajaxSampleSvc.js'></script>
    <script type='text/javascript'
    src='/ajax-demo/dwr/engine.js'></script>

    ajaxSampleSvc.js是動(dòng)態(tài)生成的:

    function ajaxSampleSvc() { }

    ajaxSampleSvc.castVote = function(callback, p0)
    {
    DWREngine._execute(callback, '/ajax-demo/dwr',
    'ajaxSampleSvc', 'castVote', p0);
    }

      現(xiàn)在可以使用JavaScript對(duì)象ajaxSampleSvc替換所有的XmlHttpRequest代碼,從而重構(gòu)raw-ajax.html文件。可以在dwr-ajax.html文件中看到改動(dòng)的結(jié)果;下面是新的JavaScript函數(shù):

    function castVote(rank) {
    ajaxSampleSvc.castVote(processResponse, rank);
    }
    function processResponse(data) {
    var voteText = "

    Thanks for Voting!

    "
    + "

    Current ranking: " + data.voteAverage
    + " out of 5

    "
    + "

    Number of votes placed: "
    + data.numberOfVotes + "

    ";
    502 502'votes').innerHTML = voteText;
    }

      驚人地簡(jiǎn)單,不是嗎?由ajaxSampleSvc對(duì)象返回的Article域?qū)ο笮蛄谢癁橐粋€(gè)JavaScript對(duì)象,允許在它上面調(diào)用諸 如numberOfVotes()和voteAverage()之類的方法。在動(dòng)態(tài)生成并插入到DIV元素“votes”中的HTML代碼內(nèi)使用這些數(shù) 據(jù)。

    下一步工作

       在后續(xù)文章中,我將繼續(xù)有關(guān)Ajax的話題,涉及下面這些方面:

    • Ajax最佳實(shí)踐

      像許多技術(shù)一樣,Ajax是一把雙刃劍。對(duì)于一些用例,其應(yīng)用程序其實(shí)沒有必要使用Ajax,使用了反而有損可用性。我將介紹一些不適合使用的模式,突出說明Ajax的一些消極方面,并展示一些有助于緩和這些消極方面的機(jī)制。例如,對(duì)Netflix電影瀏覽器來說,Ajax是合適的解決方案嗎?或者,如何提示用戶確實(shí)出了一些問題,而再次單擊按鈕也無濟(jì)于事?

    • 管理跨請(qǐng)求的狀態(tài)

      在使用Ajax時(shí),最初的文檔DOM會(huì)發(fā)生一些變化,并且有大量的頁面狀態(tài)信息存儲(chǔ)在客戶端變量中。當(dāng)用戶跟蹤一個(gè)鏈接到應(yīng)用程序中的另一個(gè)頁面時(shí),狀態(tài)就丟失了。當(dāng)用戶按照慣例單擊Back按鈕時(shí),呈現(xiàn)給他們的是緩存中的初始頁面。這會(huì)使用戶感到非常迷惑!

    • 調(diào)試技巧

      使用JavaScript在客戶端執(zhí)行更多的工作時(shí),如果事情不按預(yù)期方式進(jìn)行,就需要一些調(diào)試工具來幫助弄清出現(xiàn)了什么問題。

    結(jié)束語

      本文介紹了Ajax方法,并展示了如何使用它來創(chuàng)建一個(gè)動(dòng)態(tài)且響應(yīng)靈敏的Web應(yīng)用程序。通過使用DWR框架,可以輕松地把Ajax融合到站點(diǎn)中,而無需擔(dān)心所有必須執(zhí)行的實(shí)際管道工作。

      特別感謝Getahead IT咨詢公司的Joe Walker和他的團(tuán)隊(duì)開發(fā)出DWR這樣神奇的工具。感謝你們與世界共享它!

    下載

      本文中演示的應(yīng)用程序源代碼可供下載:ajax-demo.war(1.52 MB)。

    參考資料

    原文出處

    An Introduction To Ajax

    http://dev2dev.bea.com/pub/a/2005/08/ajax_introduction.html


    posted @ 2005-11-23 12:53 Dion 閱讀(580) | 評(píng)論 (0)編輯 收藏

         摘要: 在Java2平臺(tái)企業(yè)版中應(yīng)用異步JavaScript技術(shù)和XML(AJAX) ...  閱讀全文
    posted @ 2005-11-23 11:43 Dion 閱讀(1908) | 評(píng)論 (4)編輯 收藏

    轉(zhuǎn)載自TheServerSide網(wǎng)站,介紹使用Spring來創(chuàng)建Observer模式。
    http://www.theserverside.com/articles/article.tss?l=SpringLoadedObserverPattern
     

    This article describes an easy process of implementing the observer pattern in the Spring framework (Spring Core). Also discussed in this article are a few of the Spring Core classes as well as an easy way to start the Spring Framework in any project. Finally, this article shows developers and designers that the Spring framework is a great reason to continue design pattern advocacy in your projects.

    Recently, it seems when developers use the Spring framework to improve their projects they focus only on simple object oriented design techniques. Unfortunately some of the more brilliantly researched patterns are forgotten in place of a brilliant framework (Spring). Although the Factory Pattern and the Singleton Pattern are built into Spring, other patterns such as the Decorator Pattern, the Adapter Pattern, and the Observer Pattern are often forgotten because of the new ideas Spring has to offer. Fortunately, design patterns and the Spring framework can exist in the same application. In this article I show how the commonly used Observer Pattern fits nicely in the Spring Framework.

    Observer Pattern

    The Observer Pattern is also known as a publisher and subscriber design pattern. The pattern is useful when you have one publisher and many subscribers (one-to-many) that are interested in the publisher's state or messages. Additionally, interested subscribers have the ability to register and unregister as they please. Lastly, subscribers are notified of the publisher's messages automatically (that is, by no effort of their own). Figure 1 is an example of a typical observer pattern.

    Figure 1. Observer Pattern


    I chose to use a more widely accepted diagram to describe the Observer Pattern so you will notice that the aforementioned publisher is actually the Subject in this diagram. The subscriber is the Observer in the diagram. The intimate details of the Observer Pattern are far outside of the scope of this article, but a note worthy topic is how the Spring framework can be used to leverage good object oriented design techniques while creating the concrete classes of this pattern.

    A normal concreteObserver class is required to have code similar to this constructor (or a similar “setter” method to achieve the registering of the Observer with the Subject):

    public concreteObserver(Subject s) {
    	s.addListener(this);
    }
    

    Below you will see how the Spring framework wires the two concrete classes together with XML and not with code inside the classes. Ultimately, this allows the developer to avoid any unnecessary coupling of the concrete classes.

    Spring Considerations

    Since this article covers only the most simple implementation of the observer pattern, I utilize only the required Spring framework jars. At a minimum you need to have the spring-core.jar, the spring-context.jar, and the spring-beans.jar from the Spring framework distribution. Also to avoid any run time errors you need the commons-logging.jar from the Apache Commons project in your class path.

    Each of these jars provide a specific role that make using the Spring framework possible. First is the spring-core.jar; this jar is required for all Spring applications. It includes Spring's dependency injection classes as well as other classes that are used to create Spring beans. The spring-context.jar contains the ApplicationContext interface. This interface is used to start the Spring framework in my included example project.

    The last Spring jar is the spring-beans.jar. It contains the DesposibleBean interface which the FileSystemXmlApplicationContext bean sub-interfaces. I do not directly use the DesposibleBean interface but I use the FileSystemXmlApplicationContext bean to located the XML file used to configure the Spring framework. The code that implements these classes is shown in Listing 6.

    Wiring The Observer Pattern with Spring

    To illustrate the Observer Pattern concretely, I chose to create a Town Crier class that sends messages to any registered Town Resident class. To keep this example simple, I developed the same interfaces shown in Figure 1, but the concrete classes are TownCrier and TownResident. All four of these classes are shown in Listings 1 through 4.

    After I created the TownCrier (Listing 3) and two TownResident (Listing 4) classes I created an incomplete version the ObserverContext.xml file (Listing 5). This file contains the Spring definitions of the concrete implementation beans. Since this example is simple, I chose not to use any of the more complex attributes of the bean tag.

    Typical Bean tags for the shown classes:

    	<bean id="townCrier" class="springobserver.TownCrier"/>
    	<bean id="townResident1" class="springobserver.TownResident"/>
    	<bean id="townResident1" class="springobserver.TownResident2"/>
    

    At this point, I was able to run my ExampleRun class (Listing 6), but nothing eventful actually happened. This is because the TownResident classes were not “wired” into the TownCrier class.

    To perform the wiring of the Observer Pattern I chose to use Spring's MethodInvokingFactoryBean class. This process is a very simple way of calling a method on a class and ultimately passing a parameter into method. In this example, the parameter is the bean definition of a townResident. A snapshot of this bean definition is:

    <bean id="registerTownResident1" 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject"><ref local="townCrier"/></property>
        <property name="targetMethod"><value>addListener</value></property>
        <property name="arguments">
        <list>
          <ref bean="townResident1"/>
        </list>
        </property>
    </bean>
    

    As you can see, the targetObject is the townCrier bean, the targetMethod is the addListener method and the argument is the townResident1 bean. This configuration is the only code needed to compose the concrete implementations of the TownCrier with TownResident class.

    Now that I have the beans wired together using the MethodInvokingFactoryBean class, I can run my ExampleRun class and see that my TownResident classes are receiving messages from the TownCrier class. Results shown in Example 1.

    Conclusion

    A few lessons learned in this article include a simple way to start the Spring framework, how to use the MethodInvokingFactoryBean, and an efficient implementation the Observer Pattern in the Spring framework. Since this is a minimal approach to the Spring framework, I was able to show the relationship between the ApplicationContext and it's implementation FileSystemXmlApplicationContext class. This process for starting Spring applications is a very easy way to leverage an incredible framework.

    Part of this framework is the MethodInvokingFactoryBean. When using it you are free to employ any parameter available to you such as an Integer, a String, or in our case, another Spring bean. By allowing you to expose methods in your context xml files you can be as flexible as you can dream. This article has covered the addListener() method of the Observer Pattern. I would like to extend a challenge to you to figure out how to implement the removeListener() method using strictly the Spring framework.

    Lastly, the Observer Pattern is a common and very useful pattern. The practices shown in this article provide an example of how the concrete implementation of the Observer interface can be developed with no additional coupling to the concrete implementation of the Subject interface. This feature of Spring encourages good object oriented design techniques. As a final note, there is really no reason developers and designers can not find ways to marry proven design patterns with beautifully developed frameworks.

    Listing 1. The Observer Interface
    package springobserver;
    public interface Observer {
      public void update(String messageText);
    }
    
    Listing 2. The Subject Interface
    package springobserver;
    public interface Subject {
      public void addListener(Observer o);
      public void removeListener(Observer o);
      public void notifyListeners();
    }
    
    Listing 3. The Town Crier
    package springobserver;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class TownCrier implements Subject {
    
    	private List townResident = new ArrayList();
    	private String messageText;
    
    	// this message is added so I can give 
    	// this class a reason to call notifyListener.
    	public void setMessage(String message){
    		System.out.println("I'm the Town Crier and " +
    				"I've got a message: " + message);
    		this.messageText = message;
    		this.notifyListeners();
    	}
    	
    	public void addListener(Observer o) {
    		this.townResident.add(o);
    	}
    
    	public void removeListener(Observer o) {
    		if (this.townResident.contains(o)){
    			this.townResident.remove(o);
    		}
    	}
    
    	
    	// call the update method on 
    	// each observer (town resident)
    	public void notifyListeners() {
    		for (Iterator iter = townResident.iterator(); iter.hasNext();) {
    			Observer listener = (Observer) iter.next();
    			listener.update(messageText);
    		}
    	}
    
    }
    
    Listing 4. The Town Residents
    package springobserver;
    
    public class TownResident implements Observer {
    	public void update(String messageText) {
    		System.out.println("Greetings my name is: " + this);
    		System.out.println("I heard: " + messageText);
    	}
    
    -------- new class --------
    package springobserver;
    
    public class TownResident2 implements Observer {
    	public void update(String messageText) {
    		System.out.println("Greetings my name is: " + this);
    		System.out.println("I heard: " + messageText);
    	}
    
    }
    Listing 5. The Application Context XML (ObserverContext.xml)
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
    "http://www.springframework.org/dtd/spring-beans.dtd">
    
    <beans>
    	<!-- This bean is the town crier.  
    	He's responsible for notifying all town residents that are interested in his message -->
    	<bean id="townCrier" class="springobserver.TownCrier"/>
    	
    	<!-- this bean is a town resident interested in the town criers messages -->
    	<bean id="townResident1" class="springobserver.TownResident"/>          
           
    	<!-- this bean is another town resident interested in the town criers messages -->
    	<bean id="townResident2" class="springobserver.TownResident2"/>
        
        
         <!-- this is a method invoking bean that registers the first town resident with
              with the town crier -->   
        <bean id="registerTownResident1" 
          class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
          <property name="targetObject"><ref local="townCrier"/></property>
          <property name="targetMethod"><value>addListener</value></property>
          <property name="arguments">
          <list>
            <ref bean="townResident1"/>
          </list>
          </property>
        </bean>
        
        
         <!-- this is a method invoking bean that registers the second town 
              resident with the town crier -->   
        <bean id="registerTownResident2" 
          class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
          <property name="targetObject"><ref local="townCrier"/></property>
          <property name="targetMethod"><value>addListener</value></property>
          <property name="arguments">
          <list>
            <ref bean="townResident2"/>
          </list>
          </property>
        </bean>         
     
     </beans>
    
    Listing 6. Example Run
    package springobserver;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    
    public class ExampleRun {
    	public static void main(String[] args) {
    		// launch the spring frame work.
    		ApplicationContext ctx = new FileSystemXmlApplicationContext(
    				"/config/ObserverContext.xml");
    		// grab the Town Crier out of the spring 
    		// framework and send a message too all observers
    		TownCrier crier = (TownCrier) ctx.getBean("townCrier");
    		crier.setMessage("It is 1 O'Clock and all is well!");
    	}
    }
    
    Example 1. System Output
    I'm the Town Crier and I've got a message: It is 1 O'Clock and all is well!
    Greetings my name is: springobserver.TownResident@80fa6f
    I heard: It is 1 O'Clock and all is well!
    Greetings my name is: springobserver.TownResident2@1b9ce4b
    I heard: It is 1 O'Clock and all is well!
    

    posted @ 2005-11-22 14:17 Dion 閱讀(776) | 評(píng)論 (0)編輯 收藏

    僅列出標(biāo)題
    共5頁: 上一頁 1 2 3 4 5 
    主站蜘蛛池模板: 亚洲av无码专区在线电影天堂 | 亚美影视免费在线观看| 免费无码又爽又刺激高潮软件| AA免费观看的1000部电影| av在线亚洲欧洲日产一区二区| 亚洲免费视频播放| 国产日韩久久免费影院| 青苹果乐园免费高清在线| 亚洲乱色熟女一区二区三区丝袜| 亚洲欧洲AV无码专区| 久久成人免费电影| 亚洲欧洲自拍拍偷精品 美利坚| 亚洲人成网站日本片| 黄色片在线免费观看| 亚洲欧洲第一a在线观看| 美女被免费网站视频在线| 免费H网站在线观看的| 亚洲国产av美女网站| 少妇高潮太爽了在线观看免费| 亚洲一区二区三区高清不卡| 日韩免费的视频在线观看香蕉| 久久亚洲精品无码| a毛片全部播放免费视频完整18| 免费a级毛片无码av| 亚洲精华国产精华精华液好用| 亚洲一级免费视频| 亚洲AV无码国产精品色午友在线| 国产久爱免费精品视频| 亚洲91av视频| 日韩免费毛片视频| 亚洲国产综合AV在线观看| 免费va在线观看| a在线视频免费观看| 亚洲av永久无码嘿嘿嘿| 黄+色+性+人免费| 亚洲神级电影国语版| 4399影视免费观看高清直播| 老司机亚洲精品影院无码| 日韩精品免费在线视频| 在线亚洲午夜片AV大片| 最近2019中文免费字幕在线观看|