Tmall商城订单管理模块分析

商城订单管理

商品显示页

从商品的显示页中加入购物车或者下单。

跳转页面的请求地址(Get方式请求)

http://localhost:8080/tmall/product/{pid}

Request URL: http://localhost:8080/tmall/product/13
Request Method: GET

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ovoXg0Ek-1660310355881)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811141404430.png)]

涉及到的控制器ForeProductDetailsController

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6cAFK7o-1660310355883)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811142053341.png)]

//转到前台天猫-产品详情页
    @RequestMapping(value = "product/{pid}", method = RequestMethod.GET)
    public String goToPage(HttpSession session, Map<String, Object> map,
                           @PathVariable("pid") String pid /*产品ID*/) {
        logger.info("检查用户是否登录");
        Object userId = checkUser(session);
        if (userId != null) {
            logger.info("获取用户信息");
            User user = userService.get(Integer.parseInt(userId.toString()));
            map.put("user", user);
        }
        logger.info("获取产品ID");
        Integer product_id = Integer.parseInt(pid);
        logger.info("获取产品信息");
        Product product = productService.get(product_id);
        if (product == null || product.getProduct_isEnabled() == 1) {
            return "redirect:/404";
        }
        logger.info("获取产品子信息-分类信息");
        product.setProduct_category(categoryService.get(product.getProduct_category().getCategory_id()));
        logger.info("获取产品子信息-预览图片信息");
        List<ProductImage> singleProductImageList = productImageService.getList(product_id, (byte) 0, null);
        product.setSingleProductImageList(singleProductImageList);
        logger.info("获取产品子信息-详情图片信息");
        List<ProductImage> detailsProductImageList = productImageService.getList(product_id, (byte) 1, null);
        product.setDetailProductImageList(detailsProductImageList);
        logger.info("获取产品子信息-产品属性值信息");
        List<PropertyValue> propertyValueList = propertyValueService.getList(new PropertyValue().setPropertyValue_product(product), null);
        logger.info("获取产品子信息-分类信息对应的属性列表");
        List<Property> propertyList = propertyService.getList(new Property().setProperty_category(product.getProduct_category()), null);
        logger.info("属性列表和属性值列表合并");
        for (Property property : propertyList) {
            for (PropertyValue propertyValue : propertyValueList) {
                if (property.getProperty_id().equals(propertyValue.getPropertyValue_property().getProperty_id())) {
                    List<PropertyValue> property_value_item = new ArrayList<>(1);
                    property_value_item.add(propertyValue);
                    property.setPropertyValueList(property_value_item);
                    break;
                }
            }
        }
        logger.info("获取产品子信息-产品评论信息");
        product.setReviewList(reviewService.getListByProductId(product_id, null));
        if (product.getReviewList() != null) {
            for (Review review : product.getReviewList()) {
                review.setReview_user(userService.get(review.getReview_user().getUser_id()));
            }
        }

        logger.info("获取猜你喜欢列表");
        Integer category_id = product.getProduct_category().getCategory_id();
        Integer total = productService.getTotal(new Product().setProduct_category(new Category().setCategory_id(category_id)), new Byte[]{0, 2});
        logger.info("分类ID为{}的产品总数为{}条", category_id, total);
        //生成随机数
        int i = new Random().nextInt(total);
        if (i + 2 >= total) {
            i = total - 3;
        }
        if (i < 0) {
            i = 0;
        }
        List<Product> loveProductList = productService.getList(new Product().setProduct_category(
                new Category().setCategory_id(category_id)),
                new Byte[]{0, 2},
                null,
                new PageUtil().setCount(3).setPageStart(i)
        );
        if (loveProductList != null) {
            logger.info("获取产品列表的相应的一张预览图片");
            for (Product loveProduct : loveProductList) {
                loveProduct.setSingleProductImageList(productImageService.getList(loveProduct.getProduct_id(), (byte) 0, new PageUtil(0, 1)));
            }
        }
        logger.info("获取分类列表");
        List<Category> categoryList = categoryService.getList(null, new PageUtil(0, 3));

        map.put("loveProductList", loveProductList);
        map.put("categoryList", categoryList);
        map.put("propertyList", propertyList);
        map.put("product", product);
        map.put("guessNumber", i);
        map.put("pageUtil", new PageUtil(0, 10).setTotal(product.getProduct_review_count()));
        logger.info("转到前台-产品详情页");
        return "fore/productDetailsPage";
    }

根据最后返回的地址,确定对应的页面位置:

fore/productDetailsPage

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-snL3IfZ5-1660310355885)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811142345032.png)]

加入购物车的代码流程

<form method="get" class="context_buy_form">
      <input class="context_buyNow" type="submit" value="立即购买"/>
</form>

JS绑定事件

点击添加购物车按钮之后向后台发送请求。

涉及部分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UQhbVEXM-1660310355885)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811143348295.png)]

<dl class="context_info_member">
    <dt>数量</dt>
    <dd>
        <input type="text" value="1" maxlength="8" title="请输入购买量" class="context_buymember">
        <input type="hidden" id="stock" value="1000">
        <span class="amount-btn">
            <img src="${pageContext.request.contextPath}/res/images/fore/WebsiteImage/up.png"
                 class="amount_value_up">
            <img src="${pageContext.request.contextPath}/res/images/fore/WebsiteImage/down.png"
                 class="amount_value-down">
        </span>
        <span class="amount_unit">件</span>
        <em>库存1000件</em>
    </dd>
</dl>

知识点一:isNaN函数

定义和用法

isNaN() 函数用于检查其参数是否是非数字值。

语法
isNaN(x)
参数描述
x必需。要检测的值。
返回值

如果 x 是特殊的非数字值 NaN(或者能被转换为这样的值),返回的值就是 true。如果 x 是其他值,则返回 false。

说明

isNaN() 函数可用于判断其参数是否是 NaN,该值表示一个非法的数字(比如被 0 除后得到的结果)。

如果把 NaN 与任何值(包括其自身)相比得到的结果均是 false,所以要判断某个值是否是 NaN,不能使用 == 或 === 运算符。正因为如此,isNaN() 函数是必需的。

提示和注释

提示:isNaN() 函数通常用于检测 parseFloat() 和 parseInt() 的结果,以判断它们表示的是否是合法的数字。当然也可以用 isNaN() 函数来检测算数错误,比如用 0 作除数的情况。

实例

检查数字是否非法:

<script> document.write(isNaN(123));
document.write(isNaN(-1.23));
document.write(isNaN(5-2));
document.write(isNaN(0));
document.write(isNaN("Hello"));
document.write(isNaN("2005/12/12")); </script>

输出:

false
false
false
false
true
true

创建购物车向后端发送请求

$.trim(str)的作用是去掉字符串首尾空格

$.trim(str)

返回:string;

在前端的过程中通过jquery进行校验,如果时非法数字重新进行刷新,正常数字会发送请求参数。

发送请求的方式为post方式,

发送的地址为:/orderItem/create/{产品id}

携带的参数:product_number:购买的数量

 $(".context_buyCar_form").submit(function () {
                        if ('${sessionScope.userId}' === "") {
                            $(".loginModel").show();
                            $(".loginDiv").show();
                            return false;
                        }
                        var number = isNaN($.trim($(".context_buymember").val()));
                        if (number) {
                            location.reload();
                        } else {
                            $.ajax({
                                url: 							"${pageContext.request.contextPath}/orderItem/create/${requestScope.product.product_id}?product_number=" + $.trim($(".context_buymember").val()),
                                type: "POST",
                                data: {"product_number": number},
                                dataType: "json",
                                success: function (data) {
                                    if (data.success) {
                                        $(".msg").stop(true, true).animate({
                                            opacity: 1
                                        }, 550, function () {
                                            $(".msg").animate({
                                                opacity: 0
                                            }, 1500);
                                        });
                                    } else {
                                        if (data.url != null) {
                                            location.href = "/tmall" + data.url;  //里面的data.url为后端返回的
                                        } else {
                                            alert("加入购物车失败,请稍后再试!");
                                        }
                                    }
                                },
                                beforeSend: function () {

                                },
                                error: function () {
                                    alert("加入购物车失败,请稍后再试!");
                                }
                            });
                            return false;
                        }
                    });

在请求后端的参数成功之后。弹出添加购物车成功的弹窗

用于创建自定义动画的函数。
返回值:jQuery animate(params, [duration], [easing], [callback])

如果使用的是“hide”、“show”或“toggle”这样的字符串值,则会为该属性调用默认的动画形式。paramsOptions一组包

