详细内容、图片请查看上面地址!
Web Application 開 發 利 器 - WebSnap!
Written by Code6421
2001/9/28
更 新 記 事
( 本 篇 文 章 使 用 DELPHI 6.01 為 藍 本, 請 更 新 你 的 DELPHI 至 6.01 版!)
第 零 章 、 前 言
WebSnap 是 DELPHI 6 最 新 的 Web Application 開 發 架 構 , 她 以 前 一 版 本 的 WebBroker 為 基 礎 , 並 加 入 了 許 多 在 WebBroker+InternetExpress 架 構 中 所 缺 少 的 功 能 。 雖 然 說 是 加 強 , 但 從 技 術 角 度 上 來 看 , 兩 者 其 實 都 被 重 新 設 計 過 了 。 以 往 的 WebBroker+InternetExpress 架 構 中 , 最 大 的 問 題 是 支 援 的 功 能 過 於 簡 單 , 例 如 Session,Pages Manager,Servier-Side Scipt 等 開 發 Web Application 必 要 的 功 能 在 這 個 架 構 中 全 部 缺 席 。 使 用 者 常 常 必 須 靠 著 3rd-Party 元 件 的 支 援 , 或 自 行 撰 寫 這 類 元 件 來 滿 足 專 案 的 需 求 , 這 使 得 設 計 師 的 生 產 力 打 了 折 扣 。 WebSnap 架 構 補 足 了 這 些 功 能 並 且 加 入 了 許 多 新 的 元 件 , Borland 同 時 強 化 了 WebBroker , 加 入 了 管 理 網 頁 用 的 Multi-Modules 功 能 , 這 個 功 能 使 得 我 們 在 處 理 Pages Manager ( 網 頁 管 理 ) 工 作 變 的 簡 單 且 自 動 化 。 除 了 這 些 之 外 , WebSnap 在 架 構 上 使 用 了 許 多 新 穎 且 實 用 的 Design Patterns 概 念 , 這 個 決 定 使 得 WebSnap 整 個 架 構 可 以 橫 向 或 縱 向 延 展 , 讓 日 後 的 移 植 與 擴 充 工 作 變 的 相 當 簡 單 。 Borland 也 計 劃 在 日 後 將 WebSnap 整 個 架 構 移 植 至 Kylix 上 , 讓 DELPHI 設 計 師 能 在 Windows 及 Linux 兩 種 平 台 上 設 計 Web 應 用 程 式 , 這 對 有 跨 平 台 需 求 的 專 案 來 說 是 一 大 福 音 。 可 惜 美 中 不 足 的 是 在 DELPHI 6 出 貨 時 , 伴 隨 的 WebSnap 說 明 文 件 實 在 太 少 了 , 以 一 個 如 此 龐 大 的 架 構 而 言 , 沒 有 說 明 文 件 的 輔 助 , 使 用 者 很 難 用 的 上 手 。 在 DELPHI 6 出 貨 時 只 扮 隨 著 幾 個 WebSnap 的 範 例 程 式 , 的 確 ! 以 範 例 程 式 的 標 準 來 說 , 這 些 範 例 程 式 都 相 當 有 水 準 , 也 適 當 的 點 出 了 許 多 WebSnap 技 巧 的 應 用 方 式 , 可 惜 就 是 太 有 水 準 了 , 容 易 令 使 用 者 知 其 然 而 不 知 其 所 以 然 , 在 實 際 應 用 時 很 容 易 產 生 瓶 頸 , 此 時 又 沒 有 說 明 文 件 可 查 詢 , 所 以 使 用 者 也 只 能 靠 著 除 錯 範 例 程 式 或 是 在 NewsGroup 上 詢 問 別 人 , 藉 此 來 了 解 整 個 WebSnap 架 構 及 運 用 技 巧 , 這 不 但 沒 效 率 而 且 很 費 時 ! 因 此 我 希 望 這 篇 文 章 能 稍 稍 減 輕 這 種 現 象 , 由 於 WebSnap 架 構 相 當 的 龐 大 , 因 此 我 將 WebSnap 分 成 兩 篇 文 章 , 一 篇 是 概 觀 篇 , 另 一 篇 則 是 應 用 篇 , 概 觀 篇 中 涵 蓋 了 WebSnap 的 設 計 概 念 及 基 本 應 用 , 應 用 篇 則 涵 蓋 了 進 階 應 用 及 設 計 WebSnap 元 件 , 老 話 一 句 ! 希 望 你 能 由 這 兩 篇 文 章 中 得 到 你 想 要 的 知 識 。
第 一 章 、 WebSnap 架 構 概 觀
WebSnap 是 一 個 相 當 龐 大 的 架 構 , 為 了 使 這 個 架 構 適 應 日 後 的 擴 充 或 移 植 , Borland 使 用 了 許 多 近 代 的 Design Patterns 來 建 構 她 。 使 用 Patterns 雖 然 能 夠 使 整 個 系 統 架 構 的 延 展 性 增 加 , 可 是 對 一 些 不 熟 悉 Patterns 的 使 用 者 來 說 , 這 同 時 也 造 成 了 學 習 曲 線 增 長 的 困 擾 。 這 些 使 用 者 通 常 很 難 在 一 開 始 時 就 了 解 整 個 WebSnap 架 構 的 流 程 及 運 用 方 式 , 容 易 迷 失 在 眾 多 的 元 件 及 介 面 叢 林 中 。 但 是 你 一 旦 領 略 到 WebSnap 為 何 會 設 計 成 這 樣 後 , 你 會 發 現 到 這 個 架 構 美 麗 的 一 面 。 在 這 一 章 中 我 試 著 對 WebSnap 做 一 個 概 觀 型 的 討 論 , 讓 你 對 整 個 架 構 有 一 個 基 本 的 認 識 , 後 面 的 章 節 再 用 實 作 來 引 導 你 做 進 一 步 的 了 解 。 這 可 能 是 你 第 一 次 接 觸 WebSnap , 因 此 我 建 議 你 在 看 這 章 時 以 看 故 事 的 心 態 來 閱 讀 , 不 需 要 強 迫 自 己 了 解 這 一 章 所 談 的 所 有 東 西 , 也 不 需 要 停 留 在 本 章 太 久 。 待 日 後 再 回 到 這 一 章 來 複 習 , 這 對 你 的 學 習 之 旅 會 比 較 輕 鬆 一 點 。
1-1 WebSnap 的 八 大 元 件 類 別
WebSnap 由 數 十 個 元 件 以 及 Interface( 介 面 ) 所 組 成 , 其 中 各 個 元 件 與 Interface 之 間 的 關 係 相 當 的 複 雜 , 這 一 章 之 中 , 我 們 用 你 在 Component Palette 能 看 到 的 17 個 元 件 與 Web Module 為 基 礎 , 分 成 八 大 類 :
Web Module
PageProducer
Dispatcher
Adapters
Sessions
ValueList
Wrapper
Services
1-2 、 Web Module
在 WebSnap 眾 多 的 元 件 中 , Web Module 位 於 較 核 心 的 部 份 , 她 在 WebSnap 中 扮 演 著 容 器 元 件 的 角 色 。 你 可 以 在 Web Module 中 放 置 Web Components 或 是 其 它 的 非 視 覺 化 的 元 件 , 就 像 是 以 往 我 們 使 用 TDataModule 元 件 一 樣 。 事 實 上 她 也 是 繼 承 至 TDataModule , 只 是 加 入 了 許 多 特 別 為 Web 所 設 計 的 功 能 。 在 WebSnap 中 Web Module 分 成 兩 大 類 , 在 每 一 類 中 又 可 細 分 為 兩 小 類 :
Application Module
Page Module
Data Module
Generic Module
Page Module
Data Module
在 一 個 WebSnap 程 式 中 , 至 少 必 須 含 有 一 個 Application Module , 在 這 個 Web Module 中 你 必 須 放 置 一 個 TWebAppComponents 元 件 , 這 個 元 件 就 是 WebSnap 的 中 心 。 所 有 的 Client Request( 網 頁 要 求 或 是 Action) 都 會 經 由 她 分 送 至 其 它 的 Global Components 元 件 。 Application Module 扮 演 著 網 頁 程 式 的 Control Center( 控 制 中 心 ) 角 色 , 任 何 對 於 這 個 程 式 的 要 求 都 會 先 送 往 Application Module 。 WebSnap 提 供 了 兩 個 不 同 類 型 的 Application Module , 因 應 不 同 的 專 案 需 求 , 你 可 以 選 擇 可 輸 出 網 頁 的 Application PageModule 或 是 不 輸 出 網 頁 , 只 單 純 放 置 資 料 或 其 它 非 視 覺 化 元 件 的 Application DataModule 。 當 你 選 擇 的 是 輸 出 網 頁 的 Application Module 時 , 你 必 須 放 置 一 個 PageProducer 元 件 到 這 個 Module 中 , 這 個 元 件 的 作 用 是 提 供 PageModule 輸 出 網 頁 的 能 力 , 通 常 我 們 會 使 用 Application PageModule 來 當 成 網 站 的 首 頁 , 不 過 這 不 是 絕 對 的 , 我 們 也 可 以 使 用 Application DataModule , 將 PageDispatch 元 件 的 Default Page 特 性 值 設 成 我 們 首 頁 的 Web Module 名 稱 , 那 這 個 Web Module 就 會 成 為 首 頁 。 Application DataModule 與 Application Page Module 功 能 上 大 致 相 同 , 差 別 在 於 該 Web Module 是 否 有 輸 出 網 頁 的 能 力 。 Application DataModule 並 沒 有 輸 出 網 頁 的 能 力 , 因 此 她 只 是 一 個 擁 有 Control Center 特 質 的 元 件 容 器 。 Generic Module 與 Application Module 的 功 能 大 致 相 同 , 差 別 只 在 於 Control Center 的 特 殊 能 力 上 , 下 面 是 Web Module 的 運 作 流 程 圖 :
( 圖 :1)
在 這 個 流 程 中 有 一 個 重 點 需 要 特 別 注 意 , 那 就 是 當 你 選 擇 的 Application Module 是 PageModule 時 , 假 設 Client Request 訊 息 中 並 未 特 別 指 明 所 要 求 的 網 頁 , PageDispatcher 元 件 就 會 將 Client Request 導 向 位 於 Application PageModule 中 的 PageProducer 元 件 , 利 用 她 輸 出 網 頁 後 傳 回 Client 端 。 如 之 前 所 討 論 的 , 這 個 動 作 會 受 到 PageDispatcher 元 件 的 DefaultPage 特 性 值 所 影 響 , 你 可 以 藉 由 改 變 這 個 特 性 值 來 變 動 首 頁 的 位 置 。 由 流 程 中 你 可 以 發 現 到 , Dispatcher 元 件 在 WebSnap 中 所 扮 演 的 角 色 是 訊 息 分 發 者 , 作 用 是 將 Client Request 導 向 正 確 的 Module , 接 著 經 由 該 Module 中 的 PageProducer 元 件 所 提 供 的 輸 出 網 頁 能 力 , 將 網 頁 輸 出 後 傳 回 Client 端 。 當 要 求 的 網 頁 中 含 有 ServerSide-Script 時 , WebSnap 會 呼 叫 Active Script Engine 來 解 譯 這 些 Script 程 式 碼 , 產 生 出 最 終 的 HTML Document , 最 後 經 由 WebBroker 傳 回 給 Client 端 顯 示 。 為 了 支 援 ServiceSide-Script , 以 往 InternetExpress 架 構 中 的 TPageProducer 元 件 已 經 被 增 強 為 可 處 理 Script 的 元 件 , 你 可 以 在 她 的 ScriptEngine 特 性 值 中 設 定 你 的 程 式 所 需 要 使 用 的 Script Engine 類 型 。 目 前 的 WebSnap 支 援 JScript 及 VBScript 兩 種 Script 語 言 , 日 後 應 該 會 支 援 更 多 的 Script Engine ( 如
HP) 。 在 WebSnap 整 個 架 構 中 , 所 有 元 件 的 差 異 性 通 常 是 決 定 在 元 件 所 實 作 的 Interface 上 , Web Module 也 不 例 外 。 Application Module 與 Generic Module 之 間 的 差 異 在 於 IGetWebAppServices 這 個 介 面 上 , Application Module 中 實 作 了 這 個 介 面 , 而 這 個 介 面 中 定 義 了 取 出 TWebComponents 元 件 的 函 式 , 因 此 WebSnap 可 以 經 由 此 介 面 的 函 式 取 出 TWebAppComponets 元 件 , 再 經 由 她 取 得 Dispatcher 類 元 件 或 是 其 它 的 Global Components 。 Generic Module 則 未 實 作 此 介 面 , 這 個 介 面 是 Control Center 能 力 的 源 頭 。 PageModule 及 DataModule 之 間 的 差 異 則 是 在 於 IPageResult,ISetWebContentOptions, IGetDefaultAction, IGetProducerComponent,IProducerEditorViewSupport 這 五 個 介 面 上 , 實 作 IPageResult 介 面 的 元 件 必 須 提 供 輸 出 網 頁 的 函 式 , 當 WebSnap 遇 到 實 作 此 介 面 的 元 件 時 , 她 會 呼 叫 其 中 的 輸 出 函 式 來 取 得 網 頁 內 容 。 IGetDefaultAction 介 面 中 則 定 義 了 取 出 DefaultAction 物 件 的 函 式 , 這 個 物 件 的 意 義 常 常 被 搞 混 , 以 為 當 此 Page Module Activate( 活 化 ) 時 就 會 觸 發 這 個 Action 的 事 件 函 式 。 事 實 上 不 然 , 她 只 在 特 殊 的 情 況 下 才 會 被 觸 發 , 在 下 面 的 章 節 中 會 說 明 這 些 情 況 。 IGetProducerComponent 介 面 中 定 義 了 取 得 PageProducer 元 件 的 函 式 , Dispatcher 需 要 使 用 這 個 函 式 來 取 得 Web Module 中 的 PageProducer 元 件 , 進 而 利 用 她 來 輸 出 網 頁 。 IProducerEditorViewSupport 則 是 IDE 所 使 用 的 介 面 , 用 來 判 別 Module 擁 有 那 些 檔 案 , 如 XML,Script 等 ( 簡 單 的 說 就 是 你 能 夠 在 IDE 中 看 到 那 些 檔 案 ) 。 ISetWebContentOptions 介 面 目 前 只 使 用 在 當 Web Module 中 的 HTML Template File( 網 頁 範 本 檔 ) 含 有 IncludePage 命 令 時 暫 時 關 掉 執 行 Script 的 動 作 , 避 免 執 行 到 不 完 整 的 Script 程 式 後 產 生 不 正 確 的 內 容 。 Web Module 中 提 供 了 幾 個 事 件 讓 我 們 處 理 , 這 些 事 件 的 使 用 方 式 都 蠻 直 覺 的 。 Activate 類 事 件 是 在 Module 被 活 化 或 離 開 時 觸 發 , 也 就 是 在 Dispatcher 解 析 Client Request 取 得 需 要 的 Web Module 名 稱 , 接 著 找 到 對 應 的 Web Module 時 觸 發 OnActivate 事 件 , 以 及 離 開 該 Module 時 觸 發 OnDeactivate 事 件 。 這 裡 有 一 點 必 須 注 意 , Activate/Deactivate 事 件 不 等 於 Create/Destroy 事 件 。 當 網 頁 被 設 定 為 OnCached 模 式 時 , Activate/Deactivate 事 件 可 能 會 被 觸 發 許 多 次 , 而 Create/Destroy 事 件 只 會 在 Module 被 建 立 或 消 滅 時 才 會 觸 發 , 接 著 會 再 觸 發 Activate/Deactivate 類 事 件 , DispatchPage 類 事 件 則 會 在 Dispatcher 活 化 Web Module 後 輸 出 網 頁 的 前 後 觸 發 , 實 務 上 來 看 , 你 應 該 將 初 始 化 的 程 式 碼 放 在 Activate Event , 但 是 這 有 個 例 外 , 那 就 是 當 你 在 某 一 個 Web Module 中 提 供 一 個 Action 讓 使 用 者 執 行 , 假 如 執 行 後 所 轉 向 的 Page Module 是 自 己 本 身 時 , 在 執 行 Action 之 後 的 Activate 類 事 件 將 不 會 被 觸 發 , 這 是 因 為 當 執 行 Action 前 Module 就 已 經 被 活 化 了 , 也 就 是 說 Activate 已 被 執 行 過 了 。 這 時 你 必 須 將 初 使 化 的 程 式 碼 移 往 DispatchPage 類 事 件 中 , 這 個 事 件 會 在 每 次 輸 出 網 頁 前 後 被 觸 發 。 我 們 也 可 以 在 DispatchPage 類 事 件 內 將 網 頁 導 向 另 一 個 Web Module , 這 會 用 在 當 我 們 不 希 望 使 用 者 直 接 進 入 該 網 頁 , 而 是 希 望 她 經 由 某 個 Action 轉 向 該 網 頁 時 , 這 時 我 們 就 可 以 應 用 這 個 事 件 來 處 理 , 在 下 面 的 章 節 中 我 們 會 對 Activate 、 DispatchPage 、 DefaultAction 做 更 深 入 的 討 論 以 及 應 用 。
1-3 、 PageProducer
除 了 原 先 InternetExpress 架 構 中 的 TPageProducer 與 TxxPageProducer 元 件 之 外 , WebSnap 還 提 供 了 TXSLPageProdcuer 、 TAdapterPageProducer 這 兩 個 新 的 PageProducer 。 TAdapterPageProducer 是 目 前 我 們 在 WebSnap 中 較 常 用 的 PageProducer 元 件 。 她 可 以 讓 我 們 以 視 覺 化 設 計 網 頁 , 同 時 延 用 元 件 觀 念 來 設 計 網 頁 應 用 程 式 。 這 些 能 力 來 自 於 IWebComponentEditor 及 IProducerEditorViewSupport 這 兩 個 介 面 。 IWebComponentEditor 可 以 讓 TAdapterPageProducer 過 濾 加 入 的 子 元 件 型 別 , 這 很 重 要 , 因 為 在 WebSnap 中 是 以 實 作 的 介 面 來 區 分 元 件 類 型 , 因 此 大 部 份 的 WebSnap 元 件 都 是 繼 承 至 TComponent 而 來 , 這 時 必 須 視 她 們 實 作 的 介 面 來 決 定 是 否 可 以 成 為 TAdapterPageProducer 的 子 元 件 。 IProducerEditorViewSupport 的 功 能 與 Module 內 的 xxEditorViewSupport 介 面 相 同 , 差 別 是 Module 將 她 用 在 Code Editor 上 , 而 TAdapterPageProducer 則 是 將 她 用 在 Visual Page Designer 上 。 在 TAdapterPageProducer 元 件 中 有 一 個 WebPageItems 屬 性 , 這 個 屬 性 來 自 於 TAdapterPageProducer 的 父 類 別 TBasePageItemsProducer 。 這 就 是 TAdapterPageProducer 儲 存 子 元 件 的 地 方 , WebSnap 識 別 此 類 元 件 的 方 法 就 是 判 別 該 元 件 是 否 實 作 了 IGetWebComponentList 這 個 介 面 , 接 著 再 經 由 此 介 面 取 得 IWebComponentList 介 面 後 處 理 這 些 子 元 件 。 在 TAdapterPageProducer 中 提 供 了 三 個 事 件 , OnHTMLTag 事 件 是 用 來 識 別 某 個 Tag 時 觸 發 , 再 由 設 計 師 置 換 成 其 它 內 容 , 我 們 通 常 利 用 她 來 動 態 改 變 某 區 段 的 網 頁 內 容 。 GetContent 事 件 則 是 在 TAdapterPageProducer 輸 出 網 頁 的 前 後 觸 發 。 OnHTMLTag 只 在 HTML Template File 中 含 有 Tag( 如 <#TEST>
時 才 會 觸 發 , GetContent 事 件 則 會 在 每 次 輸 出 網 頁 前 後 觸 發 。 值 得 注 意 的 是 GetContent 事 件 觸 發 的 時 間 比 OnHTMLTag 早 , 這 也 代 表 這 你 在 OnHTMLTag 中 不 能 夠 處 理 Server-Side Script , 因 為 此 時 的 Server-Side Script 已 被 執 行 完 畢 並 轉 為 HTML 文 件 了 。 GetContent 中 則 允 許 你 處 理 Server-Side Script , 但 這 需 要 使 用 一 些 技 巧 , 我 在 Inside WebSnap 一 文 中 會 提 到 這 類 的 技 術 。 TXSLPageProducer 則 是 允 許 你 使 用 XSL 來 處 理 網 頁 , 由 於 XSL 部 份 的 知 識 範 圍 較 廣 , 因 此 我 留 待 Inside WebSnap 時 再 討 論 相 關 的 運 用 。 目 前 TAdapterPageProducer 元 件 所 產 生 出 來 的 Server-Side Script 並 不 能 被 更 動 , 如 果 你 希 望 對 ServerSide-Script 有 更 多 的 控 制 , 你 可 以 選 擇 使 用 TAdapterPageProducer 來 設 計 你 的 網 頁 , 完 成 後 再 將 HTML 內 容 複 製 到 TPageProducer 中 , 用 TPageProducer 代 替 原 來 的 TAdapterPageProducder 來 輸 出 網 頁 , 本 文 的 附 錄 中 有 詳 細 的 使 用 方 式 。
1-4 、 Dispatcher
由 圖 一 中 你 應 該 已 經 了 解 Dispatcher 在 WebSnap 架 構 中 所 扮 演 的 角 色 。 WebSnap 中 提 供 了 兩 個 Dispatcher 元 件 , TPageDispatcher 及 TAdapterDispatcher , 加 上 以 往 的 TWebDispatcher 後 , 在 DELPHI 6 中 你 就 有 三 個 Dispatcher 元 件 可 以 使 用 。 TPageDispatcher 是 用 來 分 發 網 頁 要 求 的 元 件 , 當 Client Request 一 個 網 頁 時 , TPageDispatcher 負 責 找 到 該 頁 面 並 將 控 制 權 轉 交 給 該 網 頁 的 Page Module 。 TAdapterDispatcher 則 是 用 來 分 發 Action 要 求 , 例 如 當 你 的 網 頁 中 有 一 個 按 紐 , 這 個 按 紐 連 結 了 一 個 Action , 因 此 當 使 用 者 按 下 這 個 按 紐 時 , TAdapterDispatcher 會 負 責 找 到 這 個 Action 元 件 所 在 的 Web Module 後 , 取 得 該 Action 元 件 來 執 行 該 Action 。 Dispatcher 同 時 也 提 供 了 使 用 者 權 限 的 控 制 , 在 TPageDispatcher 找 到 Client 端 所 要 求 的 頁 面 時 , 她 會 先 查 看 該 頁 面 的 權 限 資 料 來 決 定 使 用 者 是 否 有 權 限 可 以 取 得 該 頁 面 。 同 樣 的 , 在 TAdapterDispatcher 分 發 Action 時 也 會 先 查 看 Action 元 件 的 執 行 權 限 設 定 做 同 樣 的 工 作 , 後 面 的 章 節 會 介 紹 這 部 份 的 應 用 。 Dispatcher 類 元 件 雖 然 看 起 來 做 的 事 不 多 , 事 實 上 她 卻 是 WebSnap 中 Pages Manager 的 主 角 , 因 為 她 的 存 在 , 你 才 能 一 行 程 式 碼 都 不 用 寫 , 就 擁 有 了 Page Manager 的 功 能 。
( 圖 :2)
上 圖 中 我 們 可 以 清 楚 的 看 到 Dispatcher 元 件 的 運 作 模 式 , 這 裡 有 件 事 要 稍 微 注 意 一 下 , 當 Action 執 行 之 後 會 呼 叫 TPageDispatcher 元 件 來 轉 向 目 的 網 頁 , 這 時 Action 元 件 中 的 RedirectOptions 特 性 值 是 決 定 是 否 執 行 目 的 網 頁 中 DefaultAction 事 件 的 關 鍵 。
1-5 、 Adapters
Adapter 是 WebSnap 中 相 當 重 要 的 軸 心 元 件 , 同 時 也 是 最 複 雜 且 難 懂 的 部 份 。 物 件 導 向 設 計 模 式 中 , Adapter 被 定 義 成 將 舊 有 物 件 包 裝 成 為 一 個 新 的 物 件 , 並 在 另 一 種 系 統 架 構 中 運 用 她 , 以 達 到 重 用 (Reuse) 的 目 的 。 WebSnap 中 Adapter 分 為 四 類 :
Adapter Container
Adapter Items
Adapter Control Container
Adapter Control Items
Adapter Container 是 一 種 Adapter 容 器 元 件 , 她 可 以 包 含 其 它 的 Adapter Items , 例 如 TApplicationAdapter 、 TEndUserAdapter 、 TEndUserSessionAdapter 、 TDataSetAdapter 等 都 是 Adapter Container 類 元 件 。 Adapter Items 類 元 件 則 有 TAdapterField 、 TAdapterAction 、 TAdapterDataSetField 等 。 這 兩 類 Adapter 都 屬 於 Scriptable-Object , 這 也 就 是 說 你 能 夠 在 Active Script 中 使 用 她 們 來 取 得 Adapter 中 的 資 料 , 就 像 是 在 ASP 中 使 用 ASP Object 的 方 式 使 用 她 們 。 除 了 這 兩 類 Adapter 之 外 , Adapter Control Container 與 Adapter Control Items 則 是 屬 於 輔 助 型 的 Adapter 元 件 。 你 在 TAdapterPageProducer 所 看 到 的 TAdapterForm 、 TAdapterFieldGroup,TAdapterEditColumn 等 元 件 就 是 這 類 型 , 這 些 Adapter 的 主 要 目 的 是 支 援 視 覺 化 設 計 功 能 。 技 術 上 來 說 , 你 可 以 運 用 這 些 Adapter 來 連 結 Adapter Container 及 Adapter Items 並 產 生 出 HTML FORM or Script 。 這 類 Adapter 可 以 稱 之 為 Adapter 的 Adapter , 值 得 注 意 的 是 , Adapter Control Container 及 Adapter Control Items 並 不 是 Scriptable-Object , 她 們 存 在 的 意 義 是 為 了 讓 你 可 以 使 用 Visual Page Designer 來 設 計 網 頁 , 並 動 態 產 生 Script 與 HTML 碼 :
( 圖 :3)
上 圖 中 我 們 大 略 可 以 看 出 來 , Adapter Control 類 元 件 是 用 來 將 Adapter 類 元 件 的 內 容 輸 出 至 HTML 中 的 元 件 。 例 如 TAdatperForm 會 使 用 Adapter Container 來 產 生 出 HTML FORM , TAdapterEditColumn 則 會 使 用 Adapter Items 來 產 生 出 TextBox 或 是 CheckBox 這 些 樣 式 的 HTML Edit Control 。 事 實 上 她 們 所 做 的 工 作 很 多 , 例 如 產 生 Script 連 結 至 Adapter , 亦 或 是 產 生 一 些 HTML Table , 某 些 應 用 上 她 們 還 會 產 生 出 對 應 的 Client Side Script 程 式 碼 。 在 Adapter Items 中 也 分 為 兩 類 , TAdapterField 及 TAdapterAction 。 TAdapterField 是 用 來 處 理 資 料 用 的 , 你 可 以 視 她 為 可 以 在 Script 中 使 用 的 變 數 。 TAdapterAction 則 是 用 來 處 理 Action , 如 Hyperlink 、 Button 等 。 這 同 時 也 代 表 了 Adapter Control Items 中 也 會 分 為 兩 類 , 一 是 用 來 處 理 TAdapterField 的 TAdapterEditColumn 、 TAdapterDisplayField 等 元 件 , 另 一 類 則 是 用 來 處 理 TAdapterAction 的 TAdapterActionButton 元 件 。 Adapter 在 WebSnap 中 扮 演 著 相 當 重 要 的 角 色 , 因 此 了 解 她 是 你 開 發 WebSnap 程 式 的 必 要 條 件 。 後 面 的 章 節 中 , 我 會 針 對 各 種 Adapter 元 件 做 更 完 整 的 介 紹 。
1-6 、 Sessions
Session 功 能 是 一 個 網 頁 程 式 常 會 使 用 到 的 功 能 , 例 如 在 一 個 購 物 網 站 中 的 購 物 車 功 能 , 或 是 保 留 使 用 者 登 入 資 訊 等 功 能 都 需 要 她 的 幫 忙 。 在 以 往 的 WebBroker+InternetExpress 架 構 中 並 不 支 援 Session 的 運 用 , 所 以 我 們 常 常 得 藉 助 於 3rd-Party 元 件 或 自 行 撰 寫 處 理 Session 的 程 式 碼 。 在 WebSnap 中 Borland 補 上 了 這 個 缺 口 , 她 提 供 了 TSessionServices 這 個 元 件 來 控 管 Session 的 狀 態 。 當 你 的 Application Module 中 包 含 一 個 TSessionServices 元 件 時 , 當 Client Request 到 達 後 WebSnap 就 會 在 WebContext 中 建 立 一 個 Session 物 件 , 接 著 你 就 可 以 在 任 何 一 個 Web Module 中 使 用 這 個 物 件 來 處 理 Session 資 料 。 在 處 理 完 網 頁 要 求 後 , WebSnap 會 將 這 個 Session 轉 換 成 Cookie 並 傳 回 Client 端 , 這 樣 Client 在 下 次 瀏 覽 此 網 站 時 就 會 將 這 個 Cookie 送 給 Web Server , 這 時 WebSnap 程 式 再 經 由 Cookie 取 出 對 應 的 Session 。 由 這 個 討 論 中 你 可 以 發 現 到 , Session 功 能 是 建 立 在 Cookie 上 面 , 所 以 當 Client 端 的 瀏 覽 器 設 定 中 將 Cookie 關 閉 時 , Session 也 就 會 跟 著 失 效 , 這 與 一 般 的 網 頁 程 式 相 同 。目 前 的 WebSnap 並 未 將 Session 儲 存 於 檔 案 中 , 因 此 你 不 能 在 非 DLL 型 態 的 WebSnap 程 式 中 使 用 Session ,因 為 當 程 式 關 閉 後 , 存 放 於 記 憶 體 中 的 Session 也 就 跟 著 消 失 了 , 我 們 可 以 利 用 WebSnap 所 提 供 的 儲 存函 式 來 保 留 Session , 在 Session 一 章 我 們 會 討 論 這 個 技 術 。 在 WebSnap 中 使 用 Session 物 件 是 件很 輕 鬆 的 事 , 但 有 一 些 特 殊 情 況 需 要 你 多 加 注 意 , 那 就 是 當 使 用 者 開 啟 了 兩 個 瀏 覽 器 時 , 我 們 是 該 使 用兩 個 不 同 的 Session 還 是 共 用 一 個 呢 ? 這 在 一 些 網 頁 程 式 中 是 相 當 重 要 的 課 題 , 在 Session 一 章 中 ,我 們 會 深 入 的 討 論 這 些 問 題 。
1-7 、 ValueList
ValueList 類 元 件 在 WebSnap 中 是 扮 演 著 輔 助 者 的 角 色 , 例 如 TWebUserList 提 供 使 用 者 資 料 給 TEndUserAdpater 元 件 使 用 , 或 是 TDataSetValueList 提 供 Records 給 TAdapterDataSetField 元 件 使 用 。 事 實 上 ValueList 也 是 一 個 Adapter , 這 也 代 表 著 我 們 在 某 些 情 況 下 可 以 用 她 來 取 代 原 有 的 Adatper 元 件 。 ValueList 元 件 相 當 的 簡 單 並 容 易 使 用 , 你 只 要 抓 住 一 個 慨 念 即 可 輕 易 的 使 用 她 , 這 個 概 念 就 是 DELPHI 6 對 TStrings 所 增 加 的 新 功 能 Pair Value , 簡 單 的 說 就 是 一 個 名 稱 跟 著 一個 值 , 如 :Site=www.borland.com.tw , Site 就 是 名 稱 , 所 對 應 的 值 就 是 www.borland.com.tw 。 後 面 的 章 節 我 們 會 利 用 她 來 達 成 許 多 網 站 程 式 中 常 用 的 功 能 。
1-8 、 Wrapper
相 信 有 許 多 人 壓 根 兒 就 沒 有 看 過 這 個 東 西 , 在 WebSnap 中 Wrapper 扮 演 極 核 心 的 角 色 , 她 讓 你 可 以 在 Active Script 使 用 Scriptable-Object , 例 如 下 面 這 段 Script 程 式 碼 :
<%= vAdapter1_Borland.DisplayText %>
vAdapter1_Borland 是 一 個 TAdapterField 元 件 , 可 是 TAdapterField 只 能 夠 在 DELPHI 中 使 用 不 是 嗎 ? 沒 錯 ! 但 這 不 是 單 純 的 TAdapterField 元 件 , 她 是 一 個 TAdapterFieldWrapper 元 件 。 這 個 Wrapper 元 件 中 包 含 著 一 個 TAdapterField 元 件 的 參 考 (Reference) , 當 你 使 用 這 個 Wrapper 元 件 時 , 她 會 將 你 對 她 的 操 作 轉 交 給 真 正 的 TAdapterField 元 件 。 這 也 是 WebSnap 中 Scriptable-Object 的 秘 密 , 在 Windows 平 台 上 的 Wrapper 元 件 實 際 上 是 一 個 COM 物 件 , 當 PageProducer 處 理 Active Script 之 前 , 她 會 為 所 有 Scriptable-Object 建 立 Wrapper 元 件 , 完 成 之 後 再 將 Script Document 交 由 Active Script Engine 處 理 ,而 Active Script Engine 允 許 我 們 在 Script 中 使 用 COM 物 件 , 因 此 我 們 就 可 以 使 用 這 些 Wrapper 元 件 了 。當 Active Script Engine 解 譯 完 畢 後 就 會 產 生 出 最 後 的 HTML Document , 最 後 再 由 WebSnap 程 式 將 HTML傳 回 Client 端 。
1-9 、 Services
這 一 類 型 的 元 件 通 常 是 屬 於 全 域 型 的 , 主 要 是 輔 助 WebSnap 程 式 中 的 系 統 功 能 , 例 如 SessionService 元 件 負 責 提 供 WebSnap 程 式 中 的 Session 的 支 援 , 當 你 將 這 個 元 件 放 置 到 Application Module 之 後 , 你 就 可 以 在 程 式 的 任 何 一 個 地 方 使 用 Session 物 件 來 保 存 資 料 。 LocateFileService 元 件 則 負 責 了 WebSnap 程 式 中 的 檔 案 存 取 功 能 , 當 你 放 置 一 個 LocateFileService 元 件 到 Application Module 之 後 , 所 有 相 關 的 檔 案 存 取 動 作 都 會 經 過 這 個 元 件 , 因 此 你 可 以 利 用 她 的 事 件 來 讀 取 檔 案 或 是 進 行 其 它 的 處 理 。 因 為 這 些元 件 是 放 置 在 Application Module 中 , 因 此 你 可 以 在 程 式 中 的 任 何 一 個 Web Module 中 存 取 到 她 。
本 章 後 記
這 一 節 中 我 們 對 WebSnap 做 了 一 個 慨 觀 的 討 論 , 你 或 許 對 這 一 節 所 討 論 的 東 西 並 不 是 太 了 解 ,甚 至 可 以 說 模 糊 ! 別 洩 氣 , 這 很 正 常 ! 你 會 在 下 面 的 討 論 中 漸 漸 理 解 在 這 裡 所 討 論 的 東 西 。
<第 二 章 、 第 一 個 WebSnap 程 式>
--------------------------------------------------------------------------------
Copyright &copy; 1994 - 2001 Borland Software Corporation. All rights reserved