原始码追踪记(2)-Model 篇
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
} else if ("page".equals(scope)) { pageContext.setAttribute(key, entry); } //將取得內容輸出 try { JspWriter out = bc.getEnclosingWriter(); out.print(content); } catch (IOException ioe) { System.err.println("Problems with writing..."); } } } else { //若未過期則從指定範圍取出網頁內容輸出 try { JspWriter out = pageContext.getOut(); out.print(entry.getContent()); } catch (IOException ioe) { System.err.println("Problems with writing..."); } } return EVAL_PAGE; } //此類別用來幫助 CacheTag 記錄網頁內容及判別網頁內容是否過期 class Entry { String content; long timestamp; long duration; public Entry(String content, long duration) { this.content = content; //記錄網頁內容 timestamp = System.currentTimeMillis(); //記錄系統時間
PETSTORE 原始碼追蹤記(二)-Model 篇
前言
在傳統的 Java 網頁應用系統(Web Application Solution),通常以 JSP 或 Servlet 透過 JDBC 連結資料庫,用 JavaBean 來封裝資料,最後組成 HTML 回應 (response)給使用者,主要以這四種 Java 技術來建構動態網頁系統,這樣的方式 在 JSP 規格中稱為 Model 1,適用於較小型、簡單的系統。若我們要架構大型企 業應用網頁系統,必須要能易於維護、容易擴充,所以 Java 倡導將 Model(資料 模型)、View(畫面展現) 及 Controll(流程控制)三者獨立,即所謂的 MVC 模式 (Design Pattern),又稱為 Model 2。 上一期我們探討了 Petstore 的 Controll(流程控制)及 View(畫面展現)部份, 我們可以利用上一期所介紹的架構來建構流程控制與畫面展現獨立的網頁應用 系統(Web Application),如此的架構雖然很有彈性,但只能建構靜態的網頁系統, 目前一般較大型的網站都是動態網頁系統,動態網頁內容通常來自資料庫。謮取 資料庫、封裝資料,這就是 Model(資料模型)的主要工作。
資料封裝
接下來我們回到 sidebar.jsp,會看到以下程式碼: <jsp:useBean id="catalog" class="com.sun.j2ee.blueprints.catalog.client.CatalogHelper" scope="session" /> Petstore 使用這個 JavaBean 作為資料的容器,記錄寵物分類資料,它的位置 在 Petstore_home\src\components\catalog\src\com\sun\j2ee\blueprints\catalog\client\Cat alogHelper.java,程式碼很長,以下會擷取重點部份加以探討。接著在 sidebar.jsp 會見到: <c:set value="en_US" target="${catalog}" property="locale"/> <c:set value="5" target="${catalog}" property="count"/> <c:set value="0" target="${catalog}" property="start"/> Petstore 利用 JSTL 自訂標籤設定 catalog JavaBean 三個屬性 locale=”en_US”、count=”5”、 start=”0”。我們會利用 catalog JavaBean 讀取寵物 分類資料,組成 HTML 來展現,locale 是指定語系,count 指定取得資料筆數, start 指定起始取得資料列,以本例來說即從第一筆開始取 5 筆英語系資料。
this.duration = duration; //保存期限,單位以毫秒計 } public String getContent() { return content; } public boolean isExpired() { //比對當初網頁存入時間與目前系統時間之差是否大於保存期限 long currentTime = System.currentTimeMillis(); return ((currentTime - timestamp) > duration); } }
//從指定範圍取出網頁內容,本例範圍是”context” if ("context".equals(scope)) { entry = (Entry) pageContext.getServletContext().getAttribute(key); } else if ("session".equals(scope)) { entry = (Entry) pageContext.getSession().getAttribute(key); } else if ("request".equals(scope)) { entry = (Entry) pageContext.getRequest().getAttribute(key); } else if ("page".equals(scope)) { entry = (Entry) pageContext.getAttribute(key); } //判斷網頁內容是否過期 if (entry != null && entry.isExpired()) { entry = null; } //若過期則繼續執行標籤裡面內容,否則直接略過 return (entry == null) ? EVAL_BODY_BUFFERED : SKIP_BODY; } public int doEndTag() throws JspTagException { //若過期則將網頁內容存入指定範圍 if (entry == null) { BodyContent bc = getBodyContent(); if (bc != null) { String content = bc.getString(); entry = new Entry(content, duration); //本例範圍是”context” if ("context".equals(scope)) { pageContext.getServletContext().setAttribute(key, entry); } else if ("session".equals(scope)) { pageContext.getSession().setAttribute(key, entry); } else if ("request".equals(scope)) { pageContext.getRequest().setAttribute(key, entry);
寵物目錄
現在讓我們來探索 Petstore 是如何處理 Model(資料模型)部份,以首頁的左 邊的寵物目錄為例 , 它的主要功用在於提供使用者 Petstore 所販賣的寵物種類(圖 一),若使用者點選其中一類,畫面則會切換列出該種類之所有寵物(圖二):
Βιβλιοθήκη Baidu
圖一
圖二
構成這段功能的程式碼在 Petstore_home\src\apps\petstore\src\docroot\sidebar.jsp(Petstore_home 即我們安裝 Petstore 之目錄)。 sidebar.jsp <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib prefix="c" uri="/WEB-INF/c.tld" %> <%@ taglib uri="/WEB-INF/waftags.tld" prefix="waf" %> <waf:cache name="sidebar_en_US" scope="context" duration="300000"> <jsp:useBean id="catalog" class="com.sun.j2ee.blueprints.catalog.client.CatalogHelper" scope="session"/> <c:set value="en_US" target="${catalog}" property="locale"/> <c:set value="5" target="${catalog}" property="count"/> <c:set value="0" target="${catalog}" property="start"/> <table border="0" width="100%" cellpadding="1" cellspacing="0"> <tr> <td bgcolor="#336666" class="petstore_title" align="center"> <font color="#FFFFFF">Pets</font> </td> </tr> <tr> <td bgcolor="#336666"> <table border="0" width="100%" cellpadding="5" cellspacing="1"> <tr> <td bgcolor="#FFFFFF" class="petstore"> <c:forEach var="item" items="${catalog.categories.list}" > <a href="category.screen?category_id=<c:out value="${item.id}" />"> <c:out value="${item.name}" /> </a> <br> </c:forEach> </td>
</tr> </table> </td> </tr> </table> </waf:cache>
快取自訂標籤
首先看到它使用兩組自訂標籤(Custom Tag): <%@ taglib prefix="c" uri="/WEB-INF/c.tld" %> <%@ taglib uri="/WEB-INF/waftags.tld" prefix="waf" %> 第一組是 2002 年 6 月 Release 的 JSTL 1.0(JSP Standard Tag Library),它是 由 JCP 通過標準的自訂標籤,已包含在 JWSDP1.0 裡面,想要多了解它,可至 http://java.sun.com/products/jsp/jstl/ http://jakarta.apache.org/taglibs/index.html c.tld 及相關 Jar 檔的位置在 Petstore_home\src\lib\jstl。 第二組是 Petstore 自己定義的自訂標籤,waftags.tld 的位置在 Petstore_home\src\waf\src\docroot\WEB-INF。 接下來我們看到: <waf:cache name="sidebar_en_US" scope="context" duration="300000"> 它的功用是做網頁快取用,屬性 name 指定名稱;scope 指定範圍,”context”為整 個 web server、其他值尚有”session”、”request”、”page”;duration 是指定保留時 間,單位為毫秒(millisecond),使用時它會先比對當初網頁存入時間與系統時間, 若未超過則直接從指定範圍中取出網頁內容回應給使用者,否則繼續執行標籤裡 面內容,最後再將新內容存入指定範圍,程式碼在: Petstore_home\src\waf\src\view\taglibs\com\sun\j2ee\blueprints\taglibs\smart\CacheT ag.java 程式碼節錄如下: public int doStartTag() throws JspTagException { HttpServletRequest req = ((HttpServletRequest) pageContext.getRequest()); key = req.getRequestURL().toString() + '#' + name + '?' + req.getQueryString();