> # ♻️ 资源
> **大小:** 1.16MB
> **文档链接:**[**https://www.yuque.com/sxbn/ks/100010424**](https://www.yuque.com/sxbn/ks/100010424)
> **➡️ 资源下载:**[**https://download.csdn.net/download/s1t16/87388352**](https://download.csdn.net/download/s1t16/87388352)
> **注:更多内容可关注微信公众号【神仙别闹】,如当前文章或代码侵犯了您的权益,请私信作者删除!**
> ![qrcode_for_gh_d52056803b9a_344.jpg](https://cdn.nlark.com/yuque/0/2023/jpeg/2469055/1692147256036-49ec7e0c-5434-4963-b805-47e7295c9cbc.jpeg#averageHue=%23a3a3a3&clientId=u8fb96484-770e-4&from=paste&height=140&id=u237e511a&originHeight=344&originWidth=344&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=8270&status=done&style=none&taskId=ud96bf5f7-fe85-4848-b9c2-82251181297&title=&width=140.1999969482422)
# 基于 B/S 架构而设计开发的问答网站
主要为用户提供以下服务:
- 问题发布
- 评论
- 用户私信
- 关注
- 站内全文检索
![7ce612338792c8c477a9d8e407f87a77.png](https://cdn.nlark.com/yuque/0/2024/png/2469055/1711414980409-57c2c355-b57d-4fa4-83e7-d51f7e88fb77.png#averageHue=%23f7f7f6&clientId=ub7e1a545-8195-4&from=paste&height=500&id=u4c97fdb1&originHeight=625&originWidth=1366&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=115383&status=done&style=none&taskId=u16aa1f0f-af2d-4609-8e5d-de62fe96aac&title=&width=1092.8)
## 技术选型
Spring Boot + MyBatis + MySQL + Redis + FreeMarker
注意,为保证系统正常运行,请安装并创建好以下环境:
- MySQL
- Redis
- Solr(搜索服务时用到)
## 功能描述
### 注册登录
为了保证用户信息安全,系统对用户密码采用「salt + md5」方式进行加密/脱敏。用户注册/登录成功后,系统会生成一个 ticket ,将 ticket 与用户 id 相关联,并将此信息插入到数据库表 login_ticket 中,同时将 ticket 添加至 cookie 响应给客户端。
用户每次请求页面的时候,都需要先经过 PassportInterceptor 拦截器,拦截器判断此 ticket 是否真实有效,若是,根据 ticket 对应的用户 id ,查出相应用户信息,并添加至页面上下文中。
### 用户内容发布
- 问题发布
- 评论发布
- 私信发布
在以上 **UGC** (User Generated Content, 用户产生的内容)中,系统都会进行 HTML 标签及敏感词过滤,这在一定程度上防止网站被注入脚本或者充斥着不良信息。
> 若没有对 HTML 标签进行处理,当用户发布的内容含有如 `<script>alert("hahah");</script>` 时,网站页面每次加载此内容时都会弹出消息框。
对于**敏感词过滤**,按照常规的思维,也是最简单的方式,就是:对于每个敏感词,都在文本中查找该敏感词是否出现,出现则进行替换。这种方式,每个敏感词都要在一段文本中进行遍历查找,复杂度非常高。
本项目采用「前缀树」方式实现敏感词过滤,空间换时间,效率较高。前缀树结点结构如下:
```java
class TrieNode {
// 标记是否为敏感词结尾
boolean end;
// 该结点的所有直接子结点
Map<Character, TrieNode> subNodes = new HashMap<>();
// 添加一个子结点
void addSubNode(Character key, TrieNode node) {
subNodes.put(key, node);
}
// 根据key获取子结点
TrieNode getSubNode(Character key) {
return subNodes.get(key);
}
}
```
后台从敏感词文件 SensitiveWords.txt 顺序读取每一行建立前缀树。进行过滤时,遍历需要过滤的文本,用星号替换发现的敏感词。假设文本长度为 len,前缀树的最大高度为 h,那么此算法的最坏时间复杂度为 O(len*h)。
> **算法比较**
假如敏感词平均长度为 10,数量为 100000,文本长度为 len。
常规方式,复杂度 O(100000 _ (len + 10));前缀树算法复杂度 O(10 _ len)。
对于**评论功能**,系统建立的是一个统一的评论服务中心,通过 EntityType 与 EntityId 识别所评论的实体。用户对于问题/评论的回复,都可以应用此服务。查询某实体下的评论时,同样根据 EntityType 和 EntityId 查询即可。
### 用户内容赞踩
赞踩功能采用「Redis」作为数据存储。Why Redis?
比较一下 Redis 和 MySQL:
- Redis: key-value 数据库,数据放在内存
- MySQL: 关系型数据库,数据放在磁盘
Redis 适合放一些频繁使用、比较热的数据。因为数据放在了内存中,读写性能卓越。
| Redis 类型 | 数据结构 | 应用场景 |
| --- | --- | --- |
| List | 双向列表 | 最新列表、关注列表 |
| Set | 无序集合 | 赞踩、抽奖、已读、共同好友 |
| SortedSet | 优先队列 | 排行榜 |
| Hash | 哈希表 | 不定长属性数 |
| KV | 单一数值 | 验证码、PV、缓存 |
除了用户内容赞踩,在本项目中,Redis 还应用于以下场景:
- 异步事件处理
- 关注服务
- Timeline
本小节讨论用户内容赞踩服务。
用户对某一实体点赞,会将"LIKE:ENTITY_TYPE:ENTITY_ID"作为 key ,用户 id 作为 value ,存入 like 集合中。同时移除 unlike 集合中该 key 对应的用户 id。点踩服务反之。
最后将点赞数响应给页面。
### 异步事件处理
本项目涉及到多种异步事件的处理。如:
- 用户评论了某个问题
- 用户点赞了某条评论
- 用户关注了另一个实体
这些动作并不是单一的,它们会触发一些后续的操作:
> 用户评论了某个问题,系统除了处理“评论”这个动作外,还需要给该问题对应的用户发送一条消息,通知说“xx 评论你的问题”,或者还需要给用户增加积分/经验...
事件触发者并不关心这些后续的任务,系统处理完某个动作后就可以将结果返回给触发者,而后续的任务交给系统进行异步处理即可。
因此,设计一个异步事件处理框架尤为重要。
本项目的异步框架如下图所示:
![d4ada309c2712f7b6c597cb254ba8541.png](https://cdn.nlark.com/yuque/0/2024/png/2469055/1711415047816-109bcc75-8171-445e-b3ea-b5d639a9ac3c.png#averageHue=%23f8f8f8&clientId=ub7e1a545-8195-4&from=paste&height=257&id=ud0f7cb9b&originHeight=321&originWidth=1002&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=76542&status=done&style=none&taskId=u8e65d781-d1bf-4733-ab2d-38566a1645d&title=&width=801.6)
业务触发一个异步事件,EventProducer 将该事件(EventModel)序列化并存入队列(Redis List)中,EventConsumer 开启线程循环从队列中取出事件,识别该事件的类型,找出该类型对应的一系列 EventHandler,交由这些 Handler 去处理。
**EventModel** 的设计如下:
```java
class EventModel {
// 事件类型
EventType type;
// 事件触发者
int actorId;
// 事件对应的实体
int entityType;
int entityId;
// 事件对应的实体的Owner
int entityOwnerId;
// 一些扩展字段
Map<String, String> exts;
}
```
### SNS 关注服务
与评论功能类似,对于关注功能,系统同样建立了一个统一的关注服务中心,用户可以关注不同的实体(问题/用户),只需要通过 EntityType 和 EntityId 识别即可。
在数据存储方面,采用 Redis 的 zset 完成,原因有以下几个:
- zset 有序,系统可以根据用户关注实体的时间倒序排列,获取最新的关注列表;
- zset 去重,用户不能重复关注同一个实体;
- zset 可以获取两用户之间的共同关注。
一个用户,系统存储两个集合:
① 保存用户关注的实体;② 保存关注用户的人。
即 A 是 B 的粉丝,B 是 A 的关注对象。
用户关注了一个问题,需要发生两个动作:
- 将问题存入 ① 中
- 在 ② 中存入用户 id
这两个动作必须同时发生,因此,这里用到了 Redis 事务保证�
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
基于Java(Spring Boot) + MySQL 实现的问答网站【100010424】 (178个子文件)
mvnw.cmd 5KB
letter.css 430KB
index.css 311KB
result.css 302KB
detail.css 299KB
bootstrap.min.css 111KB
login.css 63KB
spinner2.8f60205d.gif 1KB
index.html 11KB
header.html 11KB
profile.html 8KB
feeds.html 7KB
popup.html 7KB
detail.html 7KB
index1.html 6KB
recommend.html 6KB
result.html 5KB
sort1显示more.html 4KB
followees.html 3KB
followers.html 3KB
login.html 3KB
sort.html 2KB
letter.html 2KB
测试.html 1KB
letterDetail.html 1KB
js.html 852B
wrl.html 210B
hello.html 144B
footer.html 14B
maven-wrapper.jar 46KB
WLRController.java 11KB
FollowController.java 10KB
weightedLeaderRank.java 7KB
JedisTest.java 7KB
JedisAdapter.java 7KB
SearchController.java 6KB
FollowServiceImpl.java 6KB
CrawlServiceImpl.java 6KB
MessageController.java 6KB
SensitiveServiceImpl.java 6KB
QuestionController.java 5KB
IndexController.java 5KB
LoginController.java 5KB
EventConsumer.java 5KB
UserServiceImpl.java 4KB
SearchServiceImpl.java 4KB
QaUtil.java 4KB
CommentController.java 4KB
FeedHandler.java 3KB
PassportInterceptor.java 3KB
MessageDAO.java 3KB
FeedController.java 3KB
RecommendController.java 3KB
CommentDAO.java 3KB
LikeServiceImpl.java 3KB
LikeController.java 3KB
AvatarGenerator.java 2KB
QuestionDAO.java 2KB
FollowService.java 2KB
EventModel.java 2KB
FollowHandler.java 2KB
RedisKeyUtil.java 2KB
JedisPoolUtil.java 2KB
CrawlController.java 2KB
Message.java 2KB
CommonResp.java 1KB
LikeHandler.java 1KB
AddCommentHandler.java 1KB
MessageServiceImpl.java 1KB
Question.java 1KB
Feed.java 1KB
LoginRequiredInterceptor.java 1KB
Comment.java 1KB
SearchService.java 1KB
UserDAO.java 1KB
CommentServiceImpl.java 1KB
QuestionServiceImpl.java 1KB
FeedDAO.java 1KB
AddQuestionHandler.java 1KB
QaWebConfiguration.java 1KB
FeedServiceImpl.java 1KB
MessageService.java 1KB
TopUserDAO.java 946B
EventProducer.java 914B
LoginTicket.java 908B
User.java 887B
CommentService.java 838B
CrawlTask.java 807B
QuestionService.java 800B
UserService.java 795B
LoginTicketDAO.java 790B
AuthUserDAO.java 788B
LikeService.java 776B
RequestUtil.java 755B
EntityType.java 744B
AuthUserServiceImpl.java 733B
HostHolder.java 708B
ceshiController.java 562B
CommonRespConst.java 538B
FeedService.java 530B
共 178 条
- 1
- 2
资源评论
神仙别闹
- 粉丝: 2679
- 资源: 7667
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功