Spring Cloud 微服务项目实战
姚秋辰(姚半仙)
PayPal 研发经理
15861 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 38 讲
结束语 (1讲)
Spring Cloud 微服务项目实战
15
15
1.0x
00:00/00:00
登录|注册

05 | 牛刀小试:如何搭建优惠券模板服务?

你好,我是姚秋辰。
今天我们来动手搭建优惠券平台的实战项目。为了让你体验从 0 到 1 的微服务改造过程,我们先使用 Spring Boot 搭建一个基础版的优惠券平台项目,等你学习到 Spring Cloud 的时候,我们就在这个项目之上做微服务化改造,将 Spring Cloud 的各个组件像添砖加瓦一样集成到项目里。
如果你没有太多 Spring Boot 的相关开发经验,通过今天的学习,你可以掌握如何通过 Spring Boot 组件快速落地一个项目。如果你之前了解过 Spring Boot,那么今天的学习不仅可以起到温故知新的作用,你还可以从我分享的开发经验里得到一些启发。
03 讲中,我们介绍了优惠券平台的功能模块。我们说过,在用户领取优惠券的过程当中,优惠券是通过券模板来生成的,因此,优惠券模板服务是整个项目的底层基础服务。今天咱就直接上手搭建这个服务模块:coupon-template-serv。不过在此之前,我们先来看看整体的项目结构是怎样搭建的。

搭建项目结构

我把整个优惠券平台项目从 Maven 模块管理的角度划分为了多个模块。
在顶层项目 geekbang-coupon 之下有四个子模块,我先来分别解释下它们的功能:
coupon-template-serv: 创建、查找、克隆、删除优惠券模板;
coupon-calculation-serv:计算优惠后的订单价格、试算每个优惠券的优惠幅度;
coupon-customer-serv:通过调用 template 和 calculation 服务,实现用户领取优惠券、模拟计算最优惠的券、删除优惠券、下订单等操作;
middleware:存放一些与业务无关的平台类组件。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文详细介绍了如何搭建优惠券模板服务的实战项目,通过Spring Boot快速落地一个项目,并在Spring Cloud的基础上进行微服务化改造。作者将整个优惠券平台项目划分为多个模块,包括coupon-template-serv、coupon-calculation-serv、coupon-customer-serv和middleware。在每个业务子模块中,作者从内部分层的角度对其做了进一步拆分,例如coupon-template-serv内部包含了coupon-template-api、coupon-template-dao和coupon-template-impl三个子模块。文章还介绍了添加Maven依赖项的原则和编写方式,以及顶层项目和子模块的pom文件内容。通过这些内容,读者可以了解到如何从0到1搭建一个优惠券模板服务的实际操作步骤,以及项目结构的设计原则和依赖管理的方法。整体来说,本文适合想要学习微服务改造和项目架构设计的开发人员阅读。文章还介绍了如何搭建coupon-template-dao模块和coupon-template-impl模块,以及在这些模块中如何使用JPA进行数据库操作和定义Service层的接口类。同时,还展示了如何通过Controller类将服务以RESTful接口的方式对外暴露。整体而言,本文内容丰富,适合对微服务架构和项目搭建感兴趣的读者阅读。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Spring Cloud 微服务项目实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(63)

  • 最新
  • 精选
  • 暮雨yl晨曦
    仔仔细细review了老师的coupon-template-serv下的代码,有几个问题请教老师。 1.@ComponentScan(basePackages = {"com.geekbang"}),我仔细核对了,所有子module的代码都是在包com.geekbang.coupon.template下,启动类也在这个包下,所以这个注解是可以去掉的。我猜测老师是为了演示,告诉大家这个注解是这么用的。 2.我们现在项目中都被强制要求不允许用fastjson,看到项目中用了这个。其实springboot是有jackson和gson的。我猜测老师也是为了方便项目演示而使用fastjson。jackson和gson上手比fastjson稍微麻烦点。 3.关于dependencyManagement中,lombok、commons-lang3、commons-codec、jakarta.validation-api,这些是可以去掉的,因为在SpringBoot中已经定义了。老师可以看spring-boot-dependencies-{version}.pom,里面都有。我估计老师是从老项目中copy出来的,springboot版本更新了,但是没关注到这些依赖也已经被springboot管理起来了。另外,guava 16的版本有点低,我自己换成最新的版本了。目前的代码中还没看到有使用的。 4.现在启动类都是类名Application,我还是喜欢分开,比如CouponTemplateApplication。为了方便我也是放到同一个git目录下。所以就会导致idea那边默认的类名:Application、Application(1)、Application(2)。。。。 5.一些细节性的代码,比如function能立即返回,但是还是先声明了变量,这是为了方便调试吗?我为了调试方便一些我也会这么写,但是调试完成会改成立即返回的形式。另外,一些import、无用的注释之类的并没有去掉、Long->可以使用long、一些属性可以声明成final等。强迫症看着难受。 6.entity中,当database column name和entity里的字段名一样的话,是可以不用特意加name="xxxx"的。

    作者回复: 1. 对滴,同学太懂我了 2. 哈哈没错,确实推荐用jackson和gson来替代,像我从阿里出来的人都有职业病潜意识里就用了fastjson,中毒不轻。fastjson早期用了很多字节码技术提高性能,埋了不少坑,以前在集团也是bug不断,现在其他json组件的解析性能都上来了,确实没必要用fastjson. 3. 对的,我直接从老项目里copy出来的,多谢同学提醒 4. 是的分开命名确实在IDEA本地启动的时候会方便一些 5. 看出同学还是比较细节的,强迫症是程序员的一个很好的特质。一般我习惯不立即返回,方便以后打debug日志输出参数 6. 这是防御性编程的习惯,以防日后code refactor的时候更改属性名称后SQL挂掉

    2021-12-22
    11
    62
  • 李峰
    orm框架,我建议换成mybatis,现在很多企业实现中都是mybatis

    作者回复: JPA才是orm框架标准,mybatis只能算是半自动。跟着spring的方向走,把手动挡的mybatis换成自动挡spring-data-jpa,简化轻量级和快速开发是主方向,在微服务的领域模型拆分下,不太需要从前那种复杂sql扮演跨多domain查询的角色

    2021-12-22
    10
    19
  • javaadu
    之前做的最复杂的SQL,是在有赞的时候弄的,为了解决深度分页的问题,使用延迟关联的写法。入下所示,第二条要远快于第一条: select * from table where xxx limit a,b; select * from table where id in (select id from table where xxx limit a,b);

    作者回复: 这个经验非常值得其他同学学习一下

    2022-07-24归属地:上海
    5
    11
  • C
    我的经验是尽可能减少级联配置,用单表查询取而代之,如果一个查询需要 join 好几张表,最好的做法就通过重构业务逻辑来简化 DB 查询的复杂度。 这个能详细解说下吗?

    作者回复: 像join,还有笛卡尔积之类的运算都是很消耗DB资源的,调出sql执行计划看选择的索引策略和时间指标,对一些低效步骤进行拆分,将一个大sql拆成若干个子sql,用代码逻辑替换sql逻辑。 - 这是单体应用下的拆分思路,至于微服务架构,如果领域划分合理的话,不太会出现跨一串表的查询,取而代之是跨服务api调用。报表类需求需要跨domain的场景,通常由数据团队,用各种EDL、data lake等等一堆大数据技术来搭建。

    2021-12-23
    6
    11
  • ~
    老师你好,经过一遍 review 本章以及下一章的代码后,我还是犯迷糊,想要请教一下老师。先讲一下我的看法。 1. CouponTemplateInfo 作为券模板封装了「一类」券的特征信息。比如某类券是叫做「满减券」,通过 type 属性与 CouponType 对应,这是「这一类」券的共同特征,所以一并存放到 CouponTemplateInfo 中; 2. CouponInfo 这个类就是具体某个券,他除了要关注券模板的信息以外,还要关注自身券对应的使用者、自身使用情况等等具象化的信息。以上两点我的理解。 3. 既然有了 CouponTemplateInfo,为何还需clone 模板这个方法?以我的理解,一个类型的券模板只需要一个就可以了,如果克隆就不是重复了吗?我又注意到, TemplateRule 是属于 CouponTemplateInfo 的属性,「过期时间」和「可享受折扣」两个属性其是一个具体的券应该关注的地方,而「每人领券上限」对应的券模版。尽管之后的 customer 模块代码中都是以这个模板过期时间为准,我感觉还是有些不理解,总觉得应该是每个券对应自己的过期时间,麻烦老师详细解答一下。 因为我自己在模型设计上,还有很多欠缺,所以在跟源码时候就特别着重这个地方,还请老师多多指教。

    作者回复: 1和2完全正确,克隆是比如有些券模板已经被设置成unavailable了,我想创建个一模一样的新的券,可以clone一个状态是avaiable的新模板。真实情况下券模板和券都要有一个单独的过期时间,模板的过期时间控制整体券活动的时间(比如双11所有券结束的时间是某日0点),券的过期时间控制个人领券后的有效使用时间,我这里对业务做了简化了没有添加券的过期时间

    2022-01-05
    2
    7
  • Michael
    老师,你这URL的设计不是很规范啊。 POST /template/addTemplate -> POST /template

    作者回复: 是的,我没有严格按照REST规范来起名字,主要是帮助大家通过url理解接口干了什么事儿,并没有将接口语义放到HTTP method中来提现。 而且REST规范太过于教课书化,如果严格遵循会给开发带来很多麻烦,尤其是用作修改场景的PUT接口,严格的PUT接口不管从实现还是接口定义上来说,都非常限制生产力

    2021-12-23
    7
  • 珠穆写码
    针对管理后台那种需要查看多个维度信息的列表和导出的业务,不去join 好像很难做到啊

    作者回复: 这类聚合查询的业务,不能硬拉DB,在高并发量下需要做数据异构方案,把DB数据异构到主搜服务里,比如opensearch之类的非结构化数据库。只有实时性要求很高的查询再考虑DB,其他查询场景尽量不要直接查DB,很多成熟公司都有慢SQL线上监控,多个join的语句只要上线并发量稍微一高就会触发报警被下掉

    2022-01-08
    3
    6
  • Layne
    遇到这样一个场景:将两张表中的数据进行union all 然后按照指定字段排序,然后分页返回。而且两张表分别需要关联很多表来带出一些附属字段信息。本来单纯两张表里总共数据库也就十几万的量,后面经过一些join和union all,查看了一下SQL的explain,统计数据量到了几百万。后面做了下调整: 1.将两张表的数据提前整合并排序,然后缓存起来; 2.将关联查询放到业务代码里来拼接,也就是分开几条SQL来查,不用全量join,只需要按分页数量的大小来查相应数量的关联信息。

    作者回复: 很赞,这两个调整都是很正确的改进方向!而且这里提到了执行计划,sql调优的重点。同学这条经验总结很到位

    2021-12-22
    3
    5
  • 奔跑的蚂蚁
    我想问下:在大型的微服务项目中,建项目的时候子模块是在同一个大项目吗?然后存在不同的git仓库中吗

    作者回复: 不同微服务是在不同的git仓库里,这样比较方便配置CICD也就是持续集成环境,也可以降低高频提交时候的代码冲突

    2022-01-04
    4
  • 201
    哎,快更新呀。

    作者回复: 男人不能太快呀:-)

    2021-12-25
    3
收起评论
显示
设置
留言
63
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部