SpringCloud商城day11 订单-2021-10-24

一. 订单渲染结算页

1. 用户收件地址查询: 登录人名称-> 收件人地址信息-> 表tb-address

(1) com.changgou.user.service.impl.AddressServiceImpl类
/***
 * 收件地址查询
 * @param username
 * @return
 */
@Override
public List<Address> list(String username) {
    Address address = new Address();
    address.setUsername(username);
    return addressMapper.select(address);
}

(2) com.changgou.user.controller.AddressController类
/****
 * 用户收件地址
 */
@GetMapping(value = "/list")
public Result<List<Address>> list(){
    //获取用户登录信息
    Map<String, String> userMap = tokenDecode.getUserInfo();
    String username = userMap.get("username");
    //查询用户收件地址
    List<Address> addressList = addressService.list(username);
    return new Result(true, StatusCode.OK,"查询成功!",addressList);
}

2. 拦截器获取令牌

@Component
public class FeignInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes!=null){
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            if (request!=null){
                Enumeration<String> headerNames = request.getHeaderNames();
                if (headerNames!=null){
                    while (headerNames.hasMoreElements()){
                        String headerName = headerNames.nextElement();
                        if (headerName.equals("authorization")){
                            String headerValue = request.getHeader(headerName);
                            requestTemplate.header(headerName,headerValue);
                        }
                    }
                }
            }
        }
    }
}

3. 通过令牌动态获取登录人信息-> TokenDecode中通过JWTHelper中的decodeAndVerfify

public class TokenDecode {
    //公钥
    private static final String PUBLIC_KEY = "public.key";
    private static String publickey="";
    /***
     * 获取用户信息
     * @return
     */
    public Map<String,String> getUserInfo(){
        //获取授权信息
        OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();
        //令牌解码
        return dcodeToken(details.getTokenValue());
    }
    /***
     * 读取令牌数据
     */
    public Map<String,String> dcodeToken(String token){
        //校验Jwt
        Jwt jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(getPubKey()));
        //获取Jwt原始内容
        String claims = jwt.getClaims();
        return JSON.parseObject(claims,Map.class);
    }

    /**
     * 获取非对称加密公钥 Key
     * @return 公钥 Key
     */
    public String getPubKey() {
        if(!StringUtils.isEmpty(publickey)){
            return publickey;
        }
        Resource resource = new ClassPathResource(PUBLIC_KEY);
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
            BufferedReader br = new BufferedReader(inputStreamReader);
            publickey = br.lines().collect(Collectors.joining("\n"));
            return publickey;
        } catch (IOException ioe) {
            return null;
        }
    }
}

4. 购物车数据回显

   @Autowired
    private CartFeign cartFeign;
    @RequestMapping("ready/order")
    public String readyOrder(Model model) {
        //1. 收件人地址信息
        List<Address> addressList = addressFeign.list().getData();
        model.addAttribute("address",addressList);
        //2. 购物车信息
        Map map = cartFeign.list();
        List<OrderItem> oderItemList = (List<OrderItem>) map.get("orderItemList");
        Integer totalMoney = (Integer) map.get("totalMoney");
        Integer totalNum = (Integer) map.get("totalNum");
        model.addAttribute("carts",oderItemList);
        model.addAttribute("totalMoney",totalMoney);
        model.addAttribute("totalNum", totalNum);
        //3.默认收件人信息
            for (Address address : addressList) {
                if ("1".equals(address.getIsDefault())){
                    //默认收件人
                    model.addAttribute("deAddr",address);
                    break;
                }
        }
        return "order";
    }

二. 用户下单实现

1. 需要操作的表:

tb_order: 订单表的相关信息(orderId); 

tb_order_item: 订单中每一项商品信息明细表(skuList)

2. 业务流程:  提交订单-> 到达订单微服务-> 保存到MySQL(订单表和订单明细表)->  订单微服务远程调用goods微服务-> 较少goods表的商品库存

