目录
6、多线程改造(CompleteableFuture并发计算)
1、加入IDiscountService和DiscountServiceImpl并将代码移位
一、前言
天机学堂day12的主题是优惠券使用,分为优惠券规则定义和优惠券智能推荐,优惠券规则定义主要是让大家了解前置背景,所以我这里就只记录优惠券智能推荐的相关接口了。本博客用于记录个人学习过程,方便后续复盘,最后会包含个人练习答案,仅供参考
二、优惠券智能推荐
1、查询用户券并初步筛选
1)代码
controller代码如下:

service代码如下:

serviceImpl代码如下:


mapper代码如下:

2)测试
启动服务,由于视频老师直接给出的相关优惠券资料笔记不是公开的,所以这里的测试我就自己进行了。我这里先查看了一下jack可以领取的优惠券以及已经领取的优惠券


看完之后我初步的想法就是把双11满100减99暴抢券给领取了,然后在swagger那里把订单总金额设置为99元试试看,这样就是一开始有两个优惠券,然后初筛之后只有一个了。下面开始测试,打开swagger,先新增参数如下:

然后请求参数如下:

发送之后打开控制台可以看到预期的日志和我们想的是一样的,所以测试成功

2、细筛
1)代码
在finaDiscountSolution中加入细筛及测试日志的代码:

封装细筛的方法


2)测试
老样子,因为拿不到老师的笔记数据,所以这里我就自己测试了。启动服务,把我下面的指定课程的优惠券领取了

领取之后我现在有三张优惠券如下,我们之前已经成功测试了初筛的功能,所以这次我的测试想法就是在swagger传200元的课程,初筛根据价钱三张优惠券都过了,但是课程的分类id和双十贝利亚活动促销的指定课程故意不一致,就会出现细筛少一张的情况

先打开数据库表看看双十贝利亚的指定课程是3594


打开swagger,这里我分类id传3394不符合3594,然后价格传200

打开控制台可以看到细筛根据限定范围筛掉了一张,可见测试是成功的

3、优惠券方案全排列组合
1)代码
从资料中导入全排列的工具类

然后在原来的方法上加入优惠券方案全排列组合的代码

2)测试
老样子还是按刚刚细筛的结果来测试,直接打开swagger发送一下。然后可以看到控制台的日志输出没有什么问题

4、计算每种方案的优惠信息(计算优惠明细)
1)代码
修改查询可用优惠券方案的方法的代码:

封装方法计算每种方案的优惠信息,代码如下:


封装方法计算每个商品的优惠明细,更新到detailMap中,代码如下:

2)测试
启动服务,老样子,打开swagger直接点击发送。观察控制台可以看到每种方案的优惠券信息,由于我这些数据是自己随便造的,所以两种优惠券先后使用顺序不同的优惠效果没有展现出来,这个效果的话大家看视频中老师的测试效果即可

5、与交易服务tj-trade联调测试
1)代码
拷贝DTO到tj-api模块:先在dto包下新建一个promotion包,再把CouponDiscountDTO和OrderCourseDTO拷贝过来

创建PromotionClient客户端:在client包下创建promotion包,然后新建一个PromotionClient接口(下面给出代码)


编写PromotionClientFallback降级类:在promotion包下新建fallback包,再新建PromotionClientFallback降级类代码,最后在PromotionClient的注解上声明指定降级工厂



配置FallbackConfig:

修改tj-trade模块的VO类:

修改tj-trade模块预下单接口实现:


2)测试
启动idea本地的PromotionApplication和TradeApplication服务,打开nacos,因为trade-service在虚拟机也启动了一份,所以这里我们要把虚拟机的给下线了(我是能成功下线的,如果下线不了就看视频跟着老师操作)

打开用户端前端,点击我的购物车,全选之后再点击去下单

在下单界面就能看到优惠券列表会显示叠加券和单券的优惠方案,由于我这里优惠券没有多设计几个特殊情况下的叠加,所以没有叠加券但是优惠金额不同的效果,但是联调测试还是成功的

6、多线程改造(CompleteableFuture并发计算)
1)代码
一开始我跟着视频完成了这部分改造,然后打开在线文档发现它自定义了一个线程池,而视频中是没有自定义线程池的,所以我结合了在线文档和视频完成了如下代码
在PromotionConfig中导入在线文档中自定义线程池的代码

结合自定义线程池改进后的代码如下:

2)测试
本地启动PromotionApplication和TradeApplication服务,打开用户端前端的购物车,老样子点击去下单。也能成功看到优惠券的方案没有问题,因为改进变成了多线程异步,所以方案的顺序会乱这是正常的,后续还会再改进

3)天机学堂中使用线程池的三个地方
第一个是异步持久化学习记录,第二个是异步生成兑换码,第三个是并行计算每种方案的优惠信息
7、筛选最优解
1)代码
筛选出最优解单独封装一个方法如下:


2)测试
老样子,由于我懒得造数据,所以大概测试一下。可以看到之前叠加2券是有两个并且其实优惠金额是一样的,现在就直接显示一个了,测试成功

三、练习
1、加入IDiscountService和DiscountServiceImpl并将代码移位
练习说是自己完成但是答案给的非常详细了,基本就是从在线文档中导入代码即可,但是我也遇到了问题。我看答案发现出现了discountService这个东西,然后我觉得奇怪就去看master分支代码发现之前写的查询可用优惠券方案也是用的discountService,但是我看自己idea里面明明用的就是userCouponService。于是我重新看了老师的视频对比在线文档发现老师当时是直接用userCouponService而在线文档是新建了IDiscountService和DiscountServiceImpl。然后我看了一下在线文档感觉确实很有道理,userCouponServiceImpl里面代码塞太多了,并且分一个出来见名知意更加优雅合理,于是我决定将代码移位

我的IDiscountService是从在线文档复制过来的,然后这里注意从在线文档复制过来的话它DTO导包都是api的,这样就会与controller不对应,大家自行修改导包。然后下面的代码直接从原来的IUserCouponService里面剪切过来

然后是DiscountServiceImpl的代码,基本框架也是从在线文档复制过来,还是DTO导包记得改。
然后这个类里面要这几个依赖注入,之前的是getBaseMapper是因为它是直接和UserCouponMapper关联的,这里是没有直接关联,所以注入UserCouponMapper。至于剩下两个都是把那几个方法照搬过来就需要的。几个方法直接从之前的UserCouponServiceImpl剪切过来,分别是findDiscountSolution、findAvailableCoupon、calculateDiscountDetails、calculateSolutionDiscount、findBestSolution






最后就是把controller修改一下,刚刚修改的所有的类都可以检查一下导包(本人测试没有出现问题)

2、根据券方案计算订单优惠明细
后续发现复制在线文档的代码还是有很多导包问题而且好像不用api的导包就是不行,所以我直接打开master分支看了一下api下的promotion包下到底有哪些DTO,最后发现就是这三个,然后这里有就可以把tj-promotion对应的这三个DTO给删了(这里的OrderCouponDTO是新增的,没导的话直接复制到api那里去也就是删两个就行),然后点开相关的所有那些类,都会自动导包的

1)接口代码
从资料中复制OrderCouponDTO,直接放api那里就行,不用往tj-promotion那里放

在CouponDiscountDTO里面加一个字段(这个也是在api里面)

controller代码如下:

service代码如下:

serviceImpl代码如下:

修改calculateSolutionDiscount方法,加上一行代码即可

mapper代码如下:

xml代码如下:(一开始我也想着还是加到@Select注解上,但是这里有动态sql,不是普通的纯sql语句所以还是写到xml里面)

2)FeignClient相关代码
定义FeignClient方法,直接复制在线文档的代码即可

添加降级逻辑

3)改造交易服务接口代码
以下修改的代码全部在OrderServiceImpl当中,首先修改placeOrder的代码如下:


再修改enrolledFreeCourse的代码如下:(实际就是在参数里加个0)

最后是修改packageOrderDetail的代码如下:

3、核销优惠券
1)接口代码
controller代码如下:

service代码如下:

serviceImpl代码如下:


这里的话couponMapper的incrUsedNum代码和xml的代码是没有给出来的,我直接去master分支找到了,下面直接复制我给出的代码就行

/**
* 批量更新优惠券已使用数量(优惠券的已使用数量 + 1)
* @param couponIds 优惠券id列表
* @param i 优惠券已使用数量
* @return 更新数量
*/
int incrUsedNum(List<Long> couponIds, int i);

<update id="incrUsedNum">
UPDATE coupon SET used_num = used_num + #{amount}
WHERE id IN
<foreach collection="couponIds" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</update>
2)FeignClient相关代码
定义FeignClient方法,直接复制在线文档的代码即可

添加降级逻辑

3)改造交易服务接口代码
找到orderServiceImpl的placeOrder方法,加入核销优惠券的代码如下:

4、退还优惠券
1)接口代码
controller代码如下:

service代码如下:

serviceImpl代码如下:

2)FeignClient相关代码
定义FeignClient方法,直接复制在线文档的代码即可

添加降级逻辑

3)改造交易服务接口代码
找到orderServiceImpl的cancelOrder代码,加入退还优惠券的代码如下:

5、分页查询我的优惠券
1)接口代码
controller代码如下:

service代码如下:

serviceImpl代码如下:

2)FeignClient相关代码
定义FeignClient方法,直接复制在线文档的代码即可

添加降级逻辑

3)改造交易服务接口代码
找到orderServiceImpl的queryOrderById方法加入如下代码:


2933

被折叠的 条评论
为什么被折叠?



