跳轉到內容

WebObjects/Web 應用程式/開發/生成靜態頁面

來自 Wikibooks,開放世界中的開放書籍

從 WebObjects 構建靜態網站

[編輯 | 編輯原始碼]

上週 WWDC 上,一位觀眾在 WebObjects 會議上問到如何使用 WebObjects 從動態網站建立靜態頁面。據我回憶,Bill Bumgarner 回答了這個問題。這是在提出任何型別的動態網站時反覆出現的一個問題。曾經,線上 WebObjects 文件的程式設計主題中包含了如何處理此問題的簡要說明,由為 BBC 設定初始網站的蘋果員工編寫;該說明沒有在網站的多次清除中倖存下來 - 這很好,因為它非常簡短和膚淺。

從動態引擎建立靜態網站有很多原因;BBC 選擇這樣做是為了擔心 WebObjects 的效能。更合理的理由是使用 html 作為便攜的文件格式;例如,建立在 CD 上分發的公司形象手冊。我參與過幾個這樣做的專案,包括上面提到的兩個。

我將完全跳過如何在 WebObjects 中建立動態頁面,而專注於如何在頁面級元件中建立靜態頁面。動態內容是一個很容易解決的問題,而且它被多次解決。建立靜態頁面的問題可以清楚地分為兩部分:明顯的部分是如何將頁面寫入 html 檔案,這通常被稱為“爬取”;不那麼明顯的部分是,所有頁面連結都必須以某種方式從 WebObjects 動態操作轉換為靜態 URL。

首先,您需要一個機制來訪問網站上的每個頁面。我通常為此目的在管理應用程式中建立一個操作。我將有一個數據庫結構,其中包含要寫入的每個頁面的記錄(企業物件)。這將包含頁面子級的關係以及父級的關係。頂層頁面可以透過它沒有父級來識別;如果需要,此結構也可以擴充套件為表示單個數據庫中的多個網站或頂層頁面。我的頁面或節點 EO 將有一個方法來將自身寫入;要寫入的檔案系統位置將根據節點路徑到當前節點計算,使用 EO 中的檔案系統名稱來標記路徑。

我在元件中使用以下方法來寫入頁面,該方法從爬取程式碼中呼叫;節點是表示頁面或節點的 EO,htmlPath 是一個明顯的方法。

   public void writeToHtml() {
       WOResponse r = null;
       String c = null;
       try {
           File folder = new File(NSPathUtilities.stringByDeletingLastPathComponent(node().htmlPath()));
           folder.mkdirs();
           BufferedWriter out = new BufferedWriter(new FileWriter(new File(node().htmlPath())));
           r = generateResponse();
           if (r == null) NSLog.debug.appendln("writeHtml: no response");
             c = r.contentString();
           if (c == null) NSLog.debug.appendln("writeHtml: no content");
             out.write(c);
           out.flush();
       } catch (IOException e) {
           System.err.println(e.getMessage());
       } catch (Throwable e) {
           System.err.println("writeToHtml(" + node().htmlPath() + "): " + e.getMessage());
       }
   }

htmlPath() 方法的示例實現如下

   public String htmlPath() {
       return NSPathUtilities.stringByAppendingPathComponent(PLUtilities.defaultForKey(null, "docroot", "/Library/WebServer/Documents").toString(), urlPath());
   }
 
   public String urlPath() {
       String fileName = name() + primaryKeyString(this) + ".html";
       return "/" + NSPathUtilities.stringByAppendingPathComponent(site().name(), fileName);
   }
 
   static public String primaryKeyString(EOEnterpriseObject object) {
       NSDictionary dict = EOUtilities.primaryKeyForObject(object.editingContext(), object);
       String result = "";
       java.util.Enumeration enumerator = dict.objectEnumerator();
       while (enumerator.hasMoreElements()) {
           Object anObject = enumerator.nextElement();
           result += anObject.toString();
       }
       return result;
   }

可能需要更智慧的實現,根據節點層次結構構建路徑字串,或者從 EO 屬性獲取檔名等。

[編輯 | 編輯原始碼]

此類網站元件中可以使用唯一的操作是 WOHyperlinks;這些可以轉換為靜態頁面引用,而表單操作等則不能。基本假設是所有頁面都將從檔案系統而不是 Web 伺服器提供服務,因此不支援 cgi。理論上,您可以使用 Javascript 來滿足頁面的任何動態需求。

由於允許網站以動態網站和靜態版本執行非常有用,因此我用以下結構替換了所有 WOHyperlinks(來自 wod 檔案)

 Generic1: WOGenericContainer {
   elementName = "a";
   href = nodeHref;
   invokeAction = nodeLink;
 }

這兩種方法必須對上下文敏感,並知道何時生成動態的 WOHyperlink 風格連結,何時生成靜態連結。在我的管理應用程式中,用於建立和編輯網站,我包含一個根據我們是否正在檢視(動態)或生成(靜態)網站而設定的標誌。

   public String nodeHref() {
       if (sessionViewMode()) return context().componentActionURL();
       return aNode.urlPath();
   }
 
   public CustomTemplate nodeLink() {
       if (aNode != null)
           return pageWithName(aNode.name());
   }

對 pageWithName() 的呼叫從節點 EO 中獲取元件名稱;同樣,這可以用更智慧的呼叫來替換,該呼叫在元件中設定值等。

通用容器使用 <A> 標記構建一個 href,該 href 將包含適當的靜態 url,或者根據 sessionViewMode() 返回的值完全充當 WOHyperlink。

華夏公益教科書