1. 帖子模块
分为 过滤敏感词,发布帖子,帖子详情,显示评论,添加评论,私信列表,发送私信。
1.1 过滤敏感词
位于 util 包下的 SensitiveFilter 。 略
1.2 发布帖子
使用 Ajax 在 index 页面发送异步请求(局部刷新)。在 Controller 层返回 Json 数据显示。
- 前提用户已经登录,否则不显示 “我要发布” 按钮。(通过hostHolder中的 loginUser 是否为空判断)
- 在首页点击 “我要发布”,填写标题和正文,映射到DiscussPostController(/discuss)层的 /add 路径。新建 DiscussPost 类,通过 hostHolder 的 User 设置 id,设置 title,content,createTime。其余默认为0。使用 discussPostService.addDiscussPost(post) 方法将其插入数据库。
- discussPostService.addDiscussPost 方法将post 中的 title,content 转义HTML标记和过滤敏感词。然后调用 discussPostMapper.insertDiscussPost(post) 存入数据。
// 转义HTML标记
post.setTitle(HtmlUtils.htmlEscape(post.getTitle()));
post.setContent(HtmlUtils.htmlEscape(post.getContent()));
// 过滤敏感词
post.setTitle(sensitiveFilter.filter(post.getTitle()));
post.setContent(sensitiveFilter.filter(post.getContent()));
- 触发发帖事件,构造 Topic 为 TOPIC_PUBLISH 的 Event,需要设置userId,EntityType,EntityId。然后使用 eventProducer.fireEvent 开始生产。(更新Elasticsearch 服务器中的帖子)
- 返回发布成功 Json 信息,异步显示,并刷新网页。
$(function(){
$("#publishBtn").click(publish);
});
function publish() {
$("#publishModal").modal("hide");
// 获取标题和内容
var title = $("#recipient-name").val();
var content = $("#message-text").val();
// 发送异步请求(POST)
$.post(
CONTEXT_PATH + "/discuss/add",
{"title":title,"content":content},
function(data) {
data = $.parseJSON(data);
// 在提示框中显示返回消息
$("#hintBody").text(data.msg);
// 显示提示框
$("#hintModal").modal("show");
// 2秒后,自动隐藏提示框
setTimeout(function(){
$("#hintModal").modal("hide");
// 刷新页面
if(data.code == 0) {
window.location.reload();
}
}, 2000);
}
);
}
1.3 帖子详情
- 在 index 页面点击帖子,映射到DiscussPostController(/discuss)层的 /detail/{discussPostId} 路径,并将帖子的 id 传入。
- 根据 id 利用 discussPostService.findDiscussPostById 方法查出 post。 根据 post.getUserId() 利用 userService.findUserById 方法查出 User。将 post,user 加入model。
- 新增:将点赞数量和状态查询处理加入model。
- 返回 /site/discuss-detail 页面。在 /site/discuss-detail 页面显示帖子和发布帖子的用户信息。
1.4 显示评论
继1.3 帖子详情后显示帖子的评论。同样在 DiscussPostController(/discuss)层的 /detail/{discussPostId} 映射中。我们将 comment 表中的 entity_type 属性在 CommunityConstant 工具类中设置了两个常量:
// 实体类型: 帖子
int ENTITY_TYPE_POST = 1;
// 实体类型: 评论
int ENTITY_TYPE_COMMENT = 2;
- 首先设置评论分页信息。
- 根据该帖子的 id 和类型利用 commentService.findCommentsByEntity 方法查询所有评论。将该评论和该评论的作者(通过 comment 中的 userId 获取),点赞数量和该用户的点赞状态加入到Map中,同时还在该Map中嵌套插入一个包括该评论的所有回复,回复作者和回复目标(target),点赞数量和该用户的点赞状态的Map。再将回复数量插入Map。最后将每个评论的Map插入List,传入Model。
- 最后返回 /site/discuss-detail 页面。在页面中展示,其中分页模块复用 index::pagination。
1.5 添加评论
添加评论有三种方式:① 回帖,② 回复评论,③ 回复某人的评论。
- ① 在 discuss-detail 页面点击最下方的回帖,映射到 CommentController 层的 /add/{discussPostId}。传入了 entityType = 1 和 entityId = post.id 。
- ② 在评论下方回复,与①映射相同,传入entityType = 2 和 entityId = comment.id。
- ③ 对某人的评论回复,与①映射相同,传入entityType = 2 和 entityId = comment.id 和 targetId。
- 对传入的 comment 进一步设置userId,Status,CreateTime。然后调用commentService.addComment(comment) 方法插入数据库。
- commentService.addComment 使用了事务注解。该方法对 comment 的 content 进行转义HTML标记和过滤敏感词。然后使用 commentMapper.insertComment 插入评论。然后通过 commentMapper.selectCountByEntity 查询帖子的评论数量,再使用 discussPostService.updateCommentCount 方法将评论数量插入帖子详情表。
// 更新帖子评论数量
if (comment.getEntityType() == ENTITY_TYPE_POST) {
int count = commentMapper.selectCountByEntity(comment.getEntityType(), comment.getEntityId());
discussPostService.updateCommentCount(comment.getEntityId(), count);
}
- 触发 Topic 为 TOPIC_COMMENT 的事件: 构建Event,设置当前登录用户id,被评论对象的type,被评论对象的id,被评论对象所在的帖子id(因为被评论的对象可能是帖子或者回复),被评论对象的用户id。然后调用 eventProducer 将 Event 发布到指定 Topic。
- 然后判断一下评论的是不是帖子,如果是则触发发帖事件。构造 Topic 为 TOPIC_PUBLISH 的 Event,需要设置userId,EntityType,EntityId。然后使用 eventProducer.fireEvent 开始生产。(更新Elasticsearch 服务器中的帖子)
- 重定向 return “redirect:/discuss/detail/” + discussPostId。 刷新帖子详情页面。
1.6 私信列表
两部分:① 点击消息进入会话列表,②点击某个会话进入私信详情页面。
-
在 index 点击消息,映射到 MessageController 层的 /letter/list 下。设置分页信息。
-
通过 messageService.findConversations 查询当前用户的会话列表, 针对每个会话只返回一条最新的私信。将每个会话装入Map, 并且使用 messageService.findLetterCount(message.getConversationId())) 方法查询会话的私信数量并装入Map。将会话的未读私信数量查出装入Map,并且将与用户对话的对方 User 装入Map。
-
把Map依次装入List,List装入Model。再将所有的未读消息数量查询出,装入Model,返回 /site/letter 。在页面中显示。
-
在私信列表点击私信内容,进入私信详情页面。映射到 MessageController 层的 /letter/detail/{conversationId}。设置分页信息。
-
通过 messageService.findLetters 方法返回与对方的全部私信。将私信和发送私信的用户 User 装入Map。将多个Map装入List。将List装入Model。将与当前用户对话的对方User装入Model。
-
放回 /site/letter-detail 页面,将数据在页面中显示。
1.7 发送私信
分为两部分:
一、① 在消息页面发私信 ,② 在与某人会话中给TA发私信。
二、将未读消息转为已读。(其实应该放置在 1.6 私信列表 )
- 在弹出框中填写发送对象和内容,点击发送。利用 letter.js 发送ajax异步请求。映射到 MessageController 层的 /letter/send 下。构造 message 对象,包括通过发送对象名称查询对象id,拼接 ConversationId。最后将 message 传递给 messageService.addMessage 方法。
- messageService.addMessage 方法将message 中的 content 进行转义HTML标记和过滤敏感词。然后插入数据库。MessageController 层中如果发送对象为空,返回 json 错误信息。否则返回 code=0。
- letter.js 接受到返回数据,显示信息并重新加载当前页面。②与① 功能实现都是调用的 letter.js。只不过在 ② 中弹出框中自动填入了发送对象名称。
- 接受私信的用户在打开私信详情页面时,未读消息就应该变成已读。在 MessageController 层的 /letter/detail/{conversationId} 路径下实现该功能。将私信列表传给 getLetterIds 函数,获得 id 列表。使用 messageService.readMessage 方法将 id 列表代表的 message 的 status 改为1。