刷新购物车页面导致商品顺序和刷新之前不一致

  昨天客户反馈,从购物车页面点击结算按钮跳转到下单页面,又想修改商品,返回到购物车页面时,商品的顺序和上次查看的顺序不一致。
              购物车页面
  查看线上日志,发现是CartController类的方法问题。大致流程是:
  1、根据用户cookie属性从数据库查到用户的购物车cart;
  2、将cart(数据库数据类型的DO)转换cartvo(页面显示的数据类型VO)返回给前端。
  其中第二步数据转换有问题,这部分的源码如下

CartVo cartVo = BeanMapper.map(cart, BeanMapper.getType(Cart.class), BeanMapper.getType(CartVo.class));

  CartVo类有如下属性(简化其他属性)

@Data
public class CartVo implements Serializable {
    /** 子购物车 */
    private List<CartVo> children;

    /** 购物车项 */
    private Set<CartItemVo> cartItems = new TreeSet<>();

  Cart类属性和CartVo类属性类似。通过阅读BeanMapper的map转换源码(第三方jar包“orika”),发现set集合使用的hashset进行集合包装,而hashset具有有序性(sort),但不具有稳定性(order),结果导致每次数据转换的顺序不稳定。BeanMapper源码如下

    public final <S, D> Set<D> mapAsSet(final Iterable<S> source, final Type<S> sourceType, final Type<D> destinationType,
            final MappingContext context) {
        return (Set<D>) mapAsCollection(source, sourceType, destinationType, new HashSet<D>(), context);
    }

  知道问题后就好处理,改为TreeSet集合来包装数据。本来想使用门面设计模式继承BeanMapper,发现它的源码很复杂,不是两小时内能搞定的,就采用再封装一层转换的思路委婉的解决这个问题。BeanMapper类中源码如下

    public static <S, D> Set<D> mapAsSet(Iterable<S> sourceList, Type<S> sourceType, Type<D> destinationType) {
        return new TreeSet<>(mapper.mapAsSet(sourceList, sourceType, destinationType));
    }

  上层Controller调用稍微复杂一些,本来1行代码现在改为8行代码,源码如下

        CartVo cartVo = BeanMapper.map(cart, BeanMapper.getType(Cart.class), BeanMapper.getType(CartVo.class));
        cartVo.setChildren(new ArrayList<CartVo>());
        for (Cart child : cart.getChildren()) {
            CartVo childVO = BeanMapper.map(child, BeanMapper.getType(Cart.class), BeanMapper.getType(CartVo.class));
            childVO.setCartItems(BeanMapper.mapAsSet(child.getCartItems(), BeanMapper.getType(CartItem.class),
                    BeanMapper.getType(CartItemVo.class)));
            cartVo.getChildren().add(childVO);
        }

知识点:
  集合的有序性是指遍历的结果按照指定的比较规则依次排列;集合的稳定性是指每次遍历,元素次序是不会改变。
  java的ArrayList是无序但稳定;HashMap是无序也不稳定;HashSet是有序但不稳定;TreeSet是有序且稳定

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在 PHP 中实现更新购物而不刷新页面的方法通常是使用 AJAX 技术。 AJAX 可以让页面在不刷新的情况下向服务器发送请求,并接收到服务器返回的数据。这样就可以实现在不刷新页面的情况下更新购物。 下面是一个简单的示例代码: 1. HTML 页面中使用 AJAX 发送请求: ```html <button onclick="updateCart()">更新购物</button> <script> function updateCart() { var xhr = new XMLHttpRequest(); xhr.open('POST', 'update_cart.php', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { // 更新购物视图 } }; xhr.send('product_id=123&quantity=2'); // 发送请求参数 } </script> ``` 2. PHP 脚本中处理 AJAX 请求: ```php <?php // 处理更新购物请求 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['product_id']) && isset($_POST['quantity'])) { $product_id = $_POST['product_id']; $quantity = $_POST['quantity']; // 更新购物数据 // ... // 返回更新后的购物数据 echo json_encode($cart_data); } ?> ``` 在上面的代码中,当用户点击“更新购物”按钮时,JavaScript 调用了 `updateCart()` 函数,该函数使用 AJAX 发送 POST 请求到 `update_cart.php` 脚本。`update_cart.php` 脚本处理该请求并返回更新后的购物数据,JavaScript 在接收到响应后更新购物视图。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值