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

文章目录

  • 1、确认下单:购物车页面点击去结算
    • 1.1、在OrderController类中创建 trade 方法
    • 1.2、在CartController类中创建 checkedCartInfos
    • 1.3、CartServiceImpl 实现 checkedCartInfos的业务功能
    • 1.4、在service-cart-client模块下定义远程openFeign接口
    • 1.5、在SpzxOrderApplication类上加上@EnableFeignClients
    • 1.6、OrderServiceImpl 实现 trade的业务逻辑
    • 1.7、此时启动 SpzxOrderApplication
  • 2、 openFeign拦截器使用
    • 2.1、使用feign拦截器拦截请求,获取token,重新传递token
      • 2.1.1、CartClientInterceptor
      • 2.1.2、@EnableCartClientConfig
      • 2.1.3、SpzxOrderApplication

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);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/778038.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java - 程序员面试笔记记录 实现 - Part3

4.1 线程与进程 线程是程序执行的最小单元&#xff0c;一个进程可以拥有多个线程&#xff0c;各个线程之间共享程序的内存空间以及一些进程级资源&#xff0c;但拥有自己的栈空间。 4.3 Java 多线程 方法一&#xff1a;继承 Thread 类&#xff0c;重写 run 方法&#xff1b;…

qt QGridLayout 简单实验1

1.概要 2.实验 2.1 实验1 简单实验跨行 2.1.1 代码 #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~W…

Golang语法规范和风格指南(一)——简单指南

1. 前引 一个语言的规范的学习是重要的&#xff0c;直接关系到你的代码是否易于维护和理解&#xff0c;同时学习好对应的语言规范可以在前期学习阶段有效规避该语言语法和未知编程风格的冲突。 这里是 Google 提供的规范&#xff0c;有助于大家在开始学习阶段对 Golang 进行一…

如何魔改vnstat-docker项目使其支持每1分钟采样?

文章目录 一、概述二、官网参考1. 官网地址2. 查看打包过程3.打包命令 三、修改过的文件四、部署运行1. 编排文件2. 运行效果 一、概述 接前文 网络流量监控神器vnStat初探 我们已经了解了vnStat的作用、使用和docker部署。 同时也了解到官方版本支持的采样统计间隔最小为5分…

【Unity】unity学习扫盲知识点

1、建议检查下SystemInfo的引用。这个是什么 Unity的SystemInfo类提供了一种获取关于当前硬件和操作系统的信息的方法。这包括设备类型&#xff0c;操作系统&#xff0c;处理器&#xff0c;内存&#xff0c;显卡&#xff0c;支持的Unity特性等。使用SystemInfo类非常简单。它的…

Linux操作系统的引导过程

系统初始化进程与文件、systemd概述、单元类型、切换运行级别、查看系统默认默认运行、永久切换、常见的系统服务&#xff08;centos&#xff09;-CSDN博客 centos 7系统升级内核&#xff08;ELRepo仓库&#xff09;、小版本升级、自编译内核-CSDN博客 ss命令详细使用讲解文…

tongweb+ths6011测试websocket(by lqw)

本次使用的tongweb版本7049m4&#xff0c;测试包ws_example.war&#xff08;在tongweb安装目录的samples/websocket下&#xff09;&#xff0c;ths版本6011 首先在tongweb控制台部署一下ws_example.war,部署后测试是否能访问&#xff1a; 然後ths上的httpserver.conf的參考配…

游戏服务器搭建选VPS还是专用服务器?

游戏服务器搭建选VPS&#xff0c;VPS能够提供控制、性能和稳定性。它不仅仅是让游戏保持活力。它有助于减少延迟问题&#xff0c;增强您的游戏体验。 想象一下&#xff1a;你正沉浸在一场游戏中。 胜利在望。突然&#xff0c;屏幕卡住——服务器延迟。 很崩溃&#xff0c;对…

PageCache页缓存

一.PageCache基本结构 1.PageCache任务 PageCache负责使用系统调用向系统申请页的内存,给CentralCache分配大块儿的内存,以及合并前后页空闲的内存,整体也是一个单例,需要加锁. PageCache桶的下标按照页号进行映射,每个桶里span的页数即为下标大小. 2.基本结构 当每个线程的…

