SpringBoot微信点餐系统(附源码)(springboot点赞功能)
moboyou 2025-07-23 17:46 10 浏览
作者 | Tommmmm
链接 |
www.jianshu.com/p/ae14101989f2
下文是对微信点餐系统项目的总结,使用 Spring Boot 开发,采用前后端分离架构,针对此项目技术细节给出具体解释,同样会分享源码给大家,可以关注微信公众号:Java后端,回复 点餐,即可获取源码地址。本文作者 Tommmmm 欢迎点击阅读原文访问作者博客。
架构
前后端分离:
部署架构:
Nginx与Tomcat的关系在我的这篇文章,几分钟可以快速了解:
https://www.jianshu.com/p/22dcb7ef9172
补充:
setting.xml 文件的作用:settings.xml是maven的全局配置文件。而pom.xml文件是所在项目的局部配置。Settings.xml中包含类似本地仓储位置、修改远程仓储服务器、认证信息等配置。
maven的作用:借助Maven,可将jar包仅仅保存在“仓库”中,有需要该文件时,就引用该文件接口,不需要复制文件过来占用空间。
注:这个“仓库”应该就是本地安装maven的目录下的Repository的文件夹
分布式锁
线程锁:当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效,因为线程锁的实现在根本上是依靠线程之间共享内存实现的。如synchronized
进程锁:为了控制同一操作系统中多个进程访问某个共享资源。
分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。
分布式锁一般有三种实现方式:1. 数据库乐观锁;2. 基于Redis的分布式锁;3. 基于ZooKeeper的分布式锁。
乐观锁的实现:使用版本标识来确定读到的数据与提交时的数据是否一致。提交后修改版本标识,不一致时可以采取丢弃和再次尝试的策略。
CAS:可以阅读我的这篇文章:
https://www.jianshu.com/p/456bb1ea9627
分布式锁基于Redis的实现:(本系统锁才用的)
基本命令:
1. SETNX(SET if Not exist):当且仅当 key 不存在,将 key 的值设为 value ,并返回1;若给定的 key 已经存在,则 SETNX 不做任何动作,并返回0。
2. GETSET:将给定 key 的值设为 value ,并返回 key 的旧值。先根据key获取到旧的value,再set新的value。
3. EXPIRE 为给定 key 设置生存时间,当 key 过期时,它会被自动删除。
Tips:欢迎订阅公众号 Java后端,接受每日技术博文推送。
加锁方式:
这里的 jedis 是Java对Redis的集成
jedis.set(String key, String value, String nxxx, String expx, int time)错误的加锁方式1:如果程序在执行完setnx()之后突然崩溃,导致锁没有设置过期时间。那么将会发生死锁。
Long result = jedis.setnx(Key, value); if (result == 1) { jedis.expire(Key, expireTime); }错误的加锁方式2:分布式锁才用(Key,过期时间)的方式,如果锁存在,那么获取它的过期时间,如果锁的确已经过期了,那么获得锁,并且设置新的过期时间
错误分析:不同的客户端之间需要同步好时间。
解锁:判断锁的拥有者后可以使用 jedis.del(lockKey) 来释放锁。
分布式锁基于Zookeeper的实现
Zookeeper简介:Zookeeper提供一个多层级的节点命名空间(节点称为znode),每个节点都用一个以斜杠(/)分隔的路径表示,而且每个节点都有父节点(根节点除外)。
例如,/foo/doo这个表示一个znode,它的父节点为/foo,父父节点为/,而/为根节点没有父节点。
client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。
Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务,实现中zxid是一个64位的数字。
Zookeeper的分布式锁原理
获取分布式锁的流程:
- 在获取分布式锁的时候在locker节点(locker节点是Zookeeper的指定节点)下创建临时顺序节点,释放锁的时候删除该临时节点。
- 客户端调用createNode方法在locker下创建临时顺序节点,然后调用getChildren(“locker”)来获取locker下面的所有子节点,注意此时不用设置任何Watcher。
- 客户端获取到所有的子节点path之后,如果发现自己创建的子节点序号最小,那么就认为该客户端获取到了锁。
- 如果发现自己创建的节点并非locker所有子节点中最小的,说明自己还没有获取到锁,此时客户端需要找到比自己小的那个节点,然后对其调用exist()方法,同时对其注册事件监听器。
- 之后,让这个被关注的节点删除,则客户端的Watcher会收到相应通知,此时再次判断自己创建的节点是否是locker子节点中序号最小的,如果是则获取到了锁,如果不是则重复以上步骤继续获取到比自己小的一个节点并注册监听。
我的解释:
A在Locker下创建了Node_n —>循环 ( 每次获取Locker下的所有子节点 —> 对这些节点按节点自增号排序顺序 —> 判断自己创建的Node_n是否是第一个节点 —> 如果是则获得了分布式锁 —> 如果不是监听上一个节点Node_n-1 等它释放掉分布式锁。)
@ControllerAdvice处理全局异常Mybatis注解方式的使用:@insert 用注解方式写SQL语句
分布式系统的下的Session
1、分布式系统:多节点,节点发送数据交互,不共享主内存,但通过网络发送消息合作。
分布式:不同功能模块的节点
集群:相同功能的节点
2、Session 与token
服务端在HTTP头里设置SessionID而客户端将其保存在cookie
而使用Token时需要手动在HTTP头里设置,服务器收到请求后取出cookie进行验证。
都是一个用户一个标志
3、分布式系统中的Session问题:
高并发:通过设计保证系统能够同时并行处理很多请求。
当高并发量的请求到达服务端的时候通过负载均衡的方式分发到集群中的某个服务器,这样就有可能导致同一个用户的多次请求被分发到集群的不同服务器上,就会出现取不到session数据的情况。
根据访问不同的URL,负载到不同的服务器上去
三台机器,A1部署类目,A2部署商品,A3部署单服务
通用方案:用Redis保存Session信息,服务器需要时都去找Redis要。登录时保存好key-value,登出时让他失效
垂直扩展:IP哈希 IP的哈希值相同的访问同一台服务器
session的一致性:只要用户不重启浏览器,每次http短连接请求,理论上服务端都能定位到session,保持会话。
Redis作为分布式锁
高并发:通过设计保证系统能够同时并行处理很多请求。(系统学习并发知识,可以在Java知音公众号回复“多线程聚合”)
同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全。
线程的Block状态:
a.调用join()和sleep()方法,sleep()时间结束或被打断
b.wait(),使该线程处于等待池,直到notify()/notifyAll():不释放资源
此外,在runnable状态的线程是处于被调度的线程,Thread类中的yield方法可以让一个running状态的线程转入runnable。
Q:为什么wait,notify和notifyAll必须与synchronized一起使用?Obj.wait()、Obj.notify必须在synchronized(Obj){…}语句块内。
A:wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。
Q:Synchronized:
A:Synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。
公平和非公平锁的队列都基于锁内部维护的一个双向链表,表结点Node的值就是每一个请求当前锁的线程。公平锁则在于每次都是依次从队首取值。
ReentrantLock重入性:
重入锁可以看这两篇文章,都比较简单
https://www.jianshu.com/p/587a4559442bhttps://www.jianshu.com/p/1c52f17efaab
Spring + Redis缓存的两个重要注解:
- @cacheable 只会执行一次,当标记在一个方法上时表示该方法是支持缓存的,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果。
- @cacheput:与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
对数据库加锁(乐观锁 与 悲观锁)
悲观锁依赖数据库实现:
select * from account where name=”Erica” for update这条sql 语句锁定了account 表中所有符合检索条件(name=”Erica”)的记录,使该记录在修改期间其它线程不得占有。
代码层加锁:
String hql ="from TUser as user where user.name='Erica'";
Query query = session.createQuery(hql);
query.setLockMode("user",LockMode.UPGRADE); //加锁
List userList = query.list();//执行查询,获取数据其它
@Data 类似于自动生成了Getter()、Setter()、ToString()等方法。
JAVA1.8的新特性StreamAPI:Collectors中提供了将流中的元素累积到汇聚结果的各种方式
List<Menu> menus=Menu.getMenus.stream().collect(Collectors.toList())For - each 写法:
for each语句是java5新增,在遍历数组、集合的时候,for each拥有不错的性能。
public static void main(String[] args) {
String[] names = {"beibei", "jingjing"};
for (String name : names) {
System.out.println(name);
}
}for each虽然能遍历数组或者集合,但是只能用来遍历,无法在遍历的过程中对数组或者集合进行修改。
BindingResult:一个@Valid的参数后必须紧挨着一个BindingResult 参数,否则spring会在校验不通过时直接抛出异常。
@Data
public class OrderForm {
@NotEmpty(message = "姓名必填")
private String name;
}后台:
result.getFeildError.getDefaultMessage()可抛出“姓名必填” 的异常。
4、List转为Map
5、Collection的子类:List、Set
List:ArrayList、LinkedList 、Vector
List:有序容器,允许null元素,允许重复元素
Set:元素是无序的,不允许元素
最流行的是基于 HashMap 实现的 HashSet,由hashCode()和equals()保证元素的唯一性。
可以用set帮助去掉List中的重复元素,set的构造方法的参数可以是List,构造后是一个去重的set。
HashMap的补充:它不是Collection下的
Map可以使用containsKey()/containsValue()来检查其中是否含有某个key/value。
HashMap会利用对象的hashCode来快速找到key。
插入过程:通过一个hash函数确定Entry的插入位置index=hash(key),但是数组的长度有限,可能会发生index冲突,当发生了冲突时,会使用头插法,即为新来的Entry指向旧的Entry,成为一个链表。
每次插入时依次遍历它的index下的单链表,如果存在Key一致的节点,那么直接替换,并且返回新的值。
但是单链表不会一直增加元素,当元素个数超过8个时,会尝试将单链表转化为红黑树存储。
为何加载因子默认为0.75?(0.75开始扩容)
答:通过源码里的javadoc注释看到,元素在哈希表中分布的桶频率服从参数为0.5的泊松分布。
源码地址:
https://github.com/923310233/wxOrder
相关推荐
- Excel技巧:SHEETSNA函数一键提取所有工作表名称批量生产目录
-
首先介绍一下此函数:SHEETSNAME函数用于获取工作表的名称,有三个可选参数。语法:=SHEETSNAME([参照区域],[结果方向],[工作表范围])(参照区域,可选。给出参照,只返回参照单元格...
- Excel HOUR函数:“小时”提取器_excel+hour函数提取器怎么用
-
一、函数概述HOUR函数是Excel中用于提取时间值小时部分的日期时间函数,返回0(12:00AM)到23(11:00PM)之间的整数。该函数在时间数据分析、考勤统计、日程安排等场景中应用广泛。语...
- Filter+Search信息管理不再难|多条件|模糊查找|Excel函数应用
-
原创版权所有介绍一个信息管理系统,要求可以实现:多条件、模糊查找,手动输入的内容能去空格。先看效果,如下图动画演示这样的一个效果要怎样实现呢?本文所用函数有Filter和Search。先用filter...
- FILTER函数介绍及经典用法12:FILTER+切片器的应用
-
EXCEL函数技巧:FILTER经典用法12。FILTER+切片器制作筛选按钮。FILTER的函数的经典用法12是用FILTER的函数和切片器制作一个筛选按钮。像左边的原始数据,右边想要制作一...
- office办公应用网站推荐_office办公软件大全
-
以下是针对Office办公应用(Word/Excel/PPT等)的免费学习网站推荐,涵盖官方教程、综合平台及垂直领域资源,适合不同学习需求:一、官方权威资源1.微软Office官方培训...
- WPS/Excel职场办公最常用的60个函数大全(含卡片),效率翻倍!
-
办公最常用的60个函数大全:从入门到精通,效率翻倍!在职场中,WPS/Excel几乎是每个人都离不开的工具,而函数则是其灵魂。掌握常用的函数,不仅能大幅提升工作效率,还能让你在数据处理、报表分析、自动...
- 收藏|查找神器Xlookup全集|一篇就够|Excel函数|图解教程
-
原创版权所有全程图解,方便阅读,内容比较多,请先收藏!Xlookup是Vlookup的升级函数,解决了Vlookup的所有缺点,可以完全取代Vlookup,学完本文后你将可以应对所有的查找难题,内容...
- 批量查询快递总耗时?用Excel这个公式,自动计算揽收到签收天数
-
批量查询快递总耗时?用Excel这个公式,自动计算揽收到签收天数在电商运营、物流对账等工作中,经常需要统计快递“揽收到签收”的耗时——比如判断某快递公司是否符合“3天内送达”的服务承...
- Excel函数公式教程(490个实例详解)
-
Excel函数公式教程(490个实例详解)管理层的财务人员为什么那么厉害?就是因为他们精通excel技能!财务人员在日常工作中,经常会用到Excel财务函数公式,比如财务报表分析、工资核算、库存管理等...
- Excel(WPS表格)Tocol函数应用技巧案例解读,建议收藏备用!
-
工作中,经常需要从多个单元格区域中提取唯一值,如体育赛事报名信息中提取唯一的参赛者信息等,此时如果复制粘贴然后去重,效率就会很低。如果能合理利用Tocol函数,将会极大地提高工作效率。一、功能及语法结...
- Excel中的SCAN函数公式,把计算过程理清,你就会了
-
Excel新版本里面,除了出现非常好用的xlookup,Filter公式之外,还更新一批自定义函数,可以像写代码一样写公式其中SCAN函数公式,也非常强大,它是一个循环函数,今天来了解这个函数公式的计...
- Excel(WPS表格)中多列去重就用Tocol+Unique组合函数,简单高效
-
在数据的分析和处理中,“去重”一直是绕不开的话题,如果单列去重,可以使用Unique函数完成,如果多列去重,如下图:从数据信息中可以看到,每位参赛者参加了多项运动,如果想知道去重后的参赛者有多少人,该...
- Excel(WPS表格)函数Groupby,聚合统计,快速提高效率!
-
在前期的内容中,我们讲了很多的统计函数,如Sum系列、Average系列、Count系列、Rank系列等等……但如果用一个函数实现类似数据透视表的功能,就必须用Groupby函数,按指定字段进行聚合汇...
- Excel新版本,IFS函数公式,太强大了!
-
我们举一个工作实例,现在需要计算业务员的奖励数据,右边是公司的奖励标准:在新版本的函数公式出来之前,我们需要使用IF函数公式来解决1、IF函数公式IF函数公式由三个参数组成,IF(判断条件,对的时候返...
- Excel不用函数公式数据透视表,1秒完成多列项目汇总统计
-
如何将这里的多组数据进行汇总统计?每组数据当中一列是不同菜品,另一列就是该菜品的销售数量。如何进行汇总统计得到所有的菜品销售数量的求和、技术、平均、最大、最小值等数据?不用函数公式和数据透视表,一秒就...
- 一周热门
- 最近发表
-
- Excel技巧:SHEETSNA函数一键提取所有工作表名称批量生产目录
- Excel HOUR函数:“小时”提取器_excel+hour函数提取器怎么用
- Filter+Search信息管理不再难|多条件|模糊查找|Excel函数应用
- FILTER函数介绍及经典用法12:FILTER+切片器的应用
- office办公应用网站推荐_office办公软件大全
- WPS/Excel职场办公最常用的60个函数大全(含卡片),效率翻倍!
- 收藏|查找神器Xlookup全集|一篇就够|Excel函数|图解教程
- 批量查询快递总耗时?用Excel这个公式,自动计算揽收到签收天数
- Excel函数公式教程(490个实例详解)
- Excel(WPS表格)Tocol函数应用技巧案例解读,建议收藏备用!
- 标签列表
-
- 外键约束 oracle (36)
- oracle的row number (32)
- 唯一索引 oracle (34)
- oracle in 表变量 (28)
- oracle导出dmp导出 (28)
- 多线程的创建方式 (29)
- 多线程 python (30)
- java多线程并发处理 (32)
- 宏程序代码一览表 (35)
- c++需要学多久 (25)
- css class选择器用法 (25)
- css样式引入 (30)
- css教程文字移动 (33)
- php简单源码 (36)
- php个人中心源码 (25)
- php小说爬取源码 (23)
- 云电脑app源码 (22)
- html画折线图 (24)
- docker好玩的应用 (28)
- linux有没有pe工具 (34)
- 可以上传视频的网站源码 (25)
- 随机函数如何生成小数点数字 (31)
- 随机函数excel公式总和不变30个数据随机 (33)
- 所有excel函数公式大全讲解 (22)
- 有动图演示excel函数公式大全讲解 (32)
