天猫整站(简易版)SSM(十四)需要登录才能使用的功能

一、购物车页面操作

购物车页面和服务端的交互主要是三个
1. 增加、减少某种产品的数量
2. 删除某种产品
3. 选中产品后,提交到结算页面

天猫整站(简易版)SSM(十四)需要登录才能使用的功能

1.1 调整订单数量

点击增加或者减少按钮后,根据cartPage.jsp 中的js代码,会通过Ajax访问/forechangeOrderItem路径

天猫整站(简易版)SSM(十四)需要登录才能使用的功能

导致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路径

天猫整站(简易版)SSM(十四)需要登录才能使用的功能

导致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

二、订单状态图

天猫整站(简易版)SSM(十四)需要登录才能使用的功能

1. 首先是创建订单,刚创建好之后,订单处于waitPay 待付款状态
2. 接着是付款,付款后,订单处于waitDelivery 待发货状态
3. 前两步都是前台用户操作导致的,接下来需要到后台做发货操作,发货后,订单处于waitConfirm 待确认收货状态
4. 接着又是前台用户进行确认收货操作,操作之后,订单处于waitReview 待评价状态
5. 最后进行评价,评价之后,订单处于finish 完成状态

以上状态都是一个接一个的,不能跳状态进行。
比较特殊的是,无论当前订单处于哪个状态,都可以进行删除操作。 像订单这样极其重要的业务数据,实际上是不允许真正从数据库中删除掉的,而是把状态标记为删除,以表示其被删掉了,所以在删除之后,订单处于 delete 已删除状态

三、生成订单

3.1 结算页操作

通过立即购买或者购物车中点击结算进入结算页面,然后提交订单

天猫整站(简易版)SSM(十四)需要登录才能使用的功能

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. 统计本次订单的总金额
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>