牛客网我的项目总结
数据库
用户表 ,包含 id、用户名、明码、盐值、邮箱、类型(一般 / 管理员 / 版主)、状态(激活 / 未激活)、激活码(随机字符串)、头像 url、注册工夫。
登录凭证表 ,包含 id、用户 id、登陆凭证(随机字符串)、登录状态(无效 / 有效)、过期工夫。
评论表 ,包含 id、评论用户 id(索引)、评论实体 id(索引)、评论类型(帖子 / 回复)、被评论指标 id、评论内容、评论状态(无效 / 有效)、评论工夫。
帖子表 ,包含 id、发帖用户 id(索引)、题目、帖子内容、类型(一般 / 置顶)、评论数量、状态(一般 / 精髓 / 拉黑)、发帖工夫。
音讯表 ,包含 id、发消息 id(索引)、收音讯 id(索引)、会话 id(由发消息单方 id 拼接,索引)、内容、状态(未读 / 已读 / 删除)、发消息工夫。
注册
判断注册合法性
- 利用 StringUtils 判断用户名、明码、邮箱是否非空。
- 别离通过用户名和邮箱查问是否曾经注册(为数据库的用户名和邮箱字段增加索引)。
通过 set
办法为用户设置各项信息 ,包含 MD5 加密后的明码、激活码等,而后插入数据库。
给用户发送激活邮件
- 在新浪邮箱关上 SMTP 服务,引入
spring-boot-starter-mail
依赖。 - 在配置文件配置主机(smtp.sina.com)、端口(465)、邮箱、受权码、协定(smtps),设置 smtp.ssl.enable = true。
- 调用 JavaMailSender 的 API 发送邮件,激活 url 由用户 id 和用户的激活码拼接而成。点击激活 url 后由 controller 中的办法进行解决(胜利 / 反复 / 失败),调用 Model 对象的
addAttribute
办法将后果返回前端。
登录
生成验证码
- 引入 kaptcha 依赖,将验证码的大小、范畴、长度等属性封装到 Properties 对象,作为参数结构 Config 对象,再用 Config 对象作为 DeafultKaptcha 对象
setConfig
办法的参数为验证码设置属性。 - 在登录的 controller 解决验证码,设置页面的响应类型为 png,通过 ImageIO 的
write
办法将图片输入到浏览器。
判断验证码正确后,调用业务层解决
- 利用 StringUtils 判断用户名、明码是否非空,之后判断用户是否存在、用户是否激活、明码是否正确,将错误信息存到 map 汇合。
- 如果全副非法,为用户生成一个蕴含过期工夫的登录凭证,将凭证存入 redis 和 map 汇合。
依据返回的 map 是否蕴含登陆凭证判断登陆状态
- 如果登录胜利,将凭证存入 cookie 并重定向至首页。
- 如果登陆失败,将 map 中的错误信息增加到 Model 对象,返回登录页。
查看登录状态
只解决带有自定义注解的办法,避免用户在未登录状况下通过 url 拜访没有权限的页面。
利用 ThreadLocal 创立 HostHolder 类,包含 set
、get
、remove
办法,模仿 session 存储用户信息。
通过实现 HandlerInterceptor 接口创立一个拦截器,在 preHandle
办法中通过查问是否有登录凭证的 cookie,如果有则通过登录凭证查问用户 ID,再通过用户 ID 查问用户。最初将用户放入 hostHolder 中,在本次申请中持有用户信息。
创立 @LoginRequired
自定义注解,作用范畴在办法上,有效期为运行时。为须要在登录状态下调用的办法,例如批改明码、上传头像等办法上等加上自定义注解。
创立拦截器,在 preHandle
中判断办法是否增加了 @LoginRequired
注解,如果加了并且从 hostHolder 获取不到用户则回绝拜访。
发帖、评论、私信
敏感词过滤
- 创立动态外部类 TrieNode,通过 boolean 结束符判断是否匹配到关键字尾部。
- 利用
@PostConstruct
注解,在构造方法执行后初始化字典树。 - 增加
filter
办法,利用双指针进行匹配,过滤敏感词。
发帖、评论、私信
- 对内容进行 HTML 本义以及过滤敏感词。
- 将信息插入数据库的帖子 / 评论 / 音讯表。
点赞
创立 RedisKeyUtil 工具类,通过实体类型和实体 id 生成对应实体取得赞的 key。
点赞 / 勾销点赞:
- 通过 RedisKeyUtil 取得实体点赞的 key,而后通过 RedisTemplate 的 API 操作,调用汇合的
isMember
办法查问 userId 是否存在于对应汇合中,如果存在则移除出点赞的用户汇合,如果不存在则增加到点赞的用户汇合。 - 通过 RedisTemplate 的
execute
办法实现事务,保障被点赞用户点和点赞用户的数据更新统一。通过isMember
办法查问用户的点赞状态,之后通过mutli
办法开启事务。
点赞数量:通过调用 set 汇合的 size
办法查问元素个数。
点赞状态:通过 set 汇合的 isMember
办法实现。
关注和粉丝
在 RedisUnitl 工具类减少两个办法
- 通过用户 id 和实体类型取得用户关注的实体汇合的 key。
- 通过实体类型和实体 id 取得实体领有的粉丝汇合的 key。
当用户关注某实体时,
- 将实体 id 和工夫作为 value 和 score 退出用户的关注汇合。
- 将用户 id 和工夫作为 value 和 score 退出实体的粉丝汇合。
当用户勾销关注某实体时,将实体从用户的关注汇合移除,用户从实体的粉丝汇合移除。
关注列表和粉丝列表
- 用户的关注列表,通过 zset 的
reverseRange
获取 value 即关注用户的 userId,再查问出 user,通过score
获取关注工夫。 - 用户的粉丝列表,通过 zset 的
reverseRange
获取 value 即粉丝的 userId,再查问出 user,通过score
获取关注工夫。 - 列表信息封装在 list 汇合中,再将 list 增加到 Model 对象里。
Kafka
发送零碎告诉
创立 Event 类,封装事件对象,包含主题(评论、点赞、关注)、用户 id、实体类型、实体 id,以及一个 map 汇合寄存其它信息。
触发事件
通过 Event 获取事件类型,并将其封装成 JSON 数据,而后调用注入的 KafkaTemplate 实例的 send 办法发送。
生产事件
通过 @KafkaListener
注解,topic 包含了评论、点赞和关注。从 recored 中获取信息,封装成 Message 对象而后调用 addMessage
办法插入数据库。