(1) OrderServiceImpl.java. 拿到购物车信息-> 封装到order表和order_item表-> 删除购物车
    /**
     * 增加
     * @param order
     */
    @Override
    @GlobalTransactional(name = "order_add")  //Fescar全局事务注解
    public String add(Order order){

        //1.获取购物车相关数据(redis)
        Map cartMap = cartService.list(order.getUsername());

        List<OrderItem> orderItemList = (List<OrderItem>) cartMap.get("orderItemList");

        //2. 统计订单总金额和数量


        //3. 填充订单数据并保存到tb_order表中
        order.setTotalNum((Integer) cartMap.get("totalNum"));
        order.setTotalMoney((Integer) cartMap.get("totalMoney"));
        order.setPayMoney((Integer) cartMap.get("totalMoney"));

        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setBuyerRate("0"); // 0:未评价; 1:已评价
        order.setSourceType("1"); //1: 来源web端
        order.setOrderStatus("0"); //0:订单未完成;  1:已完成;  2:已退货
        order.setPayStatus("0");  //0:未支付;  1:已支付
        order.setConsignStatus("0");  //0:未发货;  1:已发货

        //设置订单号
        String orderId = idWorker.nextId()+"";
        order.setId(orderId);

        //保存order到tb_order表中
        orderMapper.insertSelective(order);



        //4. 填充当前订单项数据并保存到tb_order_item
        for (OrderItem orderItem : orderItemList) {

            orderItem.setId(idWorker.nextId()+"");

            orderItem.setIsReturn("0");  //0:未退货; 1:已退货
            orderItem.setOrderId(orderId);

            orderItemMapper.insertSelective(orderItem);

        }

        //4.2 扣减库存并增加销量
        skuFeign.decrCount(order.getUsername());

        //4.3 增加用户积分, 此方法已经被下面的分布式事务消息队列实现
        //userFeign.addPoints(10);


        //在订单数据库中的任务表tb_task添加任务数据
        Task task = new Task();
        task.setCreateTime(new Date());
        task.setUpdateTime(new Date());
        task.setMqExchange(RabbitMQConfig.EX_BUYING_ADDPOINTUSER);
        task.setMqRoutingkey(RabbitMQConfig.CG_BUYING_ADDPOINT_KEY);

        Map map = new HashMap();
        map.put("username", order.getUsername());
        map.put("orderId", orderId);
        map.put("point", order.getPayMoney());
        task.setRequestBody(JSON.toJSONString(map));

        taskMapper.insertSelective(task); //


        //5. 删除购物车的数据
        redisTemplate.delete("cart_"+order.getUsername());
        //orderMapper.insert(order);


        //发送延迟消息
        rabbitTemplate.convertAndSend("", "queue.ordercreate", orderId);

        return orderId;
    }

(2) orderController.java以feign的形式进行暴露, 给web渲染服务OrderController.java调用
    @Autowired
    private OrderFeign orderFeign;

    @PostMapping("/add")
    @ResponseBody
    public Result add(Order order) {

        Result result = orderFeign.add(order);

        return result;
    }

三. 库存变更实现

1. 业务: order微服务-> 传用户名到goods微服务-> goods微服务找到redis中购物车数据-> 执行库存减少

Goods商品微服务中:
(1) SkuMapper.java
public interface SkuMapper extends Mapper<Sku> {
    //扣减库存并增加销量
    @Update("update tb_sku set num=num-#{num},sale_num=sale_num+#{num} where id=#{skuId} and num >=#{num}")
    int decrCount(OrderItem orderItem);
}

(2) SkuServiceImpl.java
 @Autowired
    private RedisTemplate redisTemplate;
    //删减库存
    @Override
    public void decrCount(String username) {
        //1. 获取购物车中数据
        List<OrderItem> orderItemList = redisTemplate.boundHashOps("cart_" + username).values();
        //2. 循环扣减库存并增加销量
        for (OrderItem orderItem : orderItemList) {
            //返回受影响的数据库行数
            int count = skuMapper.decrCount(orderItem);
            if (count<=0){
                throw new RuntimeException("库存不足,请重试!");
            }
        }
    }

(3) SkuController.java
//扣减库存
    @PostMapping("/decr/count")
    public Result decrCount(@RequestParam("username") String username) {
        skuService.decrCount(username);
        return new Result(true, StatusCode.OK, "库存扣减成功");
    }


(4) service_goods_api中SkuFeign.java
 //扣减库存
    @PostMapping("/sku/decr/count")
    public Result decrCount(@RequestParam("username") String username);

2. Order订单微服务调用goods微服务:

  (1) 商品微服务整合了Oauth2, order微服务需要传递令牌-> 使用FeignInterceptor拦截器

  (2) 拦截器以@Bean形式生命在Order订单微服务中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值