进入下一关,购物车的商品列表

一、需求

在杂货铺项目中,往日我们介绍了购物车功效模块的兑现,商品插手到购物车之后,就是到购物车结算,然后显示购物车的货色列表,点击去结算,然后到了未提交前的订单列表

1.游戏模块

①在进入H5从前,首先有一个动态的探照灯的动效,然后由“淡出”效果到H5首页。

②在点击“起首游戏”之后会有一段动画演示游戏内容,然后滑动开启娱乐,先河计时。

③成功找到对象短语之后,进入下一关。总共5关,难度递增。

④滑错之后,会唤醒滑错惩罚,第一次计时加2秒,前边每趟递增1秒。

⑤有“指示”按钮,有三次指示的时机,点击确定使用后会将正确的短语亮起荧光,一遍机遇用完提醒按钮消失。

⑥5关全体中标之后,显示游戏成绩以及战胜对手的比例。可以查看排名榜,会显得前10名+个人成就。

点击交付订单后,生成此订单,回到订单的订单号,付款金额,订单估算到达时间。订单系统是一个非凡首要的系统,大家的移动端、PC端都亟需订单系统,所以这边我们将订单系统独立作为一个劳动来,留出接口供客户单来调用

2.杂货店模块

I、打起头页,会有一段文字描述商城以及销售条款。点击“立时拥有”开头购物流程。

II、点击“顿时拥有”之后,跳转到商品列表页面,会突显商品的品名,类型,图片。商品列表是下跌类型的页面。

III、点击每个商品可以查阅商品详情,可以左右滑行查看3个意见的产品图片。鞋类的货物有取舍尺寸和尺寸参考这两个职能,包类的尚未。点击查阅产品详情可以查看商品介绍,可以插足购物袋。

IV、采取尺寸的时候列出所有的尺码,并且当以此码数只有一双的时候唤醒,仅剩一双。

V、点击“参预购物袋”,倘若商品售罄会跳转至售罄页面,假使没有跳转至购物袋。

VI、购物袋页面,以列表的款式把购物袋内容展现出来,并且可以去除。如若内部某款商品无货,则该商品的背景成为藏蓝色。可以点击“结算”按钮,倘使结算成功跳转至支付页面。

VII、结算的进程中要实时的盘算商品的库存,即使库存不足则无法结算成功,有两人同时结算同款产品的下压力。

VIII、支付页面 
分为配送情势、发票音讯、支付模式三片段,配送情势是必填,支付办法固定是微信支付,发票音信选填。点击“支付”按钮,调起微信支付,支付成功跳转至订单页面。

IX、支付失败 
会检测支付订单是否过期,即便超时跳转至首页。

X、订单页面,依据每个订单的货物分开显示,未开发的订单会有“付款”、“撤除”多少个按钮,支付的订单会有“收货地址”、“查看物流”、“申请售后”多少个按钮。

XI、“废除”或者订单超时订单都会呈现交易关闭,“付款”会跳转至付款页面,“收货地址”会显示用户的收货地址,“查看物流”会显得用户订单的忠实物流音信,“申请售后”会展现售后电话。

图片 1

 二、设计

 

1.游戏模块

 动画、效果方面根本由前端来兑现,这里不做解释。后端在戏耍部分重要包括六个地点:

①玩家在合格游戏之后的分数记录

②名次榜的精打细算

③游戏通关之后的享用和享用页面的呈现

后天我们来看下这多少个订单系统到底是怎么落实的:

2.超市模块

 商城模块除了有的页面的排版、展现需要前端来落实,其他的效益全体交由后端。重要效能包括:

①货物列表的突显,以及从个kol进来未来各产品和导航的藏匿与体现

②货品单品页商品的各样性能显示,如价格、图片、模特图、产品介绍等

③购物袋页面,要来得客户购买的东西
,可以去除商品,添加商品,结算购物袋

④结算页面,要来得与修改客户的收货地址、发票音讯、以及折扣信息(后来加的)、微信H5内群众号支付

⑤结算成功后,跳到成功页面;结算失利后,跳到订单页面。

⑥订单页面,彰显客户的享有订单号、订单状态,以及订单内的顺序单品信息、收货地址、物流音讯等

一、订单系统效能

三、实现以及问题

订单系统首要涵盖如何效率模块呢?

1.游戏模块

  游戏部分是一个近乎图案滑动解锁的游乐,在您入手这个单词划过“I
want
choo”这一个单词的时候,就会过关。连续闯过5关,游戏截止。每一关的难度会有升级,每关游戏的图腾是随机生成的,其中使用的技艺(我晓得的,因为自己不是前者,只承担后端以及互动的
部分)有下面这么些:

①绘画解锁

  图案解锁用的是一个patternlock.js的插件,在已有插件的景观要考虑的就是这么些游乐难度的政工。一最先应客户要求,最少要有50个以上的绘画供玩家玩,结果一起初客户代表还预备傻傻的去画50种图案放上去。后来设想到那多少个图案可能真的会画死人,最终决定用随意生成一个图案里面有着需要的字母,然后用canvas画在页面上。最终用patternlock.js那个js触摸解锁那些答案。效果如下:

图片 2

在触摸滑动那多少个单词错误的时候会有荒唐的音效指示,在点击“指示”后会在正确的“i
want choo”下边呈现褐色。

 ②计时器

  问题:

  1.香江客户反馈,计时器走的很慢,不是正规的一个秒数转换,而且越走越慢。

  2.会现身完了00:00.00的用户

  原因:

  计时器的话,一先河用的是setinterval,让他1000毫秒的时候,秒数地点上加1;60秒的时候分钟上边+1;听起来是不是很客观没有一点毛病,然后假设统计出先导时间和终止时间,得到他们的差值就是以这厮游戏时间。其实这是不当的。

  1.setinterval和settimeout的机制是把您要推行的代码在你设定的非常时间点插入js引擎维护的一个代码队列中,不过插入队列代码并不代表立刻执行,因为js解释引擎是单线程运行的。他会等到前边的代码先进行完将来才会来推行这些队列中的代码,因为平常页面代码很少,js执行高效,所以日常我们感到到定时器在你设置的那一刻他就开头运行了,运行的很平稳,这是一种错觉。在您设置定时器的时候取得开首时间只是代码设置的岁月,并不是定时器任务初阶的岁月。并且setInterval的回调函数并不是到时后及时执行,而是等系列总括资源空闲下来后才会执行.而下一次接触时间则是在setInterval回调函数执行完毕之后才起始计时,所以假若setInterval内推行的计量过于耗时,或者有其余耗时任务在履行,setInterval的计时会愈加不准,延迟很厉害.

  2.收获时间这里也是有漏洞的,大家平时用的Date.now()获取到的是从1970年10月1日00:00:00
UTC初始通过的阿秒数,他会依据系统时间来搜寻当前的年华戳。相当不幸的是,这么些函数会因为用户代理不同而不等同,精度异常不可靠,在同一时间不同地点获得到的岁月戳是不同的。

  3.说起来第一次探望出现00:00.00秒的用户,我的率先影响是自个儿付诸游戏数量的接口被口诛笔伐了,外人一定是拔取了另外的非法手段给本人付诸数据,我一点都没怀疑前端。我反省了后端的代码,有微信授权不太可能在微信之外的浏览器打开,不过微信授权是足以选择模拟器模拟出来的,我即刻想的是她必定是用模拟器抓包,然后交给到了自我的接口导致了00:00.00的记录。后来去查看了霎时记下数据的章程,结果的确有一些漏洞,即使本人表明了cookie和交给模式post,但是依然有漏洞的,cookie可以以假乱真,post也可以如法炮制提交。我觉着自己发现了实在的原因,并向她们确保一定不会有问题。结果第二天测试的人一玩,又并发了00:00.00,瞬间打脸。我有点不知所可,这多少个时候才起初认真想想真正的漏洞在哪儿,是自我一起始想的太多了。出现这种气象只是原因有三种:①自我的接口记录这一块出了问题导致记录成了00:00.00②前端传过来的年月就是00:00.00接口我仔细检查了代码是不曾问题的,这就只有一种可能前端传过来的值就有问题。后来经过努力好不容易搞到了这台出问题手机的型号,系统版本号和微信版本号,我们拿同样的版本号测试发现,计时器他竟是不走,平昔是00:00.00所以才导致了这种事情。后边会写为啥出现这种情状,上面是后端的笔录代码(tp5)

图片 3

  解决方案

  1.时间精度不准的事态下,接纳了H5的新接口Performance接口。Performance接口提供当前光阴在飞秒级的分辨率,使她不受系统时间的倾斜或者调整,在二〇一二年三月23日变为了W3C的引荐。Performance.now()获取到的是眼前时间的毫秒数,他标准到了层层皮秒。那个新接口拥有这许多益处,不过新生事物有一个欠缺就是兼容性,协理该API的浏览器很少,IE10,firefox15+以及Google浏览器,ios系统必须在9上述,安卓必须在4.0上述。就是因为低版本系统不帮忙的原因,所以会有部分手机根本就没获拿到开头时间导致了00:00.00的发生。后来大家提议提出,做一个补偿机制,就是在客户手机不补助这么些最新接口的情形下,才用new
Date().get提姆(Tim)e()来收获时间,然后在盘算他们之间的大运差,最后统一重临一个盘算好的年月差。不过及时项目曾经上线,客户代表这几个修改很大怕影响在线的法力,才用了其余一种情势。如果客户的无绳电话机不补助新型接口,那么提醒她提高系统之后再来玩,下边是测试襄助情况的代码。

图片 4

假设这多少个接口不被襄助,那么就会回去null。

  2.针对setinterval机制的问题,我们使用了requestAnimationFrame。requestAnimationFrame采纳系统时间距离,保持最佳绘制效用,不会因为间隔时间过短,造成过分绘制,增添支出;也不会因为间隔时间太长,使用动画片卡顿不通畅,让各个网页动画效果可以有一个联合的刷新机制,从而省去系统资源,提高系统特性,立异视觉效果。他不会去等待其他任务执行完才执行,有效的增进了计时的精度。

开创订单功用、查看订单列表、遵照订单id查询订单的详细音信、订单修改、订单废除、订单状态、订单评价等效用的贯彻。

2.百货集团部分

  相信大部分人都做过商城,像商品列表,单品这种是一定没有问题的,这里就不做牵线了,只介绍一些恐怕出问题的效用。

  1.购物袋功效

   问题

  在通过按钮进入购物袋这多少个操作,咱们一般会用ajax提交到购物袋之后跳转到购物袋页面,可是对那一个按钮的点击没有做限定,导致突发性客户觉得只点击了一回,可是却是参与了两件货物到购物车,客户体验很差。

  解决方案

  1.在交付到购物车页面这里,点击提交到购物车按钮才用一块交付到后台,等待后台再次回到的时候在展开下一步跳转到购物袋页面。2.就是用一个flag来控制提交,在交付的时候成为false,唯有拭目以待提交成功了成为true,才方可另行提交,可是这多少个只可以在正规状况下利用。

  2.结算效能

  问题

  在购物袋页面,点击结算跳转到结算页面,然后在回来购物袋页面,那些时候购物袋页面应该是空的。这多少个操作在安卓方面是从未问题的,但是在iphone下边就有题目,在结算页面的时候,点击重返到上一页的时候,他读取了栈中的缓存,并不曾再次加载这么些页面。结果就成了点击重返,上一页被结算的这一个商品还摆在那里,不过点击结算结算的数目也为空,点击删除的数目也是空的。

  解决方案

  这么些题目就是在于iphone点击重临的时候,让他刷新重回的页面。在此处页面写js刷新是没用的,因为在点击重回的时候读取的是缓存,相当于在页面刚进来的基础代谢了,这么些时候再回去它是不会刷新的。关键在于怎么捕捉iphone手机的归来事件。这里自己利用的是H5的其它一个新接口history,在页面跳到下一个页面的时候在仓库中replacestate替换掉那多少个页面,然后在用户点击再次来到的时候会触发popstate事件。这一个时候因为在仓房的history中页面已经被交流了,所以再回来的时候就会刷新这一个页面。代码如下:

图片 5

 

  3.支付页面

  问题

  在付出页面,用户填写了优惠的手机号码的时候,会有一个优惠价给到客户,然后客户可以用优惠价来支付,不过付出的那多少个音信在页面加载的时候曾经成形好了,里面富含了金额,假设有让利价格的时候修改不了

  解决方案

  微信支付在变化无常prepay_id的时候,会涉及到商户订单号,价钱。这一个东西在页面加载的时候曾经变更并且突显到了页面上,如若这厮不是优于客户,那么使用这一个曾经成形好的jsapi支付是可以的。就算这厮是有过之而无不及客户的时候,因为要修改价格,假设拿以前的订单号和价格去变通prepay_id,去调起微信的jsapi支付,就会报错商户订单号再次。这些时候我们得以再度生成一个订单号,然后用新的订单号和价格再度生成一个prepay_id来调起微信支付,代码如下

图片 6

那里要注意的是回来的json信息要转换为json对象才足以成功的调起微信支付。

  4.支付回调

  问题

  在支付成功的时候,会触发微信的回调,这么些时候才算真正的完结这么些订单。然则有些时候回调成功,有些时候回调不成功,不过真实存在付款。

  解决方案

  微信支付回调的时候,回调的链接一定不可能指引任何参数,不然就会造成回调败北。有时候回调成功,有时候回调不成功,可能的因由是你有构造函数或者其余验证的东西,微信在通过这多少个事物的时候被堵住了,并且跳到了另外的页面,我就是因为下边原因造成回调有时不成事:

  图片 7

  后来,我在其它一个独立的控制器中做了回调验证,这一个题目就迎刃而解了。

  5.库存问题

  问题

  在百货公司中的很多货物是有库存的,他们不可以超卖,因为尚未那么多货品,要在出卖的时候保证出售的数目不可能超越库存

  解决方案

  一般景观下是不会发出超卖这种事情的,因为在产出不是很高的情形下,mysql这类的关系型数据库也得以完全帮助。不过在高并发的场所下,数据库的读写速度太快的时候,会导致锁表。很多操作都在等候眼前的施行完毕释放了后头才能实施,结果也许会造成数据库挂掉。这个时候就用到了我们的nosql。我在这里运用的是redis,他得以支撑10W的出现,足以应付很多面貌。redis有二种格局可以控制库存,string和list,我推荐应用list。因为尽管redis的string也是原子性的操作,比如现在的库存是5,两个体同时买了之后,他必然是-1,而不容许是任何数字。redis的string即使可以算作数字来测算,可以利用incr和decr举行原子性的与日俱增递减操作,不过它是足以看看负数的,你可以设想一下您的库存一度是负数了,它还在减是怎么着的情况。这种气象很有可能暴发。

  所以我用了list,在用户点击商品的时候,把该商品的相应音信加载到redis缓存list中。每一趟有人购买了货物,就用lpop弹出一个行列元素,倘诺队列的尺寸为0了,他就会回来false而不会连续减下来,很好的防止了在库存一度为0的景色下超卖出去。

  这里还有一个题材是只要购物车中的商品有许多种,每种商品的库存是不同等的,倘若在结算的历程中,在并未结算完毕的动静下,某种商品没有库存了,那一个结算不成功。这些时候需要告诉客户这样商品没有了,并且分别再次来到他们分其余库存,因为有的结算了,有的没结算。这里我们可以拔取工作来支配,逐条来结算购物车货物,如若有没有的商品就回滚,保证了数据库数据的完整性。但是redis那边没有这样完整的事体帮助的,倘若有某几件货物已经操作reidis减去库存了,这么些时候怎么做吧?

图片 8

  我在循环起先前,定义了一个数组$command。在循环操作redis的时候,每操作成功一条就把操作的这些key参加到$command那些数组中。一旦某件商品没有库存了,我就循环那多少个数组,把缩短的库存总体加回来,比用数据库事务要方便点。

 图片 9

  

 

 

  小弟才疏学浅,文笔不精,哪儿有写的畸形的要么不佳的地点,欢迎我们指正!

  

  

需求->设计->实现->测试->交付

前几日我们来看下创制订单的流水线:

二、订单系统的多寡库表的宏图

创建订单说到底就是向订单表中添加多少,即insert这个消息。

下单效能肯定要使用关系型数据库表,保证数据的一致性,因为成立订单要确保在一个事情(一个事情就是指向数据库中展开的一种操作:比如插入,删除等等)里面,nosql数据库不襄助工作,可能会丢掉数据。

大家在网上购物的时候常见这么些订单包含的音信相比多,所以对于订单系统怎么样创建它的数据库也是这么些关键的。创设数据库听从数据库设计的三大范式原则来规划。

咱俩成立了两个表:tb_order(订单音讯表),tb_order_item(订单详情表),tb_order_shipping(订单配送表).

tb_order:这里带有了订单的核心音信

  图片 10

tb_order_item:订单详情表:订单的详情重要就是买入商品的音讯,通过订单的id来贯彻关系

图片 11

tb_order_shipping:订单配送表:

图片 12

这是多少个要旨的表,其实还足以有物流音信表,订单交易消息表。这里大家运用这三张表丰富。

三、订单系统接口文档,一般大家开发的时候会接收已经写好的接口文档,比如创设订单的接口文档。

图片 13

图片 14

从地方这些表中,大家得以看到该接口的url,接口的不胫而走参数和再次来到值。

接下去我们针对这六个来拓展代码的编写:

url属于controller层,

传播参数此地我们能够看到是数据库建立的三张表音信:第一个是tb_order,第二个是一个集合式的订单明细List,第五个是订单的配送信息表。

据此传入参数就是这多少个对象。这里大家是编制接口,供客户端调用,至于客户端怎么将那一个参数传递过来,那是客户端团队考虑的工作。

返回值这边运用了taotaoresult来包装了下,因为我们付出订单成功后,重回的是订单号,即订单的id所以,我们需要向客户端传递订单id过去,并展现在订单创设成功的页面。

下边看下订单服务接口的service层的落实:

service层的第一实现是将订单音信添加到数据库中,即接到controller传递过来的目的,然后补全页面没有的字段,insert数据库,这里可以运用逆向工程变更的dao。

此外还有个问题:

订单号码:订单号码用什么花样相比好呢?

 

化解方案一(无法应用):

 

运用mysql的自增长。

 

优点:不需要我们温馨生成订单号,mysql会自动生成。

 

缺点:假如订单表数据太大时需要分库分表,此时订单号会另行。倘诺数据备份后再过来,订单号会变。

 

方案二:日期+随机数

 

行使阿秒+随机数。

 

缺点:如故有重复的恐怕。不提出利用此方案。在一向不更好的缓解方案从前可以利用。

 

方案三:使用UUID

 

可取:不会再次。

 

缺点:长。可读性查。不指出采取。 

 

方案四:可读性好,不可以太长。一般订单都是全数字的。能够应用redis的incr命令变动订单号。

 

优点:可读性好,不会再也

 

症结:需要搭建redis服务器。

从而我们采取方案四作为转变订单号的方案。

这就是说service层的编码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package com.taotao.order.service.impl;
 
import java.util.Date;
import java.util.List;
 
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
 
import com.taotao.common.utils.TaotaoResult;
import com.taotao.mapper.TbOrderItemMapper;
import com.taotao.mapper.TbOrderMapper;
import com.taotao.mapper.TbOrderShippingMapper;
import com.taotao.order.dao.JedisClient;
import com.taotao.order.service.OrderService;
import com.taotao.pojo.TbOrder;
import com.taotao.pojo.TbOrderItem;
import com.taotao.pojo.TbOrderShipping;
//订单模块实现
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private TbOrderMapper orderMapper;
    @Autowired
    private TbOrderItemMapper orderItemMapper;
    @Autowired
    private TbOrderShippingMapper shippingMapper;
    @Autowired
    private JedisClient jedisClient;
    @Value("${ORDER_GEN_KEY}")
    private String ORDER_GEN_KEY;
    @Value("${ORDER_DEFAULT_KEY}")
    private String ORDER_DEFAULT_KEY;
    @Value("${ORDER_ITEM_KEY}")
    private String ORDER_ITEM_KEY;
     
//创建订单功能实现
    @Override
    public TaotaoResult createOrder(TbOrder order,List<TbOrderItem> orderItem, TbOrderShipping orderShipping) {
        //逻辑步骤:创建订单即向数据库中三个表中插入数据,所以讲数据库中的字段补全即可。页面传递过来的就不需要补全了,直接可以写入数据库
        /*第一步:订单号的生成方式:因为订单号的特殊性,订单后最好采用数字组成,且不能重复,可以采用redis中自增长的方式来实现,
         * 在redis中,如果无key,则redis自动创建你写的key的名字。采用incr的命令来实现订单号的自增。默认自增是从1开始的,因为考虑到用户的原因,在redis中设置一个默认的key值
         * 这样用户体验会好些,不会因为看到简单的1,2,3,所以设置一个默认的key值
        */
        String string = jedisClient.get(ORDER_GEN_KEY);
        if (StringUtils.isBlank(string)) {
            //如果redis中的key为空,则利用默认值
            String defaultKey = jedisClient.set(ORDER_GEN_KEY,ORDER_DEFAULT_KEY);  
        }
        //如果存在此key则,采用incr命令自增
        long orderId= jedisClient.incr(ORDER_GEN_KEY);
        //然后向订单表中插入数据
        order.setOrderId(orderId+"");
        //订单状态:状态:1、未付款,2、已付款,3、未发货,4、已发货
        order.setStatus(1);
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setBuyerRate(0);
        //补全完信息后,插入数据库表
        orderMapper.insert(order);
        //补全完订单表后,将订单明细表补全,因为之前订单写入redis,订单明细的id也写入redis吧,自动创建这个id的key。这个不需要默认编号了。对比页面传递的参数,将剩下的补全
       String string2 = jedisClient.get(ORDER_ITEM_KEY);
       long orderItemId = jedisClient.incr(string2);
       //因为传递过来的是一个集合列表,所以遍历列表
       for (TbOrderItem tbOrderItem : orderItem) {
           tbOrderItem.setId(orderItemId+"");
           tbOrderItem.setOrderId(orderId+""); 
           orderItemMapper.insert( tbOrderItem);
    
        //接下来补全订单配送表
        orderShipping.setOrderId(orderId+"");
        orderShipping.setCreated(new Date());
        orderShipping.setUpdated(new Date());
        shippingMapper.insert(orderShipping);
         
        return TaotaoResult.ok(orderId);
    }
 
}

 controller:层实现

controller需要将目的传递给service层:(客户端向服务器端传入的参数格式,详见后边博文)

我们看来接口文档中,controller接收的参数是一个json格式的字符串,也就是说客户端传递过来的是json格式的字符串。

这就关乎到springMVC是何等接受json字符串的,需要用到@RequestBody讲明。那里多说几句:

@ResponseBody讲明的法则是response只好响应一个字符串,当大家的重临值是java对象的时候,它有一个默认行为,即采取jackson包将java对象转为字符串响应。这是一个默认自动的一言一行,不需要我们设置,只要那么些讲明即可。

@RequestBody表明同理:利用那么些声明告诉springMVC大家现在收下的是一个json字符串,需要接纳默认行为接纳jackson包将json字符串转换为java对象,所以controller层大家需要一个java对象的pojo。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.taotao.order.pojo;
 
import java.util.List;
 
import com.taotao.pojo.TbOrder;
import com.taotao.pojo.TbOrderItem;
import com.taotao.pojo.TbOrderShipping;
 
public class Order extends TbOrder {
    private List<TbOrderItem> orderItems;
    private TbOrderShipping orderShipping;
    public List<TbOrderItem> getOrderItems() {
        return orderItems;
    }
    public void setOrderItems(List<TbOrderItem> orderItems) {
        this.orderItems = orderItems;
    }
    public TbOrderShipping getOrderShipping() {
        return orderShipping;
    }
    public void setOrderShipping(TbOrderShipping orderShipping) {
        this.orderShipping = orderShipping;
    }
 
}

  controller层实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.taotao.order.controller;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
import com.taotao.common.utils.ExceptionUtil;
import com.taotao.common.utils.TaotaoResult;
import com.taotao.order.pojo.Order;
import com.taotao.order.service.OrderService;
//订单管理模块
@Controller
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;
    @RequestMapping("/create")
    @ResponseBody
    public TaotaoResult createOrder(@RequestBody Order order ){//创建订单模块实现
        try {
            TaotaoResult taotaoResult = orderService.createOrder(order ,order.getOrderItems(), order.getOrderShipping());
            return taotaoResult;
        catch (Exception e) {
            e.printStackTrace();
            return TaotaoResult.build(500,ExceptionUtil.getStackTrace(e));
        }
     
    }
 
}

  以上代码是订单服务接口的创办订单接口代码实现。

接下去我们看下客户端咋样调用订单服务层的:

客户端当我们点击去购物车结算的时候,呈现购物车列表。

在购物车列表页面,当点击去结算的时候,跳转到未提交订单的页面。

点击提交订单,跳转到显示成功页面。

controller层实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.taotao.portal.controller;
 
import java.util.List;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
 
import com.taotao.portal.pojo.CartItem;
import com.taotao.portal.pojo.Order;
import com.taotao.portal.service.CartService;
import com.taotao.portal.service.OrderService;
 
@Controller
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private CartService cartService;
    @Autowired
    private OrderService orderService;
    @RequestMapping("/order-cart")
    //点击去结算,显示订单的页面
    public String showOrderPage(HttpServletRequest request,HttpServletResponse response,Model model){
        List<CartItem> list= cartService.showCartList(request);
        model.addAttribute("cartList", list);
        return "order-cart";   
    }
    //点击提交订单,显示订单号,订单金额,预计送达时间
    @RequestMapping("/create")
    public String showSuccessOrder(Order order,Model model){
     try {
 
        String orderId= orderService.createOrder(order);
        model.addAttribute("orderId ",orderId);
        model.addAttribute("payment",order.getPayment());
        model.addAttribute("date"new DateTime().plusDays(3).toString("yyyy-mm-dd"));
        return "success";
     
    catch (Exception e) {
    e.printStackTrace();
    model.addAttribute("message""创建订单出错");
    return "error/exception";
   }
    }
}

  service层实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.taotao.portal.service.impl;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
 
import com.taotao.common.utils.HttpClientUtil;
import com.taotao.common.utils.JsonUtils;
import com.taotao.common.utils.TaotaoResult;
import com.taotao.portal.pojo.Order;
import com.taotao.portal.service.OrderService;
@Service
public class OrderServiceImpl implements OrderService {
    @Value("${ORDER_BASE_URL}")
    private String ORDER_BASE_URL;
    @Value("${ORDER_CREATE_URL}")
    private String ORDER_CREATE_URL;
     
//创建订单的客户端实现
    @Override
    public String createOrder(Order order) {
    //因为httpclientUtil中dopost传递的是json格式的数据,所以需要将order这个java对象转换成Json格式 
        String json = HttpClientUtil.doPost(ORDER_BASE_URL+ORDER_CREATE_URL+JsonUtils.objectToJson(order));
        //为了获取里面的订单id,我们需要将获得的字符串转换为taotaoresult,然后获取数据,因为服务层传递过来的就是订单的id,所以获得数据也是获得的id
        TaotaoResult result= TaotaoResult.format(json);
        if (result.getStatus()==200) {
            Object orderId = result.getData();
            return orderId.toString();
        }
        return "";
    }
 
}
 
 
 

  这里同样用了pojo类Order类。

拦截器的题材:因为提交订单我们需要用户登录,所以在springMVC.xml文件中布置上:

图片 15

一起电商学习互换群:168096884  

相关文章