📄 新建 文本文档.txt
字号:
<jsp:getProperty name="receipt_bean" property="address"/></B></TD>
</TR>
<TR>
<TD WIDTH=100%> <B>电话:
<jsp:getProperty name="receipt_bean" property="phone"/></B></TD>
</TR>
</TABLE>
<!--
显示出共花去多少钱
-->
<%
BasketBean basket = (BasketBean)session.getAttribute(BasketBean.BASKET);
%>
<B>
总共价格人民币<%= basket.getStringifiedValue(basket.getTotal()) %>元 </B>
<%
basket.clear();
%>
<BR>
<BR>
</CENTER>
<BR><BR>
<%@ include file="footer.html" %>
</body>
</html>
代码六:Error.jsp
<HTML>
<HEAD>
<TITLE> 错误处理页面 </TITLE>
</HEAD>
<%@ page isErrorPage="true" %>
<BODY BGCOLOR=Black TEXT="#FFFFFF" LINK="#FFFFFF" VLINK="#FFFFFF">
<H1> 发生了一个错误... </H1>
<BR><BR><BR>
是: <BR>
<%= exception.toString() %> <BR>
</BODY>
</HTML>
现实中的应用程序模型
前面我们介绍的这个程序,只是一个简单的应用程序,仅供大家参考。然而,一个真实的应用程序其实和我们介绍的这个简单应用程序一样遵循着 MVC模式 ;让我们来看一看如何修改这个程序的某方面,来创造出一个更有现实意义的电子商务应用程序。我们的电子商店应用程序通过使用 BasketBean 类来实现了它的模型(Model),这存在着一些问题:它没能定义一个标准的接口,这样的缺陷限制了它的可维护性,可扩展性和作为一个应用程序的可伸缩性。
应用程序应该为访问应用程序模型定义一个标准的接口,接口实际上是建立一个约定,允许不同的实现应当按照要求被“插入(plugged-in)”,“可插入”的实现形式可以用桥模式来说明,桥模式的目的就是从功能的任何特定实现形式中分离出抽象的功能。例如,我们的存货清单数据最初是作为静态的信息被内嵌到Java 代码中的(见附录一InventoryBean.java),为了获得程序的灵活性,我们可以把数据从代码中提取出来,并在文件系统上存储它;而随着数据体积的不断膨胀,一个最直接的想法就是把数据转移到一个关系型数据库( RDBMS )中存储,如果我们的 BasketBean 实现一个标准的接口,那么我们就能重新实现这个接口来使用一个文件系统或一个关系型数据库,而不用重写 CustomerServlet类。因此,实际的应用程序要求从代码中分离数据,数据是经常变化的,但是代码应该尽可能少的变化,为能够把我们的应用程序移植到一个商务平台上,最小的要求就是把它分割成的数据存取层和数据管理层。两层结构允许在不影响代码的情况下增加数据。
有时候,数据的可伸缩性和数据交易的要求迫使我们涉及数据管理体系的第三级结构,CORBA 或企业版JavaBean(EJB)提供的数据管理服务接口现在已经被普便使用了,如果我们的BasketBean实现了一个标准的接口,那么我们就能把它作为一种分布式的服务来重新实现它。
宽松组件连接
JSP应用程序能遵从 MVC 模式的原因之一就是这个模式支持清楚地定义model,view和controller组件所扮演的角色,我们应该保持这些部件之间尽可能的宽松的联合。
然而,我们并没有使 CustomerServlet类宽松联合,请看下面的语句
file://取得当前的工作流程的状态。
RequestDispatcher rd = null;
String state = request.getParameter( BasketBean.STATE);
if (state == null || state.equals(BasketBean.UPDATE))
{
// 从商品目录中选择
rd = getServletConfig().getServletContext().getRequestDispatcher( "/jsp/Inventory.jsp");
}
控制器(controller)和表现形式(view)组件之间的紧密连接,使程序中如果改变一个组件就会改变相应其他的组件。在我们的例子中,如果我们想把附加的JSP页面添加到购物车工作流程中,我们也必须把附加的条件添加到 CustomerServlet中,这样怎能谈得上高可维护性和高伸缩性呢?如果我们能去掉CustomerServlet类和它的JSP页面之间的紧密连接,我们的应用程序就会有更多的可维护性和可伸缩性。要使这种紧密连接减小到最少程度的一个方法就是为每一个JSP页面都创造一个助手Bean,我们在 CustomerServlet 中安装这些助手Bean来管理所有的相关联的 JSP 页到来的HTML请求。
象这样封装每一个对象中的请求的模式是一种命令模式(command pattern)。
就象桥模式(bridge pattern)一样,实现一个命令模式的关键是声明每个请求处理器必须实现的通用的接口。在我们的例子中,这个接口的最简单的形式可能是一个单独的方法让我们传递请求参数和BasketBean对象?例如redirect()。因为接口的每一种具体的实现形式支持这个方法, CustomerServlet 就能在任何给定的处理机制上,在不知道实现形式的任何特定信息的情况下调用接口,我们可以为每一个JSP页设定助手Bean,并且根据需要使它复杂化,例如,它能够验证request发来的数据参数,不管是简单的判断输入的是否为空值还是更复杂的任务象验证信用卡信息等等。
一个JSP页面只有一个输入,但是它却有多个输出,这取决于提交按钮的数量,每个输出都能与一个不同的JSP页相联系。例如,Inventory.jsp 有两个输出,一个指向Purchase.jsp,另一个指回自己,我们能使用一个隐藏标签把每个助手Bean和输出联系起来。在 Inventory.jsp 中,我们可以使用
<TD ALIGN=left>
<INPUT TYPE=hidden NAME=<%= BasketBean.UPDATE %> VALUE="shoppingcart.UpdateHandler">
<INPUT TYPE=submit NAME=<%= BasketBean.PAGE %> VALUE=<%= BasketBean.UPDATE %>>
</TD>
代替下面的行:
<TD ALIGN=left>
<INPUT TYPE=submit NAME=<%= BasketBean.PAGE %> VALUE=<%= BasketBean.UPDATE %>>
</TD>
JavaBean“shoppingcart.UpdateHandler”将被我们的CustomerServlet类实例化,它包括一个 CustomerServlet 将调用的重定向方法。UpdateHandler 会知道怎么验证参数,更新模型,并且把请求提交给相应的JSP页,因此这是一条完善CustomerServlet的编程的非常好的途径。
小结
这样一来,JSP就能极大的扩展了 servlet 技术,由于支持 Java 脚本,JSP和Servlet就使网页设计师能够随心所欲的开发出高品质的动态网页程序。但不管怎么说,JSP也是不会代替 servlets的,因为servlets,JSP和JavaBeans在网络体系结构中起着互相补足的作用。通过遵从MVC模式, JSP应用程序能够独立地扩大或提高用于后台控制的servlet,JSP页面和现实的应用程序模型。应用程序模型能被扩展到一个两层或三层的方案,并且增加助手Bean,这都能管理JSP工作流程和支持应用程序组件之间的宽松联接。
附录一、 InventoryBean.java类(下面我将不会对代码进行过多的解释)
package shoppingcart;
public class InventoryBean {
/*
商品名称
*/
private static final String[] names =
{ "牙膏", "肥皂", "毛巾",
"口香糖", "牙刷", "练习本",
"钢笔"};
/*
商品序列号。
*/
private static final int[] skus =
{ 1, 2, 3, 4, 5, 6, 7 };
/*
商品每件的价格。
*/
private static final double[] prices =
{ 2.50, 3.90, 5.25, 1.00,
3.50, 0.40, 11.80};
private Product[] catalogue_ = null;
private static InventoryBean inventory_ = new InventoryBean();
private InventoryBean() {
catalogue_ = new Product[skus.length];
for (int i = 0; i < skus.length; i++) {
catalogue_[i] = createProduct(skus[i]);
}
}
public static Product[] getCatalogue() {
return inventory_.catalogue_;
}
private Product createProduct(int sku) {
return new Product(sku, names[sku-1], prices[sku-1]);
}
}
附录二、Product类
package shoppingcart;
public class Product implements Cloneable {
private int sku_ = 0;
private String name_ = null;
private double price_ = 0;
private int Pieces_ = 0;
public String toString() {
return "商品序列号: " + sku_ + ", 商品名: " + name_ +
", 单价: " + price_ + ", 件数: " + pieces_;
}
public Product(int sku, String name, double price) {
sku_ = sku;
name_ = name;
price_ = price;
}
public int getSKU() {
return sku_;
}
public String getName() {
return name_;
}
public double getPrice() {
return price_;
}
public double getPieces() {
return pounds_;
}
public void setPieces(int pieces) {
pieces_ = pieces;
}
public Object clone() {
Object dup = null;
try {
up = super.clone();
}
catch(CloneNotSupportedException ignore) { }
return dup;
}
}
附录三、ReceiptBean类
package shoppingcart;
import javax.servlet.*;
import javax.servlet.http.*;
public class ReceiptBean {
private String name_ = null;
private String email_ = null;
private String address_ = null;
private String phone_ = null;
public ReceiptBean() {
}
public void setName(String name) {
name_ = name;
}
public String getName() {
return name_;
}
public void setEmail(String email) {
email_ = email;
}
public String getEmail() {
return email_;
}
public void setAddress(String address) {
address_ = address;
}
public String getAddress() {
return address_;
}
public void setPhone(String phone) {
phone_ = phone;
}
public String getPhone() {
return phone_;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -