目录
3.3 ForeController.createOrder
一、购物车页面操作
购物车页面和服务端的交互主要是三个
1. 增加、减少某种产品的数量
2. 删除某种产品
3. 选中产品后,提交到结算页面
1.1 调整订单数量
点击增加或者减少按钮后,根据cartPage.jsp 中的js代码,会通过Ajax访问/forechangeOrderItem路径
导致ForeController.changeOrderItem()方法被调用
1. 判断用户是否登录
2. 获取pid和number
3. 遍历出用户当前所有的未生成订单的OrderItem
4. 根据pid找到匹配的OrderItem,并修改数量后更新到数据库
5. 返回字符串"success"
@RequestMapping("forechangeOrderItem")
@ResponseBody
public String changeOrderItem(@RequestParam("pid") int pid,@RequestParam("number") int number,Model model,HttpSession session){
User user = (User) session.getAttribute("user");
if (user == null){
return "fail";
}else {
List<OrderItem> orderItems = orderItemService.listByUser(user.getId());
for (OrderItem orderItem : orderItems){
if (orderItem.getPid() == pid){
orderItem.setNumber(number);
orderItemService.update(orderItem);
break;
}
}
return "success";
}
}
1.2 删除订单项
点击删除按钮后,根据 cartPage.jsp中的js代码,会通过Ajax访问/foredeleteOrderItem路径
导致ForeController.deleteOrderItem方法被调用
1. 判断用户是否登录
2. 获取oiid
3. 删除oiid对应的OrderItem数据
4. 返回字符串"success"
@RequestMapping("foredeleteOrderItem")
@ResponseBody
public String deleteOrderItem(@RequestParam("oiid") int oiid,Model model,HttpSession session){
User user = (User)session.getAttribute("user");
if (user != null){
orderItemService.delete(oiid);
return "success";
}else {
return "fail";
}
}
1.3 提交到结算页面
在选中了购物车中的任意商品之后,结算按钮呈现可点击状态。
点击之后,提交到结算页面,并带上(多个)被选中的OrderItem对象的id
http://localhost:8080/tmall_ssm/forebuy?oiid=8&oiid=9
二、订单状态图
1. 首先是创建订单,刚创建好之后,订单处于waitPay 待付款状态
2. 接着是付款,付款后,订单处于waitDelivery 待发货状态
3. 前两步都是前台用户操作导致的,接下来需要到后台做发货操作,发货后,订单处于waitConfirm 待确认收货状态
4. 接着又是前台用户进行确认收货操作,操作之后,订单处于waitReview 待评价状态
5. 最后进行评价,评价之后,订单处于finish 完成状态
以上状态都是一个接一个的,不能跳状态进行。
比较特殊的是,无论当前订单处于哪个状态,都可以进行删除操作。 像订单这样极其重要的业务数据,实际上是不允许真正从数据库中删除掉的,而是把状态标记为删除,以表示其被删掉了,所以在删除之后,订单处于 delete 已删除状态
三、生成订单
3.1 结算页操作
通过立即购买或者购物车中点击结算进入结算页面,然后提交订单
3.2 事务管理
在applicationContext.xml中配置事务管理
因为增加订单行为需要同时修改两个表
1. 为Order表新增数据
2. 修改OrderItem表
所以需要进行事务管理,否则当新增了Order表的数据,还没有来得及修改OrderItem的时候出问题,比如突然断电,那么OrderItem的数据就会是脏数据了(没有指向正确的Order表数据)。
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
3.3 ForeController.createOrder
提交订单访问路径 /forecreateOrder, 导致ForeController.createOrder 方法被调用
1. 从session中获取user对象
2. 通过参数Order接受地址,邮编,收货人,用户留言等信息
3. 根据当前时间加上一个4位随机数生成订单号
4. 根据上述参数,创建订单对象
5. 把订单状态设置为等待支付
6. 从session中获取订单项集合 ( 在结算功能中的ForeController.buy()方法中,订单项集合被放到了session中 )
7. 把订单加入到数据库,并且遍历订单项集合,设置每个订单项的order,更新到数据库
8. 统计本次订单的总金额,调用orderService中的getTotal方法,根据order和orderItem求订单总合。
9. 客户端跳转到确认支付页forealipay,并带上订单id和总金额
@RequestMapping("forecreateOrder")
public String createOrder(Order order,HttpSession session){
User user = (User) session.getAttribute("user");
//根据时间加上一个随机的四位数生成订单编号
String orderCode = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())+ RandomUtils.nextInt(10000);
order.setOrderCode(orderCode);
order.setCreateDate(new Date());
order.setUid(user.getId());
order.setStatus(OrderService.WAIT_PAY);
List<OrderItem> orderItems = (List<OrderItem>) session.getAttribute("ois");
float total = orderService.getTotal(order,orderItems);
return "redirect:forealipay?oid="+order.getId() +"&total="+total;
}
3.4 确认支付
1. 在上一步客户端跳转到路径/forealipay方法,导致PageController.alipay()方法被调用。 alipay()没做什么事情,就是服务端跳转到了alipay.jsp页面。
2. alipay.jsp :
中间是确认支付业务页面 alipayPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@include file="../include/fore/header.jsp"%>
<%@include file="../include/fore/top.jsp"%>
<%@include file="../include/fore/cart/alipayPage.jsp"%>
<%@include file="../include/fore/footer.jsp"%>
3. alipayPage.jsp:
显示总金额,并且让确认支付按钮跳转到页面 /forepayed页面,并带上oid和金额
<%--
Created by IntelliJ IDEA.
User:
Date: 2018/10/2
Time: 10:21
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<div class="aliPayPageDiv">
<div class="aliPayPageLogo">
<img class="pull-left" src="${pageContext.request.contextPath}/img/site/simpleLogo.png">
<div style="clear:both"></div>
</div>
<div>
<span class="confirmMoneyText">扫一扫付款(元)</span>
<span class="confirmMoney">
¥<fmt:formatNumber type="number" value="${param.total}" minFractionDigits="2"/></span>
</div>
<div>
<img class="aliPayImg" src="${pageContext.request.contextPath}/img/site/alipay2wei.png">
</div>
<div>
<a href="forepayed?oid=${param.oid}&total=${param.total}"><button class="confirmPay">确认支付</button></a>
</div>
</div>
3.5 支付成功
1. 在上一步确认访问按钮提交数据到/forepayed,导致ForeController.payed方法被调用
1.1 获取参数oid
1.2 根据oid获取到订单对象order
1.3 修改订单对象的状态和支付时间
1.4 更新这个订单对象到数据库
1.5 把这个订单对象放在model的属性"o"上
1.6 服务端跳转到payed.jsp
@RequestMapping("forepayed")
public String payed(@RequestParam("oid") int oid,@RequestParam("total") float total,Model model){
Order order = orderService.get(oid);
order.setStatus(OrderService.WAIT_DELIVERY);
order.setPayDate(new Date());
orderService.update(order);
model.addAttribute("o",order);
return "fore/payed";
}
2. payed.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@include file="../include/fore/header.jsp"%>
<%@include file="../include/fore/top.jsp"%>
<%@include file="../include/fore/simpleSearch.jsp"%>
<%@include file="../include/fore/cart/payedPage.jsp"%>
<%@include file="../include/fore/footer.jsp"%>
中间是支付成功业务页面 payedPage.jsp
3. payedPage.jsp
显示订单中的地址,邮编,收货人,手机号码等等
<%--
Created by IntelliJ IDEA.
User:
Date: 2018/10/2
Time: 10:29
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<div class="payedDiv">
<div class="payedTextDiv">
<img src="${pageContext.request.contextPath}/img/site/paySuccess.png">
<span>您已成功付款</span>
</div>
<div class="payedAddressInfo">
<ul>
<li>收货地址:${o.address} ${o.receiver} ${o.mobile }</li>
<li>实付款:<span class="payedInfoPrice">
¥<fmt:formatNumber type="number" value="${param.total}" minFractionDigits="2"/>
</li>
<li>预计10月18日送达 </li>
</ul>
<div class="paedCheckLinkDiv">
您可以
<a class="payedCheckLink" href="forebought">查看已买到的宝贝</a>
<a class="payedCheckLink" href="forebought">查看交易详情 </a>
</div>
</div>
<div class="payedSeperateLine">
</div>
<div class="warningDiv">
<img src="${pageContext.request.contextPath}/img/site/warning.png">
<b>安全提醒:</b>下单后,<span class="redColor boldWord">用QQ给您发送链接办理退款的都是骗子!</span>天猫不存在系统升级,订单异常等问题,谨防假冒客服电话诈骗!
</div>
</div>
四、我的订单
4.1 我的订单页
4.2 OrderService
修改OrderService,新增方法List list(int uid, String excludedStatus)
根据用户id查询所有状态(不包括删除状态)订单
4.3 OrderServiceImpl
@Override
public List<Order> list(int uid, String excludedStatus) {
OrderExample example = new OrderExample();
example.createCriteria().andUidEqualTo(uid).andStatusNotEqualTo(excludedStatus);
example.setOrderByClause("id desc");
return orderMapper.selectByExample(example);
}
4.4 ForeController.bought()
/forebought导致ForeController.bought()方法被调用
1. 通过session获取用户user
2. 查询user所有的状态不是"delete" 的订单集合os
3. 为这些订单填充订单项
4. 把os放在model的属性"os"上
5. 服务端跳转到bought.jsp
4.5 bought.jsp
中间是我的订单页面 boughtPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@include file="../include/fore/header.jsp"%>
<%@include file="../include/fore/top.jsp"%>
<%@include file="../include/fore/simpleSearch.jsp"%>
<%@include file="../include/fore/cart/boughtPage.jsp"%>
<%@include file="../include/fore/footer.jsp"%>
4.6 boughtPage.jsp
<%--
Created by IntelliJ IDEA.
User:
Date: 2018/10/2
Time: 12:59
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<script>
var deleteOrder = false;
var deleteOrderid = 0;
$(function(){
$("a[orderStatus]").click(function(){
var orderStatus = $(this).attr("orderStatus");
if('all'==orderStatus){
$("table[orderStatus]").show();
}
else{
$("table[orderStatus]").hide();
$("table[orderStatus="+orderStatus+"]").show();
}
$("div.orderType div").removeClass("selectedOrderType");
$(this).parent("div").addClass("selectedOrderType");
});
$("a.deleteOrderLink").click(function(){
deleteOrderid = $(this).attr("oid");
deleteOrder = false;
$("#deleteConfirmModal").modal("show");
});
$("button.deleteConfirmButton").click(function(){
deleteOrder = true;
$("#deleteConfirmModal").modal('hide');
});
$('#deleteConfirmModal').on('hidden.bs.modal', function (e) {
if(deleteOrder){
var page="foredeleteOrder";
$.post(
page,
{"oid":deleteOrderid},
function(result){
if("success"==result){
$("table.orderListItemTable[oid="+deleteOrderid+"]").hide();
}
else{
location.href="login.jsp";
}
}
);
}
})
$(".ask2delivery").click(function(){
var link = $(this).attr("link");
$(this).hide();
page = link;
$.ajax({
url: page,
success: function(result){
alert("卖家已秒发,刷新当前页面,即可进行确认收货")
}
});
});
});
</script>
<div class="boughtDiv">
<div class="orderType">
<div class="selectedOrderType"><a orderStatus="all" href="#nowhere">所有订单</a></div>
<div><a orderStatus="waitPay" href="#nowhere">待付款</a></div>
<div><a orderStatus="waitDelivery" href="#nowhere">待发货</a></div>
<div><a orderStatus="waitConfirm" href="#nowhere">待收货</a></div>
<div><a orderStatus="waitReview" href="#nowhere" class="noRightborder">待评价</a></div>
<div class="orderTypeLastOne"><a class="noRightborder"> </a></div>
</div>
<div style="clear:both"></div>
<div class="orderListTitle">
<table class="orderListTitleTable">
<tr>
<td>宝贝</td>
<td width="100px">单价</td>
<td width="100px">数量</td>
<td width="120px">实付款</td>
<td width="100px">交易操作</td>
</tr>
</table>
</div>
<div class="orderListItem">
<c:forEach items="${os}" var="o">
<table class="orderListItemTable" orderStatus="${o.status}" oid="${o.id}">
<tr class="orderListItemFirstTR">
<td colspan="2">
<b><fmt:formatDate value="${o.createDate}" pattern="yyyy-MM-dd HH:mm:ss"/></b>
<span>订单号: ${o.orderCode}
</span>
</td>
<td colspan="2"><img width="13px" src="${pageContext.request.contextPath}/img/site/orderItemTmall.png">天猫商场</td>
<td colspan="1">
<a class="wangwanglink" href="#nowhere">
<div class="orderItemWangWangGif"></div>
</a>
</td>
<td class="orderItemDeleteTD">
<a class="deleteOrderLink" oid="${o.id}" href="#nowhere">
<span class="orderListItemDelete glyphicon glyphicon-trash"></span>
</a>
</td>
</tr>
<c:forEach items="${o.orderItems}" var="oi" varStatus="st">
<tr class="orderItemProductInfoPartTR" >
<td class="orderItemProductInfoPartTD"><img width="80" height="80" src="${pageContext.request.contextPath}/img/productSingle_middle/${oi.product.productImage.id}.jpg"></td>
<td class="orderItemProductInfoPartTD">
<div class="orderListItemProductLinkOutDiv">
<a href="foreproduct?pid=${oi.product.id}">${oi.product.name}</a>
<div class="orderListItemProductLinkInnerDiv">
<img src="${pageContext.request.contextPath}/img/site/creditcard.png" title="支持信用卡支付">
<img src="${pageContext.request.contextPath}/img/site/7day.png" title="消费者保障服务,承诺7天退货">
<img src="${pageContext.request.contextPath}/img/site/promise.png" title="消费者保障服务,承诺如实描述">
</div>
</div>
</td>
<td class="orderItemProductInfoPartTD" width="100px">
<div class="orderListItemProductOriginalPrice">¥<fmt:formatNumber type="number" value="${oi.product.originalPrice}" minFractionDigits="2"/></div>
<div class="orderListItemProductPrice">¥<fmt:formatNumber type="number" value="${oi.product.promotePrice}" minFractionDigits="2"/></div>
</td>
<c:if test="${st.count==1}">
<td valign="top" rowspan="${fn:length(o.orderItems)}" class="orderListItemNumberTD orderItemOrderInfoPartTD" width="100px">
<span class="orderListItemNumber">${o.totalNumber}</span>
</td>
<td valign="top" rowspan="${fn:length(o.orderItems)}" width="120px" class="orderListItemProductRealPriceTD orderItemOrderInfoPartTD">
<div class="orderListItemProductRealPrice">¥<fmt:formatNumber minFractionDigits="2" maxFractionDigits="2" type="number" value="${o.total}"/></div>
<div class="orderListItemPriceWithTransport">(含运费:¥0.00)</div>
</td>
<td valign="top" rowspan="${fn:length(o.orderItems)}" class="orderListItemButtonTD orderItemOrderInfoPartTD" width="100px">
<c:if test="${o.status=='waitConfirm' }">
<a href="foreconfirmPay?oid=${o.id}">
<button class="orderListItemConfirm">确认收货</button>
</a>
</c:if>
<c:if test="${o.status=='waitPay' }">
<a href="forealipay?oid=${o.id}&total=${o.total}">
<button class="orderListItemConfirm">付款</button>
</a>
</c:if>
<c:if test="${o.status=='waitDelivery' }">
<span>待发货</span>
<%-- <button class="btn btn-info btn-sm ask2delivery" link="admin_order_delivery?id=${o.id}">催卖家发货</button> --%>
</c:if>
<c:if test="${o.status=='waitReview' }">
<a href="forereview?oid=${o.id}">
<button class="orderListItemReview">评价</button>
</a>
</c:if>
</td>
</c:if>
</tr>
</c:forEach>
</table>
</c:forEach>
</div>
</div>