确认下单:购物车页面点击 去结算 按钮发起两个请求trade(显示购物车的商品信息和计算商品的总金额)&findUserAddressList

1、确认下单:购物车页面点击去结算

  • 点击去结算这个按钮,会发起一个请求,这个请求是trade,然后展示我们要购买的商品商品的总金额
    在这里插入图片描述

1.1、在OrderController类中创建 trade 方法

@RestController
@Tag(name = "订单管理模块", description = "订单管理模块")
@RequestMapping("/api/order/orderInfo")
public class OrderController {
	@Resource
    private OrderService orderService;
    
	//查询购物车中选中的购物项列表 转为 orderItem 列表交给前端展示
    @Operation(summary = "确认下单:购物车页面点击去结算")
    @GetMapping("/auth/trade")
    public Result trade() {
        TradeVo tradeVo = orderService.trade();
        return Result.ok(tradeVo);
    }
}

1.2、在CartController类中创建 checkedCartInfos

@RestController
@RequestMapping("/api/order/cart")
@Tag(name = "购物车模块")
public class CartController {
	    //只要请求头中携带token,不需要再传用户id
    @Operation(summary = "查询用户购物车已选中购物项列表")
    @GetMapping("/auth/checkedCartInfos")
    public Result checkedCartInfos()
    {
        List<CartInfo> cartInfos = cartService.checkedCartInfos();
        return Result.ok(cartInfos);
    }
}

1.3、CartServiceImpl 实现 checkedCartInfos的业务功能

@Service
public class CartServiceImpl implements CartService {
    @Resource
    private RedisTemplate redisTemplate;
   
    private BoundHashOperations getUserCart() {
        UserInfo userInfo = SpzxServiceAuthInterceptor.THREAD_LOCAL.get();
        BoundHashOperations ops = redisTemplate.boundHashOps("spzx:cart:" + userInfo.getId());
        return ops;
    }
    @Override
    public List<CartInfo> checkedCartInfos() {
        //泛型1:redis键类型,泛型2:hash的key类型, 泛型3:hash的value的类型
        BoundHashOperations<String,String,CartInfo> userCart = getUserCart();

        return userCart.values().stream().filter(cartInfo -> cartInfo.getIsChecked()==1).toList();
    }
}

1.4、在service-cart-client模块下定义远程openFeign接口

@FeignClient(value = "service-cart")
public interface CartClient {

    @GetMapping("/api/order/cart/auth/checkedCartInfos")
    public Result<List<CartInfo>> checkedCartInfos();

    @DeleteMapping("/api/order/cart/auth/delCheckedCartInfos")
    public Result<Void> delCheckedCartInfos();
}

1.5、在SpzxOrderApplication类上加上@EnableFeignClients

@SpringBootApplication
@EnableSpzxServiceAuth
@EnableFeignClients(basePackages = "com.atguigu.spzx")
@EnableCartClientConfig
@MapperScan(basePackages = "com.atguigu.spzx.order.mapper")
@EnableTransactionManagement
public class SpzxOrderApplication {
    public static void main(String[] args)
    {
        SpringApplication.run(SpzxOrderApplication.class,args);
    }
}

1.6、OrderServiceImpl 实现 trade的业务逻辑

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService {
    @Resource
    private CartClient cartClient;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
	@Override
    public TradeVo trade() {

        //1、查询 当前用户 的购物车中已选中的购物项列表(cart服务管理购物车数据)
        Result<List<CartInfo>> cartInfos = cartClient.checkedCartInfos();
        if (cartInfos.getCode() != 200) {
            throw new SpzxException(ResultCodeEnum.FAIL,null);
        }
        List<CartInfo> cartInfoList = cartInfos.getData();
        if (CollectionUtils.isEmpty(cartInfoList)) {
            //没有已选中的购物项
            throw new SpzxException(ResultCodeEnum.FAIL,null);
        }
        Long token = IdUtil.getSnowflake(1,1).nextId();
        //将token存到redis:redis的大key问题
        stringRedisTemplate.opsForValue().set("spzx:order:"+token.toString(), "1",  30, TimeUnit.MINUTES);
        //2、将购物项列表转为 OrderItem列表
        List<OrderItem> orderItemList = cartInfoList.stream().map(cartInfo -> {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(token);
            orderItem.setSkuId(cartInfo.getSkuId());
            orderItem.setSkuName(cartInfo.getSkuName());
            orderItem.setSkuNum(cartInfo.getSkuNum());
            orderItem.setSkuPrice(cartInfo.getCartPrice());
            orderItem.setThumbImg(cartInfo.getImgUrl());
            return orderItem;
        }).toList();

        TradeVo tradeVo = new TradeVo();
        tradeVo.setOrderItemList(orderItemList);

        //遍历每一个订单项,计算它的小计金额返回
        //最后对所有小计金额累加 得到总金额
        tradeVo.setTotalAmount(orderItemList.stream().map(orderItem -> {
            return orderItem.getSkuPrice().multiply(new java.math.BigDecimal(orderItem.getSkuNum()));
        }).reduce(BigDecimal::add).get());
        return tradeVo;
    }
}

1.7、此时启动 SpzxOrderApplication

-点击 购物车页面的 去结算按钮 发现报错NullPointerException

java.lang.NullPointerException: Cannot invoke "com.atguigu.spzx.model.entity.user.UserInfo.getId()" 
because the return value of "com.atguigu.spzx.common.util.AuthContextUtil.getUserInfo()" is null
	at com.atguigu.spzx.cart.service.impl.CartServiceImpl.getAllCkecked(CartServiceImpl.java:147)

2、 openFeign拦截器使用

在这里插入图片描述

2.1、使用feign拦截器拦截请求,获取token,重新传递token

针对service-cart微服务是获取不到当前登录用户的信息。原因:service-order微服务调用service-cart微服务的时候,是通过openFeign进行调用,openFeign在调用的时候会丢失请求头

2.1.1、CartClientInterceptor

@Component
public class CartClientInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        //1、获取引入cartClient模块的 项目 在使用cartClient时  请求报文中的token
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("token");
        //2、将token设置到feign客户端的请求报文中
        requestTemplate.header("token", token);
    }
}

现在订单服务无法使用feign拦截器,因为这个组件类放到了com.atguigu.spzx.cart.interceptor下面,订单服务扫描不到,如果我们想启用它,可以创建注解,然后把注解加到订单服务的启动类上面

2.1.2、@EnableCartClientConfig

@Target({ElementType.TYPE})
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Documented
@Import(value = {CartClientInterceptor.class})
public @interface EnableCartClientConfig {
}

2.1.3、SpzxOrderApplication

@SpringBootApplication
@EnableSpzxServiceAuth
@EnableFeignClients(basePackages = "com.atguigu.spzx")
@EnableCartClientConfig
@MapperScan(basePackages = "com.atguigu.spzx.order.mapper")
@EnableTransactionManagement
public class SpzxOrderApplication {
    public static void main(String[] args)
    {
        SpringApplication.run(SpzxOrderApplication.class,args);
    }
}
  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值