这几天一直没有发博文,原因是在写一个书城的小项目,作为web学习的最后沉淀,接下来就要到框架的学习了。项目最后会分享源码链接。有需要的同学可以拿到自己玩一玩
--WH
一、项目介绍
从网上找的一个培训机构的小项目,名称叫做 书城购物网站 吧,其中就是分前后台,前台用于显示各种类型的书籍商品,可以用于加入购物车,可以购买付款下单,后台就用来对书籍、书类别的增删改,和对订单的处理。一个不是很复杂的项目,但是在没开始编写之前,确实是毫无头绪,无从下手,那是因为没有对该项目有一个大体的认识,不知道其中的层次模块,所以不好从哪里开始着手去写代码,等会听我慢慢道来,我会把我编写的思路和你想法一步步告诉大家,在之前,先把效果给大家看一下吧。
前台首页
没登录之前,可以查看全部书籍商品,也就点击全部分类即可,也可以通过分类找到对应类别的书籍(每页显示12个商品,有分页功能)
然后进行注册,这里用了AJAX对注册的用户名进行了校验,为了不让重名,并且可以发送激活码的邮件对帐号进行激活,没激活的用户是登录不了的。
登录之后,加入商品到购物车
、
对自己的订单进行查看(提前已经有数据的),一些订单还没有付款就可以进行付款,付款了就等待后台点击发货,发了货就等待自己点击确认收获即可。
对订单付款,选择其一个银行就会跳转到哪个银行的页面进行付款,作为实验,每次只会付一分钱,付给的是一个测试帐号。也可以自己去申请,用的是易宝支付平台
前台大概就是这样了,现在来说说后台的东西,后台很简单。就管理这些商品即可。
后台首页
其中的功能已经在左边的列表中清清楚楚的写着了,对分类,图书和订单进行管理,包括增删改查操作。这里就不做过多介绍了,对订单的管理有一个小的逻辑管理,可以对已经付款的订单进行发货处理,那么就等待前台用户点击确认收获,确认收获后,就成了已经完成的订单了。
二、分析项目结构模块
刚开始拿到这个项目的前端架子时,只能说,看起来很简单的几个操作,也就登录,注册,查看书籍信息,加入购物车,付款下单,点来点去就这样几个页面,但是让自己拿起来实现,确实是没一点头绪,不过写完了,就会对这个项目有一个总体的了解,就相当于,一开始用2D画面,现在是用上帝视角在看这个项目,一目了然的感觉。先来写说说编写思路。
首先要看懂数据库的设计,理清楚关系,然后了解项目需要分哪几个模块。搞懂了这几个,基本上就有个大概的了解,就可以动手写代码实现了。
2.1 数据库设计。
五张表,现在一个个来分析,
user表,用来进行登录注册,对用户进行识别和管理的。
uid:唯一识别码,采用UUID获得一个32位的字符串,用于标识该用户。
username:登录时的用户名,唯一,不能重复。
password:登录密码,并没有加密,按常理应该会使用加密,这样到数据库中查看数据也看不到原始密码。
email:邮箱,用于接收激活邮件
state:是否激活的状态标识。1为激活,0为未激活
cdkey:激活码。
为了了解其中的email,state,cdkey三个字段,就要知道发送激活码邮件的流程,首先注册时候,state为0,未激活状态,注册会创建一个激活码,假设为123,cdkey=123,然后通过email,用户留下来的邮箱,往该邮箱发送一个激活邮件,内容为一个 超链接,超链接中会带两个参数,一个参数存放这123,一个参数存放uid,标识该用户,点击超链接就会跳转到一个处理激活的servlet中,将拿到的激活码参数内容跟数据库中cdkey对比,看是否一样,一样的话,那么就为激活了,利用uid将用户state改为1,如果不一样,说明不是该用户点击激活码邮件过来的,不作处理。
category表,图书分类的类别表,比如玄幻,言情等。该表比较简单,看上面的项目介绍,就能够知道,主页中旁边的类别就是从该表中拿到的数据。
cid:唯一标识码,同样使用uuid,获得32位字符串来充当该值
cname:类别名称。
book表,书籍表,用于存放所有的书籍信息。
bid:唯一标识码
bname:图书名称
price:图书价格,采用的是decimal类型,保留2为小数点的。也就是价格精确到分
author:图书作者
image:图书的图片,存放的是图片的路径,而不是将图片存放在数据库中
cid:指向category表中的cid字段,是一个外键字段,作用是标识该本书籍是属于哪个类别的。
isdel:这个是图书的状态,是否下架?这个字段在我写的项目中并没有用到,我没有编写这块的逻辑代码。
分析下来,就将book表跟category表联系起来了,每本书都会有一个专属的类别,这样就可以通过类别来查询对应的书籍了,想一想前台主页上的通过分类查找到对应书籍进行显示,就是通过这两张表的关系来解决的。
orders表,订单表
oid:唯一标识码
total:价格,也就是这个订单中可能有多个商品,多个商品的总价格就为total
ordertime:下单的时间,类型,time
state:订单的状态,有四个状态,分别用1,2,3,4来识别,1:未付款,2:已经付款,待发货,3:已发货,待收货,4:已经收货,订单完成,
address:地址,送货肯定需要一个地址。
uid:指向user表中的uid字段,是一个外键字段,标识着该订单是哪位用户的。
通过orders表,就将user表给联系起来了,到时前台要显示每位用户自己的订单时,就通过orders表中的uid字段,来查询自己所有的订单。
orderitem表,订单项目表,因为一个订单中可能有多个商品,那么每个商品都要生成一个orderitem记录,这样通过一个订单就可以查找到该订单中有多少个商品。
itemid:唯一标识码
count:一件商品购买的数量,比如买A这本书一次买了两本,由于是两本A书,那么就不用生成两个orderitem记录了。
subtotal:总价为多少
bid:指向book表的bid,为一个外键字段,标识着该订单项是哪本书籍
oid:指向orders表中的oid,为一个外键字段,标识着该订单项是属于哪个订单的。
该表就将三个表联系在一起了,book表,orders表,orderitem表,user表。他们的关系应该也清楚了,一个orders表中的一条记录为一个订单,该订单是属于谁的(通过订单中的uid字段),该订单中有多少种商品(通过orderitem表中的oid字段),订单中每种商品的信息(通过orderitem表中的bid字段)。其实我们说的就是一对多的对应关系,在多的一方存储外键字段。自己可以分析分析,这5张表之间的关系,通过谁可以查找到谁。
2.2 分析前台模块
用户模块
登录,注册
注册
AJAX异步校验用户名
发送激活邮件
激活完成
登录
判断用户帐号密码和是否激活,并将自身存入session中
退出
销毁session
类别模块
查询所有分类。
首页中显示分类信息,从category表中拿去所有类别信息
图书模块
显示所有图书,根据分类查询图书,根据图书id查询图书详细信息。
点击分类模块中的类别,就能将该类别下面的图书展示出来。点击全部分类,则将全部图书都显示出来,此处就是使用category表和book表结合查询,点击其中一本图书,将显示图书的详细信息,并且提示有购买的按钮,此按钮是将其图书加入购物车
购物车模块
添加到购物车,从购物车中移除商品,清空购物车
此处使用的是一个Map来充当购物车的容器,使用LinkedHashMap,优点是存取快捷,其原理为,创建一个 购物车项(cartItem)的javabean,其中有三个属性,book对象,有购买数量acount,还有总金额allMoney,用这三个属性来标识一个商品,购物车则用Map充当,Map<String,CartItem>。 String:装的是bid(book的唯一识别码),CartItem就是装的购物车项。
将 A 书加入购物车,
首先将A书封装成CartIitem对象,book属性就是A书的所有信息,acount代表这次加入购物车的A书有几本,allMoney代表总金额为多少,
封装成CartItem后,将其加入cart(购物车,也就是map集合)
通过A书的唯一识别码bid跟cart中的所有key值进行比较,判断cart中是否已经存在A书
如果存在A书,则找到cart中key为bid的cartItem,在往cartItem中修改acount和allMoney。
如果不存在A书,则将A书存入cart中,用A书的bid充当key值,用A书封装好的CartItem充当value,
将cart(购物车,也就是map集合)存入session作用域中,存session作用域的话,就不能永久保存该用户的购物车,根据session的特性,关闭浏览器还会默认保存30分钟,并且如果不将cookie设置在浏览器保存的话,关闭浏览器即丢失sessionId,session则找不到,也就是购物车中的内容就丢失了,所以存到session中的特点就是我说的那样,也可以将购物车存到数据库中,那么用户不管什么时候登录,在哪里登录,都能够找得到自己的购物车。
订单模块
生成订单,根据用户查询订单,根据订单id查询订单项,在线支付功能,修改订单状态
将商品加入购物车后,可以点击进行付款,此时会跳转到选择支付方式页面,并且生成订单,此时的订单state为1,为未付款状态,编写地址后,进行付款,跳到付款页面,付款成功后,会跳转回我们自己的页面,此时订单state为2.称为已付款代发货状态,在生成订单的同时,也会生成orderitem(订单项),也就是将每一件商品都生成订单项。其业务操作是在service层完成的。
2.3 分析后台模块
分类管理 对category表进行操作。
1、查询分类,将所有分类信息查询出来
2、添加分类,
3、修改分类
4、删除分类
图书管理
1、查询图书
将所有图书信息查询出来
2、添加图书
文件上传(将图片信息上传)
3、修改图书
修改图书图片或其他信息
4、图书下架(删除)
订单管理
1、查询所有状态的订单
2、查询出各个状态的订单(未付款,已付款待发货,已发货待确认收货,已确认收获订单完成)
三、编写流程
3.1、搭建项目环境
使用的是三层经典架构,web层、service层、dao层,如果想使用接口编程那么就在其中在进行分接口类和实现类。
我的包结构
将所有需要使用的jar包加入。
mysql:1个jar包
c3p0连接池:1个jar
dbutils框架:1个jar
文件上传:2个jar io和核心jar(fileUpload)
邮件发送:1个jar javamail
JSP:2个jar,jstl和el表达式(因为使用JSP,可能需要使用自定义标签或者别的标签,所以就先将其带入进来,以防不备之需)
beanUtils:2个jar beanutils和logging。(我没用beanUtils)
3.2、编写代码
1、开发环境搭建好之后,首先将使用dbutils框架将连接数据库的代码编写好。
2、按照上面的模块进行编写,首先是用户模块的注册,登录,从JSP写到Servlet到service层到dao层。就这样从前写到后的顺序编写。
3、其他就是按部就班了,当真正开始编写时,一切就会能按照自己的思路进行下去,而不是像一开始那样,无从下手。
3.3、注意,
这里编写servlet时使用了反射机制,目的是为了减少servlet的个数,而为了简化servlet个数的方式有两种。
第一种。
还是按照老的方式,继承httpServlet,重写doGet和doPost方法,在发送请求时,把需要访问的servlet方法用参数的方式传过去,然后在serlvet内部判断请求参数是需要调用哪个方法,将方法体都写在该servlet下面,在doget或者dopost方法内调用即可。
第二种
利用反射机制,反射加载对应方法。此时需要大家了解servlet的生命周期经历的三个方法,最重要的是知道访问servlet会进过service方法。知道了这个一切就好办了,编写一个通过的servlet,取名为BaseServlet。
分析:将所有的方法都写在一个新的servlet类中,该类就继承BaseServlet。当访问新的servlet类中,因为需要执行service方法,而子类中并没有,就到父类BaseServlet中去寻找并执行,在在父类中会将拿到要执行的方法名,通过反射机制,去执行子类中对应的方法,所以就将需要执行的方法和service只能够代码分离开了,在子类中全部都是需要编写的逻辑代码。不用对method进行判断从而选取对应方法进行执行,省去了很多麻烦,使代码更加简洁,易懂。
四、总结
通过这个项目,使自己对三层经典架构理解的更加深刻,并且对于web中的大大小小的知识点进行了巩固,JSP中的四大作用域,9大内置对象,el表达式的使用,发送邮件,在线支付环节等等很多知识,并且通过servlet+JSP+数据库的模式确实比较复杂,从而知道了使用框架的好处,便于开发。
现在献出该项目源代码,希望对大家有所帮助。
http://pan.baidu.com/s/1i4W79BZ 67me