?? 使用javabean高效處理jsp(2).txt
字號:
作者:Eazily
email: Eazily@yeah.net
日期:6/12/2001 2:49:38 PM
JSP例子
每個頁面都必須使用指定的結構,以符合整個架構。
列表1。login.jsp
<%@ page import = "lbm.jsputil.*" %>
<jsp:useBean id="_loginJSPBean" class="lbm.examples.LoginJSPBean"
scope="session"/>
<jsp:setProperty name="_loginJSPBean" property="*"/>
<% AbstractJSPBean _abstractJSPBean = _loginJSPBean; %>
<%@ include file="includeheader.jsp" %>
<html>
<head><title>Vote Login</title></head>
<body bgcolor="white">
<font size=4>
Please enter your Voter ID and Password
</font>
<font size="3" color="Red">
<jsp:getProperty name="_loginJSPBean" property="errorMsg"/>
</font>
<font size=3>
<form method=post>
Voter ID <input type=text name=voterId value=<jsp:getProperty
name="_loginJSPBean" property="voterId"/>>
Password <input type=password name=password value=<jsp:getProperty
name="_loginJSPBean" property="password"/>>
<input type=submit value="Login">
</form>
</font>
</body>
</html>
<%@ include file="includefooter.jsp" %>
該JSP頁面的架構如下:由幾個JSP語句開始。接著的HTML代碼將沒有多少JSP指令、語句和腳本等。除了幾個必要的指令,它們負責由bean中得到動態的內容。最后,頁面使用了一個JSP include指令。
我們討論其中一些重要的JSP語句:
<jsp:useBean id="_loginJSPBean" class="lbm.examples.LoginJSPBean" scope="session"/>
<jsp:setProperty name="_loginJSPBean" property="*"/>
以上的代碼在JSP和相應的bean間建立了一個連接。第二個語句顯式傳送全部的form字段(存儲為HTTP request參數)到bean中匹配的屬性中。代碼中使用了bean的setter方法。
<% AbstractJSPBean _abstractJSPBean = _loginJSPBean; %>
<%@ include file="includeheader.jsp" %>
第一個語句讓includeheader.jsp可執行共有的處理。第二個語句將includeheader.jsp靜態包含進來。要注意到loginJSPBean和_abstractJSPBean現在指向同樣的對象,只是帶有不同的接口。
列表2:includeheader.jsp
<%-- Set the SharedSessionBean --%>
<jsp:useBean id="_sharedSessionBean" class="lbm.jsputil.SharedSessionBean" scope="session"/>
<% _abstractJSPBean.setSharedSessionBean(_sharedSessionBean); %>
<%-- Set implicit Servlet objects --%>
<% _abstractJSPBean.setRequest(request); %>
<% _abstractJSPBean.setResponse(response); %>
<% _abstractJSPBean.setServlet(this); %>
<%-- Perform the processing associated with the JSP --%>
<% _abstractJSPBean.process(); %>
<%-- If getSkipPageOutput equals false, do not output the JSP page --%>
<% if (! _abstractJSPBean.getSkipPageOutput()) { %>
includeheader.jsp是模板的核心元素之一。所有的JSP頁面都使用這個共有的元素。
列表2的前兩個語句令不同頁面但在同一HTTP session中的JSP bean之間互相進行通信。基本上,每個JSP將有兩個與它關聯的JavaBean:一個指定的JSP JavaBean(例如,LoginJSPBean)和共有的SharedSessionBean。SharedSessionBean作為一個共有的元素使用,用來連接所有的頁面;我將在后面繼續討論它。
includeheader.jsp中接著的三個語句與固有的Servlet對象有關。
<% _abstractJSPBean.setRequest(request); %>
<% _abstractJSPBean.setResponse(response); %>
<% _abstractJSPBean.setServlet(this); %>
JSP規范提供訪問Java Servlet規范中的固有對象,例如頁面處理中常用到的request、response和servlet對象。因此它們被傳送到JSP bean。
<% _abstractJSPBean.process(); %>
最后,通過上面的語句來觸發相關JSP頁面的處理。你看到我們調用的是抽象JSP bean上的方法,而不是實類LoginJSPBean上的。為什么?我將在以下的部分解釋。
運用Template Method設計方法
AbstractJSPBean是Template Method設計的主體。每個實際的JSP JavaBean都必須繼承這個類。
列表 3. AbstractJSPBean.java
package lbm.jsputil;
import java.util.*;
import javax.servlet.http.*;
import javax.servlet.*;
public abstract class AbstractJSPBean {
/* constants used for _state */
public static final int NEW = 0;
public static final int FIRSTPASS = 1;
public static final int PROC = 2;
public static final int ERR = -1;
private int _state; // current state
private String _errorMsg; // current message that is being appended during validation
private boolean _skipPageOutput; // should the page output be skipped
private SharedSessionBean _sharedSessionBean; // used for associating the JSP Bean with the HTTP Session
/* standard Servlet objects that need to be setup for each JSP Bean */
protected HttpServletRequest _request;
protected HttpServletResponse _response;
protected Servlet _servlet;
public AbstractJSPBean () {
setState(NEW);
}
protected abstract void beanProcess() throws java.io.IOException;
protected abstract void beanFirstPassProcess() throws java.io.IOException;
protected abstract void beanFooterProcess() throws java.io.IOException;
protected abstract String getJSPCode();
public void process() throws java.io.IOException {
setSkipPageOutput(false); // by default do not skip page output. Specific bean process
// methods can override it.
if (getState() == NEW) {
setState(FIRSTPASS);
beanFirstPassProcess();
} else {
resetErrorMsg();
setState(PROC);
beanProcess();
}
// validation that all common fields have been properly set by the application
// this is actually checking that the code has been written properly
String l_err = "";
if (_sharedSessionBean == null) l_err = l_err + "; SharedSessionBean must be set";
if (_request == null) l_err = l_err + "; Request must be set";
if (_response == null) l_err = l_err + "; Response must be set";
if (_servlet == null) l_err = l_err + "; Servlet must be set";
if ( ! l_err.equals("")) throw new IllegalStateException(l_err);
}
public void footerProcess() throws java.io.IOException {
beanFooterProcess();
}
protected void addErrorMsg (String addErrorMsg) {
if (_errorMsg == null) _errorMsg = addErrorMsg;
else _errorMsg = _errorMsg + " <br>\n" + addErrorMsg;
setState(ERR);
}
protected void resetErrorMsg () {
_errorMsg = null;
}
public String getErrorMsg () {
if (_errorMsg == null) return "";
else return _errorMsg;
}
protected void setState (int newState) {
_state = newState;
}
public int getState () {
return _state;
}
public void setSharedSessionBean (SharedSessionBean newSharedSessionBean) {
if (_sharedSessionBean == null) {
_sharedSessionBean = newSharedSessionBean;
_sharedSessionBean.putJSPBean(getJSPCode(), this);
} else {
if (_sharedSessionBean != newSharedSessionBean) {
throw new IllegalStateException("SharedSessionBean is not set properly. SharedSessionBean must be the same for all PageBeans within the session");
}
}
}
public SharedSessionBean getSharedSessionBean () {
return _sharedSessionBean;
}
public void setSkipPageOutput (boolean newSipPageOutput) {
_skipPageOutput = newSipPageOutput;
}
public boolean getSkipPageOutput () {
return _skipPageOutput;
}
protected void redirect (String redirectURL) throws java.io.IOException {
// skip the page output since we are redirecting
setSkipPageOutput(true);
_response.sendRedirect(redirectURL);
}
public void setRequest (HttpServletRequest newRequest) {
_request = newRequest;
}
public void setResponse (HttpServletResponse newResponse) {
_response = newResponse;
}
public void setServlet (Servlet newServlet) {
_servlet = newServlet;
}
}
AbstractJSPBean包含有以下的抽象方法:beanFirstPassProcess(), beanProcess(), and beanFooterProcess()。這些方法被稱為primitive方法。你必須在實際的JSP JavaBean子類中實現它們。每個都在JSP處理的一個特定階段中執行。
beanFirstPassProcess()--在頁面被首次調用時進行的處理,它發生在頁面開始輸出之前。它適合用來初始化動態的內容和驗證對頁面的訪問。可參見VoteJSPBean中該方法的實現,該Bean中用它來驗證頁面的訪問,并且進行應用的流程控制。
beanProcess()--發生在第二和后來的頁面調用期間的處理,在頁面輸出開始之前。你可以用它來作HTML form驗證和數據庫更新。在LoginJSPBean類中,該方法被用作HTML form處理,在VoteJSPBean類中,用來保存信息到數據庫中。
beanFooterProcess()--在頁面輸出完成后進行的處理。你可以使用它來令session無效。在ConfirmationJSPBean類中,當投票完成后,通過實現該方法令session無效,并且顯示確認的頁面。
接著我們將看一下process()方法:
public void process() throws java.io.IOException {
setSkipPageOutput(false); // by default do not skip page output. Specific bean process
// methods can override it.
if (getState() == NEW) {
setState(FIRSTPASS);
beanFirstPassProcess();
} else {
resetErrorMsg();
setState(PROC);
beanProcess();
}
....
process()首先檢查JSP的狀態;然后,根據狀態,它調用相應的primitive方法。它還設置了JSP相應的狀態。
process()和footerProcess()方法被稱為template方法。它們由JSP中真正調用(在includeheader.jsp和includefooter.jsp中)。實體的bean不應該覆蓋它們。template方法包含有共有的框架算法。一個典型模板方法的框架算法執行一個共有的處理,并且調用primitive(抽象)方法(beanFirstPassProcess()、beanProcess()和beanFooterProcess()),這些方法的實現在每個實際的JSP JavaBean中都是不同的。框架算法也可以稱為AbstractJSPBean中實現的實體方法。以上的規則是Template Method設計方法的基本點。
這種方法的好處是:
1、通過在模板方法中分解出共有的處理,你可以做到代碼重用
2、你可以對整個應用進行共有的設計和處理
除了處理邏輯外,AbstractJSPBean還包含有以下具體的方法來幫助子類(實際的JSP JavaBean)來實現它們的處理任務,你不應該覆蓋這些實際的方法。
1、與用戶錯誤管理相關的方法(addErrorMsg(), resetErrorMsg(), and getErrorMsg())
2、與頁面狀態管理相關的方法(setState(), getState())
3、管理與SharedSessionBean關聯的方法
4、控制JSP頁面的HTML部分是否輸出的方法(setSkipPageOutput(), getSkipPageOutput())
5、重定向的方法
6、訪問Servlet對象的方法: request, response和servlet
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -