Professional Documents
Culture Documents
上 书 店 。 本 章 介 绍 的 例 子 可 以 分 成 两 大 部 分 ,
第 一 部 分 是 普 通 程 序 , 用 于 客 户 在 网 上 选 购
图 书 , 第 二 部 分 是 管 理 程 序 , 用 于 在 服 务 器
端 处 理 客 户 的 定 单 。 客 户 端 程 序 由 以 下 几 个
部 分 构 成 :
default.jsp : 会 员 登 录 界 面 ( 首 页 ) ;
checklogon.jsp : 检 测 登 录 代 码 和 密 码 是 否 一 致 ,
根 据 由 JavaBean 返 回 的 结 果 显 示 不 同 的 信 息 。
BuyerBean : 会 员 的 合 法 性 检 验 所 用 的 Bean ;
booklist.jsp : 给 登 录 会 员 显 示 当 前 书 店 中 可 供 选
择 的 图 书 ;
addcart.jsp : 将 所 选 的 图 书 加 入 购 物 车 ;
shoppingcart.jsp : 查 看 购 物 车 的 内 容 ;
本 例 的 数 据 库 采 用 Access ( .MDB 数 据 库 ) , 对
数 据 库 的 访 问 采 用 便 于 理 解 的 JDBC-ODBC 方 式 ,
在 使 用 本 例 前 先 在 本 地 数 据 库 建 立 一 个 ODBC 数
据 源 : bookstore 。
设 置 步 骤 如 下 :
( 2 ) 启 动 “ 数 据 源 ( ODBC ) ” 配 置 程 序 ,
界 面 如 图 15-1 所 示 。
126
图 15-1 ODBC 数 据 源 管 理 界 面
( 3 ) 在 图 15-1 中 “ 系 统 DSN” 选 项 下 单 击 “ 添
加 ” 按 钮 , 来 添 加 一 个 系 统 的 数 据 源
( DSN ) , 则 出 现 如 图 15-2 所 示 数 据 源 驱 动 程 序
选 择 界 面 :
图 15-2 数据源驱动程序选择界面
击 “ 完 成 ” 加 载 Access 数 据 库 的 驱 动 , 则 出 现 如
图 15-3 所 示 数 据 库 ODBC 安 装 界 面 :
127
图 15-3 数 据 库 ODBC 安 装 界 面
( 5 ) 在 图 15-3 中 单 击 “ 选 择 ( S ) … ” 按 钮 ,
启 动 一 个 类 似 资 源 管 理 器 的 界 面 来 选 择 数 据
库 , 如 图 15-4 所 示 , 在 图 15-4 所 示 的 界 面 中 选 择
bookstore.mdb 。
图 15-4 数据库选择界面
15.1 会员登录
做 一 个 网 上 书 店 , 在 顾 客 开 始 购 书 之 前 ,
必 须 要 记 录 用 户 的 一 些 信 息 以 便 用 户 在 不 同
的 分 类 、 不 同 的 页 面 购 书 时 , 最 后 能 够 去 收
款 台 统 一 结 帐 , 而 且 网 上 书 店 同 时 有 许 多 人128
在 选 购 图 书 , 也 要 求 对 不 同 的 顾 客 进 行 区 分 ,
我 们 可 以 要 求 顾 客 在 购 书 之 前 进 行 注 册 成 为
会 员 , 以 后 只 用 会 员 代 码 和 密 码 即 可 登 录 。
为 了 便 于 说 明 现 在 的 电 子 商 务 网 站 , 由 JSP
做 页 面 表 现 , 由 Java Bean 做 应 用 逻 辑 的 结 构 , 在
本 例 中 将 会 员 登 录 程 序 分 成 两 大 部 分 : 一 、
Java Bean 用 于 对 数 据 库 的 操 作 , 验 证 用 户 名 和 密
码 是 否 正 确 ; 二 、 JSP 页 面 部 分 , 用 于 供 用 户
会 员 代 码 和 密 码 以 及 显 示 验 证 结 果 。
我 们 网 上 书 店 中 的 会 员 信 息 的 库 结 构 如 图
15-5 所 示 :
图 15-5 会员信息库
其 中 memberID 是 主 键 , 用 于 区 分 不 同 的 会 员 ,
新 会 员 注 册 时 只 能 使 用 没 有 被 使 用 的 用 户 代
码 。
在 验 证 时 我 们 只 要 使 用 验 证 用 户 的 memberID 和
其 pwd 是 否 一 致 即 可 判 断 该 用 户 是 否 合 法 , 如
果 合 法 则 其 登 录 次 数 加 1。
下 面 是 用 户 验 证 部 分 的 Java Bean 的 代 码
清 单 15-1 BuyerBean.Java
129
/* *BuyerBean.Java 1.10.2001
*Copyright © 2000, 2001 by cuug llp.
*getLogontimes()— 取 该 会 员 登 录 的 次 数
*getMenberName ( ) 获 得 该 会 员 的 真 实 姓 名 , 用
于 显 示 欢 迎 信 息 。
时 使 用 , 正 式 发 布 时 可 以 删 除 。
**/
package cuug;
import Java.sql.*;
public class BuyerBean {
try {
Class.forName(strDBDriver );
// 捕 获 异 常
catch(Java.lang.ClassNotFoundException e){
System.err.println(“BuyerBean():” + e.getMessage());
// 获 得 登 录 次 数 , 登 录 的 会 员 的 名 字 也 在 该
方 法 调 用 时 获 得
try{
conn = DriverManager.getConnection(strDBUrl);
‘” +
rs = stmt.executeQuery(strSql);
131
while (rs.next()){
// 登 录 的 次 数
logontimes = rs.getInt(“logonTimes”);
// 会 员 姓 名
memberName = rs.getString(“membername”);
rs.close();
// 如 果 是 合 法 会 员 则 将 其 登 录 次 数 加 1
if (logontimes != -1 ) {
stmt.executeUpdate(strSql);
stmt.close();
conn.close();
// 捕 获 异 常
catch(SQLException e){
132
System.err.println(“BuyerBean.getLogontimes():” + e.getMessage());
return logontimes ;
// 设 置 memberID 属 性 ;
this.memberID = ID;
// 设 置 pwd 属 性
this.pwd = password;
// 获 得 该 会 员 的 真 实 姓 名 , 必 须 在 取 该 会
员 登 录 的 次 数 之 后 才 能 被 赋 予 正 确 的 值
return memberName;
// 测 试 Bean 中 的 各 个 方 法 是 否 能 够 正 常 工 作
buyer.setPwd(“1234”);
System.out.println(buyer.getLogontimes());
System.out.println(buyer.getMemberName());
可 以 用 JAR ( JDK 中 带 的 打 包 工 具 ) 把 编 译 后 的
BuyerBean.class 打 包 成 JAR 文 件 在 服 务 器 的 环 境 变 量
classpath 中 给 予 指 定 , 或 者 在 服 务 器 classpath 环 境 变
量 指 定 的 目 录 下 建 一 个 cuug 文 件 夹 , 把
BuyerBean.class 放 到 cuug 目 录 下 。
会 员 登 录 要 由 两 个 部 分 来 完 成 , 第 一 个 页
面 用 于 会 员 输 入 其 ID 和 密 码 , 当 然 首 页 还 可
以 加 一 些 广 告 等 的 其 它 信 息 , 在 本 例 中 略 过 。
清 单 15-2 default.htm
<contentType=”text/html;charset=gb2312”>
<HTML>
<!—
Copyright © 1999 cuug,liu.
<HEAD>
<TITLE>CUUG ON LINE BOOK STORE – MEMBER LOGIN</TITLE>
</HEAD>
<BODY bgcolor=”white”>
<P> </P>
<P> </P>
<CENTER>
<FORM METHOD=POST ACTION=”checklogon.jsp”>
<BR>
<font size=5 color=”green”>
请 输 入 会 员 代 号 和 密 码 : <br>
<BR>
</font>
</FORM>
</CENTER>
</BODY>
</HTML>
在 本 例 中 提 供 了 一 个 文 本 框 供 用 户 输 入 会
员 代 号 和 登 录 密 码 , 其 运 行 结 果 如 图 15-6 所 示 ,
当 会 员 输 入 其 代 码 和 密 码 后 调 用 checklogon.jsp 来 验
证 该 网 络 用 户 是 否 是 合 法 会 员 。
135
图 15-6 会员登录页
在 checklogon.jsp 中 接 收 从 default.htm 中 由 用 户 所 填 的
会 员 代 码 和 密 码 , 把 它 传 给 BuyerBean , 由 BuyerBean
判 断 该 用 户 的 会 员 代 码 和 密 码 的 正 确 性 , 若
正 确 显 示 欢 迎 信 息 ; 若 不 正 确 , 则 提 供 一 个
重 新 登 录 的 链 接 。
Checklogon.jsp 的 源 代 码 如 下 :
清 单 15-3 checklogon.jsp
<%
buyer.setMemberID(memberID);
buyer.setPwd(pwd);
%>
<% int logonTimes = buyer.getLogontimes() ;
if (logonTimes > 0){
session.putValue("memberID",memberID);
%>
<%
}
else{
%>
密 码 不 一 致 </H2>
<%
}
%>
</BODY>
</HTML>
登 录 正 确 时 的 结 果 如 图 15-7 所 示 , 错 误 时 的
结 果 如 图 15-8 所 示 。
137
图 15-7 用 户 登 录 正 确 ( 会 员 abcd 的 真 实 姓 名 是 cuug001 )
图 15-8 用户登录错误
15.2 选书
会 员 登 录 之 后 , 合 法 的 用 户 将 可 以 看 到 本
书 店 中 可 供 选 择 的 图 书 , 并 且 将 他 感 兴 趣 的
书 放 入 “ 购 物 车 ” , 在 去 “ 收 银 台 ” 结 帐 之
前 , 该 用 户 可 以 放 弃 购 买 其 购 物 车 中 的 任 何
一 本 书 。 在 此 处 我 们 用 BookBean 来 获 取 图 书 的 信
息 , 在 Booklist.jsp 中 显 示 这 些 书 。
在 会 员 选 书 部 分 , 我 们 仍 用 Java Bean 来 操 作 数
据 库 , 用 jsp 来 做 页 面 表 现 。 138
15.2.1 选 书 Java Bean
图 书 信 息 的 表 结 构 如 图 15-9 所 示 , 为 了 便 于
说 明 , 在 本 例 中 price 也 设 置 成 了 String 型 , 在 实
际 应 用 中 应 该 设 置 成 货 币 或 浮 点 型 :
图 15-9 图书信息的表结构
其 中 , bookISBN 是 主 键 , 区 分 不 同 的 图 书 。 Java
Bean 要 根 据 不 同 的 图 书 的 bookISBN 来 获 得 其 相 应
的 书 名 、 作 者 、 出 版 社 、 价 格 、 简 介 等 信 息 。
同 时 Java Bean 还 要 有 列 出 书 店 中 所 有 图 书 的 信 息
的 功 能 。
清 单 15-4 BookBean..Java
/* *BuyerBean.Java 1.10.2001
*Copyright © 2000, 2001 by cuug ,llp.
* 本 Bean 中 的 各 个 方 法 的 功 能 介 绍 如 下 :
*setBookISBN(): 设 置 图 书 的 编 号 , 同 时 根 据 编 号
更 新 相 应 的 书 名 、 作 者 、 出 版 社 、 价 格 *
和 简 介
*getBookList()— 取 得 书 库 中 全 部 书 的 书 名 、 出 版
社 、 价 格 、 作 者 等 信 息 ;
*getBookISBN()— 取得当前图书的编号 ;
*getBookName()— 取 得 当 前 图 书 的 书 名 ;
*getBookAuthor()— 取 得 当 前 图 书 的 作 者 ;
139
*getPublisher()— 取 得 当 前 图 书 的 出 版 社 信 息 ;
*getPrice()— 取 得 当 前 图 书 的 价 格 ;
* getIntroduce ( ) 取 得 当 前 图 书 的 简 介 信 息 。
时 使 用 , 正 式 发 布 时 可 以 删 除 。
**/
package cuug;
import Java.sql.*;
public class BookBean {
public BookBean(){
140
// 加 载 驱 动
try {
Class.forName(strDBDriver );
catch(Java.lang.ClassNotFoundException e){
// 取 当 前 书 库 中 全 部 图 书 信 息
try{
// 建 立 与 数 据 库 的 连 接
conn = DriverManager.getConnection(strDBUrl);
bookInfo ";
rs = stmt.executeQuery(strSql);
// 捕 获 异 常
141
catch(SQLException e){
System.err.println("BookBean.getBookList():" + e.getMessage());
return rs ;
// 根 据 图 书 的 编 号 给 图 书 的 其 他 信 息 赋 值
bookName = null;
bookAuthor = null;
publisher = null;
introduce = null;
price = null;
try{
// 建 立 和 数 据 库 的 连 接
conn = DriverManager.getConnection(strDBUrl);
rs = stmt.executeQuery(strSql);
142
while (rs.next()){
bookName = rs.getString("bookName");
bookAuthor = rs.getString("bookAuthor");
publisher = rs.getString("publisher");
introduce = rs.getString("introduce");
price = rs.getString("price");
// 捕 获 异 常
catch(SQLException e){
System.err.println("BookBean.getBookList():" + e.getMessage());
// 给 图 书 的 编 号 赋 值 , 同 时 调 用 函 数 给 图 书
的 其 他 信 息 赋 值
this.bookISBN = ISBN;
getBookInfo(bookISBN);
// 取 图 书 编 号
143
public String getBookISBN (){
return bookISBN ;
// 取 书 名
return bookName ;
// 取 作 者 信 息
return bookAuthor;
// 取 出 版 社 信 息
return publisher;
// 取 图 书 简 介
return introduce ;
144
// 取 图 书 价 格
return price;
// 将 Bean 作 为 一 个 application 进 行 测 试 用
book.setBookISBN("7-5053-5316-4");
System.out.println(book.getBookName());
System.out.println(book.getBookAuthor());
System.out.println(book.getPublisher());
System.out.println(book.getIntroduce());
System.out.println(book.getPrice());
try{
while (tmpRS.next()){
System.out.println(tmpRS.getString("bookname"));
145
tmpRS.close();
// 捕 获 异 常
catch(Exception e){
System.err.println("main()" + e.getMessage());
15.2.2 选 书 JSP
会 员 正 确 登 录 之 后 , 即 可 进 入 书 店 进 行 选
书 , 我 们 已 经 在 checklogon.jsp 中 将 会 员 的 代 码
( memberID ) 放 入 系 统 的 session 中 , 为 了 保 证 用 户
只 能 从 主 页 面 登 录 进 入 书 店 , 我 们 在 给 会 员
显 示 可 供 选 择 的 图 书 之 前 , 先 检 查 session 中 是 否
有 memberID 的 合 法 值 , 如 果 没 有 则 提 示 用 户 先 去
登 录 。
清 单 15-5 booklist.jsp
{ window.open("addcart.jsp?isbn="+str,
"shoppingcart","width=300,height=200,resizable=1,scrollbars=2");
return;
}
//-->
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<%
if (session.getValue("memberID") == null||"".equals(session.getValue("memberID"))){
%>
<%
}
else{
%>
<table width="100%" border="1" cellspacing="0" bordercolor="#9999FF">
<tr>
<td> </td>
</tr>
147 <%
ResultSet rs = book.getBookList();
while(rs.next()){
%>
<tr>
<td><a href="bookinfo.jsp?isbn=
<%= ISBN%>"><%= rs.getString("bookName")%></A></td>
<td><%= rs.getString("bookAuthor")%></td>
<td><%= rs.getString("publisher")%></td>
<td><%= rs.getString("price")%></td>
<td><a href='Javascript:openwin("<%= ISBN %>")'> 加 入 购 物 车
</a></td>
</tr>
<%
}
%>
</table>
<table align="center" border="0">
<tbody>
<tr>
<td><a href="shoppingcart.jsp"><font color="#0000FF"> 查 看 购 物 车
</font></a></td>
<td></td>
</tr>
</tbody>
</table>
<p> </p>
<%
}
%>
</BODY>
</HTML>
已 经 登 录 过 的 会 员 和 没 有 登 录 过 的 会 员 进
入 该 页 面 是 的 结 构 分 别 如 图 15-10 和 图 15-11 所 示 :
正 确 登 录 的 会 员 的 会 员 代 码 在 浏 览 器 的 标 题
栏 显 示 为 : member:“ 会 员 代 码 ” 。
148
图 15-10 会 员 abcd 正 确 登 录
图 15-11 会 员 未 登 录 直 接 来 选 书
在 本 例 中 利 用 JavaScript 语 句 定 义 了 一 个 函 数 来
将 所 调 用 另 外 的 一 个 jsp 来 处 理 把 书 加 入 购 物
车 的 操 作 :
<SCRIPT language="JavaScript">
<!--
function openwin(str)
{ window.open("addcart.jsp?isbn="+str,
149 "shoppingcart","width=300,height=200,resizable=1,scrollbars=2");
return;
}
//-->
</SCRIPT>
该 函 数 用 于 打 开 addcart.jsp 并 切 将 图 书 编 号 作 为
参 数 传 给 addcart.jsp 。
addcart.jsp 利 用 Cookie 来 保 存 所 选 购 的 图 书 信 息 ,
Cookie 相 当 于 一 个 购 物 车 。 为 了 与 其 他 的 Cookie 变
量 区 分 , 每 个 写 入 Cookie 的 图 书 编 码 前 面 都 加 上
“ ISBN” 作 为 标 志 , 向 购 物 车 中 加 入 图 书 的 代 码
如 下 : ]
清 单 15-6 addcart.jsp
/*Cookie 信 息 处 理 */
/* 增 加 Cookie*/
if (request.getParameter("isbn")!=null)
cookie.setMaxAge(30*24*60*60);// 设 定 Cookie 有 效 期 限 30 日
response.addCookie(cookie);
}
%>
<html>
<head>
<script language="Javascript">
function Timer(){setTimeout("self.close()",10000)}
</script>
<META http-equiv="Content-Type" content="text/html; charset=gb2312">
150
<title> 购 物 车 — — CUUG 网 上 订 书 系 统 </title>
</head>
<BODY onload="Timer()">
<table width=100%>
<tr><td align=center> 图 书 已 经 成 功 放 入 购 物 车 !
</td></tr>
<tr><td align=center><A href="shoppingcart.jsp" target=resourcewindow>
<font class=font1 color=darkblue>
查 看 购 物 车 SHOPPING CART</font></A></u></font></td></tr>
提交定单 ORDER</font></a></u></font></td></tr>
<tr><td align=center>
LANGUAGE="Javascript" onclick="window.close()"
style="border: #006699 solid 1px;background:#ccCCcc"></td>
</tr>
<tr><td align=center>
( 此 窗 口 将 为 您 在 10 秒 内 自 动 关 闭 , 您 的
商 品 已 经 安 全 地 保 存 在 购 物 车 中 。 )
</td></tr>
</table>
</BODY>
</html>
在 addcart.jsp 中 利 用 JavaScript 定 义 了 一 个 函 数
Timer ( ) , 由 它 来 控 制 该 窗 口 的 显 示 时 间
( <BODY onload="Timer()"> ) 。 继 续 购 买 部 分 也 是 由
JavaScript 定 义 的 函 数 来 控 制 关 闭 本 窗 口 。 其 运 行
结 果 如 图 15-12 所 示 。
151
图 15-12 加 入 购 物 车
无 论 从 图 15-12 还 是 图 15-13 所 示 的 界 面 中 , 都
提 供 了 一 个 查 看 购 物 车 的 超 链 接 , 查 看 购 物
车 的 程 序 如 下 所 示 , 它 从 Cookie 中 取 出 图 书 的 编
号 , 并 将 它 传 给 BookBean , 由 BookBean 来 获 得 图 书
的 详 细 资 料 。 查 看 购 物 车 的 JSP 代 码 shoppingcart.jsp 代
码 如 下 :
清 单 15-7 shoppingcart.jsp
/* 禁 止 使 用 浏 览 器 Cache*/
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires",0);
%>
<HTML>
<HEAD>
<META http-equiv="Content-Style-Type" content="text/css">
<TITLE>
</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF"> 152
<H1 align="center">CUUG 网 上 书 店 购 物 车 </H1>
<FORM>
<TABLE border="1" width="100%" cellspacing="0" bordercolor="#9999FF">
<TR>
<TD width="82"><font color="#0000FF">ISBN</font></TD>
/* 读 取 购 物 车 信 息 */
Cookie[] cookies=request.getCookies();
String isbn=cookies[i].getName();
String num=cookies[i].getValue();
if (isbn.startsWith("ISBN")&&isbn.length()==17)
bookinfo.setBookISBN(isbn.substring(4,17));
%>
<TR>
<TD width="82"><%=bookinfo.getBookISBN()%></TD>
<TD width="258"><A href="bookinfo.jsp?isbn=<%=bookinfo.getBookISBN()%>">
153 <%= bookinfo.getBookName()%></A></TD>
<TD width="62"><%= bookinfo.getPrice()%></TD>
<TD width="36">
<INPUT size="5" type="text" maxlength="5" value="<%=num%>"
name="num" readonly>
</TD>
<TD width="43"><A href="delbook.jsp?isbn=<%= bookinfo.getBookISBN()%>">
删 除 </A></TD>
</TR>
<%
%>
</TABLE>
<BR>
<TABLE border="0" width="100%">
<TBODY>
<TR>
查 看 购 物 车 的 结 果 如 图 15-13 所 示 :
154
图 15-13 查 看 购 物 车 内 容
在 查 看 购 物 车 内 容 时 提 供 了 一 个 删 除 图 书
的 功 能 , 其 目 的 是 从 购 物 车 删 除 不 想 购 买 的
图 书 , 其 源 代 码 如 下 :
清 单 15-8 delbook.jsp
/*Cookie 信 息 处 理 */
/* 清 除 Cookie*/
if (request.getParameter("isbn")!=null)
{
cookie.setMaxAge(0);// 设 定 Cookie 立 即 失 效
response.addCookie(cookie);
}
%>
155 <!--jsp:forward page="shoppingcart.jsp" /-->
<html>
<head>
<meta http-equiv="refresh" content="0;URL=shoppingcart.jsp">
</head>
<body >
删除图书 ......
</body>
</html>
本 例 中 利 用 jsp:forward 动 作 在 删 除 图 书 动 作 完 成
之 后 , 将 页 面 继 续 转 向 购 物 车 页 面 。 即 图 15-14
只 显 示 一 瞬 间 , 浏 览 器 的 内 容 由 成 为 购 物 车
内 容 的 页 面 。
图 15-14 删 除 图 书 的 页 面
如 果 一 个 会 员 选 了 很 多 书 , 逐 个 删 除 比 较
麻 烦 。 为 了 方 便 会 员 放 弃 选 购 的 所 有 图 书 ,
重 新 开 始 选 书 , 本 例 提 供 了 清 空 购 物 车 程 序
( emptycart.jsp ) , 用 于 清 空 购 物 车 , 其 原 理 与 删
除 图 书 相 同 , 只 是 把 全 部 的 Cookie 中 图 书 的 有 关
的 内 容 都 清 空 了 。 其 代 码 如 下 :
清 单 15-9 emptycart.jsp
Cookie[] cookies=request.getCookies();
for (int i=0;i<cookies.length;i++)
{
String isbn=cookies[i].getName();
if (isbn.startsWith("ISBN")&&isbn.length()==17)
c.setMaxAge(0);// 设 定 Cookie 立 即 失 效
response.addCookie(c);
}
%>
<html>
<head>
<meta http-equiv="refresh" content="0;URL=shoppingcart.jsp">
</head>
<body >
清 空 购 物 车 ......
</body>
</html>
157
图 15-15 清 空 购 物 车 的 页 面
从 图 书 选 择 页 面 和 购 物 车 页 面 , 点 图 书 名
称 , 都 可 以 查 看 图 书 的 详 细 信 息 , 查 看 图 书
详 细 信 息 的 jsp 仍 用 BookBean 来 获 取 图 书 的 详 细 信
息 , 只 是 在 该 页 中 可 以 看 到 更 加 详 细 的 信 息 :
清 单 15-10 bookinfo.jsp
{ window.open("addcart.jsp?isbn="+str,
"shoppingcart","width=300,height=200,resizable=1,scrollbars=2");
return;
}
//--> 158
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<FORM>
<%
/* 读 取 购 物 车 信 息 */
if (request.getParameter("isbn")!=null)
{
String isbn = request.getParameter("isbn");
bookinfo.setBookISBN(isbn);
%>
<TABLE border="0" width="100%">
<TBODY>
<TR>
<TD width="116"><font color="#6600FF">ISBN</font></TD>
<TD width="349"><font color="#6600FF">
<%= bookinfo.getBookISBN()%></font></TD>
</TR>
<TR>
</TD>
</TR>
<TR>
<TD height="18" colspan="3">
<div align="right"> <br>
<TEXTAREA rows="10" cols="60" readonly name="content">
<%= bookinfo.getIntroduce()%></TEXTAREA>
</div>
</TD>
</TR>
</TBODY>
</TABLE>
<%
}
else
{ out.println(" 没 有 该 图 书 数 据 ");
}
%>
</FORM>
<TABLE align="center" border="0">
<TBODY>
<TR>
<TD><a href='Javascript:openwin("<%=request.getParameter("isbn")%>")'> 加
入 购 物 车 </a></TD>
160
<TD><A href="booklist.jsp"> 返 回 首 页 </A></TD>
<TD></TD>
</TR>
</TBODY>
</TABLE>
</BODY>
</HTML>
其 运 行 结 果 如 图 15-16 所 示 。
图 15-16 图 书 详 细 信 息
15.3 定单提交及查询
用 户 一 旦 确 定 购 物 车 中 所 选 的 图 书 都 是 其
所 要 购 买 的 , 就 要 到 去 提 交 其 定 单 , 以 便 书
店 按 照 相 应 的 方 式 进 行 处 理 。 而 且 , 为 方 便
用 户 是 否 已 经 提 交 定 单 , 及 定 单 的 状 态 , 本
例 提 供 了 定 单 查 询 功 能 。 在 此 处 我 们 用 OrderBean
来 将 定 单 提 交 到 数 据 库 中 , 在 order.jsp 中 显 示 并
提 交 定 单 信 息 , queryorder.jsp 来 查 询 定 单 。
在 会 员 选 书 部 分 , 我 们 仍 用 Java Bean 来 操 作 数
161
据 库 , 用 jsp 来 做 页 面 表 现 。
15.3.1 定 单 提 交 Java Bean
为 了 减 少 数 据 冗 余 , 定 单 信 息 由 两 张 表 来
记 录 其 信 息 : orderInfo, 记 录 定 单 的 有 关 公 用 信 息 ,
orderdetail , 记 录 该 定 单 包 含 哪 些 书 籍 及 数 量 , 表
结 构 分 别 如 下 :
图 15-17 定 单 信 息 表 结 构
图 15-18 定 单 详 细
所 有 的 对 数 据 库 的 操 作 都 由 JavaBean 来 完 成 ,
其 代 码 如 下 :
清 单 15-11 OrderBean.Java
package cuug;
import Java.sql.*;
public OrderBean(){
try {
Class.forName(strDBDriver );
catch(Java.lang.ClassNotFoundException e){
}
163
}
/**
* 返 回 定 单 的 总 价 。
* @return Java.lang.String
*/
public Java.lang.String getOderprice() {
return oderprice;
/**
* 返回定单的日期 。
* @return Java.lang.String
*/
public Java.lang.String getOrderDate() {
return orderDate;
/**
* 返 回 定 单 的 ID 号 。
* @return Java.lang.String
*/
public Java.lang.String getOrderID() {
return orderID;
} 164
/**
* 返 回 定 单 的 备 注 信 息 。
* @return Java.lang.String
*/
public Java.lang.String getOrderRem() {
return orderRem;
/**
* 返 回 接 收 者 的 地 址
* @return Java.lang.String
*/
public Java.lang.String getReceiverAddress() {
return receiverAddress;
/**
* 返 回 接 收 者 的 姓 名 。
* @return Java.lang.String
*/
public Java.lang.String getReceiverName() {
return receiverName;
/**
* 返 回 接 收 者 的 邮 政 编 码 。
* @return Java.lang.String
*/
public Java.lang.String getReceiverZip() {
return receiverZip;
/**
165
* 获 得 用 户 ID 。
* @return Java.lang.String
*/
public Java.lang.String getUserID() {
return userID;
/**
* 给 图 书 信 息 赋 值 。
* @param newBooks Java.util.Properties
*/
public void setBookinfo(Java.lang.String newBookinfo) {
bookinfo = newBookinfo;
createNewOrder();
int fromIndex = 0;
int tmpIndex = 0;
int tmpEnd = 0;
try{
conn = DriverManager.getConnection(strDBUrl);
while(bookinfo.indexof(';',fromIndex) != -1 ){
tmpEnd = bookinfo.indexOf(';',fromIndex);
tmpIndex = bookinfo.lastIndexof('=',tmpEnd);
166
strSql = "insert into orderdetail (orderID ,bookISBN ,bookcount)"
stmt.executeUpdate(strSql);
fromIndex = tmpEnd + 1;
stmt.close();
conn.close();
catch(SQLException e){
System.err.println("BuyerBean.getLogontimes():" + e.getMessage());
/**
* 给 定 单 的 总 价 赋 值 。
* @param newOderprice Java.lang.String
*/
public void setOderprice(Java.lang.String newOderprice) {
oderprice = newOderprice;
/**
* 给 定 单 的 备 注 赋 值 。
167 * @param newOrderRem Java.lang.String
*/
public void setOrderRem(Java.lang.String newOrderRem) {
orderRem = newOrderRem;
/**
* 给 接 收 者 的 地 址 赋 值 。
* @param newReceiverAddress Java.lang.String
*/
public void setReceiverAddress(Java.lang.String newReceiverAddress) {
receiverAddress = newReceiverAddress;
}
/**
* 给 接 收 者 的 姓 名 赋 值 。
* @param newReceiverName Java.lang.String
*/
public void setReceiverName(Java.lang.String newReceiverName) {
receiverName = newReceiverName;
/**
* 给 接 收 者 的 邮 政 编 码 代 码 赋 值 。
* @param newReceiverZip Java.lang.String
*/
public void setReceiverZip(Java.lang.String newReceiverZip) {
receiverZip = newReceiverZip;
/**
* 给 用 户 代 码 赋 值 。
* @param newUserID Java.lang.String
*/
public void setUserID(Java.lang.String newUserID) {
userID = newUserID;
168
}
/**
* 创 建 一 个 新 定 单
*/
private void createNewOrder() {
try{
conn = DriverManager.getConnection(strDBUrl);
receiverAddress,receiverZip,orderRem,orderPrice,Orderdate)"
stmt.executeUpdate(strSql);
orderID = 0;
rs = stmt.executeQuery(strSql);
169
while (rs.next()){
orderID = rs.getString("OrderID");
rs.close();
stmt.close();
conn.close();
catch(SQLException e){
System.err.println("BuyerBean.getLogontimes():" + e.getMessage());
}
}
在 本 Bean 中 , 如 果 一 张 定 单 中 有 多 种 书 籍 ,
15.3.2 定 单 提 交 JSP
用 jsp 页 面 来 显 示 用 户 所 选 的 图 书 的 信 息 ,
并 提 供 一 个 提 交 按 纽 , 为 便 于 程 序 的 管 理 ,170
我 们 将 显 示 和 处 理 结 果 放 在 一 个 JSP 中 , 其 代
码 如 下 :
清 单 15-12 order.jsp
/* 禁 止 使 用 浏 览 器 Cache , 网 页 立 即 失 效 */
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires",0);
%>
<HTML>
<HEAD>
<META http-equiv="Content-Style-Type" content="text/css">
<TITLE>
填 写 订 单
</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<%
if ("send".equals(request.getParameter("send")))
{
orderBean.setUserID(session.getValue("memberID"));
String str=request.getParameter("receivername");
orderBean.setReceiverName(str==null?"":str);
str=request.getParameter("orderprice");
orderBean.Oderprice(Java.lang.Float.valueOf(str==null?"0":str).floatValue());
str=request.getParameter("address");
171
orderBean.setReceiverAddress(str==null?"":str);
str=request.getParameter("postcode");
orderBean.setReceiverZip(str==null?"":str);
str=request.getParameter("bookinfo");
orderBean.setBookinfo(str==null?"":str);
str=request.getParameter("memo");
orderBean.setMemo(str==null?"":str);
int orderID=orderBean.getOrderID();
if (orderID>0)
{ /* 清 空 Cookie( 购 物 车 ) 信 息 */
Cookie[] cookies=request.getCookies();
{ String isbn=cookies[i].getName();
if (isbn.startsWith("ISBN")&&isbn.length()==17)
c.setMaxAge(0);// 设 定 Cookie 立 即 失 效
response.addCookie(c);
}
172
%>
<%
else
out.print(" 订 购 失 败 \n");
else
{ float price=0;
String bookInfo="";
%>
<FORM method="post" name="frm">
<TABLE border="1" width="100%" cellspacing="0" bordercolor="#9999FF">
<TR>
<TD width="90">ISBN</TD>
173
<TD width="75"> 数 量 </TD>
</TR>
<% /* 读 取 购 物 车 信 息 */
Cookie[] cookies=request.getCookies();
{ String isbn=cookies[i].getName();
String num=cookies[i].getValue();
if (isbn.startsWith("ISBN")&&isbn.length()==17)
bookinfo.setBookISBN(isbn.substring(4,17));
%>
<TR>
<TD width="90"><%= bookinfo.getBookISBN()%></TD>
<TD width="269"><A href="bookinfo.jsp?isbn=<%=
bookinfo.getBookISBN()%>"><%= bookinfo.getBookName()%></A></TD>
<TD width="50"><%= bookPrice%></TD>
<TD width="75">
<INPUT size="5" type="text" maxlength="5" value="<%= num%>" name="num"
readonly></TD>
Java.lang.Integer.parseInt(num)%></TD>
</TR>
<%
174
price += bookPrice.floatValue()*Java.lang.Integer.parseInt(num);
bookInfo += bookinfo.getBookISBN()+"="+num+";";
%>
</TABLE>
<p> </p>
<table width="100%" border="0">
<tr>
<td width="34%"> </td>
<td width="41%">
<div align="center"><a href="shoppingcart.jsp"> 修 改 图 书 订 单
</a></div>
</td>
<td width="25%"> </td>
</tr>
</table>
<p><font color="#0000FF"> 如 以 上 信 息 无 误 , 请 填 写 以
下 信 息 并 按 提 交 按 钮 提 交 订 单 , 完 成 网 上 订
书 : </font></p>
<table width="100%" border="0">
<tr>
<td width="83%">
<input type="text" name="receivername" size="10" maxlength="10">
</td>
</tr>
<tr>
<td width="83%">
<input type="text" name="address" size="60" maxlength="60">
</td>
</tr>
<tr>
<td width="83%">
<input type="text" name="postcode" size="6" maxlength="6">
</td>
</tr>
<tr>
<td width="83%">
<textarea name="memo" cols="60" rows="6"></textarea>
</td>
</tr>
<tr>
<td width="17%"><font color="#0000FF"></font></td>
<td width="83%">
在 本 JSP 中 将 图 书 信 息 按 照 “ BOOKISBN =
图 15-19 定 单 提 交 信 息
177
图 15-20 定 单 正 确 提 交
图 15-21 定 单 未 正 确 提 交
小 结 :
本 文 提 供 的 是 一 个 简 单 的 网 上 书 店 的 例 子 ,
本 文 提 供 的 例 子 中 尚 有 许 多 可 以 改 进 的 地 方 。
例 如 , 文 中 数 据 库 表 orderinfo 中 提 供 了 handled 字 段
在 对 定 单 进 行 处 理 发 出 书 之 后 , 可 对 该 字 段
进 行 设 置 , 将 其 值 设 成 非 0 值 , 另 增 加 一 个 供
用 户 对 定 单 进 行 查 询 的 JSP 页 面 。 对 定 单 的 处
理 程 序 可 用 JSP
, 也 可 以 用 传 统 MIS 来 实 现 。 希
望 读 者 对 本 例 进 行 进 一 步 的 完 善 。
178