博主目前东南大学研究生在读,近一个月开发了一款社区系统,为接下来的校招做准备,同时开源出来和各位小伙伴一起交流学习。项目仍然存在很多不完善的地方,大家多多指教~
在线体验:项目已经部署到腾讯云服务器,各位小伙伴们可直接线上体验:http://1.15.127.74/
已内置三种不同身份的用户:
username | password | 特殊权限 | |
---|---|---|---|
管理员 | admin | admin | 数据统计、删除帖子 |
版主 | master | master | 置顶帖子、加精帖子 |
普通用户 | user | user |
文档地址:文档通过 Docsify + Gitee Pages 生成,在线访问地址: https://veal98.gitee.io/echo
后端:
前端:
首页:
登录页:
帖子详情页:
个人主页:
朋友私信页:
私信详情页:
系统通知页:
通知详情页:
账号设置页:
数据统计页:
搜索详情页:
注册
登录 | 登出
账号设置
帖子模块
评论模块
私信模块
统一处理 404 / 500 异常
统一记录日志
点赞模块
关注模块
系统通知模块
搜索模块
网站数据统计(管理员专属)
优化网站性能
以下是我个人发现的本项目存在的问题,但是暂时没有头绪无法解决,集思广益,欢迎各位小伙伴提 PR 解决:
以下是我觉得本项目还可以添加的功能,同样欢迎各位小伙伴提 issue 指出还可以增加哪些功能,或者直接提 PR 实现该功能:
各位如果需要将项目部署在本地进行测试,以下环境请提前备好:
然后修改配置文件中的信息为你自己的本地环境,直接运行是运行不了的,而且相关私密信息我全部用 xxxxxxx 代替了。
本地运行需要修改的配置文件信息如下:
1 )application-develop.properties
:
2 )logback-spring-develop.xml
:
每次运行需要打开:
另外,还需要事件建好数据库表,详细见下文。
用户 user
:
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
:
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
:
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
:
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 方法
单向红色箭头:数据库或缓存操作
进入登录界面,动态生成验证码,并将验证码短暂存入 Redis ( 60 秒)
用户登录成功(验证用户名、密码、验证码),生成登录凭证且设置状态为有效,并将登录凭证存入 Redis
注意:登录凭证存在有效期,在所有的请求执行之前,都会检查凭证是否有效和是否过期,只要该用户的凭证有效并在有效期时间内,本次请求就会一直持有该用户信息(使用 ThreadLocal 持有用户信息)
勾选记住我,则延长登录凭证有效时间
用户登录成功,将用户信息短暂存入 Redis ( 1 小时)
用户登出,将凭证状态设为无效,并更新 Redis 中该用户的登录凭证信息
下图是登录模块的功能逻辑图,并没有使用 Spring Security 提供的认证逻辑(我觉得这个模块是最复杂的,这张图其实很多细节还没有画全)
此处只画出修改头像:
评论部分前端的名称显示有些缺陷,有兴趣的小伙伴欢迎提 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 就是这个用户的获赞数量
将某个用户关注的实体相关信息存储在 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,每隔一段时间就从缓存中取出这些帖子进行计算分数。
帖子分数 /热度计算公式:分数(热度) = 权重 + 发帖距离天数
// 计算权重
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);
想要自己从零开始实现这个项目或者深入理解的小伙伴,可以扫描下方二维码关注公众号『飞天小牛肉』,第一时间获取配套教程, 不仅会详细解释本项目涉及的各大技术点,还会汇总相关的常见面试题,目前尚在更新中。
并推荐我的开源教程类项目 『 CS-Wiki 』,Gitee 推荐项目,目前已 0.9k star: 致力打造完善的 Java 后端知识体系,不仅仅帮助各位小伙伴快速且系统的准备面试(秋招 /社招),更指引学习的方向
有什么问题也可以添加我的微信,记得备注来意:格式 <u>(学校或公司 - 姓名或昵称 - 来意)</u>
本项目参考牛客网 — Java 高级工程师课程,感谢老师和平台
1
stabc 2021-02-12 20:52:03 +08:00
你这是招聘贴么?
|
2
coolyan 2021-02-12 21:45:46 +08:00
请问你的图是用什么软件画的?
|
3
smallbeef1998 OP @stabc 不是 哈哈哈哈,标题好像有歧义,是我自己准备秋招做的项目🤣
|
4
smallbeef1998 OP |
5
smallbeef1998 OP @smallbeef1998 改成 备战秋招 /校招,哈哈哈哈
|
6
NIYIKI 2021-02-12 22:49:38 +08:00
不错,已 star
|
7
smallbeef1998 OP @NIYIKI 😁 感谢,后续会不断完善
|
8
selendipity 2021-02-13 00:06:47 +08:00
做成这样一个项目可以进什么公司?
|
9
smallbeef1998 OP @selendipity 结果并不重要吧 重要的是弄懂项目包含的技术点
|
10
alexkuang 2021-02-13 00:32:31 +08:00
谢谢大佬,功能逻辑图很详细,正好最近学校做个项目包含社区系统,参考一下
|
11
Mirage09 2021-02-13 00:44:28 +08:00 via iPhone
Why Kafka?
|
12
smallbeef1998 OP @alexkuang 不是大佬啦,点个 star 就是最大的支持😁
|
13
smallbeef1998 OP @Mirage09 高吞吐量、分布式架构、发布订阅模型
|
14
learningman 2021-02-13 03:28:24 +08:00 via Android 1
就挺离谱的,都写了这么多页面了,在多写一个 install 也没多麻烦啊。。。
每次看到这种要手动导入 SQL 的玩意儿就觉得一股业余的味 |
15
smallbeef1998 OP @learningman 大佬 我确实经验不足😂
|
16
smallbeef1998 OP @learningman 不知道您说的 install 是个啥意思😅
|
17
JustSong 2021-02-13 08:13:57 +08:00 via Android
@smallbeef1998 应该就是一个安装配置页面,类似 WordPress 的初始配置页面
|
18
smallbeef1998 OP @JustSong 这不太好整吧,毕竟大家本地环境不一样😂
|
19
JustSong 2021-02-13 08:34:41 +08:00 via Android
@smallbeef1998 配置下数据库而已呀,本地环境有啥影响
|
20
Cbdy 2021-02-13 08:57:43 +08:00 via Android
蛮怪的
|
21
smallbeef1998 OP @Cbdy 大佬,怎么说😄
|
22
smallbeef1998 OP 为什么大家都在收藏却不愿意给个 star😂
|
23
wbd31 2021-02-13 12:25:03 +08:00
项目的 kafka 是用在了什么地方
|
24
smallbeef1998 OP @wbd31 关注、点赞、评论的系统通知,以及相应的触发 Elasticsearch 数据的更新。可以看看逻辑图😀
|
25
anrgct 2021-02-13 14:51:34 +08:00 via iPhone
冲这么多字支持一下😬
|
26
smallbeef1998 OP @anrgct 🥳
|
27
Austin2035 2021-02-13 17:23:59 +08:00
这种项目适合学习与教学,能说明轮子玩的够熟。
|
28
Austin2035 2021-02-13 17:31:35 +08:00
我的建议是:
1. console 提的报错与警告修改一下 ```JavaScript Uncaught SyntaxError: Unexpected token 'export' DevTools failed to load SourceMap: Could not load content for http://1.15.127.74/js/bootstrap.min.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE ``` 2.如果有余力,可以把网站修改为,首屏 SSR,其余的使用 restful API. 好处在于,1. 增加了前后端分离的模式 2.提升了用户体验 3.减轻了服务器后端的压力(尤其高并发场景,能节约带宽与算力) |
29
smallbeef1998 OP @lookcos 感谢大佬建议啊😄 不过对我这样的初学者来说,前后端不分离相对来说比较友好,强行前后端分离容易把我搞懵
|
30
lasfresas 2021-02-13 17:47:40 +08:00
感觉做的挺好
|
31
smallbeef1998 OP @lasfresas 感谢😁
|
32
wolfan 2021-02-13 18:36:05 +08:00 via Android
移动端适配不成。
|
33
chenlee9876 2021-02-14 02:19:38 +08:00 via iPhone
老哥你直接把 IP 暴露出来真的大丈夫嘛?不考虑整个域名之类的嘛?
|
34
smallbeef1998 OP @chenlee9876 不考虑😂 练手项目 没必要吧
|
35
tousfun 2021-02-14 08:59:48 +08:00 via iPhone
up 研一已经学了这么多东西了吗 本科也是 cs ?
|
36
smallbeef1998 OP @919615766 对的
|
37
Adaocean 2021-02-14 14:24:12 +08:00 via Android
@smallbeef1998 前辈的作品完整度也太高了。
|
38
smallbeef1998 OP @Adaocean 哈哈哈哈 不然怎么在疯狂的内卷里活下来
|
39
smallbeef1998 OP @wolfan 是这样的 我一个人精力实在有限 开源出来也是期待诸位大佬们帮助完善 让我跟在后面学习学习😀
|
40
Adaocean 2021-02-14 15:24:32 +08:00 via Android
@smallbeef1998 很棒 赞赞赞
|
41
hello2060 2021-02-14 18:16:33 +08:00 via iPhone
4 系老校友只能帮顶了
|
42
smallbeef1998 OP @hello2060 哈哈哈哈哈 多谢学长
|
43
wssy 2021-02-16 08:44:56 +08:00 via Android
图画的蛮好
|
44
smallbeef1998 OP @wssy 多谢🍭
|
45
golangLover 2021-02-16 21:35:37 +08:00
大神厉害了
|
46
smallbeef1998 OP @golangLover 不是大神😂 共同进步
|
47
lycbug666 2021-05-24 14:13:42 +08:00
4 系老校友只能帮顶了
|