自律社区
# 后端设计
# 用户
# 登录
采用Spring Security框架,JWT认证。需要配置令牌存储方式,配置用户名密码认证,标识哪些接口需要访问权限。
# 验证
重写UserDetailsService中的loadUserByUsername,该方法表示通过用户名从某个地方取出用户,与框架待验证的用户进行对比。验证成功后,将用户信息AuthenticationHolderContext存储到Session中。之后每次请求到来,可以从Session中取出Authentication用户信息。也可以从Jwt令牌中取出用户信息。
JWT由三部分组成:
Header : 描述 JWT 的元数据,定义了生成签名的算法以及 Token
的类型。
Payload : 用来存放实际需要传递的数据
Signature(签名):服务器通过 Payload、Header 和一个密钥(Secret)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。
对于登录成功的用户,将限时JWT令牌发送给客户端,存储到客户端的cookie中,之后每次请求都带上该JWT令牌。服务器验证只需要验证无状态的JWT令牌即可,无需访问数据库。验证方式:
将Header.Payload与服务器的秘钥进行加密,如果密文与令牌第三部分Signature相同,则认为该令牌合法。
续签机制:
登录后返回两个JWT令牌,请求中如果第一个令牌过期,则再次发送第二个令牌,如果没过期,则服务器返回一个新的令牌,否则要求客户端重新登录。
# 自习室
1.通过自习室ID,或者自习室名称,在页面进行查询对应的自习室。
2.简单的一个根据索引,查询MySQL。
3.加入自习室:每个用户至多加入一个自习室,只需要在用户与自习室的关系表中插入一条数据。
4.退出自习室:如果是成员,那么只需要在用户与自习室的关系表中删除一条数据。如果是房主,那么就是解散该自习室,简单的一个事务,需要对在自习室表中删除该自习室,以及在用户与自习室的关系表中,移除这些成员。
5.转让房主:只需要更改一下自习室表的创造者ID。
# 留言版与点赞
1.加入自习室后,可以进行留言。也可以对留言进行回复,对回复进行回复。
2.对留言点赞,对回复点赞。点赞记录到点赞表中,可以判断某个用户是否点赞,进行对对应的留言或者回复增减赞的数量。个人认为点赞数量的显示不需要做到实时,所以不需要频繁更新数据库中的数据。首先将各个实体点赞的数量存储到Redis中,前端只操作的Redis数据,后端定时更新点赞表,与更新对应数据的点赞数量。
# 方案一:
Redis是单线程的,不会有线程安全问题。存储方案
message:
messageId1: {userId1, userId2, userId3...}
messageId2: {userId4, userId2, userId6...}
reply:
replyId1: {userId1, userId2, userId3...}
replyId2: {userId4, userId2, userId6...}
后端定期拿到Redis的数据,清空。然后将这些userId去点赞表中查看,如果不存在,则点赞。如果存在,则判断status是点赞状态还是未点赞状态。根据状态,去更新对应的留言表或回复表的点赞数量。
缺点:只维护了点赞的效率,每次请求,都需要从MySQL中查。
将哪些留言放入缓存中?
一些缓存策略
::: Cache Aside 旁路缓存
先更新数据库,再删除缓存
:::
::: Read/Write Through (读穿/写穿)
用户只与缓存打交道,例如本地Caffeine缓存。
:::
::: Write Back (写回)
对于修改的数据只存在缓存中,标记为脏。如果下次读缓存时,如果这个缓存是脏,那么就将它写回数据库,再将数据库的值存入缓存。
:::
# 方案二
使用Hash存储,格式为点赞者::被点赞者 : 1 or 0
,被点赞者: 被点赞数
。定时任务将两者存储MySQL中。
# 表设计
用户表 | ||
---|---|---|
id | 主键索引 | |
username | 用户名 | 二级索引 |
password | 密码 | |
salt | 盐 | |
status | 用户状态 | |
room_id | 加入的自习室id | 二级索引 |
last_login | 上次登录时间 | |
creat_time | 创建时间 |
签到表 | ||
---|---|---|
id | ||
uid | 用户id | 联合索引字段1 |
year | 签到年 | 联合索引字段2 |
month | 签到月 | 联合索引字段3 |
bit | 这个月签到情况 |
自习室表 | ||
---|---|---|
id | 主键索引 | |
create_id | 创建者 | 联合索引字段1 |
name | 自习室名称 | 联合索引字段2 |
create_time | 创建时间 |
内容表 | ||
---|---|---|
id | 主键索引 | |
uid | 发表人 | 联合索引字段1 |
room_id | 自习室 | 联合索引字段2 |
content | 发表内容 | |
status | 内容状态 | |
like_count | 被点赞数量 | |
score | 得分 | |
create_time | 发表时间 |
站内通知表 | ||
---|---|---|
id | ||
from_id | 发送方 | 点赞或关注发送方是系统 |
to_id | 接收方 | |
type | 通知类型(点赞,关注,评论,私信) | |
content | 内容 | 谁对什么点赞了。谁对什么评论了 |
status | 是否已读 | |
create_time | 发送时间 |
用户点赞表 | ||
---|---|---|
id | ||
uid | 点赞人 | 联合索引字段1 |
target_type | 点赞类型 | 联合索引字段2 |
target_id | 被点赞的内容 | 联合索引字段3 |
target_uid | 被点赞人 | |
status | 是否点赞 |
回复表 | ||
---|---|---|
id | ||
uid | 回复人 | |
type | 对消息回复,对回复进行回复 | 联合索引字段1 |
target_id | 回复目标的id | 联合索引字段2 |
target_uid | 被回复的人 | |
like_count | 这条回复被点赞数量 | |
create_time | 回复时间 |