进入旧版 | 服务项目 | 成功案例 | 联系方式 | 过客留言 | 友情链接
   
设为首页
加入收藏
联系我们
网站首页 | 新闻资讯 | 操作系统 | 办公软件 | 网络软件 | 工具软件 | 媒体动画 | 网页制作 | 网站开发 | 程序开发 | 平面设计
Photoshop视频教程 | Word入门 | Flash入门 | JScript | VBScript | ASP | PHP | ADO | 网页特效 | 3DS MAX6.0命令 | 系统进程
您当前的位置:GOODSGY电脑学习网 -> 网站开发 -> JSP -> 文章内容  
使用JavaBean高效处理JSP


  摘要:JavaServer Pages Model II的一个基本思想就是将表现(HTML)和处理逻辑分开。这篇文章介绍的是一个高效、可重用的设计方法,将动态的内容、处理和验证由JavaServer Page中分离出来,放到一个相应的JavaBean中。它使用Template Method的设计方法,可提高代码在整个Web应用中的重用性。此外,它还介绍了在一个HTTP Session中bean间如何通信的简单技巧。

  JavaServer Pages(JSP)技术提供了许多的特性,可让你简易和快速地开发Web应用。不过,如果你无计划和结构地使用这些技术,你的JSP代码将会是各种HTML标记、JSP标记和Java代码的混合,很难于看懂、调试和维护。

  这里的目标是将全部的JSP处理代码封装到JavaBean中。这种方法的好处是HTML编程者和美工可以做表现的开发(使用HTML编辑器),而Java编程者可以集中开发编程逻辑。此外,这种方法可便于你为同一个Web应用提供不同的外观。

  我将介绍的架构使用Template Method方法,可集中实现整个应用的共有设计部分和实现每个JSP的共有处理。就这个例子,共有的处理包括有页面状态管理、共有的页面处理、共有的错误处理,以及在页面间共享信息的技术。所有这些仅是定义一次,你可在页面设计时再处理特定的细节。

  我将以一个简单的"投票"应用为例,介绍如何使用这个架构。你应有基本的JSP和Java知识,并且最好懂得一些UML知识。

  总的静态结构

  这个部分将介绍该架构核心部分的概观,以及投票应用的例子。图一显示了该架构的一个UML框图:



**************图一*******************
(UML类框图)

  该架构的中心部分由两个共有的JSP包含文件和两个类组成,下面将会谈到。它们的作用是完成共有的处理。

   includeheader.JSP:这个JSP文件必须被静态包含在每个JSP文件的开头。

   includefooter.JSP:这个JSP文件必须被静态包含在每个JSP文件的末尾。

  AbstractJSPBean:这是一个抽象类,你应该将它作为所有JSP JavaBean类的一个超类使用。它是该架构的核心类。

   SharedSessionBean:在一个HTTP session中,为所有的JSP JavaBean对象提供关联。

  JSP网页只是用作表现的。每个JSP页面都应该使用一个相应的JavaBean来处理特定页面的逻辑。每个JSP页面都应该静态包含includeheader.JSP和includefooter.JSP。每个JavaBean都必须扩展AbstractJSPBean,该抽象类包含有模板方法,可完成共有的处理。

  这个投票的应用包含有以下的JSP和相应的JavaBean:

   login.JSP, LoginJSPBean:投票者认证和登录

   vote.JSP, VoteJSPBean: 执行投票

   confirmation.JSP, ConfirmationJSPBean: 显示确认和投票的结果

  我将不会详细讨论数据库和商业逻辑的部分((Voter, Candidate和VoteDB),不过它们对于这个例子是必需的。

  以上我们已经对整体有了一个概观,接着我们将讨论例子中的每个JSP页面。


  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


  form处理、动态内容和bean通信

  列表4展示了一个具体的JSP JavaBean--LoginJSPBean,用来实现特定的页面处理

  列表4。LoginJSPBean


package lbm.examples;

import lbm.JSPutil.*;
import java.util.*;

public class LoginJSPBean extends AbstractJSPBean {

public static final String PAGE_CODE = "login";

private String _voterId;
private String _password;
private Voter _voter = null;

public LoginJSPBean() {
}

public void setVoterId (String newVoterId) {
_voterId = newVoterId;
}

public String getVoterId() {
if (_voterId == null) return "";
else return _voterId;
}

public void setPassword (String newPassword) {
_password = newPassword;
}

public String getPassword() {
if (_password == null) return "";
else return _password;
}

public Voter getVoter () {
return _voter;
}

protected void beanProcess () throws java.io.IOException {
if (_voterId == null || _voterId.equals("")) {
addErrorMsg("Voter must be entered");
}

if (_password == null || _password.equals("")) {
addErrorMsg("Password must be entered");
}

if (getState() != ERR) {
file://If all the fields are entered, try to login the voter
Voter voter = VoteDB.login(_voterId, _password);
if (voter == null) {
addErrorMsg("Unable to authenticate the Voter. Please try again.");
}
else {
_voter = voter;

if (_voter.getVotedForCandidate() != null) {
// if the voter has already voted, send the voter to the last page
redirect("confirmation.JSP");
}
else {
// go to the Vote page
redirect("vote.JSP");
}
}
}
}

protected void beanFirstPassProcess() throws java.io.IOException {
}

protected void beanFooterProcess() throws java.io.IOException {
}

protected String getJSPCode() {
return PAGE_CODE;
}
}


  观察LoginJSPBean类中的set和get方法。就象上面提及的,它们用作动态的匹配,并且用来在form字段(request参数)和bean属性间传送值。

  列表4中的beanProcess()方法,展示了form处理的一些基本点。这个方法发生在页面输出前,在第二和全部后来的页面调用期间执行。这意味着它将仅在用户按下登录按钮并且提交form后执行。

  你首先要验证voteId和password的输入,产生的错误将通过addErrorMsg方法记录下来。这个方法设置AbstractJSPBean类的errorMsg属性。该属性可被JSP用来显示用户的错误:

   <JSP:getProperty name="_loginJSPBean" property="errorMsg"/>

  如果数据的输入成功通过,beanProcess()方法将会调用数据库来验证用户。最后,它通过调用AbstractJSPBean类中实现的redirect()方法,将请求重定向到相应的页面。

  以下我们将讨论VoteJSPBean类中的一些方法。它们将可以解释该架构的一些其它方面,例如JSP JavaBean之间的通信和应用的流程控制。

  列表5。VoteJSPBean类中的beanFirstPassProcess()


protected void beanFirstPassProcess() throws java.io.IOException {
// get the Voter from Login page
_voter = null;

LoginJSPBean loginJSPBean =
(LoginJSPBean) getSharedSessionBean().getJSPBean(LoginJSPBean.PAGE_CODE);

if (loginJSPBean != null) {
_voter = loginJSPBean.getVoter();
}

if (_voter == null) {
// voter is not logged in yet. Send it to Login page
setState(NEW);
redirect("login.JSP");
}
}


以上的方法使用了AbstractJSPBean类中_sharedSessionBean对象。SharedSessionBean类通过使用一个简单的方法,让所有的JSP JavaBean对象在一个HTTP session中进行通信。它保存有一个session内的全部JSP JavaBean中的一个Map。Map是Java Collections框架的一个接口,它是Java 1.2推出的。对熟悉Java 1.1的人来说,它与Hashtable非常类似。一个JSP JavaBean的主键是它的PAGE_CODE,它作为一个常数存储在每个JSP JavaBean类中。

  在这个例子中,beanFirstPassProcess()方法首先定位到LoginJSPBean对象。接着,它由LoginJSPBean对象中得到Voter对象,并且存储一个到它的引用,以便以后使用。如果Voter为null,这意味着用户没有首先登录就进入Voter页面,因此它重定向到登录页面。这是一个应用流程控制的简单例子。你可以设计更复杂的方法,例如使用一个智能的调度程序,不过这些讨论已经超出了本文的范围。

  列表6。VoteJSPBean类的getCandidateList()方法


public String getCandidateList () {
StringBuffer candidateList = new StringBuffer();
Candidate candidate;

Iterator candidates = VoteDB.getCandidates();
while (candidates.hasNext()) {
candidate = (Candidate) candidates.next();

candidateList.append("<input type=radio name=\"candidateName\" value=\"");
candidateList.append(candidate.getName());
candidateList.append("\"> ");
candidateList.append(candidate.getName());
candidateList.append("<br>\n");
}

return candidateList.toString();
}


  以上的getCandidateList()方法被vote.JSP调用,通过以下的方法:

   <JSP:getProperty name="_voteJSPBean" property="candidateList"/>

  根据由数据库得到的内容不同,该方法提供不同的动态HTML内容输出。它需要开发JavaBean的Java编程者懂得一些HTML知识。

  你也可以使用一个利用HTML的独立库来格式化HTML,它可以接受一个预定义的输入。例如Iterator,然后以预定义的格式产生HTML输出。另一个方法是使用标签库。


  最后的要点:框架

  通过将表现和逻辑分离开来,该架构可让你独立地修改表现(JSP)和逻辑(bean)。这意味着你可以修改bean中的逻辑而无需改动JSP,只要你保持bean的属性不变就行了。相反也是成立的,你可以将JSP代码交给HTML开发者和美工来改变站点的外观,而不会影响其中的Java代码。

  你可以稍微修改该框架的核心元素来满足你应用的特别需要。你可以加入新的或者修改现有的方法,或者修改模板的方法。重要的一点是,在你的整个应用中,全部的JSP和JSP JavaBean都应该使用这个架构。

  在刚开始时,这个架构看来比较复杂,特别是对于一个只有三页的例子应用来说。不过,如果你开始写你的应用,你将会发现当应用变复杂时,代码量的增长却没有预期的大。

  这个架构并没有谈到Web应用中通常用到的多层设计。它主要集中在JSP的表现层。要建立真正的三层或者多层的系统,JSP JavaBeamn将需要调用Enterprise JavaBean或者一些其它的商业逻辑实现。

  例子还介绍了让应用跟踪HTTP session的架构。不过,如果你不想依赖session的话,该架构仍然可以工作得很好。应用的页面和流程应该是分别设计的。你可能将不需要SharedSessionBean。你的页面只是用作表现,而独立的页面将仅用作处理和验证,而不会有任何的HTML输出。为此,你将主要使用beanFirstPassProcess() 方法。

  最后的要点:例子

  我使用Tomcat3.1来测试这个例子,Tomcat3.1符合JSP1.1和Servlet2.2规范。这篇文章将不会讨论如何在Tomcat中配置JSP应用的详细情况。

  在测试该例子时,你可以在VoteDB类的源代码中得到Voter ID,以便可以进行登录测试(密码和ID是一样的)。

  你必须在浏览器中允许cookies,否则不能成功运行例子。如果你需要在禁止cookies时仍然可以运行这个应用,你必须重新写URL(使用the javax.servlet.http.HttpServletResponse类的encodeURL()方法)。你需要重写全部应用中的URL,包括你的JSP中的链接,form标记中的action,以及在JSP JavaBean中用来重定向URL的HTTP请求。

  结论

  这篇文章介绍的架构为JSP的应用设计提供了一个全面的解决办法。它改进了代码重用,确定了应用的体系,并且便于扩展。一个最大的好处是将表现和逻辑分开,你可以独立改变它们,而不会影响另一方。

*************源程序下载**************




【责任编辑:方舟 频道主编:赵家雄

 

在百度中搜索:使用JavaBean高效处理JSP
在Google中搜索:使用JavaBean高效处理JSP
在Yahoo中搜索:使用JavaBean高效处理JSP

收藏到网摘:新浪VIVI 365key 我摘 POCO网摘 博采中心 YouNote 和讯网摘 天天收藏
[] [返回上一页] [打 印] [收 藏]
下一篇文章:PHP自动更新新闻DIY

 相关文章    最新文章
· [组图] 简单使用PS历史画笔快速美化照片
· [图文] WPS演示中应用荧光笔的使用技巧
· WinServer 2008下调教IE使用有巧招
· 消除使用QQ后带来的安全隐患
· [图文] 网页标准制作:使用ul多行多列布局..
· 高效使用Linux的七个习惯
· 普通用户Excel使用VBA的几个误区
· [图文] Excel使用技巧:分列功能的妙用
· [图文] Excel技巧:使用中国式排名效果
· 选择使用新版Excel 2007的10条理由
 
· 提升JSP页面响应速度的七大秘籍绝招
· 开发一个调试JSP的Eclipse插件
· JSP报表打印的一种简单解决方案
· JSP/Servlet的重定向技术综述
· java的md5加密类(zt)
· 一个用来访问http服务器的东西。功能类似..
· 菜鸟调试手记一(sql server 中文问题)
· Java性能优化技巧集锦(2)
· 用java压缩文件示例(没有中文问题)
· 使用XML/HTC/DHTML模拟标准Windows菜单

∷相关文章评论∷    (评论内容只代表网友观点,与本站立场无关!) [更多评论…]
站内搜索

精彩图文
  网站导航  
操作系统 办公软件 网络软件
Vista Windows2003 WindowsXP Windows2000/NT Windows9X/ME Linux 其他 Word Excel Powerpoint Outlook 金山系列 其他 网页浏览 上传下载 联络聊天 邮件工具 服务器软件 网络辅助
工具软件 媒体动画 网页制作
系统工具 媒体工具 压缩工具 图文处理 文件管理 其他 3DMAX Authorware Director Maya 视频处理 其他 Flash Dreamweaver FireWorks FrontPage LiveMotion Golive HTML/CSS 其它
网站开发 平面设计 程序设计
ASP JSP PHP CGI JavaScript VBScript XML/SOAP Web服务器 Photoshop PhotoImpact CorelDraw Illustrator Freehand 设计欣赏 其他 VB VC .NET C/C++ DELPHI JAVA

冀ICP备05019428号
Copyright © 2004-2008 电脑学习网 Inc.All rights reserved.
TEL:13832340607
QQ:39873155
E_Mail:goodsgy(#)hotmail.com   (把(#)替换成@)
MSN:goodsgy(#)hotmail.com   (把(#)替换成@)