📚 项目简介
该项目采用了当前流行的Java开发技术堆栈,主要包括SpringBoot、MyBatis、MySQL、Redis、Kafka、Elasticsearch和Spring Security等。同时,项目还提供了完整的开发指南和相关的教学材料。它涵盖了多种功能模块,如发布帖子、评论互动、发送私信、接收系统通知、实现点赞功能、用户之间的关注机制、搜索服务、用户个性化设置以及数据统计分析等。
🎀 页面
主页:
登录:
密码重置:
帖子发布
帖子详情
帖子详情
个人主页
朋友私信页
私信详情页
系统通知页
通知详情页
账号设置页
数据统计页
搜索详情页
🎨 功能列表
注册
登录 | 退出
账号设置
过滤敏感词
帖子模块
评论模块
未登录用户无法使用评论功能
发布对帖子的评论(过滤敏感词)
分页显示评论
发布对评论的回复(过滤敏感词)
权限管理
私信模块
未登录用户无法使用私信功能
查询某个会话所包含的所有私信
访问私信详情时,将显示的私信设为已读状态
支持分页显示
查询当前用户的会话列表
每个会话只显示一条最新的私信
支持分页显示
发送私信(过滤敏感词)
私信列表
私信详情
权限管理
统一异常处理
统一记录日志
点赞模块
关注模块
未登录用户无法使用关注相关功能
关注功能
取消关注功能
统计用户的关注数和粉丝数
我的关注列表(查询某个用户关注的人),支持分页
我的粉丝列表(查询某个用户的粉丝),支持分页
权限管理
系统通知模块
搜索模块
网站数据统计(管理员专属)
只有管理员可以查看网站数据统计
支持单日查询和区间日期查询
支持单日查询和区间日期查询
独立访客 UV
日活跃用户 DAU
权限管理
优化网站性能
🌱 本地运行
提前安装以下软件:
Java 8
MySQL 5.7
Redis
Kafka 2.13-2.7.0
Elasticsearch 6.4.3
修改配置文件。
修改的配置文件信息如下:
1)application-develop.properties
:
MySQL
Spring Mail(邮箱需要开启 SMTP 服务)
Kafka:consumer.group-id(该字段见 Kafka 安装包中的 consumer.proerties,可自行修改, 修改完毕后需要重启 Kafka)
Elasticsearch:cluster-name(该字段见 Elasticsearch 安装包中的 elasticsearch.yml,可自行修改)
七牛云(用来存放上传的头像图片)
2)logback-spring-develop.xml
:
每次运行需要打开:
MySQL
Redis
Elasticsearch
Kafka
数据库 greatecommunity,依次运行 sql 文件夹下的sql 文件建立数据库表:
🌌 部署架构
我每个都只部署了一台,以下是理想的部署架构:
🎯 功能逻辑图
画了一些不是那么严谨的图帮助各位小伙伴理清思绪。
单向绿色箭头:
双向绿色箭头:表示 Controller 和前端模板之间进行参数的相互传递或使用
单向蓝色箭头:A -> B,表示 A 方法调用了 B 方法
单向红色箭头:数据库或缓存操作
注册
登录 | 登出
登录认证模块跳过了 Spring Secuity 自带的认证机制。主要逻辑如下:
进入登录界面,随机生成一个字符串来标识这个将要登录的用户,将这个字符串短暂的存入 Cookie(60 秒);
动态生成验证码,并将验证码及标识该用户的字符串短暂存入 Redis(60 秒);
为登录成功(验证用户名、密码、验证码)的用户随机生成登录凭证且设置状态为有效,并将登录凭证及其状态等信息永久存入 Redis,再在 Cookie 中存一份登录凭证;
使用拦截器在所有的请求执行之前,从 Cookie 中获取登录凭证,只要 Redis 中该凭证有效并在有效期内,本次请求就会一直持有该用户信息(使用 ThreadLocal 持有用户信息,保证多台服务器上用户的登录状态同步);
勾选记住我,则延长 Cookie 中登录凭证的有效时间;
用户登出,将凭证状态设为无效,并更新 Redis 中该登录凭证的相关信息。
下图是登录模块的功能逻辑图,并没有使用 Spring Security 提供的认证逻辑(我觉得这个模块是最复杂的,这张图其实很多细节还没有画全)
分页显示所有的帖子
账号设置
此处只画出修改头像:
发布帖子(异步请求)
发布帖子(过滤敏感词),将其存入 MySQL
显示评论及相关信息
评论部分前端的名称显示有些缺陷,有兴趣的小伙伴欢迎提 PR 解决 ~
关于评论模块需要注意的就是评论表的设计,把握其中字段的含义,才能透彻了解这个功能的逻辑。
评论 Comment 的目标类型(帖子,评论) entityType 和 entityId 以及对哪个用户进行评论/回复 targetId 是由前端传递给 DiscussPostController 的
一个帖子的详情页需要封装的信息大概如下:
添加评论(事务管理)
发布对帖子的评论(过滤敏感词),将其存入 MySQL
私信列表和详情页
发送私信(异步请求)
点赞(异步请求)
将点赞相关信息存入 Redis 的数据结构 set 中。其中,key 命名为 like:entity:entityType:entityId
,value 即点赞用户的 id。比如 key = like:entity:2:246
value = 11
表示用户 11 对实体类型 2 即评论进行了点赞,该评论的 id 是 246
某个用户的获赞数量对应的存储在 Redis 中的 key 是 like:user:userId
,value 就是这个用户的获赞数量
我的获赞数量
关注(异步请求)
将某个用户关注的实体相关信息存储在 Redis 的数据结构 zset 中:key 是 followee:userId:entityType
,对应的 value 是 zset(entityId, now)
,以关注的时间进行排序。比如说 followee:111:3
对应的value (20, 2020-02-03-xxxx)
,表明用户 111 关注了一个类型为 3 的实体即人(用户),关注的这个实体 id 是 20,关注该实体的时间是 2020-02-03-xxxx
同样的,将某个实体拥有的粉丝相关信息也存储在 Redis 的数据结构 zset 中:key 是 follower:entityType:entityId
,对应的 value 是 zset(userId, now)
,以关注的时间进行排序
关注列表
发送系统通知
显示系统通知
搜索
类似的,置顶、加精也会触发发帖事件,就不再图里面画出来了。
置顶加精删除(异步请求)
网站数据统计
独立访客 UV
存入 Redis 的 HyperLogLog
支持单日查询和区间日期查询
日活跃用户 DAU
存入 Redis 的 Bitmap
支持单日查询和区间日期查询
权限管理(Spring Security)
帖子热度计算
每次发生点赞(给帖子点赞)、评论(给帖子评论)、加精的时候,就将这些帖子信息存入缓存 Redis 中,然后通过分布式的定时任务 Spring Quartz,每隔一段时间就从缓存中取出这些帖子进行计算分数。
帖子分数/热度计算公式:分数(热度) = 权重 + 发帖距离天数
// 计算权重
double w = (wonderful ? 75 : 0) + commentCount * 10 + likeCount * 2;
// 分数 = 权重 + 发帖距离天数
double score = Math.log10(Math.max(w, 1))
+ (post.getCreateTime().getTime() - epoch.getTime()) / (1000 * 3600 * 24);
项目地址: