springcloud之项目实战搭建单体
写在前面
在上篇文章 中我们介绍了项目的整体内容以及架构,本文就开始实现一个单体的版本,在之后的文章中,在使用springcloud相关组件将这个单体的版本一步步的拆分为微服务的版本,在开始之前再贴下组件图:

本文我们分别来实现这四个组件。
源码 。
1:优惠券模板服务
完成后结构如下图:

1.1:api
定义服务请求和相应需要用到的公共的beans,单独定义的好处是,如果需要用到的话,单独引用即可,不需要引入其他不需要的类。
首先来定义优惠券类型的枚举:
@Getter
@AllArgsConstructor
public enum CouponType {UNKNOWN("unknown", "0"),MONEY_OFF("满减券", "1"),DISCOUNT("打折", "2"),RANDOM_DISCOUNT("随机减", "3"),LONELY_NIGHT_MONEY_OFF("晚间双倍优惠券", "4");private String description;// 存在数据库里的最终codeprivate String code;public static CouponType convert(String code) {// .orElse(UNKNOWN) 避免有人使坏return Stream.of(values()).filter(bean -> bean.code.equalsIgnoreCase(code)).findFirst().orElse(UNKNOWN);}
}
然后定义优惠券模板类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CouponTemplateInfo {private Long id;@NotNullprivate String name;// 优惠券描述@NotNullprivate String desc;// 优惠券类型@NotNullprivate String type;// 适用门店 - 若无则为全店通用券private Long shopId;/** 优惠券规则 */@NotNullprivate TemplateRule rule;private Boolean available;}
优惠券类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CouponInfo {private Long id;private Long templateId;private Long userId;private Long shopId;private Integer status;private CouponTemplateInfo template;}
具体的参考源码。
1.2:dao
采用spring data jpa 约定由于配置,提高生产力!。dao继承JpaRepositry,拥有基础的增删改查功能:
/*** coupon_template 表的spring data jpa(构建在hibernate之上的db操作框架)接口* https://blog.csdn.net/wang0907/article/details/131550318*/
public interface CouponTemplateDaoextends JpaRepository<CouponTemplate, Long> {// 根据Shop ID查询出所有券模板List<CouponTemplate> findAllByShopId(Long shopId);// IN查询 + 分页支持的语法Page<CouponTemplate> findAllByIdIn(List<Long> Id, Pageable page);// 根据shop ID + 可用状态查询店铺有多少券模板Integer countByShopIdAndAvailable(Long shopId, Boolean available);// 将优惠券设置为不可用@Modifying@Query("update CouponTemplate c set c.available = 0 where c.id = :id")int makeCouponUnavailable(@Param("id") Long id);
}
1.3:controller
定义模板模块对外的接口:
@Slf4j
@RestController
@RequestMapping("/template")
public class CouponTemplateController {@Autowiredprivate CouponTemplateService couponTemplateService;// 创建优惠券@PostMapping("/addTemplate")public CouponTemplateInfo addTemplate(@Valid @RequestBody CouponTemplateInfo request) {log.info("Create coupon template: data={}", request);return couponTemplateService.createTemplate(request);}...
}
测试如下,则为成功:

2:优惠券计算模块

2.1:api
定义其他模块可能用到的pojo,具体参考源码。
2.2:calculator
具体计算模块,定义各种优惠券的计算服务,主要的技术点是采用了模板方法设计模式 ,类图如下:

具体参考源码。
测试如下,则为成功:

json:
{"products":[{"price":3000,"count":2,"shopId":3},{"price":1000,"count":4,"shopId":1}],"couponId":10,"couponInfos":[{"id":10,"templateId":2,"userId":null,"shopId":null,"template":{"name":"单店满减","desc":"满40减5","type":"1","available":true,"shopId":1,"rule":{"limitation":10,"discount":{"quota":500,"threshold":4000}}}}],"userId":1}
3:用户服务

在pom中需要引入template和calculator,这样我们就有了一个三合一的单体应用了(后面我们来一起改造它!!!)。
3.1:api
定义用到的pojo,具体看源码。
3.2:dao
具体看源码。
3.2:impl
定义接口,服务层代码,定义用户领券,删除券等操作,如下用户领券代码:
@PostMapping("requestCoupon")
public Coupon requestCoupon(@Valid @RequestBody RequestCoupon request) {return customerService.requestCoupon(request);
}
启动后测试领券:
{"userId": 1,"couponTemplateId": 2
}


优惠券试算:
{"products": [{"price": 3000,"count": 2,"shopId": 3},{"price": 1000,"count": 10,"shopId": 1}],"couponIDs": [1],"userId": 1
}

这样我们的一个单体应用就完成了,掌声!!!
4:平台组建
写在后面
参考文章列表
相关文章:
springcloud之项目实战搭建单体
写在前面 在上篇文章 中我们介绍了项目的整体内容以及架构,本文就开始实现一个单体的版本,在之后的文章中,在使用springcloud相关组件将这个单体的版本一步步的拆分为微服务的版本,在开始之前再贴下组件图: 本文我们分…...
Mac 点击桌面 出现黑边框 解决
1、桌面黑框效果 2、解决:设置为 仅在台前调度中...
深度学习(2)---循环神经网络(RNN)
文章目录 一、序列数据和语言模型1.1 序列数据1.2 语言模型 二、循环神经网络(RNN)2.1 概述2.2 门控循环单元(GRU)2.3 长短期记忆网络(LSTM) 一、序列数据和语言模型 1.1 序列数据 1. 在深度学习中,序列数据(Sequence data)是指具有前后顺序…...
[NOIP2010 提高组] 机器翻译
[NOIP2010 提高组] 机器翻译 题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词…...
配置文件生成器-秒杀SSM的xml整合
配置文件生成器-秒杀SSM的xml整合 思路: 通过简单的配置,直接生成对应配置文件。 maven坐标 <dependencies><!-- 配置文件生成 --><dependency><groupId>org.freemarker</groupId><artifactId>freemarker<…...
小黑开始了拉歌训练,第一次进入部室馆,被通知要去当主持人心里有些紧张的leetcode之旅:337. 打家劫舍 III
小黑代码(小黑卡在了bug中,上午一步步探索做出,非常NB!!!) # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left lef…...
flutter开发实战-inappwebview实现flutter与Javascript方法调用
flutter开发实战-inappwebview实现flutter与Javascript方法调用 在使用inappwebview时候,需要flutter端与JS进行交互,调用相应的方法,在inappwebview中的JavaScript Handlers。 一、JavaScript Handlers 要添加JavaScript Handlers&#…...
alsa pcm设备之硬件参数
硬件参数包含了stream描述比如格式,采样率,通道数,和ringbuffer 圆形缓存区大小等. 使用snd_pcm_hw_params_t ,ALSA pcm设备使用了参数重定义系统相关的硬件参数,应用程序首先选择全范围的配置, 然后应用程序设置单个参数,直到所有参数都是基本的(确定的). 格式 量化位數&#…...
websocket拦截
python实现websocket拦截 前言一、拦截的优缺点优点缺点二、实现方法1.环境配置2.代码三、总结现在的直播间都是走的websocket通信,想要获取websocket通信的内容就需要使用websocket拦截,大多数是使用中间人代理进行拦截,这里将会使用更简单的方式进行拦截。 前言 开发者工…...
深度强化学习之 PPO 算法
深度强化学习之 PPO 算法 强化学习原理学习策略 基于行为价值 & 基于行为概率策略梯度算法:计算状态下所有行为的概率演员 - 评论家算法:一半基于行为价值,一半基于行为概率DQN 算法(深度Q网络)Q-Learning&#x…...
iPhone升级iOS17出现无法连接互联网的错误提示怎么办?
最新的iOS 17系统已经发布了快一个月了,很多人都已升级体验更多全新功能,但有部分用户却在升级过程中遇到一些问题:如无法验证更新,iOS17验证失败,因为您不再连接到互联网、 iPhone无法检查更新等错误问题。明明网络稳…...
Spring:处理@Autowired和@Value注解的BeanPostProcessor
AutowiredAnnotationBeanPostProcessor,它实现了MergedBeanDefinitionPostProcessor,因此会调用postProcessMergedBeanDefinition方法。 它实现了InstantiationAwareBeanPostProcessor,因此在属性注入时会调用postProcessPropertyValues方法 如果Autowired注解按类型找到了大…...
极坐标系下的交换积分次序
极坐标系下的交换积分次序 我把极坐标系下的交换积分次序总结为动静与静动之间的转换,下面通过一个例子感受一下 ρ 1 、 ρ 1 cos θ \rho1、\rho1\cos\theta ρ1、ρ1cosθ ∫ 0 π / 2 d θ ∫ 1 1 cos θ f ( ρ cos θ , ρ sin θ ) ρ d…...
MySQL命令行中文乱码问题
MySQL命令行中文乱码问题: 命令行界面默认字符集是gbk,若字符集不匹配会中文乱码或无法插入中文。 解决办法:执行set names gbk; 验证: 执行命令show variables like ‘char%’;查看默认字符集。 创建数据库设置字符集utf8&…...
图论---图的遍历
在图论中,图的遍历一般有两种,分别为DFS(深度优先遍历)、BFS(广度优先遍历),以下是这两种遍历方式的模板: DFS(深度优先搜索) 代码框架: void …...
AM@无穷小和无穷大
文章目录 abstract本文符号说明无穷小无穷小和自变量变化过程无穷小和函数极限的关系定理👺证明 无穷大无穷大不是数极限无穷大的说法证明函数极限为无穷大 无穷大和无穷小见的关系定理无穷小无穷大的运算法则 abstract 无穷小和无穷大的概念和相关性质 本文符号说…...
玄子Share- IDEA 2023 SpringBoot 热部署
玄子Share- IDEA 2023 SpringBoot 热部署 修改 IDEA 部署设置 IDEA 勾选如下选项 新建 SpringBoot 项目 项目构建慢的将 Spring Initializr 服务器 URL 改为阿里云:https://start.aliyun.com/ 在这里直接勾选Spring Boot Devtools插件即可 测试 切出 IDEA 项目文…...
kafka集群工作机制
一、kafka在zookeeper上的元数据解释 kafka中的broker要选举Controller角色来管理整个kafka集群中的分区和副本状态。一个Topic下多个partition要选举Leader角色和客户端进行交互数据 Zookeeper客户端工具: prettyZoo。 下载地址:https://github.com/vr…...
JVM上篇之虚拟机与java虚拟机介绍
目录 虚拟机 java虚拟机 简介 特点 作用 位置 整体结构 类装载子系统 运行时数据区 java执行引擎 Java代码执行流程 jvm架构模型 基于栈式架构 基于寄存器架构 总结 jvm的生命周期 1.启动 2.执行 3.退出 JVM的发展历程 虚拟机 所谓虚拟机,指的…...
在公众号上怎么创建微信付费课程功能呢
微信付费课程功能是一项比较受欢迎的在线教育服务,可以帮助教育机构或个人更好地管理和销售课程资源,提高知识分享和变现的效率。下面将介绍如何创建微信付费课程功能。 一、了解微信付费课程功能 在创建微信付费课程功能之前,需要先了解微信…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章 摘要: 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言,受限于 C 语言本身的内存安全和并发安全问题,开发复杂模块极易引入难以…...
