跳轉到內容

WebObjects/Web 應用程式/開發/WO 元件/程式碼模板和 WODs

來自華夏公益教科書,開放世界的開放書籍

WebObjects 是使用模型-檢視-控制器架構設計的。這意味著您的應用程式被分成幾個不同的角色。您的 EOModels 和它們的 EOEntities 構成了模型層。檢視和控制器使用 WOElements 和 WOComponents 實現,這些元件分佈在三個不同的部分:程式碼、模板和 WOD。WebObjects 的一個有趣之處在於,元件架構並不假定生成 HTML。您可以使用相同的元件系統建立 HTML、XML、CSS、XSLT、電子郵件或任何其他型別的動態資料。

程式碼

[編輯 | 編輯原始碼]

無論您擴充套件 WODynamicElement 還是 WOComponent,您始終都有一個 Java 類來實現元件的邏輯,並可選地儲存其狀態。預設情況下,Java 類的名稱決定了您將在整個應用程式中如何引用您的元件,您將在後面的示例中看到幾個例子。在實現 WODynamicElements 和 WOComponents 之間有一些關鍵區別。

WODynamicElements

[編輯 | 編輯原始碼]

如果您正在構建一個WODynamicElement,您的類將沒有模板或 WOD 檔案。所有輸出都直接在程式碼中生成。WODynamicElements 也不得不假設每個使用都會有一個例項,而是您的類的單個例項可能會同時為多個元件提供服務。因此,您的 WODynamicElement 必須完全執行緒安全。這些屬性使 WODynamicElements 非常適合生成相對較小的輸出或“計算”的輸出。如果您發現自己編寫大量程式碼來處理輸出資料,您可能需要考慮從構建 WOComponents 中獲得的模板的好處。

根據您的元素提供的或所需的互動型別,您可以在您的 WODynamicElement 中實現三種主要方法

  • takeValuesFromRequest
  • invokeAction
  • appendToResponse

有關這些方法在執行時的執行順序的更多資訊,請閱讀請求-響應迴圈部分。

要從請求中接收值(例如,表單資料),請實現 takeValuesFromRequest 方法。如果您的 WODynamicElement 響應使用者操作,您必須實現 invokeAction 方法。如果您的 WODynamicElement 生成輸出,您必須實現 appendToResponse 方法。在執行時,您的 WODynamicElement 將連線到一個 WOComponent,您可以透過傳遞到上述三個方法中的每個方法的 WOContext 訪問它,該上下文可用於解析頁面上特定外觀中的繫結。例如,要檢索繫結的值,它可能看起來像

 private WOAssociation myNameAssociation;
 ...
 public void appendToResponse(WOResponse _response, WOContext _context) {
   WOComponent component = _context.component();
   String name = (String) myNameAssociation.valueInComponent(component);
   super.appendToResponse(_response, _context);
 }

這種相同的模式用於無狀態 WOComponents。WODynamicElement 可以提供一個 .api 檔案來描述其繫結。有關 .api 檔案的更多資訊,請參見下面的 .API 檔案部分。

WOComponents

[編輯 | 編輯原始碼]

WOComponents 在 WODynamicElements 之上增加了幾個主要功能。主要額外功能是支援模板。當您建立 WOComponent 時,您還可以建立一個“.wo”資料夾,其中包含三個檔案:一個 .html 或 .xml 模板,一個 .wod 繫結宣告和一個 .woo 檔案。與 WODynamicElements 一樣,WOComponents 也可以提供一個可選的 .api 檔案(如下所述)。WOComponent 的程式碼可以簡單到僅宣告您的類擴充套件 WOComponent 以及它的建構函式。例如

 public class MyComponent extends WOComponent {
   public MyComponent(WOContext _context) {
     super(_context);
   }
 }

上面針對 WODynamicElements 描述的三種核心方法也存在於 WOComponent 中,但是由於 WOComponents 可以是有狀態的,因此您也可以在元件中宣告例項變數 (ivars),您可以將其繫結到。每次在頁面上使用 WOComponent 時,都會建立一個新例項,這是與 WODynamicElement 相比的另一個重大區別。您的 WOComponents 不必是執行緒安全的。

WO 資料夾

[編輯 | 編輯原始碼]

預設情況下,WOComponent 模板可以是 .html 或 .xml 檔案。WebObjects 模板將所有繫結宣告分離到一個名為 .WOD 檔案的單獨檔案中,這與許多其他 Web 框架不同。因此,模板通常更容易閱讀,並且通常可以更輕鬆地交給設計師處理,而無需擔心程式碼相關的繫結意外被修改。WOComponents 在模板中使用“webobject 標籤”宣告,它看起來像 HTML 標籤

 <webobject name = "PersonName"></webobject>

在 WebObject 標籤中宣告的名稱將用作在您的 WOD 檔案中查詢相應繫結定義的鍵。

WOD 檔案

[編輯 | 編輯原始碼]

WOD 檔案(Web 物件宣告?)定義了模板中每個元件引用的繫結。例如,如果上面的引用連線到元件上的一個“public String personName()”方法,則 WOD 宣告可能如下所示

 PersonName : WOString {
   value = personName;
 }

此宣告有幾個部分。第一個標記是出現在模板中的 WebObject 標籤名稱。這些值必須完全匹配才能使 WebObjects 解析繫結資訊。如果您在模板中引用了一個名稱但沒有宣告相應的 WOD 條目,WebObjects 將在執行時丟擲異常。

