基于JSP网上书店系统
前 言
随着Internet国际互联网的发展,越来越多的企业开始建造自己的网站。基于Internet的信息服务,商务服务已经成为现代企业一项不可缺少的内容。很多企业都已不满足于建立一个简单的仅仅能够发布信息的静态网站。现代企业需要的是一个功能强大的,能提供完善的电子商务服务的动态商务网站。
JSP是Sun公司推出的一种网站开发技术,Sun公司借助自己在Java上的不凡造诣,又把人们引进JSP时代,JSP即Java Server Page,它可以在Servlet和JavaBean的支持下,完成功能强大的Web应用程序。所以,在我的毕业设计中,我采用了JSP作为开发工具,构建了一个能实现简单的电子商务的小型动态商务网站——网上书店销售系统。该系统能实现用户的注册、登录功能;能够实现商品的查询,订购等功能。该系统基本上具备一个网上商品销售系统应该具备的功能,该设计项目基本上体现了构建一个动态商务网站所需要的技术,可以说,目前的大型商务网站也就是我们这个小型网站在内容上的扩充和重复。
通过这次的毕业设计,我了解了目前流行的动态商务网站的构成和运作原理,掌握了用JSP构建动态网站的相关知识和技术原理,锻炼了自己的动手实践能力。更重要的是,通过这次的毕业设计,我培养出了刻苦钻研的学习精神和严肃认真的学习态度,这对我以后的学习和工作有很大的益处。
在这次毕业设计过程中,我得到了指导老师符老师和其他同组同学的悉心指导。在此,我对他们表示衷心的感谢!
第一章 概 述
1.1 开发背景
随着时代的发展,信息技术、Internet/Intranet技术、数据库技术的不断发展完善,网络进程的加快,传统的购物方式也越来越不能满足人们快节奏的生活需求,使得企业的IT部门已经认识到Internet的优势,电子商务就是在这样一个背景下产生发展起来的。伴随着电子商务技术的不断成熟,电子商务的功能也越来越强大,注册用户可以在网上搜索购买到自己想要的各种商品,初步让人们体会到了足不出户,便可随意购物的快感。我的毕业设计也就正是一个电子商务系统的开发---网上商品销售系统。
1.2 JSP简介
JSP(Java Server Pages)是由Sun Microsystems 公司倡导、许多公司参与一起建立的一种动态网页技术标准,JSP技术在Servlet技术基础上发展起来的,它正在飞速发展中,现已成为Java服务器编程的重要组成部分。它虽然还未成型,但是它必将和J2EE(Java 2 Enterprise Edition)一起发展。
JSP是结合markup(HTML和XML)和Java代码来处理一种动态页面。每一页第一次被调用时,通过JSP引擎自动被编译成Servlet,然后被执行,以后每次调用时,执行编译过的Servlet。JSP提供了多种方式访问Java class、Servlet、Applets和Web Server,因此,Web应用的功能可以分成多个明确定义公用接口的组件,通过JSP将它们结合在一起。
1.2.1 JSP的运行原理
在JSP第一次获得来自于客户端浏览器的请求时,JSP文件将被JSP引擎(JSP engine)转换成一个Servlet,即将”.jsp”文件编译成Java Class文件。当Servlet引擎接收到请求后,如果设置了使用最新的JSP,它就会去找JSP文件,检查该文件在上次编译后是否改动过。如果改动过,就会重新编译生成新的Servlet,最终将请求转交给编译好的Servlet引擎执行。如图1-1:若图片无法显示请联系QQ3710167
在编译时如果发现JSP文件有任何语法错误,转换过程将中断,并向客户端发出出错信息;如果编译成功,则所转换产生的Servlet代码被编译,然后该Servlet被JSP引擎加载到内存中。此时JSP引擎还请求了jspInit()方法的执行,并对此Servlet初始化。JspInit()方法在Servlet的生命周期中只被请求一次,然后将被调用来处理客户端的请求和回复操作。对于所有随后对该JSP文件的请求,服务器将检查该JSP文件自最后一次被存取后是否经过修改。如果没有修改,则将请求交还给还在内存中的Servlet的jspService()方法,执行回复操作。由于Servlet始终驻于内存,所以响应是非常快的。Jsp页面在第一次访问时由于要转化和编译,运行速度较慢,但是当第二次访问该页时,由于文件已经被编译成字节码文件了,所以速度非常得快。
1.2.2 JSP页面的组成
JSP页面看上去像标准的HTML和XML页面,并附带有JSP引擎能够处理和解析执行的代码与组件。通常,JSP代码和组件用于创建在最终页面上显示的文本。通常来说,JSP页面包括编译指令,动作指令,声明,表达式和程序段等内容。
1)编译指令:使用JSP编译指令(〈%@ 和 %〉内的)来指定所使用的脚本语言,Servlet实现的接口,Servlet扩展的类,Servlet导入的软件包。JSP指令的一般语法形式为:<%@ 指令名=“值”%>。
2)动作指令(标识):动作指令用于执行某些动作。在JSP规范中有2种类型的动作指令的标识。第一种是标准动作,它定义的是无论在什么版本的JSP引擎或Web服务器下总是可用的动作。第二种是自定义动作,它通过使用taglib指令来实现。例如JSP:useBean;JSP:setProperty;JSP:getProperty就是标准动作。
3)声明:用于声明合法的变量和方法。与任何语言相同,JSP语言使用变量来保存数据。这些变量用declaration元素声明,声明的语法为<%! declaration(s) %>。当页面被初始化的时候,JSP页面中的所有声明都被初始化。除了简单的变量,方法也能被声明。声明不对当前的输出流产生任何影响。
4)表达式:通过计算表达式所得到的结果来表示某个值。表达式的形式为:<%=expression>。表达式求值的结果被强制转换为一个字符串,并插入到当前的输出流中。
5)程序段:JSP可以在页面中包含的一段程序,称之为程序段。程序段是一个代码片断,在请求的处理过程中被执行。程序段可以和页面中的静态元件组合起来创建动态生成的页面。程序段在“<% %>”中定义,在这对标识中的所有东西都会被当成JSP程序执行。
基于JSP网上书店系统
1.2.3 JavaBean技术介绍
JavaBean技术是一种基于Java的组件技术,JavaBean组件可以用来执行复杂的计算任务,或负责与数据库的交互以及数据的提取等,是解决代码重用问题的一种策略。
以前的组件无法实现真正的代码重用,其主要原因就是它们对于处理平台的依赖和对开发语言的依赖过重。由于Java语言在这些方面所具有的特点和优势,使得基于它的软件JavaBean组件技术倍受人们的关注。它的任务就是:一次编写,可以在任何地方执行,
可以在任何地方重用。JavaBean组件可以在任何地方冲用包括了可以在应用程序、其他组件、文档、Web站点和应用程序构造器工具等多种方案中再利用。
为了创建和使用Java软件组件,JavaBean被实现为一种独立于平台和结构的应用程序接口,它的实现可以忽略内部的结构及细节问题,只需要定义其外部的特征及对外功能就行。其中,属性、方法和事件三种接口可以独立对外进行开发。
JavaBean的实质就是一个.class文件,也可以成为类文件。JavaBean以binary格式保存,可以保护Java源代码不容易被他人抄袭。
1.2.4 JSP的运行环境
要运行Jsp(注意,不是浏览Jsp页面),需要有支持Jsp的服务器。这里分2种情况:一种是自身就支持Jsp的服务器,如Jrun,Weblogic,JSWDK等;而另一种则是在不支持Jsp的服务器上安装Jsp引擎的插件,如在IIS,Apache等服务器上安装WebSphere,tomcat,Resin等插件。其中主流服务器是Weblogic和tomcat.
Weblogic是一款功能强大的服务器软件,配置比较简单,而且Jsp的扩展功能较多,附带了数据库的JDBC驱动程序。,支持JHTML(一种与Jsp十分相似的技术),是目前市场占有率最高的服务器。不过,Weblogic的运行情况不太稳定,使用它调试Jsp文件,出现语法错误或者数据库连接错误时,Weblogic就有可能崩溃。
Tomcat服务器是Apache Group Jakarta小组开发的一个免费服务器软件,适合于嵌入Apache中使用,而且,它的源代码可以免费获得,你可以自由地对它进行扩充。访问的地址 http://jakarta. apache.org/tomacat/index.html, Tomcat服务器的兼容性很好,如WebLogic服务器采用其为Web服务器引擎,Jbuilder将其作为标准的测试服务器,Sun公司也将其作为JSP技术应用的示例服务器。不足之处是它的配置比较麻烦,而且有一些安全性的问题没有解决。但是Tomcat服务器有众多大软件公司的支持,而且服务器的性能稳定,其发展前景很好。
1.3 系统开发环境
1.3.1 服务器的配置
前面介绍了JSP的生命周期,为了说明JSP对运行环境的要求,先简单的介绍一下它的运作过程。服务器在接收到客户端传过来的一个页面请求时,先判断是否是JSP页面请求(从扩展名来判断),如果不是,只是一般的HTML页面请求,则直接把HTML文档传给客户端,完成客户端与服务器的一次连接。如果判断是JSP页面请求,则由JSP引擎(或Servlet引擎)将JSP页面代码转换成Servlet代码,再通知服务器上的JVM(Java虚拟机)对转换过来的Servlet代码进行编译,将生成的字节码文件放在服务器上相应的地方,并执行编译后得到的字节码,然后把结果传送给客户端,这样就完成一次连接。以后如果有相同的JSP页面的请求,则直接由JSP引擎通知JVM执行已有的字节码,并把结果传送给客户端。
从上面JSP运作全过程可见,运行JSP最少需要三样东西:JSP引擎、Web服务器和JVM。最常用的Java开发工具就是JDK和Jbuilder,它们之间的很大不同就是JDK是字符界面,而Jbuilder是窗口界面。本系统直接采用JDK作为JVM和java编译器。所用的操作系统是Windows2000,服务器采用的是tomcat,利用了它充当Jsp引擎,同时还利用了它的信息发布功能。首先把JDK,tomcat安装到本地硬盘D盘根目录下,下面详细的介绍如何配置运行环境:
★ 配置环境变量
第一步:进入我的桌面,右击“我的电脑”,选择“属性”选项,进入“系统属性“对话框,单击”高级标签“,如图1-2所示:若图片无法显示请联系QQ3710167第二步:点击上图箭头所示“环境变量”,进入图1-3画面。
第三步:单击 “系统变量”部分的 “新建按扭”,创建JAVA-HOME变量,在变量值栏内输入C:\jdk1.4.2_05; 如图1-4所示:JAVA_HOME指明JDK安装路径,就是刚才安装时所选择的路径C:\jdk1.4.2_05,此路径下包括lib,bin,jre等文件夹(此变量最好设置,因为以后运行tomcat,eclipse等都需要依靠此变量)
第四步:同样的方法创建CLASSPATH 变量,在变量栏内输入,.;%JAVA_HOME%\lib;
%JAVA_HOME%\lib\tools.jar (要加.表示当前路径)CLASSPATH为java加载类(class or lib)路径,只有类在classpath中,java命令才能识别。
第五步:创建PATH变量,在变量栏内输入,%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
Path使得系统可以在任何路径下识别java命令。
第六步:创建Tomcat-Home变量,在变量栏内输入
C:\Tomcat5.0; 如图1-5所示:若图片无法显示请联系QQ3710167
第七步:检测配置是否成功:
1)检测JDK是否配置成功
编写一个java程序,例如:
public class HelloWorldApp
{
public static void main(String args[])
{
System.out.println(“HelloWorld!”);
}
}
首先把它放到一个名为HelloWorldApp.java的文件中,这里,文件名应和类名相同,因为java解释器要求公共类必须放在与其同名的文件中。然后对它进行编译:
c:\>javac –g HelloWorldApp.java
编译的结果是生成字节码文件HelloWorldApp.class。最后用java解释器来运行该字节码文件:
c:\>java HelloWorldApp
结果是在屏幕上显示“Hello World!”
至此,JDK完全安装成功。
2)检测tomcat是否配置成功
进入C:\Tomcat5.0\bin目录,双击startup.bat执行文件启动Tomcat服务器,成功启动后的界面如图1-6所示:
我们现在就可以通过浏览器看Tomcat服务器的示例程序了,打开浏览器,键入http://localhost:8080/index.jsp进入Tomcat服务器的主页面。 若图片 无法显示请联系QQ3710167
基于JSP网上书店系统
1.3.2 数据库后台环境的配置
SQSQL Server是由Microsoft开发和推广的关系数据库管理系统(DBMS),它最初是由Microsoft、Sybase和Ashton-Tate三家公司共同开发的,并于1988年推出了第一个OS/2版本。 SQL Server近年来不断更新版本,1996年,Microsoft 推出了SQL Server 6.5版本;1998年,SQL Server 7.0版本和用户见面;SQL Server 2000是Microsoft公司于2000年推出的最新版本。
◆ JSP与SQL Server数据库的连接
本系统使用ODBC驱动程序建立SQL Server的数据连接。创建步骤如下: (1)选择任务栏的 “开始” “控制面板” “性能与维护” “管理工具” 双击ODBC数据源 单击系统DSN标签,单击“添加”选择SQL Server的ODBC数据源,如图1-7所示: 若图片无法显示请联系QQ3710167
(1) 定义ODBC数据源的名字和SQL Server所在的服务器,如图1-8所示:
(1) 定义连接数据库的方式,使用Windows的验证连接数据库。
(2) 选择要连接的数据库,如图1-9所示:
其于各项保留默认值,最后单击“完成”进入数据源的测试窗口,测试成功后显示如图1-10,这样就完成了本系统数据库的ODBC数据源的创建。
◆ 建立数据库
选择任务栏的 “开始” “所有程序” “Microsoft SQL Server”
“企业管理器”,然后右击数据库选 “新建数据库”,如图1-11,在弹出的对话框中输入数据库名,完成后回到图1-11的界面,单击 “数据库”,选择你刚刚建立的数据库cart,右击选择新建表选项,这样就可以创建自己的数据表了,通过建好的数据表就组成了数据库。
若图片无法显示请联系QQ3710167
第二章 需求分析
2.1 系统说明
本系统是一个中小型的电子商务系统----网上书店,可以为各类用户提供方便的在线买书环境,符合目前国内流行的电子商务模式。用户可以在系统中实现注册、浏览商品、搜索查询商品、下定单、处理定单等功能;管理员可以通过用户管理、定单管理、商品管理、评论管理等管理功能来对系统进行维护更新。
网站的组成有以下几个子系统组成:
1. 主页,显示欢迎界面,提供近期的书本。
2. 购物车,处理订购并显示想要订购的书本。
3. 查询系统,通过书本编号、书本名称来查询是否有自己需要的书本。
4. 用户注册系统,处理新用户的注册和老用户买书时的确认。
2.2 系统功能简介
2.2.1 基本功能
l 游客可以浏览网站
l 用户登陆
l 用户能够浏览网站
l 提供搜索引擎,使用户能够按特定的条件对所需商品进行搜索
l 用户下定单购买商品
l 用户处理定单
2.2.2 用户界面设计
2.3 系统运行环境
操作系统:Windows 9X、Windows NT Workstation/Server 4.0以上、Windows 2000 Server/Professional、Windows XP Professional。
CPU:没有很高的要求,只要能够顺利运行Windows系列操作系统就可以了。当然,CPU的处理速度越快,运行JSP代码的效率越高。
内存:最低配置32MB,建议使用64MB以上内存,如果使用Windows 2000或Windows XP建议使用128MB以上内存。
硬盘空间:至少需要50MB以上的硬盘空间来安装所需的组件。
运行JSP的服务器端要求:(如表2.1所示)
表2.1
操作系统
需要安装的J2SDK Tomcat
Windows 98
J2sdk-1_4_1_01 Tomcat 4.0以上
Windows NT 4.0 Server
J2sdk-1_4_1_01 Tomcat 4.0以上
Windows 2000
J2sdk-1_4_1_01 Tomcat 4.0以上
Windows XP
J2sdk-1_4_1_01 Tomcat 4.0以上
第三章 系统设计
3.1 系统设计思想
本系统采用三层架构设计,它的工作原理如图3-1所示。若图片无法显示请联系QQ324114
采用三层构架以后,用户界面层通过统一的接口向业务层发送请求,业务层按自己的逻辑规则将请求处理之后进行数据库操作,然后将数据库返回的数据封装成类的形式返回给用户界面层。这样用户界面层甚至可以不知道数据库的结构,它只要维护与业务层之间的接口即可。
基于JSP网上书店系统
3.2 系统功能模块化
如图3-2为本系统的功能模块图。
若图片无法显示请联系QQ3710167
3.3 数据库设计
数据库在一个信息管理系统中占有非常重要的地位,数据库结构设计的好坏将直接对应用系统的效率,以及实现的效果产生影响。合理的数据库结构设计可以提高数据存储的效率,保证数据的完整和一致。
3.3.1 数据库需求分析
针对一般在线书店的需求,得出如下需求信息。
§ 用户分为游客和已注册用户。
§ 订单分为单张详细订单和总订单。
§ 一个用户可以购买多本图书。
§ 一个用户对应一张订单。
§ 一个列表对应多张订单。
针对本系统功能分析,总结出如下的需求信息。
§ 用户,包括数据项:用户ID、用户名、密码。
§ 图书,包括数据项:图书编号、图书名、价格、图书介绍。
§ 订单列表,包括数据项:订单编号、图书编号、购书数量。
§ 订单,包括数据项:订单编号、用户编号、下单时间。
3.3.2 数据库概念结构
从本系统中规划出的实体有:用户实体、图书实体、订单实体、订单列表实体。
实体之间关系的E-R图如图3-3所示。
购书
用户
订单列表
订单
图书
1 N
M N
1
L
N
图3-3
用户信息实体的E-R图如图3-4所示。
图书实体的E-R图如图3-5所示。
订单实体的E-R图如图3-6所示。
订单列表实体的E-R图如图3-7所示。
若图片无法显示请联系QQ3710167
数据库逻辑机构设计
在线书店数据库中各个表的设计结果如下面的标和所示。
表3-8为图书信息列表。
第四章 详细设计
4.1 系统概述
我设计的这个系统是一个由JSP实现的网上购书系统。它实现了基本的登录验证、查询商品、分页处理、购物车处理以及订单处理功能,其主要界面见图4-1:若图片无法显示请联系QQ3710167
4.2 系统主要文件
这个购书系统主要有2类文件,一类是Bean文件,我把它们统一放在了cart文件夹里,保存在jakarta-tomcat-5.0.27\common\classes\cart下,(这是tomcat要求的默认存放Bean的路径);另一类是jsp文件,保存在jakarta-tomcat-5.0.27\webapps\ROOT。(这是tomcat的默认工作环境)
Bean文件:CartManager.java,OrderEntity.java,OrderItemEntity.java
ProductEntity.java,UserEntity.java
Jsp文 件:cart.jsp
4.3 详细代码及说明
4.3.1实现用户实体的Bean
1)用户作为实体,我把他的id, 姓名,密码作为其属性在Bean里面做了定义,它们都是和数据库里的user表相对应的,在这个Bean里封装的方法也主要是对这个表进行操作.这个几个属性都被定义为类的私有成员,外界不可访问
private String id;
private String userName;
private String userPassword;
2)构造函数里做了2件事情,第一:寻找数据库连接驱动;第二:对上面的3个私有成员初始化:
public static String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver";
public static String sConnStr = "jdbc:odbc:cart";
public static Connection conn = null;
public UserEntity(String id,String userName,String userPassword)
{
try
{
Class.forName(sDBDriver);
//采用Class.forName方法显式加载一个驱动程序
}
catch(java.lang.ClassNotFoundException e)
{
System.err.println("UserEntity: " + e.getMessage());
}
this.id=id;
this.userName=userName;
this.userPassword=userPassword;
}
根据上面对变量sDBDriver ,sConnStr的定义和初始化可以看出,我在连接数据库的时候采用的是jdbc-odbc桥的方式,这种方式采用的驱动是JDK自带的,不需要另外安装。但是,为了与特定的数据库连接,我们必须建立一个数据源:cart。给3个属性赋值,我利用了this指针。
3)这个类我封装了2类方法:一是查找特定用户名的所有记录,代码如下:
public static UserEntity queryUser(String userName) throws SQLException
{
try
{
Class.forName(sDBDriver);
}
catch(java.lang.ClassNotFoundException e)
{
System.err.println("UserEntity: " + e.getMessage());
}
//query from database
String sql="select id,user_name,user_password from user where user_name= ? ";
ResultSet rs = null;
try
{
conn = DriverManager.getConnection(sConnStr);
PreparedStatement prepStmt = conn.prepareStatement(sql);
prepStmt.setString(1,userName);
rs = prepStmt.executeQuery();
}
catch(SQLException ex)
{
System.err.println("OrderItemEntity executeQuery: " + ex.getMessage());
}
UserEntity user=null;
if(rs.next())
user=new UserEntity(rs.getString(1),rs.getString(2),rs.getString(3));
return user;
}
这个函数有1个参数,String userName,就是通过这个用户名在user表里查询相应的用户的。要查询数据库里user表,就必须先连接数据库。连接数据库第一步是加载驱动,之后就是进行连接。我采用DriverManager类的getConnection方法来建立与cart数据源的连接,连接成功后,返回一个Connection类的对象conn.要查找特定用户名的纪录,其实就是对uesr进行查询操作。PreparedStatement对象就是用于查询语句的执行,它是Statement的子类,与Statement不同的地方,PreparedStatement对象可以接受参数,这里需要接受的参数是user_name,然后进行预编译。在每一次执行这个查询,都可以给sql语句传输不同的user_name,这样大大提高了灵活性。要想查询后的结果最后显示给用户,必须对ResultSet对象进行操作,即对rs进行操作。我在程序里是把该记录赋给一个UserEntity对象。
该类封装的另一种方法是:用户名和密码的获得。这个主要是为了方便后面验证用户合法性使用
public String getUserName()
{
return userName;
}
public String getUserPassword()
{
return userPassword;
}
4.3.2实现商品实体的Bean
虽然我做的是一个购书系统,但考虑到系统的可扩展性,我把书当作一种商品来进行定义。同样,参照数据库里的product表,我给商品这个类定义了如下4个属性,商品id,商品名称,商品价格,商品note,其类型同样是该类的私有属性:
private String id;
private String productName;
private String productPrice;
private String productNote;
1)其构造函数和用户实体类基本上一致,所以代码及其说明我在这里就省略了。
2)对商品的操作也主要是2类,一类是对特定商品的查询,其原理和查询用户是一样的,但是有一点小小的区别,即查询商品可以使查询所有的商品,或者是查询特定id的商品,我通过以下代码把这2种查询合在了queryProduct这个函数里:
String sql="select id,product_name,product_price,product_note from product ";
if(productId.compareTo("")!=0)
sql=sql+" where id = ? ";
Vector v=new Vector();
ResultSet rs = null;
其关于连接数据库,查询记录的代码和上面的大致雷同,所以在这里就省略了。
显示商品是分页显示的,其代码如下:
while(rs.next())
{
++i;
if(i>pageCount*pageSize)
{
if(i<=(pageCount+1)*pageSize)
v.add(new ProductEntity(rs.getString(1),rs.getString(2),rs.getString(3),rs.getString(4)));
基于JSP网上书店系统
else
break;
}
}
这一段代码的主要功能是:每一页最多显示pageSize个商品,如果超过pageSize个,就分页显示。PageSize在后面将会定义,其值我设置为10。
1)第二类方法是查询商品的id,全称,价格和note. 例如查找商品的ID:
public String getProductId()
{
return id;
}
4.3.3 实现订购单实体的Bean
客户每次购买一种商品都会产生一次订购单,它包括订单号,所购买的书号,所购买这种书的数量,这些构成了这个类的私有属性:
private String id;
private String orderId;
private String productId;
private String productNum;
1)客户每次选中一种商品后,点击放入购物车,就会产生一个订单,其实现代码如下:
String sql="insert into order_item(order_id,product_id,product_num) values(?,?,?) ";
ResultSet rs = null;
try
{
conn = DriverManager.getConnection(sConnStr);
PreparedStatement prepStmt = conn.prepareStatement(sql);
prepStmt.setString(1,orderId);
prepStmt.setString(2,productId);
prepStmt.setString(3,productNum);
prepStmt.executeUpdate();
}
订购单,书号,购买数量都是作为参数传过来的。很明显,新建一张订购单其实就是在order_item表里插入一条新纪录就可以了。其原理已经在上面说过来了,就不在此重复了。
2)在后面的购物车里,一名顾客的最终消费总额就是根据这里一张张的订购单得到的,所以查找特定订单号的订购单是这个类里面不可缺少的方法,它的算法实质上就是条件查询,和前面的无条件查询相比,我只把sql语句作了改动:
String sql="select id,order_id,product_id,product_num from order_item where order_id= ? ";
2)第3个被封装的方法是设置,获得订购单号,书号,定购数量,并且还可以获得session price.
4.3.4 实现购物车实体的Bean
在现实生活中,人们去超市买东西,都是把商品放在一个购物篮里,等到把所有要买的东西选购完毕后,一起拿到收银台前付钱。我在程序里定义的购物车实体就是模拟这个功能.作为购物车,购物人,购物时间,所购书的总价格都是必不可少的:
private String id;
private String userName;
private String orderDate;
private String orderPrice;
我觉得在这个Bean里面主要要解决的一个问题,如何解决一个新的购物车。当一个顾客买完书提交购物车后,我们必须插入一个新的购物车纪录,这是由insertOrder()方法来实现的:其插入代码如下:
conn = DriverManager.getConnection(sConnStr);
PreparedStatement prepStmt = conn.prepareStatement(sql);
String curDate=(java.util.Calendar.getInstance().getTime()).toString();
prepStmt.setString(1,userName);
prepStmt.setString(2,curDate);
prepStmt.setString(3,orderPrice);
prepStmt.executeUpdate();
这里,插入的原理和前面是相同的,但是有一个地方需要解释:即购物时间字段,是采用的java.util.Calendar.getInstance().getTime(),这是一个库函数,被封装在java.util,在这个类定义的开头,我把这个库文件包含进来:
import java.util.*;
这个方法返回的结果必须把转化成String,否则后面插入数据库时会出现类型不匹配的错误。toString()就是用来实现类型转换的。
为了方便后面对这个购物车进行操作,我在这个方法里还获得了该购物车的id:
String selectStatement ="select id " +"from orderlist where user_name=? order by id desc ";
PreparedStatement prepStmt = conn.prepareStatement(selectStatement);
prepStmt.setString(1,userName);
ResultSet rs = prepStmt.executeQuery();
rs.next();
String result=rs.getString(1);
return result;
在sql里,查询特定用户购物车的id号,并且按照降序排列。是因为,针对一个网上购书系统,顾客可以多次在这里购书,那么在购物车表单里,针对一个顾客会有很多条他的购物纪录,而在数据库里,各条记录的id是安装时间先后顺序逐渐递增的,如果安装降序排列,那么得到的第一条记录则是最新插入的纪录。result=rs.getString(1)表示只把该条记录的第一个字段传给result,即把购物车的id号传给result。
4.3.5 实现购物实体的Bean
1)买书的第一步便是用户登录,现在购书网站都要求已经注册过的用户才能购买书籍,这样便于网站管理。checkUser(String userName,String userPassword)就是用来检验用户的合法性的:
public int checkUser(String userName,String userPassword)
{
int result=0;
UserEntity user=null;
try{
user=UserEntity.queryUser(userName);
}
catch(SQLException ex)
{
System.err.println(ex.getMessage());
}
if(user==null)
return 0;
String pass=user.getUserPassword();
if(pass.compareTo(userPassword)==0)
{
result=1;
this.userName=userName;
}
return result;
}
这个函数传过来的2个参数分别是用户登录时候填写的用户名和密码,前面已经介绍过,在UserEntity里面有一个查询特定用户名的记录的方法,我根据用户登录上填写的用户名查询记录:queryUser(userName),并把结果赋给一个对象user。把传过来的密码和和这个对象的密码比较,
pass.compareTo(userPassword)==0,如果相同,则用户是合法的,可以购买本网站的书籍,result=1;如果不相同,则说明他是非法登录的,只能浏览网站,不能买书,result=0。Result就是这个函数的返回值,是一个整型变量。
4.3.3 实现订购单实体的Bean
客户每次购买一种商品都会产生一次订购单,它包括订单号,所购买的书号,所购买这种书的数量,这些构成了这个类的私有属性:
private String id;
private String orderId;
private String productId;
private String productNum;
1)客户每次选中一种商品后,点击放入购物车,就会产生一个订单,其实现代码如下:
String sql="insert into order_item(order_id,product_id,product_num) values(?,?,?) ";
ResultSet rs = null;
try
{
conn = DriverManager.getConnection(sConnStr);
PreparedStatement prepStmt = conn.prepareStatement(sql);
prepStmt.setString(1,orderId);
prepStmt.setString(2,productId);
prepStmt.setString(3,productNum);
prepStmt.executeUpdate();
}
订购单,书号,购买数量都是作为参数传过来的。很明显,新建一张订购单其实就是在order_item表里插入一条新纪录就可以了。其原理已经在上面说过来了,就不在此重复了。
2)在后面的购物车里,一名顾客的最终消费总额就是根据这里一张张的订购单得到的,所以查找特定订单号的订购单是这个类里面不可缺少的方法,它的算法实质上就是条件查询,和前面的无条件查询相比,我只把sql语句作了改动:
String sql="select id,order_id,product_id,product_num from order_item where order_id= ? ";
2)第3个被封装的方法是设置,获得订购单号,书号,定购数量,并且还可以获得session price.
4.3.4 实现购物车实体的Bean
在现实生活中,人们去超市买东西,都是把商品放在一个购物篮里,等到把所有要买的东西选购完毕后,一起拿到收银台前付钱。我在程序里定义的购物车实体就是模拟这个功能.作为购物车,购物人,购物时间,所购书的总价格都是必不可少的:
private String id;
private String userName;
private String orderDate;
private String orderPrice;
我觉得在这个Bean里面主要要解决的一个问题,如何解决一个新的购物车。当一个顾客买完书提交购物车后,我们必须插入一个新的购物车纪录,这是由insertOrder()方法来实现的:其插入代码如下:
conn = DriverManager.getConnection(sConnStr);
PreparedStatement prepStmt = conn.prepareStatement(sql);
String curDate=(java.util.Calendar.getInstance().getTime()).toString();
prepStmt.setString(1,userName);
prepStmt.setString(2,curDate);
prepStmt.setString(3,orderPrice);
prepStmt.executeUpdate();
这里,插入的原理和前面是相同的,但是有一个地方需要解释:即购物时间字段,是采用的java.util.Calendar.getInstance().getTime(),这是一个库函数,被封装在java.util,在这个类定义的开头,我把这个库文件包含进来:
import java.util.*;
这个方法返回的结果必须把转化成String,否则后面插入数据库时会出现类型不匹配的错误。toString()就是用来实现类型转换的。
为了方便后面对这个购物车进行操作,我在这个方法里还获得了该购物车的id:
String selectStatement ="select id " +"from orderlist where user_name=? order by id desc ";
PreparedStatement prepStmt = conn.prepareStatement(selectStatement);
prepStmt.setString(1,userName);
ResultSet rs = prepStmt.executeQuery();
rs.next();
String result=rs.getString(1);
return result;
在sql里,查询特定用户购物车的id号,并且按照降序排列。是因为,针对一个网上购书系统,顾客可以多次在这里购书,那么在购物车表单里,针对一个顾客会有很多条他的购物纪录,而在数据库里,各条记录的id是安装时间先后顺序逐渐递增的,如果安装降序排列,那么得到的第一条记录则是最新插入的纪录。result=rs.getString(1)表示只把该条记录的第一个字段传给result,即把购物车的id号传给result。
4.3.5 实现购物实体的Bean
1)买书的第一步便是用户登录,现在购书网站都要求已经注册过的用户才能购买书籍,这样便于网站管理。checkUser(String userName,String userPassword)就是用来检验用户的合法性的:
public int checkUser(String userName,String userPassword)
{
int result=0;
UserEntity user=null;
try{
user=UserEntity.queryUser(userName);
}
catch(SQLException ex)
{
System.err.println(ex.getMessage());
}
if(user==null)
return 0;
String pass=user.getUserPassword();
if(pass.compareTo(userPassword)==0)
{
result=1;
this.userName=userName;
}
return result;
}
这个函数传过来的2个参数分别是用户登录时候填写的用户名和密码,前面已经介绍过,在UserEntity里面有一个查询特定用户名的记录的方法,我根据用户登录上填写的用户名查询记录:queryUser(userName),并把结果赋给一个对象user。把传过来的密码和和这个对象的密码比较,
pass.compareTo(userPassword)==0,如果相同,则用户是合法的,可以购买本网站的书籍,result=1;如果不相同,则说明他是非法登录的,只能浏览网站,不能买书,result=0。Result就是这个函数的返回值,是一个整型变量。
若图片无法显示请联系QQ3710167
基于JSP网上书店系统
2)证明是合法用户后,就必须给这个用户一个购物车,用户每次选中一本书,点击“放入购物车”,就必须添加一个订购单。这就相当于把用户要买的书放入购物车里,insertOrder()就是用来实现这些的,其主要代码如下:
public void insertOrder()//insert intoDataBase
{
try
{
if(orderPrice==0)
return;
OrderEntity oe=new OrderEntity("null",userName,"null",Integer.toString(orderPrice));
//insert order
orderId=oe.insertOrder();
//创建一个购物车,并且获得它的id号
//insert order items
for(int i=0;i
{
OrderItemEntity oi=(OrderItemEntity)orderItem.elementAt(i);
oi.setOrderId(orderId);
oi.insertOrderItem();
}
}
catch(SQLException ex)
{
System.err.println("InsertOrder executeQuery: " + ex.getMessage());
}
//clear order variable
orderItem.removeAllElements();
orderPrice=0;
}
当orderPrice==0,说明用户还没有开始买书,在这个时候创建购物车,并且获得它的id号,保存在orderId这个变量里。一个客户可以有很多张订购单,但是购物车id号是一样的,所以在插入订购单的时候,必须把其购物车的id号设置为orderId。
3)addOrderItem(String productId,String productPrice)实现的是购买一种商品多次:
public void addOrderItem(String productId,String productPrice)
{
for(int i=0;i {
OrderItemEntity oi=(OrderItemEntity)orderItem.elementAt(i);
String pId=oi.getProductId();
if(pId.compareTo(productId)==0)
{
int num=Integer.parseInt(oi.getProductNum());
++num;
oi.setProductNum(Integer.toString(num));
//修改购买productId的书的数量
this.orderPrice+=Integer.parseInt(productPrice);
//总价格要加上新买的书的价格
return;
}
}
OrderItemEntity oiNew=new OrderItemEntity("null","null",productId,"1",Integer.parseInt(productPrice));
orderItem.add(oiNew);
this.orderPrice+=Integer.parseInt(productPrice);
}
因为每点击一次“放入购物车”,只能购买相应的商品一次,并且数量之能为1。但是购买的是同一个商品,其productId是一致的,要重新写入一张订购单,就必须把原来productId的订购单修改一下就可以了。比较用户确实是买的一样id的书:pId.compareTo(productId),如果是,则修改订购单的数量,num++,把总价格加上本书的价格:
this.orderPrice+=Integer.parseInt(productPrice); 通过以上的操作,把修改后的结果作为新的属性重新插入成新的订购单。
4)用户可以购买一种书多次,那么当它放入购物车后,发现拿多了,也应该可以把多余的退出来,其实现原理和addOrderItem是一样的,其具体代码陈列如下:
public void deleteOrderItem(String productId)
{
for(int i=0;i {
OrderItemEntity oi=(OrderItemEntity)orderItem.elementAt(i);
String pId=oi.getProductId();
if(pId.compareTo(productId)==0)
{
int num=Integer.parseInt(oi.getProductNum());
--num;
oi.setProductNum(Integer.toString(num));
if(num==0)
orderItem.removeElementAt(i);
基于JSP网上书店系统
this.orderPrice-=oi.getPrice();
return;
}
}
}
1)在CartManager类里,还封装了一个书查询的方法,主要是调用了
ProductEntity类里的queryProduct方法。需要说明的地方是,先是查询结果的时候分页显示的,每页显示的书籍的资料最多不超过10本。这是由pageSize这个变量来实现的。关于这个变量,我把它定义成CartManage的私有成员:
private int pageSize=10;
public void setPageSize(int pageSize)
{
this.pageSize=pageSize;
}
4.3.6 前台运行程序cart.jsp
通过这个jsp程序,我实现了3个功能:
1:显示主页面;
2:把主页面里浏览者的资料和请求传给后台的Bean来处理;
3:调用Bean,来实现系统的登录,查询,分页处理,购书等功能
在程序的开头有这样2条语句:
<%@ page language="java" import="java.util.*,cart.*" %>
上面已经说明,我把所有的Bean文件都放在了cart里面,要使得能在jsp文件中使用它们,就必须用import把cart包含进来。
下面我想介绍一下useBean这个动作,通过useBean动作我建立了一个类型为cartManager的Bean对象cartManager,我实现的所有功能都是通过调用这个对象的方法来实现的。
1)我把主页面分为3个部分,每个部分作为一个表格来处理:
实现登录框的表格:若图片无法显示请联系QQ3710167
实现书籍清单的表格:
|
商品ID |
商品名称 |
商品价格 |
商品说明 |
当前第<%=pageCount%>页 |
实现购物信息的表格:若图片无法显示请联系QQ3710167
基于JSP网上书店系统
购物车 |
商品ID |
数量 |
上面只列出了部分代码,从上面的代码里很容易发现一个共同点,就是它们都是用了标签.我通过这个标签,把前台的数据传给后台的函数.form有2个很重要的属性,一是action,它用来指明从客户端保存的数据传到哪里去,在我的程序里,它通常都只向cart.jsp,然后在cart.jsp里,用request对象来接收这些数据,最终作为函数的参数使用;二是method,它是指传递数据的方式,在这里我都是采用的post方式。Form里面很重要的另外一个东西就是:input,它是与用户进行交互的主要工具。根据不同的类型,可以有不同的作用。我使用了其空白框给用户填写数据,其type=’text’,按钮是form里必不可少的,type=’submit’,只有当用户点击确定按钮,客户端才会最终把这些数据传给cart,jsp来处理。
2)我在实现这个系统的时候,主要是根据用户对页面的点击做出回应的,所以在cart.jsp里我设置了一个String op=request.getParameter("op");当op取不同的值的时候,就调用不同的函数完成不同的功能,其代码如下:
if(op!=null&&op.compareTo("login")==0)
{
int result=cartManager.checkUser(request.getParameter("userName"),request.getParameter("userPassword"));
if(result==1)
loginInfo="登录成功!欢迎你";
else
loginInfo="登录失败!";
}
//表示顾客点击的是‘登录’,这个时候就调用cartManager类里的checkUser()方法,这里用的对象cartManager就是先前在开通通过uesBean动作定义的那个对象。UserName是刚刚通过登录表格的form标签传过来的用户名,它作为checkUser的实参。这个参数返回一个int值,1表示登录成功,0表示登录失败。
if(op!=null&&op.compareTo("cart")==0)
{
if(cartManager.getUserName().compareTo("")!=0)
cartManager.addOrderItem(request.getParameter("productId"),request.getParameter("productPrice"));
else
loginInfo="请先登录!";
}
//如果客户点击放入购物车,这时就会有2种情况,一种是这位顾客还没有登录,那么他是不能买书的;另外一种是登录成功,那必须为这次采购插入一张订购单。我是通过购物车类中的usename来识别这2种情况的。因为只要他登录成功,系统就会为他创建一个购物车类的对象,那么他的username一定不为空,就执行cartManager 对象的addOrderItem()方法,这个函数在调用的时候必须传过去的参数是:书名号,书价格。如果比较的结果为空,则打印请先登录的提示信息。
if(op!=null&&op.compareTo("cartDeleteItem")==0)
{
cartManager.deleteOrderItem(request.getParameter("productId"));
}
//如果顾客把书放入购物车后又不想买了,就会执行cartManager对象的 deleteOrderItem()方法,为什么这里不需要像上面一样比较是否登录呢?是因为顾客既然要删除订购单,那么肯定是成功买了书,根据上面可以知道,卖过书的顾客肯定是成功登录过的。其中,productId是它的实参。
if(op!=null&&op.compareTo("submitOrder")==0&&Integer.parseInt(cartManager.getOrderPrice())!=0)
{
cartManager.insertOrder();
orderInfo="您的购物单已提交,ID是:"+cartManager.getOrderId();
}
//最后是顾客购买活动全部结束,提交购物车,这时插入这个购物车,并且核算金额。
//set the product list
cartManager.setPageSize(10);
Vector vProduct=cartManager.queryProduct(pageCount);
// out.print("queryProductId:"+cartManager.getQueryProductId()+" ");
//set the orderItem list
Vector vOrderItem=cartManager.getOrderItem();
基于JSP网上书店系统
第五章 总结
本文论述了一个基于WEB的网上商品销售系统,基本上体现了电子商务各方面的优点。
我所设计的网上书店,主要是熟悉和掌握JSP的技术以及对电子商务进行初步的探讨和设计。在几个月的设计过程中,我初步了解了JSP的优点和先进之处,也看到了JSP技术在电子商务应用上的光明前途。通过这次设计,我设计的网上书店基本完成了要求的诸项基本功能,实现了一个简单的不同部分以数据为中心的模型,在方案的各部分在实际运作中能够解决相应的问题。
在设计和制作网上书店这一个整体项目的过程中,也培养了自己的综合能力和从全局考虑的思想。将复杂的问题简单化,作为电子商务应用的一个缩影,我所涉及的模块项目完成了其后台具有的基本功能,使自己对于电子商务的了解更加深入和明了。
当然,其中也遗留下了一些待解决的问题,但出于自己水平有限,作为一个网上书店系统,该项目上有一些不完善和函待改进之处,特别是在网站信息的安全性上需要进一步加强。
致谢
经过三个多月的毕业设计,在指导老师符琦的指导下基本开发完成了网上书店。本系统功能还不是十分的完善,但基本上能完成用户在网上购买书籍。其主要功能有用户登录,书籍查询,购物车,以及订单处理等功能。界面美观,明了,易操作。
通过毕业设计我学到了很多新知识,个人能力与了很大的提高。在设计中经常遇到种种困难与挫折,几次陷入停顿状态。在这种情况下,指导老师不但给予我的很多的鼓励,而且在设计上提出了很多正确的建议和善意的批评。还有同组的宋浩同学,跟我是做一个类型的设计。大家一起搜集各种相关资料,一起探讨技术问题,一起攻克设计中的各种困难。使我深刻体会到团队精神的重要性。
在这里,顺利完成毕业设计我首先要感谢指导老师符老师的细心指导,他帮助解决了我们设计中的疑难和困惑,为我完成设计提供了极大的帮助。符琦老师为我设计了提纲和基本要求,在这个学期中,我随时都能与他取得联系询问相关问题,他总是耐心的为我作出解答,并多次给热心地帮我查找相关书籍资料。我的这次设计顺利完成离不开符琦老师的帮助;同组的设计成员宋浩同学也为我提供了不少的帮助,在此一并向他们表示衷心的感谢!
不过对我们来说,由于时间有限,也包括我们的知识水平有限,系统中有不足之处,还请各位老师指导指正。
参考文献
[1] 汪孝宜、刘中兵、徐佳晶等编著,JSP数据库开发实例精粹,电子工业出版社,2005
[2] 姚晓春、郑文清等编著,Java编程技术教程,清华大学出版社,1999
[3] 吴逸贤、吴目诚编著,Java2程序设计,科学出版社,2003
[4] Http://www.java.sun.com
[5] Http://www.jspcn.net (Jsp 中文网)
| |