程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 用Google Gears增強您的Web應用程序

用Google Gears增強您的Web應用程序

編輯:關於JAVA

本文將簡要介紹如何用 Google Gears 提供的 API 增強您的 Web 應用程序, 包括增加離線支持,提高運行速度和本地數據庫支持等。

眾所周知,Ajax 可以使得 Web 應用程序的響應速度提高一大塊,然而雲計算 和 SaaS(Software as a Service) 的用戶仍然期望獲得更快的響應速度,那 Web 應用程序還能更快嗎?答案是肯定的。隨著硬件技術的不斷升級,客戶端計算機 的計算能力逐步提高,如果 Web 應用程序可以充分利用閒置的客戶端計算能力, 那將進一步提高其響應速度,但如何充分利用客戶端計算能力便成了開發者新的 挑戰, Google Gears 正是幫助 Web 應用程序開發者應對這種挑戰的有力工具。 其次,用戶有時希望在離線的情況下也可以使用 Web 應用程序,這無形當中增加 了 Web 應用程序開發者的痛苦指數, Google Gears 恰好可以減輕開發者在這方 面的痛苦。最後,企業用戶對於采納雲計算和 SaaS 總會存在一種顧慮,那就是 企業的核心數據拱手交給第三方公司來存儲和管理,這顯然使得企業難以保護自 己公司的商業機密 , 而 Google Gear 可以允許用戶將 Web 應用程序產生的用戶 數據存儲到用戶自己的電腦中,而不是將數據存儲到雲端或者 SaaS 提供商的數 據中心。本文將逐個介紹 Google Gears 提供的各種特性和 API,並且會提供使 用這些 API 的例子。

Google Gears 簡介

Google Gears 是 Google 公司推出的一個開源項 目,它是一個浏覽器的插件,它會添加新的功能到浏覽器,並暴露相應的 JavaScript API 給 Web 應用程序,以此增強 Web 應用程序的功能和性能。目前 Google Gears 支持 Firefox 1.5+, Internet Explorer 6.0+ 和 Safari 3.1.1+ 等主流浏覽器。

首先, Google Gears 提供的 LocalServer API 可以將 Web 應用程序的 HTTP 資源緩存到用戶的硬盤中,這樣可以在 Ajax 的基礎上進一步提高 Web 應 用程序的響應速度,同時也使得用戶在沒有網絡連接的情況下依然可以使用 Web 應用程序;其次, Google Gears 提供了 WorkerPool API 幫助 Web 應用程序在 後台進行耗時的運算以提高 UI 的響應能力, Web 應用程序也可以用這種方式將 原來由服務器承擔的一部分運算工作交給客戶端來處理;第三, Google Gears 提供的 Database API 則可以讓 Web 應用程序將數據保存到用戶的硬盤中並遵守 同源安全策略,以此保護用戶的敏感數據不被外露。除此之外, Google Gears 還提供了 Desktop, Geolocation 等 API 來豐富已有的功能。目前有 Google Docs, Google Reader 和 Zoho 等 Web 應用程序利用 Google Gears 來提供更多 的功能。下面將介紹如何利用 Google Gears 提供的各種 API 來增強你的 Web 應用程序。

環境准備

為了開發 Google Gears 應用程序,你需要先安裝 Google Gears 插件到你的浏覽器,用你的浏覽器訪問 http://gears.google.com/,如果 你的浏覽器沒有安裝 Google Gears 插件,在顯示的網頁右上角會出現一個 Install Gears 的按鈕,點擊它將會開始安裝 Google Gears。接下來你還需要到 http://code.google.com/intl/zh-CN/apis/gears/tools.html 下載 gears_init.js 文件,把該文件放到你的 Web 應用程序裡面。由於 Google Gears 提供的 API 是基於 JavaScript 語言的,所以你不需要安裝額外的 IDE 插件來開發 Google Gears 程序,僅需要普通的文本編輯器就可以。如果你的浏 覽器是 Firefox, 可以安裝 Firebug 來調試 JavaScript。

走出第一步

為了使你的 Web 應用程序的某一個頁面能用上 Google Gears 的功能, 需要把清單 1 所示的代碼嵌入到網頁的 Html 代碼裡面 , src 的值是前面下載 的 gears_init.js 的相對路徑。

清單 1. 為網頁增加對 Google Gears 的 JavaScript 庫的引用

<script type="text/javascript"  src="gears_init.js"></script>

檢測是否安裝了 Google Gears

只有在浏覽器安裝了 Google Gears 插件的情況下,Google Gears 提供的 JavaScript API 才會生效,所以你的 Web 應用程序需要在一開始 就檢測用戶的浏覽器是否安裝了 Google Gears, 如果沒有就轉到 Google Gears 的安裝頁面。清單 2 所示代碼能夠幫你做到這些

清單 2. 檢測浏 覽器是否安裝了 Google Gears

<script>
 if (! window.google || !google.gears) {
  location.href =
   "http://gears.google.com/?action=install&message=<your  welcome message>";
 }
</script>

在上 面代碼中你可以用 message 參數自定義顯示在安裝頁面的消息。

使用 LocalServer API

雖然 Google Gears 不僅僅是為了給 Web 應用程序賦予 離線功能而生,但離線功能卻無疑是 Google Gears 最重要的使命之一。 LocalServer, WorkerPool 和 Database 這三個 Gears 最早的,同時也是最核心 的功能模塊,為完成這一使命提供了必不可少的利器。

LocalServer 的主 要功能是將 Web 應用程序的 HTTP 資源緩存到用戶的本地硬盤中,並且當用戶需 要再次訪問同樣的網絡資源的時候,對其進行攔截,轉而用本地已存儲的 HTTP 資源來代替服務器端的資源,為用戶提供服務。這樣,不但可以在 Ajax 的基礎 上進一步提高 Web 應用程序的響應速度,同時也使得用戶在沒有網絡連接,或者 網絡連接狀況不好的情況下依然可以像使用本地應用程序一樣的流暢使用 Web 應 用程序。

然而,即使有了 LocalServer 的支持,也並不意味著我們需要 一股腦的把所有的 Web 應用程序都拿到本地來執行,很多實時性很強,或者數據 量過大的 Web 應用程序,都並不適合進行本地存儲和利用本地資源來提供服務。 因此,在利用 LocalServer API 對 Web 應用程序提供離線使用的功能之前,更 重要的是要根據不同應用程序的應用場景,考量和分析哪些 Web 應用程序,或者 某個 Web 應用程序的哪些功能和資源適合放到本地,並且能相對容易放到本地, 放到本地之後能有更好的使用效果和用戶體驗。

在確定了要存儲 Web 應 用程序的哪些功能和資源之後,我們可以利用 LocalServer 提供的兩種緩存方式 來獲取 HTTP 資源:

ResrouceStore – 獲取指定 URL 的用戶數據 ,PDF 文件,圖片,樣式表,JavaScript, 和 HTML 頁面等。

ManagedResourceStore – 根據 manifest 文件事先聲明的內容, 獲取一系列版本可控的相關的網絡資源。

與利用 ResourceStore 獲取並 存儲相對獨立的網絡資源相比,利用 ManagedResourceStore 獲取一系列相關聯 的網絡資源會復雜一些。不過 manifest 文件的引入,也讓由 ManageResourceStore 方式獲取的網絡資源變得相對的簡單和一目了然。該 manifiest 文件由一個包括版本信息和資源清單在內的 JSON 對象組成,其中的 “entries”屬性,列出了所有需要被獲取和存儲的資源的 URL。

此外,以上兩種存儲方式最主要的區別是在於對所存資源的更新方式有所 不同。ResourceStore 方式存儲的資源不會自動被更新。如果需要更新,開發人 員要在代碼中顯示地調用 captrure() 方法。而利用 ManagedResourceStore 存 儲的資源,由於在 manifest 文件中記錄了版本的信息,因此可以同時支持手動 和自動兩種更新方式。開發人員既可以通過調用 checkForUpdate() 來手動檢查 並更新本地資源,也可以在 Google Gears 攔截或提供來自 ManagedResourceStore 的請求的同時,自動比較服務器和本地版本的差異,如有 不同,注意這裡是不同,也就是說即使服務器版本要低於本地版本,也會觸發更 新。

LocalServer API 提供了三個主要的類來創建和管理由 ResourceStore 和 ManagedResourceStore 兩種方式獲取的網絡資源。

LocalServer – 創建、打開和刪除 ResourceStore 和 ManagedResourceStore 兩種存儲方式的網絡資源。

ManagedResourceStore – 管理以 ManagedResourceStore 方式存 儲的網絡資源。

ResourceStore – 管理以 ResourceStore 方式存 儲的網絡資源。

在使用包括 LocalServer API 在內的 Google Gears 的 API 之前,首先需要利用 Factory API 中的 create() 方法,指定需要用到的接 口。正如清單 3 所示的代碼,在調用 LocalServer API 的方法之前,需要先調 用 create() 方法創建出一個 LocalServer 類型的對象。

清單 3. 在使用 Google Gears 的 API 之前需先創建出相應類型的對象

<script type="text/javascript">
var localServer  = google.gears.factory.create('beta.localserver');
</script>

下面我們以將一個最簡單的 HTML 頁面用 ManagedResourceStore 方式存儲到本地為例,來簡單的說明 LocalServer API 是怎樣將網絡資源存儲到本地,並且及時更新的。代碼和 manifest 文件,分別 如清單 4 和清單 5 所示。

清單 4. 以 ManagedResourceStore 方 式將普通 HTML 頁面存儲到本地

<html>
   <head>
    <title>Google Gears  ManagedResourceStore</title>
    <script  type="text/javascript" src="gears_init.js"></script>
     <script>
      var STORE_NAME =  "MangedResourceStore_Sample";
      var MANIFEST_FILENAME  = "manifest.json";
      var localServer;
       var store;

      function createManagedStore() {
        // 創建出一個 LocalServer 類型的對象
         localServer = google.gears.factory.create ("beta.localserver");
      // 創建一個  ManagedResourceStore 類型的本地存儲,如果該存儲已經存在,就直接打開
        store = localServer.createManagedStore (STORE_NAME);

        store.manifestUrl =  MANIFEST_FILENAME;
        store.enabled = true;
         // 手動觸發一次更新,該更新會在後台異步運行,用戶可繼續 操作頁面,無需等待響應 
        store.checkForUpdate ();

        var timerId = window.setInterval (function(){
         // 一旦獲得本地存儲的版本信息,表 明本地存儲或更新已經結束。 
          if  (store.currentVersion) {
             window.clearInterval(timerId);
            alert ('Done! Current Version is ' + 
             store.currentVersion);
          }
         }, 500);

      }

      function  removeManagedStore(){
        // 刪除已創建的本地存儲 
        localServer.removeManagedStore(STORE_NAME);
      }
    </script>
  </head>
  <body>
    <h1>ManagedResourceStore -  Version 0.01</h1>
    <form>
       <input type="button" value="Create Managed Store"
         onclick="createManagedStore();">
      <input  type="button" value="Remove Managed Store"
         onclick="removeManagedStore();">
    </form>
   </body>
 </html>

清單 5. 對應的 manifest 文件

{
  "betaManifestVersion": 1,
  "version":  "1.0",
  "entries": [ 
    { "url":  "ManagedResourceStore.html"},
    { "url":  "gears_init.js"}
  ]
}

首先,將 HTML 頁面和 manifest 文件部署到 HTTP 服務器上,之後我們便可以通過浏覽器訪問該頁面。 點擊 "Create Managed Store" 按鈕,會觸發一個創建 ManagedResourceStore 類型的本地存儲的事件,該事件會將 manifest 文件裡列出的所有同源網絡資源 下載並存儲到本地硬盤。如果你想知道它們被存儲到了哪裡,存放路徑因 操作系統和浏覽器的不同而不同,具體的位置可以參看:

http://code.google.com/intl/zh- CN/apis/gears/api_database.html#directories

接下來用戶便可 以通過訪問與連網時相同的 URL,或者通過創建的桌面快捷方式(在後面的章節 會提到如何為你的離線 Web 應用程序創建桌面快捷方式),在即使沒有網絡連接 的情況下依然可以訪問並使用這個頁面。這時,如果我們更新了服務器端的資源 文件,並且相應的更新了 manifest 文件中的版本信息,你會看到,存儲到本地 的網頁信息,也會跟著自動被更新。當然,如果你等不及自動更新,也可以通過 再次點擊 "Create Managed Store" 按鈕,調用 checkForUpdate() 方法手動更 新頁面。

使用 WorkerPool API

在一個頁面執行計算量比較大的任 務或 I/O 操作時,Web 應用程序經常會慢到不響應,這個時候 WorkerPool 就有 了用武之地。WorkerPool 可以用來在父頁面的後台獨立地執行計算量大的任務, 而父頁面則繼續執行自己的任務。清單 6 演示了如何使用 WorkerPool API

清單 6. 使用 WorkerPool API

父頁面代碼
<html>
  <head>
    <title>Google  Gears WorkerPool API</title>
    <script  type="text/javascript" src="gears_init.js"></script>
     <script type="text/javascript">
     // 父頁面 的 JavaScript 代碼,也就是父 Worker
     // 創建兩個  workerPool 對象
     var wp1 =  google.gears.factory.create('beta.workerpool');
     var wp2  = google.gears.factory.create('beta.workerpool');

      function onMsg(a,b,message){
      var msg =  document.getElementById("msg");
      msg.innerHTML = '收 到的消息來自 worker '
        + message.sender + ', 消息內容如下 : <br/>'
        + message.body;
     }

     // 設置當父 worker 收到消息時用  onMsg 方法來處理
     wp1.onmessage = onMsg;
      wp2.onmessage = onMsg;

     function callWorker1 (){
      /* 創建一個子 Worker, 調用完  createWorkerFromUrl 方法後,
       * 父 worker 和子  worker 將並行運行,當然子 worker 是在後台運行   
        */ 
      var childWorkerId =  wp1.createWorkerFromUrl('worker.js');
      // 父 worker  發送消息給子 worker
      wp1.sendMessage(["Hello,",  {"gears": "Google Gears!"}], childWorkerId);
     }

     function callWorker2(){
      var  childWorkerId = wp2.createWorkerFromUrl('worker.js');
       wp2.sendMessage(["您好 ,", {"gears": "世界 !"}],  childWorkerId);
     }

    </script>
  </head>
  <body>
    <h1>Hello,  WorkerPool API</h1>
    <input type="button"  value="WorkPool A Calls Child Worker"
       onclick="callWorker1();">
    <input type="button"  value="WorkPool B Calls Child Worker"
       onclick="callWorker2();"><hr/>
    <div  id="msg"></div>
  </body>
</html>

worker.js 文件 
(function(){
 // 子 worker 可以 在此執行計算量很大的代碼
})();

var wp =  google.gears.workerPool;
wp.onmessage = function(a, b,  message) {
  var reply = "This is reply message from  child work:"
    + message.body[0]
    +  message.body[1].gears;
  wp.sendMessage(reply,  message.sender);
}

WorkerPool 不是單例對象,所以可以 看到在上面的父頁面中可以創建兩個 WorkerPool。在父頁面的 Javascript 代碼 相當於父 worker, 你可以用 WorkerPool 對象的 createWorkerFromUrl() 方法 創建一個子 worker, 該方法的參數是 JavaScript 文件的 URL, 也可以用 createWorker() 方法創建,參數是一段 JavaScript 代碼。創建完子 worker 之 後,父 worker 和子 worker 將並行運行 , 子 worker 在後台承擔計算量大的任 務,而父 worker 在前面繼續響應處理用戶操作。

另外,由於 WorkerPool 更像是一個進程池,而不是線程池,所以 worker 之間不共享執行狀 態,他們之間的相互通訊只能通過消息傳遞,也就是調用 WorkerPool 對象的 sendMessage() 方法,該方法有兩個參數:

第一個參數是要傳遞的消息內 容。

第二個參數是接受該消息的 worker 的 ID,WorkerPool 對象的兩個 方法 createWorkerFromUrl() 和 createWorker() 返回的就是創建的子 worker 的 ID, 可以用來作為該參數的值。

不管是父 worker 還是子 worker, 要 想得到 sendMessage() 方法傳過來的消息,都需要事先定義回調函數 onmessage ,用於處理接收到的消息。

正是由於 WorkerPool 之間不共享執行狀態, 作為結果,子 worker 不能訪問父頁面的 DOM,以及 document, window 這樣的 對象,只有父 worker 能訪問這些對象。如果子頁面要訪問這些對象,可以通過 給父 worker 發消息讓父 worker 來訪問。但是,子 worker 還是能調用 JavaScript 的內置函數和大部分 Google Gears API。

使用 Database API

為了讓 Web 應用程序支持離線操作,首先需要解決的問題是將 Web 應用程序包含的 HTTP 資源緩存到用戶本地的文件系統中,這個已經可以通過前 面介紹的 LocalServer 來解決,第二個需要解決的問題是要讓用戶在使用 Web 應用程序的過程中產生的用戶數據能夠存放到本地,然後在連上網絡的時候將本 地的數據與服務器端的數據進行同步,這個問題可以用 Google Gears 提供的本 地浏覽器數據庫來解決。之所以叫本地浏覽器數據庫,是因為數據庫是運行在用 戶本地電腦上的,並且浏覽器可以通過 JavaScript 操作該數據庫。當然,本地 浏覽器數據庫還可以用於存放用戶希望保密的數據在用戶自己的文件系統,而不 是存放在雲端。同時,即使在連上網絡的情況下,也可以通過訪問本地數據帶來 性能上的巨大提升,畢竟這要比訪問服務器端的數據快得多。

為了讓浏覽 器上運行的 Web 應用程序能夠操作本地浏覽器數據庫, Google Gears 提供了一 套 Database API, 它使得 Web 應用程序可以將用戶數據存放到用戶自己的電腦 中, Google Gears 是用開源的關系數據庫系統 SQLite 作為這個本地浏覽器數 據庫,當用戶將 Google Gears 安裝為浏覽器的插件之後,用戶實際上就把 SQLite 安裝到了他 / 她的電腦中, Web 應用程序則可以調用 Google Gears 提 供的 Database API 來操作 SQLite, Database API 允許開發人員在 JavaScript 裡面直接用 SQL 語句從 SQLite 讀取數據或者寫入數據到 SQLite。 在這一節我們將介紹如何調用 Database API 來操作 SQLite。

清單 7 所 示代碼演示了如何用 Database API

打開或創建一個新數據庫

創建 表

刪除表中的記錄

插入記錄到表中

查詢表中的數據以及遍 歷返回的結果集

更新表中的數據

刪除表

清單 7. 使 用 Database API 操作 SQLite 數據庫

<html>
  <head>
  <meta http-equiv="content-type"  content="text/html; charset=utf-8"/>
  <script  type="text/javascript" src="gears_init.js"></script>
   <script type="text/javascript">
   // 創建 Database  對象
   var db = google.gears.factory.create ('beta.database');
   // 打開名為'testdb'的 SQLite 數據庫, 如果不存在,則創建它
   db.open('testdb');

    function create(){
    // 如果在名為'testdb'的數據庫中找不到 表 emp, 就創建一個新表 emp 
    db.execute('create table  if not exists emp' + 
          ' (empno int,  name text, age int, phone text)');
    // 刪除表 emp  中所有的數據
    db.execute('delete from emp');
     // 插入 3 條數據到表 emp 
    db.execute('insert into  emp values (?, ?, ?, ?)', [111, 'Tony', 35, '1234567']);
    db.execute('insert into emp values (?, ?, ?, ?)',  [122, '傅飛', 31, '2345678']);
    db.execute('insert into  emp values (?, ?, ?, ?)', [135, 'Dave', 26, '3456789']);
   }

   function update(){
    // 更新表  emp 的記錄 
    db.execute('update emp set phone = ?  where empno=?', ['88888888',122]);
    db.execute('update  emp set age = ? where empno=?', [28,135]);
    query ();
   }

   function query(){
    //  查詢表 emp 的所有記錄,返回一個結果集對象
    var rs =  db.execute('select * from emp order by empno desc');
     var con = document.getElementById("content");
     con.innerHTML = "<ol>";
    // 遍歷結果集對象
     while (rs.isValidRow()) {// 判斷是否能調用 field() 等提取字 段值的方法。 
     // 用 field(int fieldindex) 方法獲取 特定字段的值 
     con.innerHTML += "<li>"
        + rs.field(0)+", "
       + rs.field(1)+",  "
       + rs.field(2)+", "
       +  rs.field(3)+"</li>";
     // 遍歷下一條記錄 
      rs.next();
    }
    con.innerHTML +=  "</ol>";
    // 當遍歷完結果集後記得調用 close 方法 釋放占用的資源
    rs.close();
   }

    function del(){
    // 刪除表 emp 
     db.execute('drop table emp');
    document.getElementById ("content").innerHTML= "";
   }
  </script>
 </head>
 <body>
  <h1>Hello,Database  API</h1><hr/>
  <input type="button"  value="Create table and populate rows"
     onClick="create()"/>
  <input type="button"  value="Update" onClick="update()"/>
  <input  type="button" value="Query" onClick="query()"/>
  <input  type="button" value="Delete table"
    onClick="del ()"/></br>
  <div  id="content"></div><br/>
 </body>
  </html>

當調用 db.open('testdb') 方法時, Google Gears 會檢測是否已經存在名為 "testdb" 的數據庫,如果沒有,就創建一個新 的名為 "testdb" 的數據庫。你也許會想知道這些數據庫存放在哪裡,存放路徑 因操作系統和浏覽器的不同而不同,具體的位置可以參看 http://code.google.com/intl/zh- CN/apis/gears/api_database.html#directories 。中文字符 SQLite 默認是用 utf-8 編碼來存儲數據庫文件,因此能支持中文字符。也許你注意到了,清單 7 所示的代碼中有一條插入語句,把中文字符“傅飛”插入到表 emp 裡 面。需要注意的是,SQLite 不會對 SQL 語句中的字符串自動轉換為 utf-8 編碼 ,所以開發人員需要確保這些字符串是正確編碼的,方法是將代碼文件用 utf-8 編碼保存即可。

全文檢索

Google Gears 包含了 SQLite 的一個擴 展 fts2, 用於支持全文檢索功能。fts2 使你能在一個表中類型為 Text 的所有 字段上搜索指定的關鍵字。為了利用 fts2 的全文檢索功能,你需要用 fts2 擴 展來創建表,如清單 8 所示。

清單 8. 創建支持全文檢索的表

 var db = google.gears.factory.create('beta.database');
 db.open('testdb');
 db.execute('create virtual table movie  using fts2(name, director, stars)')

上面的代碼會創建 一個能支持全文檢索的表,這個表有以下特性

依然可以用標准的 Insert, Update 和 Delete 語句操作表中的數據,如清單 9 所示。

表中 3 個字 段 name, director 和 stars 的類型都是 Text 的。

表中隱式包含了一 個跟表名相同的字段名,該列會在全文檢索的時候用到。由於該列的存在,當你 用 Insert 語句插入新記錄的時候有必要把你要更新的字段列舉出來,同樣,用 Select 語句檢索的時候也要列舉出你期望得到哪些字段的值,如清單 9 所示。 如果只是用 Select * from movie 檢索 , SQLite 將會拋出異常。

清單 9. 操作支持全文檢索的表

 // 插入幾條數據到表 movie 
 var sql = "insert into movie (name,director,stars)  values (?, ?, ?)";
 db.execute(sql, ['國產凌凌漆', '李力持',  '周星馳 谷德昭 李力持']);
 db.execute(sql, ['功夫', '周星馳 ', '周星馳 元華']);
 db.execute(sql, ['The Dark Knight',  'Christopher Nolan', 'Heath Ledger']);
 // 更新數據
  var sql = 'update movie set stars = ? where name=?';
  db.execute(sql, ['Heath Ledger,Christian Bale','The Dark  Knight']);
 db.execute(sql, ['周星馳 元華 馮小剛','功夫']) 
 // 刪除表格 
 db.execute('drop table if exists  movie');
 // 檢索數據
 db.execute('select  name,director,stars from movie order by name');

為了 能夠全文檢索上面創建的表,你需要用 “< 表名 | 字段名 > match < 查詢字符串 >” 作為檢索條件。如果用表名,實際上是用表中隱 含的跟表名同名的字段名,這將會檢索表中所有類型為 Text 的字段;如果用字 段名,這只在指定的字段上進行檢索,這種情況並不是全文檢索。我們這裡用表 名作為例子,假設表 movie 中已經有了如表 1 所示的記錄,注意 Stars 字段中 的人名是用空格隔開的,空格是 fts2 的分詞符, fts2 全文檢索的時候是按詞 來索引的,如果一個字段值沒有包含一個空格,該字段值將被視為一個詞。

表 1. 表 movie 的所有記錄
Name Director Stars 國產凌凌漆 李力持 周星馳 谷德昭 李力持 功夫 周 星馳 周星馳 元華 馮小剛 葉問 葉偉信 甄子丹 任達華 非誠勿擾 馮小剛 葛優 范偉 The Dark Knight Christopher Nolan Heath Ledger Forrest Gump Robert Zemeckis Tom Hanks

我們現在用清單 10 所示的全文檢索語句來檢 索 movie 表,其中查詢字符串是“周星馳”。

清單 10. 全文檢索的 Select 語句

 var sql = 'select  name,director,stars from movie where movie match ?';
 var  rs = db.execute(sql,['周星馳']);

我們將得到如表 2 所示的 結果,可以看出,表 movie 中任何一個字段,只要包含“周星馳”, SQLite 都會將該記錄返回給結果集。

表 2. 檢索任意字段中包含' 周星馳'的記錄
Name Director Stars 國產凌凌漆 李力持 周星馳 谷德昭 李 力持 功夫 周星馳 周星馳 元華 馮小剛

查詢字符串本身也有自己的語法,表 3 中列舉出了 一些例子。

表 3. 查詢字符串的語法
語法 例子 描述 movie match '周星馳 馮小剛' 返回任意一個字段中既包含“周星馳”又包含“馮小 剛”的記錄 movie match '周星馳 OR 馮小剛' 返回任意一個字段中包含“周星馳”和“馮小剛 ”兩者中的任一個的記錄,OR 必須大寫。 movie match '國產 *' 返回任意一個字段中包含以“國產”字符 起頭的詞的記錄 movie match 'stars: 周星馳 國產 *' 返回的記錄必須滿足下面兩個條件:

 

stars 字段必須包 含“周星馳”

任意一個字段中包含以“國產”字符 起頭的詞

movie match '"周星馳 元華"' 返回的記 錄必須滿足以下條件:
任意一個字段中“元華”緊跟著“ 周星馳” movie match '"周星馳 –馮小剛"' 返回的記錄必須滿足下面兩個條件:

 

任意一個字段中包 含“周星馳”

任意一個字段中不包含“馮小剛 ”

不適合存到本地的數據

有了本地浏覽 器數據庫,你可以盡量多地把數據存放到本地,因為訪問本地浏覽器數據確實比 訪問服務器端的數據要快得多。然而不是所有的數據都適合存放到本地,有些情 況下你還是需要去服務器端獲取數據,下面列舉了一些例子。

頻繁更新的 數據,將這種數據保存到本地意義不是很大,因為這種數據很短時間就會過時, 比如股票價格,期貨價格和等。

不常用的數據,比如存儲用戶偏好信息的 數據,這些數據很少使用,如果將這類數據存放到本地,所需的成本也許還大於 所帶來的收益。

太大的數據,由於客戶端的硬盤空間有限,不能將這些數 據悉數存到本地。

數據同步

對於支持離線模式的 Web 應用程序來 說,數據同步顯然是一個很重要的話題,一般以下兩種情況會用到數據同步:

當應用程序離線時,需要將服務器端的最新數據同步到本地,這樣才能確 保離線時 Web 應用程序照樣能運行。

當應用程序離線後,用戶使用 Web 應用程序時所產生的數據存放在本地,這部分數據需要在連上網絡的時候同步到 服務器端。

Google Gears 本身並沒有提供數據同步 API, 你需要自己實 現數據同步的功能,這涉及到浏覽器端代碼和服務器端代碼。下面我們介紹兩種 實現數據同步功能的思路。

顯式同步

這是一種最常見也是最簡單 的同步方法,用戶可以決定什麼時候進行同步,實現上可以顯式地放置一個同步 按鈕在網頁上,點擊該按鈕將觸發數據同步,把本地新的數據上傳到服務器端, 並把服務器端新的數據下載到本地。

顯示同步的優點是:

實現起 來比較簡單。

比較容易測試。

缺點是:

如果同步的數據塊 比較大,將會一次性消耗很長的時間,而 Web 應用程序在數據同步期間是不可用 的,這將讓用戶等待很長時間。

在網絡連接時斷時續的情況下,用戶將會 疲於點擊同步按鈕來同步數據,用戶還不得不對網絡狀況保持敏感以在適當的時 候手工同步數據。

後台同步

在後台同步中,Web 應用程序持續地 將本地數據與服務器端數據進行同步,同步操作是在後台進行的,不需要用戶顯 式地觸發,同步過程中用戶依然可以使用 Web 應用程序,實現上可以用 WorkerPool 在後台設定每隔一段時間跟服務器同步一次。

後台同步的優 點是:

同步操作對用戶是透明的,用戶不需要做任何操作,也不需要對網 絡狀況保持敏感。

同步操作一直在後台進行,即時當網絡意外中斷的情況 下,本地數據和服務器數據都能保持較高的一致性。

缺點是:

實 現起來比較復雜。

同步是在後台進行的,不太容易進行測試。

同 步的間隔不能太頻繁,否則會產生太多的 HTTP 連接,從而降低服務器的響應能 力。

使用 Desktop API

Desktop API 能幫你在用戶桌面上創建你 的 Web 應用程序的快捷方式,調用代碼如清單 11 所示。

清單 11. 創建桌面快捷方式

 // 創建 Desktop 對象
 var  desktop = google.gears.factory.create('beta.desktop');
 // 創 建桌面快捷方式 
 desktop.createShortcut('Google Gears Desktop  API Example',
           'http://www.testapp.net/gears/DesktopAPI.html',
           { '128x128':'http://www.testapp.net/gears/test128.png',
            '48x48':  'http://www.testapp.net/gears/test48.png',
            '32x32': 'http://www.testapp.net/gears/test32.png',
            '16x16': 'http://www.testapp.net/gears/test16.png'},
           'Google Gears Desktop API  @www.testapp.net');

createShortcut 方法有以下幾個參數 :

name, 這是用戶看到的快捷方式的名字,在清單 11 中設為 "Google Gears Desktop API Example"

url, 當用戶啟動快捷方式時要訪問的 Web 應用程序的 url, 在清單 11 中設為" http://www.testapp.net/gears/DesktopAPI.html "

icons, 這是一個 JSON 對象,可以設定不同尺寸的圖標,在清單 11 中設定了 4 中不同尺寸的圖 標

description, 這是一個可選參數,用於描述將要創建的這個快捷方式 的更詳細信息,當清單 11 的代碼在用戶浏覽器裡執行時,會彈出一個確認對話 框,description 參數確定的文本將會顯示在該確認對話框裡面,如圖 1 所示。

當清單 11 所示代碼在 Window 上的浏覽器執行的時候,不管是 Internet Explorer 還是 Firefox, 都會出現如圖 1 所示的確認對話框,讓用戶 選擇是否需要在桌面,開始菜單和快速啟動欄裡面創建 Web 應用程序的快捷方式 。

圖 1. 創建桌面快捷方式

使用 Geolocation API

Geolocation API 使你的 Web 應用程序 能獲取用戶的當前位置,結合 Google Maps API 可以立刻在 Google 地圖上顯示 用戶當前的位置,代碼如清單 12 所示。

清單 12. 結合使用 Geolocation API 和 Google Maps API

 <html  xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <meta http-equiv="content-type" content="text/html; charset=utf- 8"/>
  <title>Google Maps API and Google Gear  Geolocation API Example</title>
  <script  src="http://ditu.google.cn/maps? file=api&v=2&key=<your_map_api_key>"
    type="text/javascript"></script>
  <script  type="text/javascript" src="gears_init.js"></script>
  <script type="text/javascript">
 // 創建 Geolocation 對 象
  var geo = google.gears.factory.create ('beta.geolocation');
  var map;
  function  updatePosition(p) {
  alert('Current lat/lon is: ' +  p.latitude + ',' + p.longitude);
 // 在地圖中顯示用戶當前位 置 
  map.setCenter(new GLatLng (p.latitude,p.longitude),13);
 }

 function  handleError(positionError) {
  alert('Attempt to get  location failed: ' + positionError.message);
 }

   function load() {// 初始化地圖 
   if  (GBrowserIsCompatible()) {
    map = new GMap2 (document.getElementById("map"));
    map.addControl(new  GLargeMapControl());
    map.addControl(new  GSmallZoomControl());
    map.addControl(new GScaleControl ());
    map.addControl(new GMapTypeControl());
     map.addControl(new GOverviewMapControl());
    map.setCenter (new GLatLng(39.617, 116.197), 13);
   }
  }

 function gotoMyposition(){
 // 獲取用戶當前位置 
  geo.getCurrentPosition(updatePosition, handleError);
  }

  </script>
 </head>
 <body  onload="load()" onunload="GUnload()">
   <h1>Hello,Google Maps API and Google Gears Geolocation  API</h1>
  <div id="map" style="width: 800px;  height: 600px"></div>
  <br/>
 <input  type="button" value="Go to my position" onClick="gotoMyposition ()"/>
 </body>
 </html>

上面代 碼中的關鍵點是用 geo.getCurrentPosition(updatePosition, handleError) 來 獲取用戶的當前位置,當 Google Gears 拿到用戶的當前位置信息後,將其值傳 給 updatePosition 函數來處理,該函數調用 Google Maps API 將地圖的中心位 置設為用戶的當前位置。如果 Google Gears 拿不到用戶的當前位置,將會調用 handleError 函數來處理錯誤信息。

使用 HttpRequest API

Google Gears 提供的 HttpRequest API 實現了 W3C XmlHttpRequest specification 的一個子集 , 你可以用 HttpRequest API 發起一個 Ajax 請求 。你肯定會問在浏覽器中我們已經可以用 XmlHttpRequest 對象來創建 Ajax 請 求,為什麼 Google Gears 還要提供另外一種方式呢?這是因為在前面提到的子 worker 裡面是不能訪問浏覽器的 XmlHttpRequest 對象,所以 Google Gears 提 供了 HttpRequest API 使得子 worker 也能創建 Ajax 請求,當然 , 你依然可 以在普通網頁裡面使用 HttpRequest API,而不是非得到子 worker 裡面才能用 。為了簡單起見,我們只介紹如何在普通網頁裡面使用 HttpRequest API,如清 單 13 所示

清單 13. 使用 HttpRequest API

  <html>
 <script type="text/javascript"  src="gears_init.js"></script>
 <script  type="text/javascript">
 // 創建 HttpRequest 對象
  var request = google.gears.factory.create('beta.httprequest');

 function handleResult(){
 //readyState 為 4 表示  HttpRequest 請求的狀態是已被服務器響應 
 if  (request.readyState == 4) {
  var con =  document.getElementById("content");
  // 從 HttpRequest 請求 中讀取響應信息並顯示在網頁上 
  con.innerHTML =  request.responseText;
 }
 }

 function get() {
 // 確定 HttpRequest 對象要訪問的 Web 資源和訪問方式 ,  要訪問的資源必須在同一個域下面 
 request.open('GET',  'http://www.testapp.net/gears/test.txt');
 // 設置請求狀態改變 時的事件處理函數 
 request.onreadystatechange =  handleResult;

 var con = document.getElementById ("content");
 con.innerHTML = "Waiting...";
 // 發送  HttpRequest 請求 
 request.send();
 }
  </script>
 <body>
 <h1>Hello, Google  Gears Request API</h1>
 <div  id="content"></div>
 <br/>
  <input  type="button" value="Fetch content of test.txt" onClick="get ()"/>
   <input type="button" value="Clear"
    onClick="document.getElementById('content').innerHTML = ''"/>
 </body>
 </html>

需要注意的是當用 HttpRequest 的 open 方法確定要訪問的 Web 資源時必須遵守同源策略,否則浏 覽器將報錯。

使用 Timer API

與 HttpRequest API 相似,由於子 worker 不能訪問 window 對象,所以也就不能調用它的兩個定時器方法 setTimeout 和 setInterval, Google Gears 專門提供了 Timer API,讓子 worker 裡面的 JavaScript 代碼也可以調用定時器方法。Timer API 的功能和 window 對象的定時器方法是一樣的,在此也不再舉例。

關注安全

在這一節中,我們將介紹 Googler Gears 用到的安全策略以及如何在開發過程中 寫出安全的代碼。

同源策略

同源策略不允許一個網站上的 JavaScript 訪問另一個網站上的的任何資源。 Google Gears 就是用同源策略作 為基本的安全策略,具體體現為:

運行在一個網站上的 LocalServer API 只能抓取同一個網站上的 URL 或者用同一個網站上的 manifest 文件。

運行在一個網站上的 Database API 只能打開為同一個網站創建的 SQLite 數據 庫。

用戶許可

為了保護用戶的客戶端,當 Google Gears 的 API 嘗試訪問本地資源的時候,浏覽器會彈出一個許可對話框讓用戶選擇是否允許該 操作,當用戶選擇允許該操作的時候, Google Gears 會記住這個決定,以後同 樣的操作就不會再彈出許可對話框。但用戶仍然可以更改被記住的決定,方法是 在浏覽器的菜單中選擇“工具”->“Gears 設置”,在 彈出的對話框中進行修改,如圖 2 所示。

圖 2.Gears 設置對話框

用戶數據保護

Google Gears 的數據,包括 localServer API 抓取到本地的 Html 文件和 Database API 創建的本地數據庫文件,都是存放在 操作系統的當前用戶目錄,操作系統的其他用戶是不能訪問這些文件的。

防止 SQL 注入

為了避免攻擊者用 SQL 注入方式攻擊你的 Web 應用程序 ,不要直接把用戶的輸入作為值傳給 SQL 語句,而是通過問號占位符將用戶的輸 入傳給 SQL 語句,如清單 14 所示。

清單 14. 防止 SQL 注入

 db.execute('select * from emp where name=?', [user_input]);// 推薦使用 
 db.execute('select * from emp  where name="'+user_input+'"');// 不推薦使用 

結束語

Google Gears 提供了大量功能可以增強我們的 Web 應用程序,作為 Web 應用程序開發人員,為了開發出更強大的應用程序,我們就需要考慮如何在已有 的 Web 應用程序裡面用好 Google Gears, 或者在我們架構一個新的 Web 應用程 序的時候,盡量考慮如何充分利用 Google Gears 提供的功能。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved