【无标题】

redis

  • keys *

  • flushdb

  • 键值对的健是string类型才可以获取到.

  • HashMap是一个key:value对象

  • set是一个数组对象.

  • HashMap的entrySet

            Iterator<Map.Entry<Long, Set<Long>>> iterator = activityIdToSkuIdListMap.entrySet().iterator();

//             是哟nentry使用为可以遍历,在HashMap是不可以遍历的,只能通过GetKey()获得value.

            List<CartInfo> currentActivityCartInfoList = null;
            while (iterator.hasNext()) {
                Map.Entry<Long, Set<Long>> next = iterator.next();
//                key
                Long activityId = next.getKey();
//                value
                Set<Long> value = next.getValue();
//一个是购物车数据  一个是有活动的数据.
                currentActivityCartInfoList = cartInfoList.stream().filter(cartInfo -> value.contains(cartInfo.getSkuId()))
                        .collect(Collectors.toList());
            }
//

import lombok.Data;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class demo1 {

    public static void main(String[] args) {
        List<User> list = new ArrayList();
        User user = new User(new BigDecimal(100));
        User user1 = new User(new BigDecimal(200));
        list.add(user);
        list.add(user1);


        BigDecimal bigDecimal = list.stream().map(User::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println(bigDecimal);

    }


}

@Data
class User {
    private BigDecimal money;

    public User(BigDecimal money) {
        this.money = money;
    }


    public BigDecimal getMoney() {
        return this.money;
    }

    public void setMoney(BigDecimal money) {
        this.money = money;
    }

}
 BigDecimal reduceAmount = cartActivityList.stream().filter(item -> item.getActivityRule() != null)
                .map(cartActivity -> cartActivity.getActivityRule().getReduceAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);

  Map<Long, CartInfo> ShopcartIdToInfoMap = null;
//            获得所有的购物车数据
            if (!CollectionUtils.isEmpty(collect)) {
                ShopcartIdToInfoMap = cartInfoList.stream().collect(Collectors.toMap(CartInfo::getSkuId, CartInfo -> CartInfo));
            }

map的需要collect(Collectors.toMap()).

优惠券

在这里插入图片描述

  • 检查库存(判断),之后锁定库存。
  • 两个请求都检查了库存,都检查为1,之后一起执行操作。导致库存直接变为-1,导致超卖。
    怎么解决?加锁。
    在这里插入图片描述
    在这里插入图片描述
  • 可是加锁之后。只是对应着系统层面而已。系统一多就不起作用了。
  • 所以使用分布式锁。解决超卖问题。

springboot配置类。

  • 分布式锁会把检查库存和锁定库存和更新库存.加分布式锁.
  • 分布式锁比锁可以适用更多系统集群上,
  • 加锁就是在操作购物车的数据会加上锁.在操作这三个步骤的时候,别的请求操作不了.

redission

在产品列表的数据库有,stock和lock_stock(锁定库存)两个字段,我们锁定库存数量写道lock_stock中的。

订单

  • 确认订单 --》 生成订单 --》

1.1 确认订单生成订单号,存储到redis中。
1.2 查询地址信息。和优惠券信息。

2.1 订单号查重
2.2 验证库存

优惠券

优惠券_info:有三种类型,sku和分类和通用.任选一种.
优惠券规则:有多个可以是多个商品或者是多个分类.或者是一个分类.
优惠券info与规则是一对多关系.

    private Map<Long, List<Long>> findCouponIdToSkuIdMap(List<CartInfo> cartInfoList, List<CouponRange> couponRangesList) {
        Map<Long, List<Long>> couponIdToSkuIdMap = new HashMap<>();
//        根据优惠券id分组优惠券range信息.
        Map<Long, List<CouponRange>> couponRangeGroupList = couponRangesList.stream().collect(Collectors.groupingBy(CouponRange::getCouponId));
        Iterator<Map.Entry<Long, List<CouponRange>>> iterator = couponRangeGroupList.entrySet().iterator();
//        优惠券分组. value是优惠券的信息(类型和包含种类)
//        Map  优惠券id -- 优惠券list规则。
        while (iterator.hasNext()) {
            Map.Entry<Long, List<CouponRange>> entry = iterator.next();
//            相当于给mao一个迭代指针.
            Long couponId = entry.getKey();
            List<CouponRange> couponRangeList = entry.getValue();
//把有优惠券的加入集合.
            Set<Long> skuIdSet = new HashSet<>();
//            遍历每一个商品
            for (CartInfo cartInfo : cartInfoList) {
//                遍历每个优惠规则。
                for (CouponRange couponRange : couponRangeList) {
                    if (CouponRangeType.SKU == couponRange.getRangeType()
//                            优惠券是sku的
                            && couponRange.getRangeId().longValue() == cartInfo.getSkuId().intValue()) {
                        skuIdSet.add(cartInfo.getSkuId());
                    } else if (CouponRangeType.CATEGORY == couponRange.getRangeType()
                            && couponRange.getRangeId().longValue() == cartInfo.getCategoryId().intValue()) {
//                        优惠券是分类券。
                        skuIdSet.add(cartInfo.getSkuId());
                    } else {

                    }
                }
            }
//            这是优惠券id对应的有优惠的skuId集合.
//            这个优惠券可以用在这些商品上.已经把没有的排除掉了.
            couponIdToSkuIdMap.put(couponId, new ArrayList<>(skuIdSet));
//           收集到了这张优惠券info可以用的商品.
        }
        return couponIdToSkuIdMap;
    }
  • 得到每个优惠券可以使用的商品
  • 之后可以对比每个优惠券的优惠力度. 选择最优惠的优惠券.
  • 只有得到这个优惠券info可以使用的购物商品的集合.实现了优惠券与商品的对应关系.
   CouponInfo couponInfo = baseMapper.selectById(couponId);
   couponInfo.setSkuIdList(value);
  • 在生成订单的时候应该保存好最优优惠券的id及其相关信息.之后确认订单需要重新计算金额.

分摊优惠:

商品A的分摊优惠:10元(100/180 * 20)
商品B的分摊优惠:8元(80/180 * 20)
实际支付:商品A = 90元,商品B = 72元,总计162元。
这样,消费者可以清楚地看到每个商品的实际价格和节省的金额。

总之,优惠分摊提供了一种更细致、透明和公平的方式来处理优惠,有助于提高消费者信任,符合会计和税务要求,并为商家提供更准确的销售数据。

在这里插入图片描述

  • 订单项的金额相加和优惠金额相加 , 还有订单id关联订单项目order_id.

在这里插入图片描述

订单问题需要事务处理,如果订单项有一个插入失败,那么都失败.

@EnableTransactionManagement
public class MybatisPlusConfig {

    /**
    @Transactional(rollbackFor = {Exception.class})
   public Long saveOrder(OrderSubmitVo orderParamVo, List<CartInfo> cartInfoList) {

订单确认—> 生成订单 --> 订单详情.

  • 订单和订单项目,订单项目需要根据活动和优惠进行减少订单项目的金额。
  • 订单需要一共减少了多少金额,填写信息。之后更新优惠券使用信息。
  • 订单项目放在redis中

在这里插入图片描述

  • 生成订单之后要删除购物车部分。
  • MQ是使用在模块的之间的,如果一个模块的请求的数据或者操作不是立马使用的话(feign),就可以使用mq,因为订单模块删除购物车数据,不是订单模块立马需要的,所以使用mq.

Rabbit

  1. 使用RabbitServic文件,有交换机和路由器和信息参数。需要在yml配置文件设置好mq的链接账号密码。
  2. rabbit有队列和交换机和路由器.

发送端

        rabbitService.sendMessage(MqConst.EXCHANGE_ORDER_DIRECT, MqConst.ROUTING_DELETE_CART, orderParamVo.getUserId());

package com.atguigu.ssyx.mq.service;


import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

//发送消息
@Service
public class RabbirService {

    @Autowired
    private RabbitTemplate rabbitTemlate;

    /**
     *
     * @param exchange  交换机
     * @param routingKey  队列名字key
     * @param message   消息
     * @return
     */
    public  boolean sendMessage(String exchange,String routingKey,Object message){
        rabbitTemlate.convertAndSend(exchange,routingKey,message);
        return true;
    }
}
  • 这是mq的通用模块文件.

接收端

  • 在接收模块写一个receive文件
package com.atguigu.ssyx.cart.receiver;


import com.atguigu.ssyx.cart.service.CartInfoService;
import com.atguigu.ssyx.mq.constant.MqConst;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class CartReceiver {

    @Autowired
    private CartInfoService cartInfoService;

    /*
    第一个参数是队列中的参数,
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_DELETE_CART, durable = "true"),
            exchange = @Exchange(value = MqConst.EXCHANGE_ORDER_DIRECT),
            key = {MqConst.ROUTING_DELETE_CART}
    ))
    public void deleteCart(Long userId, Message message, Channel channel) throws IOException {
        if (userId == null) {
            return;
        }
        cartInfoService.deleteCartCheck(userId);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

    }
}

  • value是队列 exchange是一个交换机 key是路由器.
  • 拿到数据之后开始发给service层.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@追求卓越

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

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

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

打赏作者

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

抵扣说明:

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

余额充值