含作为动画属性和终值的样式属性和及其值的集合

完成成功之后的操作对应着,创建自定义提示的交互过程

后端的ForeOrderController控制器接收请求

涉及到的控制器:ForeOrderController(核心的订单处理控制器)

核心控制器中包含的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pds1fNSi-1660310355887)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811145943234.png)]

//创建订单项-购物车-ajax
@ResponseBody
@RequestMapping(value = "orderItem/create/{product_id}", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
public String createOrderItem(@PathVariable("product_id") Integer product_id,
                              @RequestParam(required = false, defaultValue = "1") Short product_number,
                              HttpSession session,
                              HttpServletRequest request) {
    JSONObject object = new JSONObject();
    logger.info("检查用户是否登录");
    Object userId = checkUser(session);
    if (userId == null) {
        object.put("url", "/login");
        object.put("success", false);
        return object.toJSONString();
    }

    logger.info("通过产品ID获取产品信息:{}", product_id);
    Product product = productService.get(product_id);
    if (product == null) {
        object.put("url", "/login");
        object.put("success", false);
        return object.toJSONString();
    }

    ProductOrderItem productOrderItem = new ProductOrderItem();
    logger.info("检查用户的购物车项");
    List<ProductOrderItem> orderItemList = productOrderItemService.getListByUserId(Integer.valueOf(userId.toString()), null);
    for (ProductOrderItem orderItem : orderItemList) {
        if (orderItem.getProductOrderItem_product().getProduct_id().equals(product_id)) {
            logger.info("找到已有的产品,进行数量追加");
            int number = orderItem.getProductOrderItem_number();
            number += 1;
            productOrderItem.setProductOrderItem_id(orderItem.getProductOrderItem_id());
            productOrderItem.setProductOrderItem_number((short) number);
            productOrderItem.setProductOrderItem_price(number * product.getProduct_sale_price());
            boolean yn = productOrderItemService.update(productOrderItem);
            if (yn) {
                object.put("success", true);
            } else {
                object.put("success", false);
            }
            return object.toJSONString();
        }
    }
    logger.info("封装订单项对象");
    productOrderItem.setProductOrderItem_product(product);
    productOrderItem.setProductOrderItem_number(product_number);
    productOrderItem.setProductOrderItem_price(product.getProduct_sale_price() * product_number);
    productOrderItem.setProductOrderItem_user(new User().setUser_id(Integer.valueOf(userId.toString())));
    boolean yn = productOrderItemService.add(productOrderItem);
    if (yn) {
        object.put("success", true);
    } else {
        object.put("success", false);
    }
    return object.toJSONString();
}

在执行核心的方法之前首先检查,登录状态:调用Basecontroller

//检查用户是否登录
protected Object checkUser(HttpSession session){
    Object o = session.getAttribute("userId");
    if(o==null){
        logger.info("用户未登录");
        return null;
    }
    logger.info("用户已登录,用户ID:{}", o);
    return o;
}

知识点二:@PathVariable 映射 URL 绑定的[占位符]

  • 带占位符的 URLSpring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
  • 通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。

知识点三:JSONObject 对象

用法实例

import org.json.JSONObject;

public class JSONObjectSample {
public static void main(String[] args) {
    createJson();
}
 
private static void createJson() {
    JSONObject obj = new JSONObject();
    obj.put("name", "John");
    obj.put("sex", "male");
    obj.put("age", 22);
    obj.put("is_student", true);
    obj.put("hobbies", new String[] {"hiking", "swimming"});
    //调用toString()方法可直接将其内容打印出来
    System.out.println(obj.toString());
}

执行结果

{“hobbies”:[“hiking”,“swimming”],“sex”:“male”,“name”:“John”,“is_student”:true,“age”:22}

断点调试,查看返回的商品信息

根据id获取需要添加到购物车中的产品信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LnX7y0X9-1660310355888)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811151359660.png)]

返回商品信息之后在创建ProductOrderItem(产品订单项)
private Integer productOrder_id/*订单ID*/;
private String productOrder_code/*订单流水号*/;
private Address productOrder_address/*订单地址*/;
private String productOrder_detail_address/*订单详细地址*/;
private String productOrder_post/*订单邮政编码*/;
private String productOrder_receiver/*订单收货人名称*/;
private String productOrder_mobile/*订单收货人号码*/;
private Date productOrder_pay_date/*订单支付日期*/;
private Date productOrder_delivery_date/*订单发货日期*/;
private Date productOrder_confirm_date/*订单确认日期*/;
private Byte productOrder_status/*订单状态*/;
private User productOrder_user/*订单对应用户*/;
private List<ProductOrderItem> productOrderItemList/*订单项集合*/;

Integer.valueOf()和Integer.valueOf()这两个方法都是Integer的静态方法,都可以传入一个只包含整数的字符串类型,将其转换为整数。

List<ProductOrderItem> orderItemList = productOrderItemService.getListByUserId(Integer.valueOf(userId.toString()),

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LFbXzxot-1660310355889)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811152410217.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6UqtD4i8-1660310355890)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811152744678.png)]

执行for循环语句,找到购物车中的原有项数目加number,没有则会跳出循环,来创建新订单

for (ProductOrderItem orderItem : orderItemList) {
            if (orderItem.getProductOrderItem_product().getProduct_id().equals(product_id)) {
                logger.info("找到已有的产品,进行数量追加");
                int number = orderItem.getProductOrderItem_number();
                number += 1;
                productOrderItem.setProductOrderItem_id(orderItem.getProductOrderItem_id());
                productOrderItem.setProductOrderItem_number((short) number);
                productOrderItem.setProductOrderItem_price(number * product.getProduct_sale_price());
                boolean yn = productOrderItemService.update(productOrderItem);
                if (yn) {
                    object.put("success", true);
                } else {
                    object.put("success", false);
                }
                return object.toJSONString();
            }
        }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RFEy8PhP-1660310355890)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811153702936.png)]

如果匹配成功则会在for循环中修改订单的信息完成对应的修改操作。

调用update语句修改订单项,之后完成数据库更新

boolean yn = productOrderItemService.update(productOrderItem);

到这位置添加购物车订单的流程执行完毕

购物车显示页

请求地址:

Request URL: http://localhost:8080/tmall/cart

请求方式:get方式

请求方法说明://转到前台天猫-购物车页

返回地址:fore/productBuyCarPage(前端的购物车显示页面)

//转到前台天猫-购物车页
    @RequestMapping(value = "cart", method = RequestMethod.GET)
    public String goToCartPage(Map<String, Object> map, HttpSession session) {
        logger.info("检查用户是否登录");
        Object userId = checkUser(session);
        User user;
        if (userId != null) {
            logger.info("获取用户信息");
            user = userService.get(Integer.parseInt(userId.toString()));
            map.put("user", user);
        } else {
            return "redirect:/login";
        }
        logger.info("获取用户购物车信息");
        List<ProductOrderItem> orderItemList = productOrderItemService.getListByUserId(Integer.valueOf(userId.toString()), null);
        Integer orderItemTotal = 0;
        if (orderItemList.size() > 0) {
            logger.info("获取用户购物车的商品总数");
            orderItemTotal = productOrderItemService.getTotalByUserId(Integer.valueOf(userId.toString()));
            logger.info("获取用户购物车内的商品信息");
            for (ProductOrderItem orderItem : orderItemList) {
                Integer product_id = orderItem.getProductOrderItem_product().getProduct_id();
                Product product = productService.get(product_id);
                product.setSingleProductImageList(productImageService.getList(product_id, (byte) 0, null));
                product.setProduct_category(categoryService.get(product.getProduct_category().getCategory_id()));
                orderItem.setProductOrderItem_product(product);
            }
        }
        map.put("orderItemList", orderItemList);
        map.put("orderItemTotal", orderItemTotal);

        logger.info("转到前台天猫-购物车页");
        return "fore/productBuyCarPage";
    }

ForeOrderController处理请求完成页面跳转

方法名goToCartPage()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1tYGsEZI-1660310355891)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811155541174.png)]

断点调试:走获取购物车信息的流程

之前要先获取用户的信息(从session中的userid中获取信息->查出user的信息)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfJTMI5P-1660310355892)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811155958480.png)]

通过调用业务逻辑层(和之前的复用)

List<ProductOrderItem> orderItemList = productOrderItemService.getListByUserId(Integer.valueOf(userId.toString()), null);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2jW28ShK-1660310355892)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811160309917.png)]

最后获取购物车中的商品总数和对应的信息,完成操作

orderItemTotal = productOrderItemService.getTotalByUserId(Integer.valueOf(userId.toString()));

if (orderItemList.size() > 0) {
            logger.info("获取用户购物车的商品总数");
            orderItemTotal = productOrderItemService.getTotalByUserId(Integer.valueOf(userId.toString()));
            logger.info("获取用户购物车内的商品信息");
            for (ProductOrderItem orderItem : orderItemList) {
                Integer product_id = orderItem.getProductOrderItem_product().getProduct_id();
                Product product = productService.get(product_id); //获取一条产品
                product.setSingleProductImageList(productImageService.getList(product_id, (byte) 0, null));//获取对应的图片
                product.setProduct_category(categoryService.get(product.getProduct_category().getCategory_id()));
                orderItem.setProductOrderItem_product(product);
            }
        }
        map.put("orderItemList", orderItemList);
        map.put("orderItemTotal", orderItemTotal);

        logger.info("转到前台天猫-购物车页");
        return "fore/productBuyCarPage";

//设置订单对应的产品

private Product productOrderItem_product/*订单项对应产品*/;

最后通过map集合进行封装,将携带的数据返回到前台的jsp页面中

map.put("orderItemList", orderItemList);
        map.put("orderItemTotal", orderItemTotal);

        logger.info("转到前台天猫-购物车页");
        return "fore/productBuyCarPage";
在前台的页面进行map集合数据的遍历和渲染

${requestScope.orderItemTotal}

<div id="J_FilterBar">
                <ul id="J_CartSwitch">
                    <li>
                        <a href="${pageContext.request.contextPath}/cart" class="J_MakePoint">
                            <em>全部商品</em>
                            <span class="number">${requestScope.orderItemTotal}</span>
                        </a>
                    </li>
                </ul>
                <div class="cart-sum">
                    <span class="pay-text">已选商品(不含运费)</span>
                    <strong class="price"><em id="J_SmallTotal"><span
                            class="total-symbol">&nbsp;</span>0.00</em></strong>
                    <a id="J_SmallSubmit" class="submit-btn submit-btn-disabled">结&nbsp;算</a>
                </div>
                <div class="wrap-line">
                    <div class="floater"></div>
                </div>
            </div>

数据表格渲染(c:foreach标签)

<c:forEach items="${requestScope.orderItemList}" var="orderItem">
    <tr class="orderItem_category">
        <td colspan="6"><span class="shop_logo"></span><span
                class="category_shop">店铺:贤趣${orderItem.productOrderItem_product.product_category.category_name}旗舰店</span>
        </td>
    </tr>
    <tr class="orderItem_info">
        <td class="tbody_checkbox"><input type="checkbox" class="cbx_select"
                                          id="cbx_orderItem_select_${orderItem.productOrderItem_id}"
                                          name="orderItem_id"><label
                for="cbx_orderItem_select_${orderItem.productOrderItem_id}"></label></td>
        <td><img class="orderItem_product_image"
                 src="${pageContext.request.contextPath}/res/images/item/productSinglePicture/${orderItem.productOrderItem_product.singleProductImageList[0].productImage_src}"
                 style="width: 80px;height: 80px;"/><span class="orderItem_product_name"><a
                href="${pageContext.request.contextPath}/product/${orderItem.productOrderItem_product.product_id}">${orderItem.productOrderItem_product.product_name}</a></span>
        </td>
        <td><span
                class="orderItem_product_price">¥${orderItem.productOrderItem_price/orderItem.productOrderItem_number}</span>
        </td>
        <td>
            <div class="item_amount">
                <a href="javascript:void(0)" οnclick="up(this)"
                   class="J_Minus <c:if test="${orderItem.productOrderItem_number<=1}">no_minus</c:if>">-</a>
                <input type="text" value="${orderItem.productOrderItem_number}"/>
                <a href="javascript:void(0)" οnclick="down(this)" class="J_Plus">+</a>
            </div>
        </td>
        <td>
            <span class="orderItem_product_realPrice">¥${orderItem.productOrderItem_price}</span>
        </td>
        <td><a href="javascript:void(0)" οnclick="removeItem('${orderItem.productOrderItem_id}')"
               class="remove_order">删除</a></td>
        <td>
            <input type="hidden" class="input_orderItem" name="${orderItem.productOrderItem_id}"/>
        </td>
    </tr>
</c:forEach>

购物车删除操作

请求路径:http://localhost:8080/tmall/orderItem/909

请求方式:delete方式

携带参数:订单编号

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rLJgC2em-1660310355893)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220811170949637.png)]

ForeOrderController控制器处理删除操作

//删除订单项-购物车-ajax
    @ResponseBody
    @RequestMapping(value = "orderItem/{orderItem_id}", method = RequestMethod.DELETE, produces = "application/json;charset=utf-8")
    public String deleteOrderItem(@PathVariable("orderItem_id") Integer orderItem_id,
                                  HttpSession session,
                                  HttpServletRequest request) {
        JSONObject object = new JSONObject();
        logger.info("检查用户是否登录");
        Object userId = checkUser(session);
        if (userId == null) {
            object.put("url", "/login");
            object.put("success", false);
            return object.toJSONString();
        }
        logger.info("检查用户的购物车项");
        List<ProductOrderItem> orderItemList = productOrderItemService.getListByUserId(Integer.valueOf(userId.toString()), null);
        boolean isMine = false;
        for (ProductOrderItem orderItem : orderItemList) {
            logger.info("找到匹配的购物车项");
            if (orderItem.getProductOrderItem_id().equals(orderItem_id)) {
                isMine = true;
                break;
            }
        }
        if (isMine) {
            logger.info("删除订单项信息");
            boolean yn = productOrderItemService.deleteList(new Integer[]{orderItem_id});
            if (yn) {
                object.put("success", true);
            } else {
                object.put("success", false);
            }
        } else {
            object.put("success", false);
        }
        return object.toJSONString();
    }

注意:批量删除操作还没有实现

购物车单个结算的操作

单个结算的购物地址:http://localhost:8080/tmall/orderItem

请求方式Put

说明:在提交订单之前完成先更新购物车中的信息

知识点四:JSONObject、MAP、对象、字符串互相转换

实体类(User类)、JSON对象、json字符串

JSONObject jsonObject = JSON.parseObject(user); // 转换为json对象 JSONObject jso = (JSONObject) JSON.toJSON(user); // 转换为json对象`

String personStr = JSONObject.toJSONString(user); // 转换为json字符串

String str = JSON.toJSONString(user); // 转换为json字符串`

User user = jsonObject.toJavaObject(User.class); // json对象转换为实体类 JSON.parseObject(“{“band”:“XX”,“price”:“888”}”, User.class) //String类型json转换为实体类`
2)、List、数组、Map与json代码转换

JSONObject itemJSONObj = JSONObject.parseObject(JSON.toJSONString(itemMap)); //将Map类型的itemInfo转换成json,再经JSONObject转换实现。
JSONObject itemJSONObj = JSONObject.parseObject(JSON.toJSONString(list)); // list转换
JSONArray jsonArray1 = JSONArray.parseObject(JSON.toJSONString(array)); // 数组转换为JSONObject

搞清楚JSONObject的操作步骤

JSONObject orderItemString = JSON.parseObject(orderItemMap);
Set<String> orderItemIDSet = orderItemString.keySet();

Integer. valueOf()方法的作用

Integer. valueOf()可以将基本类型int转换为包装类型Integer,或者将String转换成Integer,String如果为Null或“”都会报错

ForeOrderController控制器实现购物车更新

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qtEbTvkz-1660310355893)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220812195218087.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWO6fgyK-1660310355894)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220812195301363.png)]

 productOrderItemService.get(Integer.valueOf(key));

根据产品订单项的id获取数据库中的一条订单条目信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YiYByV0h-1660310355895)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220812195946955.png)]

说明改订单已经生成了不在属于购物车

Short number = Short.valueOf(orderItemString.getString(key));
                if (number <= 0 || number > 500) {
                    logger.warn("订单项产品数量不合法!");
                    object.put("success", false);
                    return object.toJSONString();
                }
//获取前台提供的订单数判断时候合法符合规定
在结算的时候先更新结算的状态
 //更新购物车订单项数量-ajax
    @ResponseBody
    @RequestMapping(value = "orderItem", method = RequestMethod.PUT, produces = "application/json;charset=utf-8")
    public String updateOrderItem(HttpSession session, Map<String, Object> map, HttpServletResponse response,
                                  @RequestParam String orderItemMap) {
        JSONObject object = new JSONObject();
        logger.info("检查用户是否登录");
        Object userId = checkUser(session);
        if (userId == null) {
            object.put("success", false);
            return object.toJSONString();
        }

        JSONObject orderItemString = JSON.parseObject(orderItemMap);
        Set<String> orderItemIDSet = orderItemString.keySet();
        if (orderItemIDSet.size() > 0) {
            logger.info("更新产品订单项数量");
            for (String key : orderItemIDSet) {
                ProductOrderItem productOrderItem = productOrderItemService.get(Integer.valueOf(key));
                if (productOrderItem == null || !productOrderItem.getProductOrderItem_user().getUser_id().equals(userId)) {
                    logger.warn("订单项为空或用户状态不一致!");
                    object.put("success", false);
                    return object.toJSONString();
                }
                if (productOrderItem.getProductOrderItem_order() != null) {
                    logger.warn("用户订单项不属于购物车,回到购物车页");
                    return "redirect:/cart";
                }
                Short number = Short.valueOf(orderItemString.getString(key));
                if (number <= 0 || number > 500) {
                    logger.warn("订单项产品数量不合法!");
                    object.put("success", false);
                    return object.toJSONString();
                }
                double price = productOrderItem.getProductOrderItem_price() / productOrderItem.getProductOrderItem_number();
                Boolean yn = productOrderItemService.update(new ProductOrderItem().setProductOrderItem_id(Integer.valueOf(key)).setProductOrderItem_number(number).setProductOrderItem_price(number * price));
                if (!yn) {
                    throw new RuntimeException();
                }
            }
            Object[] orderItemIDArray = orderItemIDSet.toArray();
            object.put("success", true);
            object.put("orderItemIDArray", orderItemIDArray);
            return object.toJSONString();
        } else {
            logger.warn("无订单项可以处理");
            object.put("success", false);
            return object.toJSONString();
        }
    }

购物车结算时前台向后台发送的请求

function create(obj) {
    obj = $(obj);
    if (!obj.hasClass("selected")) {
        return true;
    }
    var orderItemMap = {};
    var tr = $("input.cbx_select:checked").parents("tr.orderItem_info");
    tr.each(function () {
        var key = $(this).find(".input_orderItem").attr("name");
        orderItemMap[key] = $(this).find(".item_amount").children("input").val();
    });
    $.ajax({
        url: "/tmall/orderItem",
        type: "PUT",
        data: {
            "orderItemMap": JSON.stringify(orderItemMap)
        },
        traditional: true,
        success: function (data) {
            if (data.success) {
                location.href = "/tmall/order/create/byCart?order_item_list=" + data.orderItemIDArray;
                return true;
            } else {
                alert("购物车商品结算异常,请稍候再试!");
                location.href = "/tmall/cart";
            }
        },
        beforeSend: function () {
        },
        error: function () {
            alert("购物车商品结算异常,请稍候再试!");
            location.href = "/tmall/cart";
        }
    });

我们可以通过 JSON.stringify() 把 JavaScript 对象转换为字符串。

JSON.stringify()语法

JSON.stringify(value[, replacer [, space]])

JSON.stringify()不是只有一个参数,它最多可以有三个参数,只是一般后面两个用不到,所以我们会忽略它们。

value

将要序列化成 一个 JSON 字符串的值。

replacer [可选]

如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。

space [可选]

指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;如果该参数没有提供(或者为 null),将没有空格。

“orderItemMap”: JSON.stringify(orderItemMap)

traditional: true,
这个属性可以让ajax传数组,或对象

修改购物车的状态完成之后发送请求

/tmall/order/create/byCart?order_item_list=" + data.orderItemIDArray;

说明创建多个订单(集合)

跳转到购物车建立订单页

 //转到前台天猫-购物车订单建立页
    @RequestMapping(value = "order/create/byCart", method = RequestMethod.GET)
    public String goToOrderConfirmPageByCart(Map<String, Object> map,
                                             HttpSession session, HttpServletRequest request,
                                             @RequestParam(required = false) Integer[] order_item_list) throws UnsupportedEncodingException {
        logger.info("检查用户是否登录");
        Object userId = checkUser(session);
        User user;
        if (userId != null) {
            logger.info("获取用户信息");
            user = userService.get(Integer.parseInt(userId.toString()));
            map.put("user", user);
        } else {
            return "redirect:/login";
        }
        if (order_item_list == null || order_item_list.length == 0) {
            logger.warn("用户订单项数组不存在,回到购物车页");
            return "redirect:/cart";
        }
        logger.info("通过订单项ID数组获取订单信息");
        List<ProductOrderItem> orderItemList = new ArrayList<>(order_item_list.length);
        for (Integer orderItem_id : order_item_list) {
            orderItemList.add(productOrderItemService.get(orderItem_id));
        }
        logger.info("------检查订单项合法性------");
        if (orderItemList.size() == 0) {
            logger.warn("用户订单项获取失败,回到购物车页");
            return "redirect:/cart";
        }
        for (ProductOrderItem orderItem : orderItemList) {
            if(orderItem.getProductOrderItem_user().getUser_id().equals(userId)==false){
//            if (orderItem.getProductOrderItem_user().getUser_id() != userId) {
                logger.warn("用户订单项与用户不匹配,回到购物车页");
                return "redirect:/cart";
            }
            if (orderItem.getProductOrderItem_order() != null) {
                logger.warn("用户订单项不属于购物车,回到购物车页");
                return "redirect:/cart";
            }
        }
        logger.info("验证通过,获取订单项的产品信息");
        double orderTotalPrice = 0.0;
        for (ProductOrderItem orderItem : orderItemList) {
            Product product = productService.get(orderItem.getProductOrderItem_product().getProduct_id());
            product.setProduct_category(categoryService.get(product.getProduct_category().getCategory_id()));
            product.setSingleProductImageList(productImageService.getList(product.getProduct_id(), (byte) 0, new PageUtil(0, 1)));
            orderItem.setProductOrderItem_product(product);
            orderTotalPrice += orderItem.getProductOrderItem_price();
        }
        String addressId = "110000";
        String cityAddressId = "110100";
        String districtAddressId = "110101";
        String detailsAddress = null;
        String order_post = null;
        String order_receiver = null;
        String order_phone = null;
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                String cookieName = cookie.getName();
                String cookieValue = cookie.getValue();
                switch (cookieName) {
                    case "addressId":
                        addressId = cookieValue;
                        break;
                    case "cityAddressId":
                        cityAddressId = cookieValue;
                        break;
                    case "districtAddressId":
                        districtAddressId = cookieValue;
                        break;
                    case "order_post":
                        order_post = URLDecoder.decode(cookieValue, "UTF-8");
                        break;
                    case "order_receiver":
                        order_receiver = URLDecoder.decode(cookieValue, "UTF-8");
                        break;
                    case "order_phone":
                        order_phone = URLDecoder.decode(cookieValue, "UTF-8");
                        break;
                    case "detailsAddress":
                        detailsAddress = URLDecoder.decode(cookieValue, "UTF-8");
                        break;
                }
            }
        }
        logger.info("获取省份信息");
        List<Address> addressList = addressService.getRoot();
        logger.info("获取addressId为{}的市级地址信息", addressId);
        List<Address> cityAddress = addressService.getList(null, addressId);
        logger.info("获取cityAddressId为{}的区级地址信息", cityAddressId);
        List<Address> districtAddress = addressService.getList(null, cityAddressId);

        map.put("orderItemList", orderItemList);
        map.put("addressList", addressList);
        map.put("cityList", cityAddress);
        map.put("districtList", districtAddress);
        map.put("orderTotalPrice", orderTotalPrice);

        map.put("addressId", addressId);
        map.put("cityAddressId", cityAddressId);
        map.put("districtAddressId", districtAddressId);
        map.put("order_post", order_post);
        map.put("order_receiver", order_receiver);
        map.put("order_phone", order_phone);
        map.put("detailsAddress", detailsAddress);

        logger.info("转到前台天猫-订单建立页");
        return "fore/productBuyPage";
    }
获取购物车中结算的信息用来创建订单

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dsncsw5U-1660310355896)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220812203303586.png)]

return "fore/productBuyPage";

根据控制器中的信息判端出前端的返回地址

//转到前台天猫-购物车订单建立页
@RequestMapping(value = "order/create/byCart", method = RequestMethod.GET)
public String goToOrderConfirmPageByCart(Map<String, Object> map,
                                         HttpSession session, HttpServletRequest request,
                                         @RequestParam(required = false) Integer[] order_item_list) throws UnsupportedEncodingException {
    logger.info("检查用户是否登录");
    
    return "fore/productBuyPage";
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序小旭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值