转自:https://blog.csdn.net/eson_15/article/details/51418350
上一节我们将商品的详细页面做完了,并使用了Hibernate的二级缓存加载详细页面来提高系统的性能。这节我们开始做购物车部分。
1. 添加新的表
首先我们向数据库中添加几张表:用户表、订单状态表、订单表(购物车表)以及购物项表。用户表中存有用户的基本信息,订单状态表中主要存储订单的状态,比如已发货这种,订单表主要存储用户的信息和订单的状态,所以跟用户表和订单状态表关联,购物项表存储某个商品以及所属的订单,所以跟商品表和订单表相关联。具体的表信息见下面的sql语句:
1 /*============================*/ 2 /* Table: 用户表结构 */ 3 /*============================*/ 4 create table user 5 ( 6 /* 用户编号,自动增长 */ 7 id int primary key not null auto_increment, 8 /* 用户登录名 */ 9 login varchar(20), 10 /* 用户真实姓名 */ 11 name varchar(20), 12 /* 用户登录密码 */ 13 pass varchar(20), 14 /* 用户性别 */ 15 sex varchar(20), 16 /* 用户电话 */ 17 phone varchar(20), 18 /* 用户Email */ 19 email varchar(20) 20 ); 21 22 /*=============================*/ 23 /* Table: 订单状态表结构 */ 24 /*=============================*/ 25 create table status 26 ( 27 /* 状态编号,自动增长 */ 28 id int primary key not null auto_increment, 29 /* 订单状态 */ 30 status varchar(10) 31 ); 32 33 /*=============================*/ 34 /* Table: 购物车(订单)表结构 */ 35 /*=============================*/ 36 create table forder 37 ( 38 /* 订单编号,自动增长 */ 39 id int primary key not null auto_increment, 40 /* 收件人名字 */ 41 name varchar(20), 42 /* 收件人电话 */ 43 phone varchar(20), 44 /* 配送信息 */ 45 remark varchar(20), 46 /* 下单日期 */ 47 date timestamp default CURRENT_TIMESTAMP, 48 /* 订单总金额 */ 49 total decimal(8,2), 50 /* 收件人邮编 */ 51 post varchar(20), 52 /* 收件人邮编 */ 53 address varchar(200), 54 /* 订单状态 */ 55 sid int default 1, 56 /* 会员编号 */ 57 uid int, 58 constraint sid_FK foreign key(sid) references status(id), 59 constraint uid_FK foreign key(uid) references user(id) 60 ); 61 62 /*=============================*/ 63 /* Table: 购物项表结构 */ 64 /*=============================*/ 65 66 create table sorder 67 ( 68 /* 购物项编号,自动增长 */ 69 id int primary key not null auto_increment, 70 /* 被购买商品的名称 */ 71 name varchar(20), 72 /* 购买时商品的价格 */ 73 price decimal(8,2), 74 /* 购买的数量 */ 75 number int not null, 76 /* 所属商品编号 */ 77 pid int, 78 /* 此订单项,所属的订单编号 */ 79 fid int, 80 constraint pid_FK foreign key(pid) references product(id), 81 constraint fid_FK foreign key(fid) references forder(id) 82 );
然后我们将这些表通过逆向工程转换为POJO,具体不在赘述。
2. 购物车的后台逻辑
2.1 Service层的逻辑
当用户将某个商品加入购物车时,我们首先要通过商品的id获取该商品信息,然后将该商品添加到购物车中,在添加之前,我们首先得判断当前session中有没有购物车,如果没有的话,我们得先创建一个购物车,如果有,我们将当前的购物项添加到购物车里,在添加之前,需要先判断该购物项在购物车中是否已经存在了,如果存在了只需要增加相应的购物数量即可,如果不存在则添加,然后计算购物总价格,最后将购物车存到session中。整个流程见下面的示意图:
接下来我们来实现具体的逻辑,首先新建两个Service接口:SorderService和ForderService。SorderService中主要定义了两个方法:将用户添加的商品转换为购物项,然后将购物项添加到购物车;ForderService中主要定义了计算购物车总价格的方法,如下:
1 //SorderService接口 2 public interface SorderService extends BaseService<Sorder> { 3 //添加购物项,返回新的购物车 4 public Forder addSorder(Forder forder, Product product); 5 //把商品数据转化为购物项 6 public Sorder productToSorder(Product product); 7 } 8 9 //ForderService接口 10 public interface ForderService extends BaseService<Forder> { 11 //计算购物总价格 12 public double cluTotal(Forder forder); 13 }
然后我们具体实现这两个接口:
1 //SorderServiceImpl实现类 2 @Service("sorderService") 3 public class SorderServiceImpl extends BaseServiceImpl<Sorder> implements 4 SorderService { 5 6 @Override 7 public Forder addSorder(Forder forder, Product product) { 8 boolean isHave = false; //用来标记有没有重复购物项 9 //拿到当前的购物项 10 Sorder sorder = productToSorder(product); 11 //判断当前购物项是否重复,如果重复,则添加数量即可 12 for(Sorder old : forder.getSorders()) { 13 if(old.getProduct().getId().equals(sorder.getProduct().getId())) { 14 //购物项有重复,添加数量即可 15 old.setNumber(old.getNumber() + sorder.getNumber()); 16 isHave = true; 17 break; 18 } 19 } 20 //当前购物项在购物车中不存在,新添加即可 21 if(!isHave) { 22 forder.getSorders().add(sorder); 23 } 24 return forder; 25 } 26 27 @Override 28 public Sorder productToSorder(Product product) { 29 Sorder sorder = new Sorder(); 30 sorder.setName(product.getName()); 31 sorder.setNumber(1); 32 sorder.setPrice(product.getPrice()); 33 sorder.setProduct(product); 34 return sorder; 35 } 36 } 37 38 //ForderServiceImpl实现类 39 @Service("forderService") 40 public class ForderServiceImpl extends BaseServiceImpl<Forder> implements ForderService { 41 42 @Override 43 public double cluTotal(Forder forder) { 44 45 double total = 0.0; 46 for(Sorder sorder : forder.getSorders()) { 47 total += sorder.getNumber() * sorder.getPrice(); 48 } 49 return total; 50 } 51 52 }
然后我们需要将这两个bean注入到BaseAction中,供SorderAction使用:
1 @Controller("baseAction") 2 @Scope("prototype") 3 public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> { 4 5 //省略其他无关代码…… 6 7 @Resource 8 protected ForderService forderService; 9 @Resource 10 protected SorderService sorderService; 11 12 }
好了,Service层的逻辑做完了,接下来准备做Action部分:
2.2 Action部分的逻辑
我们新建一个SorderAction,将上面的逻辑图上显示的流程走一遍即可完成添加购物车的逻辑了。代码如下:
1 @Controller 2 @Scope("prototype") 3 public class SorderAction extends BaseAction<Sorder> { 4 public String addSorder() { 5 6 //1. 根据product.id获取相应的商品数据 7 Product product = productService.get(model.getProduct().getId()); 8 9 //2. 判断当前session是否有购物车,如果没有则创建 10 if(session.get("forder") == null) { 11 //创建新的购物车,存储到session中 12 session.put("forder", new Forder(new HashSet<Sorder>())); 13 } 14 15 //3. 把商品信息转化为sorder,并且添加到购物车中(判断购物项是否重复) 16 Forder forder = (Forder) session.get("forder"); 17 forder = sorderService.addSorder(forder, product); 18 19 //4. 计算购物的总价格 20 forder.setTotal(forderService.cluTotal(forder)); 21 //5. 把新的购物车存储到session中 22 session.put("forder", forder); 23 return "showCart"; 24 } 25 }
配置一下struts.xml文件:
1 <action name="sorder_*" class="sorderAction" method="{1}">
2 <result name="showCart">/showCart.jsp</result>
3 </action>
然后跳转到购物车显示页面showCart.jsp,showCart.jsp中关于购物车部分的前台程序如下:
3. 前台链接的跳转
后台部分全部做完了,接下来将前台detail.jsp页面添加购物车的链接地址该成访问SorderAction即可:
这样就能正确跳转了,下面我们看一下购物车显示页面的具体效果:
这样我们购物车的基本功能就做完了,后面我们再对其做一些完善。