网上书店系统
1.需求分析。
参考设计要求,及可行性的分析,我们确定了如下的需求:
1.数据库设计科学合理。
2.网站主页面简洁美观,可以天蓝色为主色调。
3.网站主页显示各个分类的及总的畅销表、新书榜、推荐榜,显示论坛新帖。
4.单本图书的详细资料页面显示同类图书的畅销榜,同一作者的畅销榜,购买了同一本书的读者此外还购买的图书。
5.可按作者,或者书名,或者出版社搜索图书。
6.用户注册登录后可以使用购物车、订单等功能,可以修改密码、个人资料,还可以在论坛发表新帖、回复。
7.具备友好的用户界面,提供适当的操作提示,如用户登录时的密码错误等。
8.网站管理员可通过后台管理界面,修改密码,添加、删除用户,添加、删除、修改图书的详细资料。
2.总的设计思想、系统平台、开发工具。
团队工作模式:以组长为核心,充分沟通与交流,保证概念的完整性与进度的良好控制。
采用自顶向下的设计方法,策略上采取复用、分而治之。
首先,清晰的结构和表达方式更容易对需求和模块功能进行精确的描述。其次,模块分割和模块独立性避免了系统级的bug。另外,细节的隐藏使结构上的缺陷更加容易识别。第四,设计在每个精化步骤的层次上是可以测试的,所以测试可以尽早开始,并且每个步骤的重点可以放在合适的级别上。
一次添加一个构件(功能模块)。在添加了新的构件(功能模块)之后,用它们来测试子系统。因为那些原来可以在子系统上成功运行的用例,必须在现有系统上重新运行,对系统进行回归测试。
精确、完整地定义接口、功能模块时,将具有一定集成度并可以重复使用的模块抽象出来,经验证后发放给组员以供复用,尽可能地避免代码的重复生产,提高代码的重用率,从而合理化、并简化开发过程,减少总的开发工作量与维护代价,提高生产率。
通过QQ、邮箱、局域网内的共享等,共享调试记录。
系统平台:Windows XP SP2 。
开发工具:Tomcat,JDK 1.5,Eclipse,Access 2003,Macromedia Dreamweaver MX 2004。
3.数据结构。
在 Microsoft Office Access 2003 中建立数据库。
表-1 book ,图书的详细资料。
字段名称 | 数据类型 | 意义 | 说明 |
---|---|---|---|
bookId | 自动编号 | 图书编号(主键) | |
bookTitle | 文本 | 书名 | |
bookAuthor | 文本 | 作者 | |
bookDate | 日期/时间 | 出版日期 | 形如:2007-01-22 |
bookPublish | 文本 | 出版社 | |
bookPrice | 数字 | 标价 | |
bookStorage | 数字 | 库存 | |
bookSold | 数字 | 售出数量 | |
bookPhoto | 备注 | 封面图片的路径和文件名 | |
bookSort | 文本 | 类别 | 科技、文艺、管理、经济,等 |
bookIsbn | 文本 | ISBN号 | |
bookWords | 数字 | 字数 | |
bookYC | 数字 | 印次 | |
bookBC | 数字 | 版次 | |
bookSheet | 文本 | 纸张 | |
bookValue | 数字 | 售价 | |
bookSummary | 备注 | 内容提要 | |
bookAuthorInformation | 备注 | 作者简介 | |
bookComment | 备注 | 评论 | |
bookCommend | 文本 | 推荐方式 | inAll(全局推荐)、inSort(在其所属类别内推荐) |
表-2 user , 用户的详细资料。
字段名称 | 数据类型 | 意义 | 说明 |
---|---|---|---|
userId | 自动编号 | 用户编号(主键) | |
userName | 文本 | 用户名 | |
userFigure | 文本 | 身份 | 总管、读者 |
userSex | 文本 | 性别 | 男、女 |
userAge | 数字 | 年龄 | >0 , <150 |
userBirthday | 日期/时间 | 出生日期 | 形如:2007-01-22 |
userAddress | 文本 | 现居住地 | |
userHome | 文本 | 籍贯 | |
userPwd | 文本 | 密码 | |
userNumber | 文本 | 身份证号 |
表-3 orderTotal ,订单的整体属性资料。
字段名称 | 数据类型 | 意义 | 说明 |
---|---|---|---|
orderId | 数字 | 订单编号(主键) | |
userId | 数字 | 用户编号 | |
orderDate | 日期/时间 | 订购日期 | 形如:2007-01-22 |
checkDate | 日期/时间 | 审核日期 | 形如:2007-01-22 |
totalValue | 数字 | 总价 |
表-4 orderItem ,订单中的图书条目资料。
字段名称 | 数据类型 | 意义 | 说明 |
---|---|---|---|
orderId | 数字 | 订单编号 | |
bookId | 数字 | 图书编号 | |
buyNum | 数字 | 购买数量 | |
bookSta | 文本 | 图书状态 | 缺书、待审、已发 |
bookValue | 数字 | 图书售价 |
表-5 topic ,论坛的主帖的详细资料。
字段名称 | 数据类型 | 意义 | 说明 |
---|---|---|---|
topicId | 数字 | 主帖编号(主键) | |
topicDate | 日期/时间 | 发表日期 | 形如:2007-01-22 |
topicContent | 备注 | 内容 | |
topicTitle | 备注 | 标题 | |
userName | 文本 | 发表的用户名 | |
followTotal | 数字 | 回复数 | |
userId | 文本 | 发表的用户编号 |
表-6 topic_follow ,主帖与回帖的对应关系。
字段名称 | 数据类型 | 意义 | 说明 |
---|---|---|---|
followId | 数字 | 回帖编号(主键) | |
topicId | 数字 | 主帖编号 | |
followUserId | 数字 | 回帖的用户编号 |
表-7 follow ,回帖的详细资料
字段名称 | 数据类型 | 意义 | 说明 |
---|---|---|---|
followId | 数字 | 回帖编号(主键) | |
followDate | 日期/时间 | 发表日期 | |
followContent | 备注 | 内容 | |
followTitle | 文本 | 标题 |
表-8 hotSearch ,热门搜索关键词的详细资料。
字段名称 | 数据类型 | 意义 | 说明 |
---|---|---|---|
hotSearchId | 自动编号 | 编号(主键) | |
searchMode | 文本 | 搜索方式 | 作者、书名、出版社 |
searchWord | 文本 | 搜索关键词 |
4.功能模块。
4.1首页 index-main.jsp 部分代码—1。
变量、函数的声明,网页标题的显示。
<%@ page language="java" contentType="text/html; charset=gb2312"
import="java.sql.*,myPk.*" %>
<% request.setCharacterEncoding("gb2312"); %>
<%!
//转换字符集
public String toChi(String str)
{
if (str==null)
return "";
try
{
String temp_p=str;
byte[] temp_t=temp_p.getBytes("ISO8859-1");
String temp=new String(temp_t);
return temp;
}
catch(Exception e) { }
return str;
}
%>
<%
String sort=null;
String pageTitle="首页";//网页标题
String bookHot="";//栏目的标题
String sql="select * from book";
Pageable rs=null;
Pageable rsNew=null;
Pageable rsHot=null;
Pageable rsCam=null;
if(request.getParameter("sort")!=null)
{
/*Javascript脚本中页面跳转时传递的参数,
以及HTML中链接(跳转)时传递的参数,
即使在发送端用了 request.setCharacterEncoding("GB2312");
接收时,仍然要用自定义的函数转换字符集,否则参数中的中文会显示为乱码。
*/
sort=toChi(request.getParameter("sort"));
pageTitle="["+sort+"]";
bookHot=pageTitle;
sql=sql+" where bookSort='"+sort+"'";
}
%>
4.2首页 index-main.jsp 部分代码—2。
显示全局推荐、类别内推荐的书目。
<%=bookHot %>推荐 |
<% Conn con=null; try { String comSql=""; if(request.getParameter("sort")!=null) comSql+=sql+" and bookCommend='inSort'"; else comSql+=sql+" where bookCommend='inAll'"; comSql+=" order by bookSold desc"; con=new Conn(); Pageable rsCom=con.getRs(comSql); rsCom.setPageSize(10); rsCom.gotoPage(1); for(int i=0;i { if(sort==null) { %> <% } %> <%=rsCom.getString("bookAuthor")%> <%=rsCom.getString("bookDate").substring(0,10) %> <% rsCom.next(); } con.closeRs(); }catch(Exception e) { out.print(e.toString()); } %> |
4.3订单处理文件 deal-order.jsp 的部分代码—1。
函数声明。
<%@ page language="java" contentType="text/html; charset=gb2312" import="java.sql.*,myPk.*" %>
<% request.setCharacterEncoding("gb2312"); %>
<%!
/*订单(session) order 形如 -bookId,buyNum-bookId,buyNum- ,
依次为 -图书编号,购买数量-图书编号,购买数量-*/
/* 如果字符串 str 的长度小于 n ,则在其左边填充足够的 * 号,使其长度为 n 。<-左,右-> */
public String appString(String str,int n)
{
int strLen=str.length();
if(strLen>=n)
return str;
String sTem="";
String sBlank="*";
for(int i=0;i<(n-strLen);i++)
sTem+=sBlank;
sTem+=str;
return sTem;
}
/* 将 str 以 - 为标志分段,于各小段中再以 , 分为两段(形如段a,段b),在每个段a的左边填充 * 号,使每个段a的长度均为 n */
public String appLongStr(String str,int n){
String[] sTem=str.split("-");
String sRet="";
for(int i=0;i String[] splitByDot=sTem[i].split(","); splitByDot[0]=appString(splitByDot[0],n); sTem[i]=splitByDot[0]+","+splitByDot[1]; } if(sTem.length==1) return sTem[0]; for(int i=0;i<(sTem.length-1);i++) sRet+=sTem[i]+"-"; sRet+=sTem[sTem.length-1]; return sRet; } %> 4.4订单处理文件 deal-order.jsp 的部分代码—2。 放弃购物车中的指定书本。 <% if(act.equals("del")){ //将某书从购物车中移除 if(sOrderSession.indexOf("-")==-1) sTem="";//删除的是 session order 中仅有的一个记录项 else{ sSessionLeft=sOrderSession.substring(0,sOrderSession.indexOf(bookId+",")); sSessionRight=sOrderSession.substring(sOrderSession.indexOf(bookId+",")); if((sSessionLeft.indexOf("-")==-1)&&(sSessionRight.indexOf("-")!=-1)) sTem=sSessionRight.substring(sSessionRight.indexOf("-")+1);//删除的是 session order 中最左的记录项。 else if((sSessionLeft.indexOf("-")!=-1) &&(sSessionRight.indexOf("-")==-1)) sTem=sSessionLeft.substring(0,sSessionLeft.lastIndexOf("-"));//删除的是 session order 中最右的记录项 else sTem=sSessionLeft.substring(0,sSessionLeft.lastIndexOf("-"))+sSessionRight.substring(sSessionRight.indexOf("-"));//删除的是 session order 中间位置的记录项 } }//if(act.equals("del") %> 5.运行结果。 5.1首页。 5.2智能图书搜索。 搜索栏的输入框的下边有相应搜索方式的热门搜索关键词。可分别按作者、书名、出版社搜索图书,同时支持模糊搜索,如,按“出版社”搜索“长江[空格]人民”可搜索到出版社名字中含有“长江”、“人民”的图书(全图)。 5.3购物车。 5.4订单列表。 5.5论坛。 5.6添加图书。 5.7管理图书。 6.总结。 伴随着第一场雪的降临,这个课程设计才接近了尾声。在这次课程设计里,可以说是全身心地投入,――正式开始动工之前,有很多关于网站架设的想法,觉得网站无非就是数据库+标签,真正下手后,深刻体会到了其中的艰辛,特别是当第一场雪哗啦啦地下下来,而我却不得不坐在电脑前继续调试时。 虽然没能赶在第一场雪的时候去堆雪人,不过现在看着埋头做了一个多星期的设计结果,有点苦尽甘来的味道。 这次的课程设计,有两个方面的收获,一个是心态,一个是技术。 在心态上,端正了之前的心浮气躁、眼高手高,更加磨练了韧劲,增强了团队合作精神,提高了对软件开发中的工程设计思路的认识和理解。 技术上,在JSP动态网站开发方面积累了实践经验。对CSS有了新的认识,提高了对HTML的熟练程度及使用技巧,尤其是与Javascript联手打造胖客户端的一些方法和思路。 在做这个网上书店系统的论坛时,帖子的发表功能采用的方法是UBB编辑器,通过开发UBB编辑器,接触到正则表达式并可以灵活运用。在开发的过程中,无意中发现UBB编辑器的一个不足之处,它在获取当前激活选中区,即高亮文本块,或文档中用户可执行某些操作的其它元素的时候,用的是document.selection.createRange().duplicate() ,所以当选中非编辑区的文本时(如同一个页面内的导航时),然后单击UBB编辑器的功能按钮,非编辑区的文本会响应UBB编辑器,这是开发人员不想看到的--它会导致页面凌乱。查找相关资料也未能找到解决办法,除非摒弃UBB编辑器,改用HTML在线编辑器。 在实现购物车、订单的功能时,一开始想全部用数据库实现。考虑到购物车中的书本并不一定是读者最终要购买的,如果用数据库实现,那么购物车的每次变动都要更新数据库,这必然会给数据库增加无谓的负担。思考再三,自定义了一个固定形式的session来保存购物车的书目,当读者确定支付购买时,再将这个 session“解密”后将购买信息写入数据库。这个session的格式为:。。。。。。-图书编号,购买数量-图书编号,购买数量-。。。。。。 ,当对购物车中的书目进行添加、更改、删除时,通过判断需要添加、更改、删除的书目在这个session中的位置(session为空,或是session中仅有的一个书目,或是session中最左的一个书目,或是session中最右的一个书目)来作不同的操作。 在测试中,发现这样实现的购物车功能有bug,原因是一本书的编号(如1)可能跟另一本书的编号(如21)的低位相同,于是我就想到,每次在操作这个session时先将其中的图书编号从左边用*号填充至10位,操作完成后去除所有*号还原。问题迎刃而解。 整个网站系统共用一个信息提示的处理页面tip.jsp,该页面通过读取传进来的tip变量判断输出给用户的友好提示信息,传进来的desPage变量则为tip.jsp页面3秒倒计时后前往的页面地址。 网页头部页面head.jsp中调用了包java.text,其中通过实例化SimpleDateFormat类获取并格式化日期,所以在Eclipse中加载此项目时,除了正确配置数据源,还需要在项目的配置中加载Tomcat\common\lib\servlet-api.jar 。 7.参考资料。 1.电子版网页制作完全手册(含DHTML参考、HTML参考、CSS属性参考),手册的内容全部来自Microsoft MSDN Library,由 lemon 整理编辑,资料从http://clgigi.8u8.com下载。 2.电子版JScript 语言参考手册(含正则表达式简介),手册的内容全部来自Microsoft MSDN Library。 3.《JSP动态网站开发实用教程》,机械工业出版社,宝贝工作室 策划。 4.电子版《JSP 2.0技术手册》,林上杰、林康司 著,电子工业出版社。