这个跳过了社交登录和单点登录,直接看的购物车功能,从P236开始
创建购物车微服务,把静态资源放到nginx里
修改templates两个文件的src
排除数据库的自动配置(这个为啥回头自己查查)
配置服务的host地址,请求先根据路径映射到达虚拟机,再由虚拟机的nginx转发给网关,网关再根据域名转发给购物车服务
用户购物车和离线购物车
如上图,购物车在redis中的存储方式
为了修改购物车方便,存hash(map)比较合适,如上面两张图。
编写好cart和cartItem两个VO
注意,需要计算的属性,得重写get方法。
如上图,京东商城是通过cookie里的userkey标识用户身份(一个月过期)
如上图,即使登录以后,userkey还是存在的
如上图, 每一个请求过来,tomcat会开一个线程进行处理,这些过程都在同一个线程中。
如上图,添加一个WebMvcConfig类,用来配置拦截器。
这个是编写的拦截器类,拦截功能在controller之前执行。
如果没登陆,也不是临时用户,那么必须创建一个userkey,注意看上图,这个userkey的作用域还挺大的。
放在cookie中传给浏览器
把添加商品到购物车等功能的页面跳转弄对了。
注意看,点击加入购物车,调用了addToCart方法,并传递了两个参数,如下图,
这个方法就获取了这两个参数 ,接下来编写service。
如上图,绑定一个redis的hash操作
调用远程服务,查询sku
如上图,这里改了一下方法名(回头自己查查为啥能改)
如上图,查到商品信息以后,封装在刚才创建的skuInfoVo里,注意这个new TypeReference<SkuInfoVo>(),用来做类型的转换。
配置好cart服务的线程池,然后注入。
如上图,这里用了concat(),可以连接两个字段
如上图,@Param("skuId")给参数命名。
如上图,在xml文件中创建方法
如上面两张图,把服务写到feign文件里面。
注意看异步编排,并且因要要两个任务都完成才能操作redis,所以使用CompletableFuture.allOf(a,b).get()。
这个是保存以后的结果。
旧商品只要取出cartItem,修改数量,新商品才需要添加。
如上图,这样改了以后,重复刷新只是在查数据,不会重复给购物车添加操作(这个没认真看,回头再看看)。
如上图,不用model了,这个RedirectAttributes.addFlashAttribute是用来模拟session的。
上面这个方法可以使得skuId自动添加到url里面。 效果如下图
上面:取到购物车中的数据并返回
判断登录了没,合并购物车 ,后面一段前端的没认真看。
如上图,选中功能的实现,这里面也是有一个响应,使得请求重定向。
如上面两张图,在父元素里找到子元素(这块其实不怎么懂,以后再看看) 改变购物项数量
删除和跳回功能
下面是rabbitMq
如上图,三个主要的功能
AMQP协议,rabbitMq就是用这个实现的,兼容了JMS。
消息(消息头:路由键等+消息体:不透明),生产者,交换机。
一条长连接里,开了很多个channel。
如上图,记住,先来到指定的虚拟主机,找到虚拟主机指定的交换机,交换机根据收到的路由键,根据绑定关系,决定发送给哪个队列。
在Docker中安装RabbitMq
在15672端口登陆进来了
overview,概览信息
直接交换机,得路由键完全匹配才行
如上图, 广播模式,全部发送。
主题订阅交换机。根据通配符(#,*)匹配。
创建一个新的交换机。
创建了四个新的队列,将交换机和四个队列绑定,路由键直接写名字 。
如上图,如果用fanout交换机的话,无论路由键用的什么,四个队列全收到了消息。
如上图,这个用的topic交换机绑定的队列(刚才忘记写了:*这个符号代表这个位置必须有个单词)
注意看,四个队列全部都收到了消息。
如上图,添加注解@rabbit,并配置好配置信息 。
注意看,在这里按住ctrl+H,可以查看这个接口的实现。
创建新的交换机,注意看三个参数,然后再日志中打印出来(注意要添加注解 @Slf4j)。
创建队列和绑定关系
注意看日志打印结果
注意看,发送消息的话不用amqpAdmin了,用rabbitTemplate.convertAndSend()
对象也是可以通过这种方式发送的,需要对象必须实现Serializable接口。
如上图,为了使得接收到的payload是Jason形式的,我们自己编写一个消息转换器。 在方法上标注@RabbitListener,用来监听指定的队列。
查询所有的端口,用netstat -ano,然后查9000端口,用findstr 9000
查到19796这个进程是哪个。
修改rabbitListener的参数,添加了传输的实体类,还有channel。
如上图,添加多个订单服务监听消息队列,发现,消息发送到了两个不同的订单服务,但是一个消息只发送一次。
@Rabbithandler只能标注在方法上,刚才 那个在类和方法都可以标注,这个主要用来处理不同的情况,使用方法的重载。
编写controller发送请求,两种消息都接收到了。
下面是重点了:rabbitMq的消息确认机制
如上图,主要是三个过程。对应了三个机制:confirmCallback机制,returnCallback机制(这两个都是发送端),ack机制(这个是消费端)。
如上图,消息只要被Broker接收到,就会执行确认回调。
首先把这个开启。
在rabbitMq的配置类中,对rabbitTemplate进行定制,用setConfirmCallback方法。前面加个注解@PostConstruct
如上图,配置好三个参数。
测试结果,如上图所示。
队列的抵达确认的话,把上面两个配置好。
设置消息抵达队列的确认回调(失败了才触发这个回调方法)
这个控制台的打印好像是整个服务的,之前好像没弄明白。
注意看,这个是放行按钮。
把ack改成手动的,只要不明确告诉MQ被接收了,就处于unacked状态,不会删除。
使用这个basicAck方法进行手动签收。
使用basicNack进行拒收,里面有个参数可以设置成true的话,会发回服务器,重新入队。
没有调用方法,都是unack状态,不会丢弃,而是切换成ready状态。
RabbitMq这几集就学完了,后面订单服务和秒杀服务新开一篇博客。