文件、文本阅读与重定向、路径与理解指令——linux指令学习(一)

前言&#xff1a;本节内容标题虽然为指令&#xff0c;但是并不只是讲指令&#xff0c; 更多的是和指令相关的一些原理性的东西。 如果友友只想要查一查某个指令的用法&#xff0c; 很抱歉&#xff0c; 本节不是那种带有字典性质的文章。但是如果友友是想要来学习的&#xff0c;…

Python 空间和时间高效的二项式系数(Space and time efficient Binomial Coefficient)

这里函数采用两个参数n和k&#xff0c;并返回二项式系数 C(n, k) 的值。 例子&#xff1a; 输入&#xff1a; n 4 和 k 2 输出&#xff1a; 6 解释&#xff1a; 4 C 2 等于 4!/(2!*2!) 6 输入&#xff1a; n 5 和 k 2 输出&#xff1a; 10 解释&#xff1a; 5 C …

moonlight+sunshine+ParsecVDisplay ipad8-windows 局域网串流

1.sunshine PC 安装 2.设置任意账户密码登录 3.setting 里 network启用UPNP IPV4IPV6 save apply 4.ParsecVDisplay虚拟显示器安装 5.ipad appstore download moonlight 6.以ipad 8 为例 2160*1620屏幕分辨率 7.ParsecVDisplay里面 custom设置2160*1620 240hz&#xff0c;…

python conda查看源,修改源

查看源 conda config --show-sources 修改源 可以直接vim .condarc修改源&#xff0c;

CSS中 实现四角边框效果

效果图 关键代码 border-radius:10rpx ;background: linear-gradient(#fff, #fff) left top,linear-gradient(#fff, #fff) left top,linear-gradient(#fff, #fff) right top,linear-gradient(#fff, #fff) right top,linear-gradient(#fff, #fff) left bottom,linear-gradient(…

CentOS7安装Mysql8.4.0

简介 本文介绍了Linux CentOS系统下Mysql8.4.0的下载和安装方法 环境 (rpm -q centos-release) centos-release-7-2.1511.el7.centos.2.10.x86_64 正文 一、去官网下载Mysql8.4.0 下载参考我另一篇mysql5.7.4的安装 CentOS7.9安装Mysql5.7-m14_centos下mysql5.7下载-CSDN博客…

flutter开发实战-Webview及dispose关闭背景音

flutter开发实战-Webview及dispose关闭背景音 当在使用webview的时候&#xff0c;dispose需要关闭网页的背景音或者音效。 一、webview的使用 在工程的pubspec.yaml中引入插件 webview_flutter: ^4.4.2webview_cookie_manager: ^2.0.6Webview的使用代码如下 初始化WebView…

AJAX-个人版-思路步骤整理版

前置知识&#xff1a;老式的web创建工程方法就是创建项目然后添加web工件&#xff0c;然后添加lib依赖如&#xff1a;tomcat,servlet&#xff0c;等。 传统请求 对于传统请求操作&#xff1a;整体流程也就是创建静态页面&#xff0c; <!DOCTYPE html> <html lang&q…

每日一题~ leetcode 402 (贪心+单调栈)

click me! 这个贪心的推导在leetcode上已经很明确了。 click me! 删除k个数&#xff0c;可以先考虑删除一个数。这也是一种常见的思路。&#xff08;如果进行同样的操作多次&#xff0c;可以先只 考虑一次操作如何实现&#xff0c;或者他的影响。完成这一次操作后&#xff0c;…

MySQL基础篇(二)

如何创建一个数据库&#xff1a; create database 数据库名; 使用数据库&#xff1a; use 数据库名&#xff1b; 如何查看都有哪些数据库&#xff1a; use databases;//后面需要加s 容易忘 如何查看都有哪些表&#xff1a; use tables;//后面需要加s 如何清屏&#xff…

texStudio使用(小白)

原先使用overleaf在线编译&#xff0c;可能eps格式的图片太大导致需要充钱&#xff0c;所以考虑本地安装 安装教程参考B站视频&#xff1a;B站Latex本地编译器安装&#xff1a;TexLive TextStudio 踩到坑&#xff1a; 1. 编译器位置要选择对 因为BibTex选成了Biber导致出现无…