茫茫網海中的冷日 - 對這文章發表回應
茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1729150 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
F09_784.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

對這文章發表回應

發表限制: 非會員 可以發表

發表者: 冷日 發表時間: 2008/4/22 15:38:06

複製JSP

觀察一下基本的JSP,為了方便我們做移植`,有一些功能還是是需要的。

在下面的例子,我們設定了content type,產生一個JavaBean (一個Date物件),包含了一些JSP "片段(fragment)"檔,使用JSTL taglib中的 fmt 以呈現 ResourceBundle 中的文字。最後一行呼叫 getTime 此Date的方法(也可以很簡單地透過JSTL c:out 來取得同樣的值)


<%@ page contentType="text/html; charset=UTF-8" %>
<fmt:setBundle basename="com.lateralnz.messages" var="sysm" />
<jsp:useBean id="test" scope="session" class="java.util.Date" />
<html xmlns="http://www.w3.org/1999/xhtml">
<%@ include file="htmlhead.jsf" %>
<body>
<%@ include file="header.jsf" %>
<h1><fmt:message key="app.welcome_title" bundle="${sysm}" /></h1>
<p><fmt:message key="app.welcome_text" bundle="${sysm}" /></p>
<p><%= test.getTime() %></p>
</div>
</body>
</html>

Velocity提供了一些同樣功能的directive,但並非全部。 在標準的Velocity安裝中, Date ResourceBundle 會被放在Servlet Context之中,所以可以在樣板中直接呼叫。第二步,滿足需求(先暫時不管之前我所講的MVC的目標)。我寫了屬於自己的 #usebean 的directive(參照 UseBeanDirective.java 的程式碼)。它傳進name、使用的class name、還有它的scope。 UseBeanDirective 則會產生JavaBean且把它放在context之中。如果scope是"application",它會被放在static HashMap 供之後使用;如果scope是"session",則它會被放在使用者的session之中。

VMServlet 中,同樣需要一個method可以在template中如JSP中同樣的方法去設定content type。我目前的選擇是快取content type,以requesrtURI當作Key,並使用Velocity樣板的 getData 方法來找此頁中( $contentType )這個變數:


private final String determineContentType(
Node node) {
for (int i = 0;
i < node.jjtGetNumChildren();
i++) {
StringBuffer sb = new StringBuffer();
Node n = node.jjtGetChild(i);
if (n instanceof org.apache.velocity.
runtime.parser.node.ASTSetDirective) {
Token t =
findTokenWithPrefix(n.getFirstToken(),
"$");
if (t == null ||
!t.toString().equalsIgnoreCase(
"$contentType")) {
continue;
}
else {
t = findTokenWithPrefix(t, "\"");
String ct = StringUtils.remove(
t.toString(), "\"");
return ct;
}
}
}
return "text/html";
}
private final Token findTokenWithPrefix(
Token t,
String prefix) {
if (t == null) {
return null;
}
else if (t.toString().startsWith(prefix)) {
return t;
}
else {
return findTokenWithPrefix(t.next, prefix);
}
}

雖然很明顯地,這是竄改原始碼,但是也達到了目的。因此,我加了以下的程式碼到 processRequest:


String contentType;
if (contentTypes.containsKey(requestURI)) {
contentType =
(String)contentTypes.get(requestURI);
}
else {
contentType =
determineContentType((Node)tmp.getData());
contentTypes.put(requestURI, contentType);
}

最終的Velocity樣板如下面所示:


#set ( $contentType = "text/html" )
<html xmlns="http://www.w3.org/1999/xhtml">
#usebean ( test "java.util.Date" page )
#usebean ( sysm
"com.lateralnz.MyMessagesBundle" application )
#parse ( "htmlhead.vm" )
<body>
#include ( "header.vm" )
<h1>
$sysm.getString('app.welcome_title')
</h1>
<p>
$sysm.getString('app.welcome_text')
</p>
<p>$test.getTime()</p>
</body>
</html>

如您所見,跟原本的JSP頁面沒有太大的改變。而程式碼中 ResourceBundle 是透過一個JavaBean的方式讀進來,但在真正的系統下,我把它快取在 VMServlet 中,並且自動地當作隱含物件讀進來中。

還有一小塊我們還沒有提到。如果使用JSTL可能還會用到一些Jakarta taglibs。如果是這個情況的話,則還需要一些程式碼。幸好,透過產生新的directive去延伸Velocity是很容易的事情 (事實上我發現比寫taglib還簡單,除了API相對少以外)。到目前為止,我只需要產生一些額外的directive:一個是產生格式化的日期,一個是格式化的數字,還有一些簡單 的directive去終止繪製一個樣板(以貼在Velocity mailing list中的一個小技巧為基礎):


public class ExitDirective extends Directive {
private static final String EXIT = "exit";
private static final
StopRenderingException STOP_RENDER_EXCEPTION =
new StopRenderingException();
public boolean render(
InternalContextAdapter context,
Writer writer,
Node node)
throws IOException,
ResourceNotFoundException,
ParseErrorException,
MethodInvocationException {
throw STOP_RENDER_EXCEPTION;
}
public int getType() {
return DirectiveConstants.LINE;
}
public String getName() {
return EXIT;
}
}

VMServlet processRequest 方法中,會捕捉到 StopRenderingException ,並且有效地終止樣板繪製。在我們的系統中,我們用這個特別的directive在WAP header中去檔掉沒有登入的使用者:


#if ( !$session.getAttribute(USER_ID) )
<card id="message" title="Invalid Session">
<p>Sorry, but your session has
timed out.</p>
</card>
</wml>
#exit ( )
#end

總結

Velocity提供Web開發者一個強大的樣板機制—然而,也可能對想要從JSP和taglibs移植的人剛開始就帶來不算小的障礙。使用簡單的servlet,還有採用directive去延伸Velocity,大家可以效法這 些方來完成大部分JSP的功能。也因此讓移植的工作可以以小規模、低風險的方式一步一步地邁進。

相關鏈結

最後一點:如果您是*nix的開發者,絕對不要忘記 sed 這個好用的工具,它可以幫您做掉許多移植JSP時所需面對的苦工。我並不是sed的專家,但也只花了我一點時間就馬上轉換了90%的程式碼。

Jason R. Briggs is a technical architect and developer for a wireless technology company

原文出處:ONJava.com: Migrating to Velocity [Apr. 14, 2004]
內容圖示
url email imgsrc image code quote
樣本
bold italic underline linethrough   












 [詳情...]
validation picture

注意事項:
預覽不需輸入認證碼,僅真正發送文章時才會檢查驗證碼。
認證碼有效期10分鐘,若輸入資料超過10分鐘,請您備份內容後,重新整理本頁並貼回您的內容,再輸入驗證碼送出。

選項

Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|