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