第二個標記,冒號之後,是將在您的模板中例項化的元件或元素的名稱。此名稱使用 NSBundle 查詢規則解析,預設情況下,此規則將找到與標記名稱相同的任何類,不包括包名稱。例如,WOString 實際上可能是“com.webobjects.appserver._private.WOString”,但該類的名稱(不包括其包名稱)是“WOString”。這很重要,因為它意味著如果您使用此語法,您必須在所有包中唯一地命名您的類(一個 Objective-C 遺產,其中不存在包的概念)。但是,您可以選擇完全限定您的類名,在這種情況下,上面示例中的“WOString”將變為“com.webobjects.appserver._private.WOString”,並且類解析將沒有歧義。可以使用 NSUtilities 上的方法覆蓋正常的 NSBundle 查詢過程

 NSUtilities._setClassForName(com.bla.TestComponent.class, "TestComponent");

此呼叫將 WOD 引用中出現的名稱 "TestComponent" 繫結到類 com.bla.TestComponent,避免進一步的類“查詢”。這也有助於用您自己的類替換內部元件實現。例如,您可以用您自己的類替換 WOString 的實現,Project WOnder 廣泛使用此功能來提供對核心元件的錯誤修復和增強。

在 WOD 檔案中繼續前進,在花括號內,您可以提供一系列鍵值對,每個鍵值對以分號作為分隔符。等號左側是繫結名稱。繫結名稱在 WOComponent 上透過嘗試找到與以下命名約定之一匹配的 mutator 方法或欄位來解析:public void setValue(Xxx param)、public void _setValue(Xxx param)、public Xxx value、public Xxx _value(假設上面的繫結名為“value”)。因此,如果您的 WOComponent 具有 setValue 方法,並且啟用了自動繫結同步,則將呼叫 setValue 方法,並傳入繫結右側的計算值。在上面的示例中,右側是 "personName"。如果 personName 在上面的示例中實際上是用引號引起來的,則它將被視為字串文字,並將等效於呼叫 setValue("personName")。

但是,personName 沒有引號,因此使用 Key-Value-Coding (KVC) 進行解釋。Key-Value-Coding 允許您將一系列訪問器方法呼叫或欄位引用串聯成一個字串,WebObjects 將使用 Java 反射動態解析該字串。例如,在上面的示例中,personName 將嘗試查詢任何名為:public String getPersonName()、public String _getPersonName()、public String personName()、public String _personName()、public String personName、public String _personName 的訪問器或欄位。因此,如果您的 Java 類具有 public String getPersonName() 方法,則該方法的返回值將傳遞到您的 WOComponent 的 setValue(..) 方法。KVC 變得更加有趣的地方在於,您可以構造一系列方法呼叫。例如,想象一下,您的 WOSession 有一個 "public Person person()" 方法,該方法有一個 "public Address address()" 方法,該方法有一個 "public String zipCode()" 方法。您的 WOD 檔案繫結可能如下所示:"value = session.person.address.zipCode;",這會將您會話中人員地址的郵政編碼繫結到 value。Foundation 提供的 NSArray 操作更有趣。例如,如果您的會話有一個 "public NSArray purchaseAmounts()" 方法,該方法返回一個 BigDecimal 陣列,則可以引用繫結 "value = session.purchaseAmounts.@sum",它將返回陣列中值的總和。Foundation 類中還有其他一些陣列操作可用,而 Project Wonder 在其 ERXArrayUtilities 類中提供了更多操作。有關更高階的 KVC 功能,請閱讀 Project Wonder 的 WOOgnl 部分。

單個 WOD 條目可以包含多個繫結宣告,而 WOD 檔案可以包含多個條目。例如,以下是一個實際 WOD 檔案的摘錄

 FilterAction : WOSubmitButton {
   action = filter;
   value = "filter";
 }
 
 EditAction : WOHyperlink {
   action = editRequest;
 }
 
 NoRequestsConditional : WOConditional {
   condition = requestsDisplayGroup.allObjects.count;
   negate = true;
 }

WOO 檔案

[編輯 | 編輯原始碼]

至少,WOO 檔案聲明瞭 WO 版本和模板的字元編碼。例如,一個簡單的 WOO 檔案可能看起來像這樣

 {
   "WebObjects Release" = "WebObjects 5.0"; 
   encoding = NSMacOSRomanStringEncoding; 
 }

此外,WOO 檔案可以包含您的 WO 元件可以引用的例項化物件的定義。如果您使用 WOBuilder 構建元件,您將在元件的 WOO 檔案中找到 WODisplayGroups 屬性的定義。

API 檔案

[編輯 | 編輯原始碼]

API 檔案是可選檔案,它們出現在與您的 .WO 相同的資料夾中,並提供有關您的元件的元資料,IDE 可以使用這些元資料為您的元件使用者提供更好的體驗。例如,API 檔案聲明瞭您元件的所有繫結、繫結型別(布林值、日期等),以及用於定義繫結驗證的相當廣泛的 XML 語言。

例如

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <wodefinitions>
   <wo wocomponentcontent="true" class="AjaxSortableList.java">
     <binding name = "id"/>
     <binding name = "list"/>
     <binding name = "listItemIDKeyPath"/>
     <binding name = "startIndex"/>
     <binding name = "action"/>
 
     <validation message = "'id' is a required binding">
       <unbound name = "id"/>
     </validation>
   
     <validation message="'listItemIDKeyPath' must be bound when 'list' is bound">
       <and>
         <bound name = "list"/>
         <unbound name = "listItemIDKeyPath"/>
       </and>
     </validation>    
   </wo>
 </wodefinitions>

在此示例中,API 定義了頂部的繫結,以及一系列驗證。當驗證內部的宣告計算結果為“true”時,將在 IDE 中顯示驗證訊息。例如,對於第一個驗證,如果 "id" 值未繫結,則將顯示驗證訊息。在第二種情況下,如果 "list" 值已繫結,但 "listItemIDKeyPath" 未繫結,則將顯示訊息。

華夏公益教科書