前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开源社区系统 Echo 超全文档助力春招

开源社区系统 Echo 超全文档助力春招

作者头像
飞天小牛肉
修改2021-03-01 15:55:40
2.3K0
修改2021-03-01 15:55:40
举报
文章被收录于专栏:飞天小牛肉

寒假前半个月到现在差不多一个多月,断断续续做完了这个项目,现在终于可以开源出来了,我的想法是为这个项目编写一套完整的教程,包括技术选型分析、架构分析、业务逻辑分析、核心技术点分析、常见面试题等。不过说实话,这里面涉及的一些技术我仍然停留在仅仅是会用的阶段,当然,后面我会不断学习,了解透彻这些技术的底层原理,不断完善这套教程。

? 项目简介

Echo 是一套前后端不分离的开源社区系统,基于目前主流 Java Web 技术栈(SpringBoot + MyBatis + MySQL + Redis + Kafka + Elasticsearch + Spring Security + ...),并提供详细的开发文档和配套教程。包含帖子、评论、私信、系统通知、点赞、关注、搜索、用户设置、数据统计等模块。

「源码链接」:已托管在 Github 和 Gitee:

  • Gitee(Gitee 官方推荐项目):https://gitee.com/veal98/Echo(推荐,国内访问速度较快)
  • Github:https://github.com/Veal98/Echo

「在线体验」:项目已经部署到腾讯云服务器,各位小伙伴们可直接线上体验:http://1.15.127.74/。已内置三种不同身份的用户:

username

password

特殊权限

管理员

admin

admin

数据统计、删除帖子

版主

master

master

置顶帖子、加精帖子

普通用户

user

user

「文档地址」:文档通过 Docsify + Gitee Pages 生成,国内访问速度较快,在线访问地址:https://veal98.gitee.io/echo

? 核心技术栈

后端:

  • Spring
  • Spring Boot 2.1.5 RELEASE
  • Spring MVC
  • ORM:MyBatis
  • 数据库:MySQL 5.7
  • 分布式缓存:Redis
  • 本地缓存:Caffeine
  • 消息队列:Kafka 2.13-2.7.0
  • 搜索引擎:Elasticsearch 6.4.3
  • 安全:Spring Security
  • 邮件任务:Spring Mail
  • 分布式定时任务:Spring Quartz
  • 日志:SLF4J(日志接口) + Logback(日志实现)

前端:

  • Thymeleaf
  • Bootstrap 4.x
  • Jquery
  • Ajax

? 开发环境

  • 操作系统:Windows 10
  • 构建工具:Apache Maven
  • 集成开发工具:Intellij IDEA
  • 应用服务器:Apache Tomcat
  • 接口测试工具:Postman
  • 压力测试工具:Apache JMeter
  • 版本控制工具:Git
  • Java 版本:8

? 界面展示

首页:

登录页:

帖子详情页:

个人主页:

朋友私信页:

私信详情页:

系统通知页:

通知详情页:

账号设置页:

数据统计页:

搜索详情页:

? 功能列表

  • 「注册」
    • 用户注册成功,将用户信息存入 MySQL,但此时该用户状态为未激活
    • 向用户发送激活邮件,用户点击链接则激活账号(Spring Mail)
  • 「登录 | 登出」
    • 进入登录界面,动态生成验证码,并将验证码短暂存入 Redis(60 秒)
    • 用户登录成功(验证用户名、密码、验证码),生成登录凭证且设置状态为有效,并将登录凭证存入 Redis 注意:登录凭证存在有效期,在所有的请求执行之前,都会检查凭证是否有效和是否过期,只要该用户的凭证有效并在有效期时间内,本次请求就会一直持有该用户信息(使用 ThreadLocal 持有用户信息)
    • 勾选记住我,则延长登录凭证有效时间
    • 用户登录成功,将用户信息短暂存入 Redis(1 小时)
    • 用户登出,将凭证状态设为无效,并更新 Redis 中该用户的登录凭证信息
  • 「账号设置」
    • 将用户选择的头像图片文件上传至七牛云服务器
    • 修改头像
    • 修改密码
  • 「帖子模块」
    • 未登录用户无法发帖
    • “版主” 可以看到帖子的置顶和加精按钮并执行相应操作
    • “管理员” 可以看到帖子的删除按钮并执行相应操作
    • “普通用户” 无法看到帖子的置顶、加精、删除按钮,也无法执行相应操作
    • 支持按照 “发帖时间” 显示
    • 支持按照 “热度排行” 显示(Spring Quartz)
    • 发布帖子(过滤敏感词),将其存入 MySQL
    • 分页显示所有的帖子
    • 查看帖子详情
    • 权限管理(Spring Security + Thymeleaf Security)
  • 「评论模块」
    • 未登录用户无法使用评论功能
    • 发布对帖子的评论(过滤敏感词),将其存入 MySQL
    • 分页显示评论
    • 发布对评论的回复(过滤敏感词)
    • 权限管理(Spring Security)
  • 「私信模块」
    • 未登录用户无法使用私信功能
    • 查询某个会话所包含的所有私信
    • 访问私信详情时,将显示的私信设为已读状态
    • 支持分页显示
    • 查询当前用户的会话列表
    • 每个会话只显示一条最新的私信
    • 支持分页显示
    • 发送私信(过滤敏感词)
    • 私信列表
    • 私信详情
    • 权限管理(Spring Security)
  • 「统一处理 404 / 500 异常」
    • 普通请求异常
    • 异步请求异常
  • 「统一记录日志」
  • 「点赞模块」
    • 未登录用户无法使用点赞相关功能
    • 支持对帖子、评论/回复点赞
    • 第 1 次点赞,第 2 次取消点赞
    • 首页统计帖子的点赞数量
    • 详情页统计帖子和评论/回复的点赞数量
    • 详情页显示当前登录用户的点赞状态(赞过了则显示已赞)
    • 统计我的获赞数量
    • 权限管理(Spring Security)
  • 「关注模块」
    • 未登录用户无法使用关注相关功能
    • 关注功能
    • 取消关注功能
    • 统计用户的关注数和粉丝数
    • 我的关注列表(查询某个用户关注的人),支持分页
    • 我的粉丝列表(查询某个用户的粉丝),支持分页
    • 权限管理(Spring Security)
  • 「系统通知模块」
    • 未登录用户无法使用系统通知功能
    • 分别显示每种类型的系统通知的未读数量
    • 显示所有系统通知的未读数量
    • 分页显示某一类主题所包含的通知
    • 进入某种类型的系统通知详情,则将该页的所有未读的系统通知状态设置为已读
    • 显示评论、点赞、关注三种类型的通知
    • 通知列表
    • 通知详情
    • 未读数量
    • 导航栏显示所有消息的未读数量(未读私信 + 未读系统通知)
    • 权限管理(Spring Security)
  • 「搜索模块」
    • 从 Elasticsearch 服务器搜索帖子
    • 从 Elasticsearch 服务器删除帖子(当帖子从数据库中被删除时)
    • 发布帖子时,通过消息队列将帖子异步地提交到 Elasticsearch 服务器
    • 为帖子增加评论时,通过消息队列将帖子异步地提交到 Elasticsearch 服务器
    • 发布事件
    • 搜索服务
    • 显示搜索结果
  • 「网站数据统计」(管理员专属)
    • 只有管理员可以查看网站数据统计
    • 存入 Redis 的 Bitmap
    • 支持单日查询和区间日期查询
    • 存入 Redis 的 HyperLogLog
    • 支持单日查询和区间日期查询
    • 独立访客 UV
    • 日活跃用户 DAU
    • 权限管理(Spring Security)
  • 「优化网站性能」
    • 使用本地缓存 Caffeine 缓存热帖列表以及所有用户帖子的总数

? 本地运行

各位如果需要将项目部署在本地进行测试,以下环境请提前备好:

  • Java 8
  • MySQL 5.7
  • Redis
  • Kafka 2.13-2.7.0
  • Elasticsearch 6.4.3

然后「修改配置文件中的信息为你自己的本地环境,直接运行是运行不了的」,而且相关私密信息我全部用 xxxxxxx 代替了。

本地运行需要修改的配置文件信息如下:

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

  • LOG_PATH:日志存放的位置

每次运行需要打开:

  • MySQL
  • Redis
  • Elasticsearch
  • Kafka

另外,还需要事件建好数据库 greatecommunity,然后依次运行项目 sql 文件夹下的这几个 sql 文件建立数据库表:

? 数据库设计

用户 user

代码语言:javascript
复制
DROP TABLE IF EXISTS `user`;
SET character_set_client = utf8mb4 ;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL,
  `password` varchar(50) DEFAULT NULL,
  `salt` varchar(50) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `type` int(11) DEFAULT NULL COMMENT '0-普通用户; 1-超级管理员; 2-版主;',
  `status` int(11) DEFAULT NULL COMMENT '0-未激活; 1-已激活;',
  `activation_code` varchar(100) DEFAULT NULL,
  `header_url` varchar(200) DEFAULT NULL,
  `create_time` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_username` (`username`(20)),
  KEY `index_email` (`email`(20))
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8;

讨论帖 discuss_post

代码语言:javascript
复制
DROP TABLE IF EXISTS `discuss_post`;
SET character_set_client = utf8mb4 ;
CREATE TABLE `discuss_post` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `title` varchar(100) DEFAULT NULL,
  `content` text,
  `type` int(11) DEFAULT NULL COMMENT '0-普通; 1-置顶;',
  `status` int(11) DEFAULT NULL COMMENT '0-正常; 1-精华; 2-拉黑;',
  `create_time` timestamp NULL DEFAULT NULL,
  `comment_count` int(11) DEFAULT NULL,
  `score` double DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

评论(回复)comment

代码语言:javascript
复制
CREATE TABLE `comment` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `entity_type` int(11) DEFAULT NULL COMMENT '评论目标的类别:1 帖子;2 评论 ',
  `entity_id` int(11) DEFAULT NULL COMMENT '评论目标的 id',
  `target_id` int(11) DEFAULT NULL COMMENT '指明对谁进行评论',
  `content` text,
  `status` int(11) DEFAULT NULL COMMENT '状态:0 正常;1 禁用',
  `create_time` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_user_id` (`user_id`),
  KEY `index_entity_id` (`entity_id`)
) ENGINE=InnoDB AUTO_INCREMENT=247 DEFAULT CHARSET=utf8;

私信 message

代码语言:javascript
复制
DROP TABLE IF EXISTS `message`;
SET character_set_client = utf8mb4 ;
CREATE TABLE `message` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `from_id` int(11) DEFAULT NULL,
  `to_id` int(11) DEFAULT NULL,
  `conversation_id` varchar(45) NOT NULL,
  `content` text,
  `status` int(11) DEFAULT NULL COMMENT '0-未读;1-已读;2-删除;',
  `create_time` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_from_id` (`from_id`),
  KEY `index_to_id` (`to_id`),
  KEY `index_conversation_id` (`conversation_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

? 部署架构

我每个都只部署了一台,以下是理想的部署架构:

? 功能逻辑图

画了一些不是那么严谨的图帮助各位小伙伴理清思绪。

❝单向绿色箭头:

  • 前端模板 -> Controller:表示这个前端模板中有一个超链接是由这个 Controller 处理的
  • Controller -> 前端模板:表示这个 Controller 会像该前端模板传递数据或者跳转

双向绿色箭头:表示 Controller 和前端模板之间进行参数的相互传递或使用 单向蓝色箭头:A -> B,表示 A 方法调用了 B 方法 单向红色箭头:数据库或缓存操作 ❞

注册

  • 用户注册成功,将用户信息存入 MySQL,但此时该用户状态为未激活
  • 向用户发送激活邮件,用户点击链接则激活账号(Spring Mail)

登录 | 登出

  • 进入登录界面,动态生成验证码,并将验证码短暂存入 Redis(60 秒)
  • 用户登录成功(验证用户名、密码、验证码),生成登录凭证且设置状态为有效,并将登录凭证存入 Redis 注意:登录凭证存在有效期,在所有的请求执行之前,都会检查凭证是否有效和是否过期,只要该用户的凭证有效并在有效期时间内,本次请求就会一直持有该用户信息(使用 ThreadLocal 持有用户信息)
  • 勾选记住我,则延长登录凭证有效时间
  • 用户登录成功,将用户信息短暂存入 Redis(1 小时)
  • 用户登出,将凭证状态设为无效,并更新 Redis 中该用户的登录凭证信息

下图是登录模块的功能逻辑图,并没有使用 Spring Security 提供的认证逻辑(我觉得这个模块是最复杂的,这张图其实很多细节还没有画全)

分页显示所有的帖子

  • 支持按照 “发帖时间” 显示
  • 支持按照 “热度排行” 显示(Spring Quartz)
  • 将热帖列表和所有帖子的总数存入本地缓存 Caffeine(利用分布式定时任务 Spring Quartz 每隔一段时间就刷新计算帖子的热度/分数 — 见下文,而 Caffeine 里的数据更新不用我们操心,它天生就会自动的更新它拥有的数据,给它一个初始化方法就完事儿)

账号设置

  • 修改头像(异步请求)
    • 将用户选择的头像图片文件上传至七牛云服务器
  • 修改密码

此处只画出修改头像:

发布帖子(异步请求)

显示评论及相关信息

❝评论部分前端的名称显示有些缺陷,有兴趣的小伙伴欢迎提 PR 解决~ ❞

关于评论模块需要注意的就是评论表的设计,把握其中字段的含义,才能透彻了解这个功能的逻辑。

评论 Comment 的目标类型(帖子,评论) entityType 和 entityId 以及对哪个用户进行评论/回复 targetId 是由前端传递给 DiscussPostController 的

一个帖子的详情页需要封装的信息大概如下:

添加评论(事务管理)

私信列表和详情页

发送私信(异步请求)

点赞(异步请求)

将点赞相关信息存入 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 就是这个用户的获赞数量

我的获赞数量

关注(异步请求)

  • 若 A 关注了 B,则 A 是 B 的粉丝 Follower,B 是 A 的目标 Followee
  • 关注的目标可以是用户、帖子、题目等,在实现时将这些目标抽象为实体(目前只做了关注用户)

将某个用户关注的实体相关信息存储在 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),以关注的时间进行排序

关注列表

发送系统通知

显示系统通知

搜索

类似的,置顶、加精也会触发发帖事件,就不再图里面画出来了。

置顶加精删除(异步请求)

网站数据统计

帖子热度计算

每次发生点赞(给帖子点赞)、评论(给帖子评论)、加精的时候,就将这些帖子信息存入缓存 Redis 中,然后通过分布式的定时任务 Spring Quartz,每隔一段时间就从缓存中取出这些帖子进行计算分数。

帖子分数/热度计算公式:分数(热度) = 权重 + 发帖距离天数

代码语言:javascript
复制
// 计算权重
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);

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 飞天小牛肉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ? 项目简介
  • ? 核心技术栈
  • ? 开发环境
  • ? 界面展示
  • ? 功能列表
  • ? 本地运行
  • ? 数据库设计
  • ? 部署架构
  • ? 功能逻辑图
    • 注册
      • 登录 | 登出
        • 分页显示所有的帖子
          • 账号设置
            • 发布帖子(异步请求)
              • 显示评论及相关信息
                • 添加评论(事务管理)
                  • 私信列表和详情页
                    • 发送私信(异步请求)
                      • 点赞(异步请求)
                        • 我的获赞数量
                          • 关注(异步请求)
                            • 关注列表
                              • 发送系统通知
                                • 显示系统通知
                                  • 搜索
                                    • 置顶加精删除(异步请求)
                                      • 网站数据统计
                                        • 帖子热度计算
                                        相关产品与服务
                                        云数据库 Redis
                                        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                                        领券
                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档