准备做一个伙伴匹配的h5系统,支持人员分配标签,组队,创建队伍,加入队伍。 很多时候在我自己去设计一个系统的时候,往往我不知道我到底要做什么,到底解决了什么痛点问题,这也可能是项目做得少了的原因。 没有发生质变,那么一定是量的积累还不够。 黄金圈
- why 为什么要做这个系统? 因为看到了小伙伴之间就是想要找到一个和自己志同道合的伙伴,一起学习、鼓励、共同进步。如果是以往再各种社交媒体群中寻找伙伴,其实无疑是大海捞针,而设计这个系统的话就可以帮助有共同兴趣爱好的小伙伴聚集在一起。 做这个系统可以学习到什么? h5布局,vue的相关知识(以及周边的技术vite...vant..),springboot,mysql数据库,redis缓存.. 最重要的是相要学习设计一个系统应该是如何去设计,现在这一点很匮乏。
- how 这个系统应该如何做?
- 需求分析,看到存在的问题,提取出问题,抽离出可以实现的核心功能进行主要实现
- 技术选型阶段,确定这个系统应该设计成什么样子,前后端使用的技术应该如何来定
- 数据库设计阶段,确定完成这个系统需要那些表,表中有哪些字段...
- 前端页面的设计(交互)
- 后台接口设计(业务实现)
- 系统测试
- 系统部署上线
- what 最终实现什么样子的?
- h5页面,尽量的适配pc端布局
- 有个人中中心,组队,搜索队伍等功能 需求分析
- 用户可以自定义标签,通过标签进行搜索(java/python)
- 主动搜索(redis缓存)
- 组队功能 a. 创建队伍 b. 加入队伍 c. 删除队伍 d. 查询队伍
- 允许用户去修改自己的标签
- 相似度匹配算法 技术选型 使用git管理代码仓库 前端 vue3 + ts + vite + vantui(h5) 后端 springboot2.7 + redis + mysql + mybatisplus + swagger 2023-10-16今日计划 前端项目搭建 15min 创建数据表 15min 用户表 标签表 后端项目初始化 15min 前端页面开发-更具标签搜索用户 1h 后端业务开发 - 更具标签搜索用户 1h 前端项目搭建 使用pnpm工具创建vite项目,然后安装vantui组件库。√ 这儿使用全局引入组件的方式,目的是方便开发,当然局部引入的方式是最佳选择。 布局:tabbar + content + topbar √
tabbar: 主页 队伍页 用户页 topbar 返回 标题 搜索 主体内容 数据库表设计 我们主要是通过标签去进行检索,因此需要设计一张标签表,因为有存在修改标签的需求,所以这张表不能省略 新增标签表(类似分类) 类似分类表,但是标签的方式更加的灵活 性别:男、女 状态:emo中,开心,难过 方向:java,前端,go 字段 id 主键 bigint 标签名 varchar 非空 父标签 bigint 是否是父标签 tinyint(0不是,1是) 创建时间 createTime,datetime 更新时间 updateTime,datetime 是否删除 isDelete, tinyint(0、1) 如何查询所有标签=》全量查询 √ 如何查询用户对应的所有标签 √ 修改用户表:
- 在用户表中新增tags字段,使用json存储用户的标签['java', '男'] 查询方便,实现简单。但是就是多增了一列,但是其实标签可以作为用户的固有属性,这样设计也可以接受。
- 新增一个关联表 需要关联查询,增加了一张表,较为复杂 tips:增加关联表一般是需要考虑是否需要正向和反向的查询。如果知识单项的查询的话就可以考虑简单点的实现。
后端接口开发
- 标签查询,支持模糊查询,直接使用like关键字即可。还可以通过直接将数据全量查询到内存,之后到内存中进行操作即可,这种方式比较灵活,而使用sql的方式的话就可以一把梭。15min java8新特性: 使用到了Optional这个类,简化了if-else: List usersList = Optional.ofNullable(users).orElse(new ArrayList<>()); 10-18今日计划 前端
- 完成标签搜索页面,通过标签进行搜索 20min √
- 整合vueRouter路由 5min √
- 用户信息页面 10min √
- 用户信息编辑页面 10min √ js数组中的flatMap方法:这个方法是将嵌套的数组合并成一个新的数组,类似说就是扁平化的意思。 [1,2,3,4,5].flatMap(i => i == 2 ? [111,222]:i) =》 得到的是[1, 111, 222, 3, 4, 5] 后端
- 编写根据标签查询用户的接口 5min √
- 编写全量查询标签的接口,全量查询所有的标签,并且以前端需要的结构进行返回 5min √ idea中ctrl + shift + - 这个快捷键可以快速的折叠方法。ctrl + shift + + 展开方法 序列化和反序列化: GSON google的 jackson alibaba的漏洞多一点 fastjson 10-19日计划(逾期到10-21日) 前端
- 引入axios类库 5min √
- 配置请求工具类 5min √ a. https://www.axios-http.cn/docs/interceptors
- 接入后端接口 15min √
- 新增搜索结果页面(查询后的用户页面) 20min √
- 用户登录接口对接 10min√ 类型声明文件,这种xxx.d.ts这中后缀的引入方式需要加一个type才不会报编译错误。 加了就不报错了,因为这个文件名属于特殊类型,表示类型声明,所以引入的时候也需要特殊对待,
后端
- 将单击session登录方式变为分布式登录,redis存储session。(很简单就是引入redis配置一下就可以)5min √
ES6动态设置对象的key,使用语法: const userReq = { // as string 是ts [form.formLabel as string]: values.value } vue3(ts)中组件的props设置默认值: withDefaults这个方法。 后端
- 主页相似度匹配搜索(查询接口) 11-1日计划 前端
- 队伍页面 后端
- 添加用户推荐到redis缓存,因为数据量大了,响应数据时间太长了
- 缓存预热 优点:1. 可以减少响应的时间 2. 增强用户体验 缺点:1.占用内存 2. 后端编码复杂度增加 3. 可能会造成数据一致性问题 最佳实践:当数据量大的时候,并且数据的修改和新增少,只是查询的次数多,那么就可以使用缓存代替。
- 队伍页(数据表,以及增删改查) 定时任务: spring Schedule定时任务,这个使用EbableSchedule进行开启,然后需要使用的时候就可以使用@Schedule注解进行开启定时任务,书写corn表达式进行任务执行。
- redission分布式锁 redission的基本操作:其实这个redis的客服端,可以让你像操作java集合类一样简单,底层其实实现的就是集合类的接口,做了一层封装,这就是接口开发的好处,扩展性很强。
锁 作用是为了解决在同一时刻只允许一个线程进行访问,但是本地锁得话只限制得了在一个jvm内得线程。 实现方法:synchronized, 并发包,第三方锁 分布式锁 分布式锁解决在分布式场景下同一时刻只允许一个线程访问,其实原理就是让不同得服务器,在完成业务操作之前应该给集中得一个中间件访问,获得锁的才可以进行操作,其他的只能等待或者拒绝。 续锁 如果说执行的代码耗时比较长,那么就可能会导致在执行代码的时候锁被自动释放了,那么此时此刻就会导致别的线程进来执行,这显然是不正确的。而且这种情况还会导致释放掉别人的锁。 不恰当的例子:有三个人去上厕所,假设给他们叫做A,B,C,其中A先到达厕所给厕所加了一把锁,那么B,C就只能在外面等着。(假设锁是有过期时长的)那么可能会出现一下三种情况:
-
正常情况下,A上完厕所以后释放锁,给B C去抢。
-
如果说锁没有过期时长,那么当A掉进了茅坑,就无法释放锁,导致死锁的情况
-
如果有过期时长,但是因为A便秘,需要的时间长一点,但是此时此刻这把锁自动解锁了,那么就会有人又跑进来,那么厕所就有两个人一起上厕所,显然不正常。(这时候就需要续锁了,没有完成那么就需要给锁加一点儿时间)。此时其实还有一种情况,在3的基础上,A上完了,但是因为厕所里面有其他人,A需要出去,那么A就可能会把其他人的锁给释放掉,那么长此以往的执行逻辑就与事想不一样啦。 redission看门狗 https://blog.csdn.net/a3337779/article/details/131667731 看门狗主要的作用就是检测锁的过期时间与方法是否执行完毕,其实就是用于做锁续期。 11-7日 今日最要是一些增删改查的业务的编写。 前端
-
队伍列表页(p0)√ 页面布局: √ 头部搜索 公开,加密队伍切换 内容布局: 需要展示队伍头像,队伍名称,队伍数量,队伍创建时间,队伍过期时间 加入队伍按钮, 解散队伍按钮(如果是创建人的话),如果用户没有登录,那么只是可以查看队伍,加入等操作需要登录才可以。
-
申请加入队伍(如果是公开的,那么直接可以加入,这儿不考虑通知创建者的方式,直接可以加入,如果后期相要做,那么就是就是一个来回)(p0) a. 审核加入 b. 统一入队 c. 队满通知
-
查看自己所加入的队伍(p1)
-
查看自己创建的队伍(p2)
-
队伍创建页面 (p1 ) 后端
-
队伍创建(p0)√(未做并发测试) a. 队伍是否状态(是否公开,密码) b. 队伍最大人数 c. 一个人最多可以创建10个队伍(保留开会员的这个入口)
-
加入队伍(p1)√ a. 需要屏蔽掉自己创建的队伍 b. 只能看到公开,或者加密的队伍(加密需要密码)
-
邀请入队(暂时不做) 可考虑生成邀请二维码
-
退出队伍(如果队伍是自己创建,且如果队伍里面没有人,那么解散该队伍;如果队伍中有人,那么根据退位机制,选取最先加入队伍的那个人作为该队伍的创建者)(p0)√
-
分页查询队伍列表 p2 √
-
修改队伍信息 √ 以后计划
-
队伍创建 a. 队伍是否状态(是否公开,密码) b. 队伍最大人数
-
加入队伍 a. 需要屏蔽掉自己创建的队伍 b. 只能看到公开,或者加密的队伍(加密需要密码)
-
邀请入队 可考虑生成邀请二维码
-
退出队伍(如果队伍是自己创建,且如果队伍里面没有人,那么解散该队伍;如果队伍中有人,那么根据退位机制,选取最先加入队伍的那个人作为该队伍的创建者) a. 谁退出队伍(队友 | 创建者) b. 退出那个队伍(队伍id)
-
队长踢人(删除成员其实就是) a. 不能删除自己 基础知识复习 线程的创建有四种方式: Thread类,Runable接口,Callable接口,线程池。 线程池的创建方式
-
Executors工具类的方式创建
-
使用java类库(ThreadPoolExecutor对象)
-
使用原生的自定义线程池的参数
-
使用第三方的框架进行创建 TODO
-
在高并发的情况下还是出现了一个人创建了超过10个队伍的问题,加了分布式锁没有解决。
-
高并发压测时,加入队伍我接口也是出现了"超卖"的情况
-
其他优化点(骨架加载,速度优化,状态应该在后台判断不该在前台)
-
我创建的队伍裂变页(简单)
-
我所加入的列表页面(简单)