仿牛客网社区项目(二十七)发送系统通知
触发事件
- 触发事件
- 评论后,发布通知
- 点赞后,发布通知
- 关注后,发布通知
- 处理事件
- 封装事件对象
- 开发事件的生产者
- 开发事件的消费者
- 创建对象实体
public class Event {
//事件类型
private String topic;
//消息发送方Id,1为管理消息
private int userId;
//实体类型,点赞,评论,关注
private int entityType;
//对应的实体id
private int entityId;
//接收方Id
private int entityUserId;
private Map<String, Object> data = new HashMap<>();
public String getTopic() {
return topic;
}
//链式编程
public Event setTopic(String topic) {
this.topic = topic;
return this;
}
public int getUserId() {
return userId;
}
public Event setUserId(int userId) {
this.userId = userId;
return this;
}
public int getEntityType() {
return entityType;
}
public Event setEntityType(int entityType) {
this.entityType = entityType;
return this;
}
public int getEntityId() {
return entityId;
}
public Event setEntityId(int entityId) {
this.entityId = entityId;
return this;
}
public int getEntityUserId() {
return entityUserId;
}
public Event setEntityUserId(int entityUserId) {
this.entityUserId = entityUserId;
return this;
}
public Map<String, Object> getData() {
return data;
}
public Event setData(String key, Object value) {
this.data.put(key, value);
return this;
}
}
- 创建生产者,也就是队列消息的发送端
@Component
public class EventProduce {
@Autowired
private RabbitTemplate rabbitTemplate;
//传递User对象将其转换为Json,接收方再转回object,使用序列号也可以,自行尝试
public void send(Event event){
rabbitTemplate.convertAndSend("X",event.getTopic(), JSONObject.toJSONString(event));
}
}
- 创建消费者,也就是消息的处理者
@Slf4j
@Component
public class EventConsumer implements CommunityConstant {
@Autowired
private MessageService messageService;
//三种类型消息,分别处理
//follow队列
@RabbitListener(queues = "QA")
public void receiveLike(String jsonString, Channel channel){
if( jsonString==null||jsonString.length()==0){
log.error("消息为空");
}
Event event = JSONObject.parseObject(jsonString, Event.class);
if (event==null){
log.error("类型转换失败");
}
sendMessage(event);
}
//comment队列
@RabbitListener(queues = "QB")
public void receiveComment(String jsonString, Channel channel){
if( jsonString==null||jsonString.length()==0){
log.error("消息为空");
}
Event event = JSONObject.parseObject(jsonString, Event.class);
if (event==null){
log.error("类型转换失败");
}
sendMessage(event);
}
//like 队列
@RabbitListener(queues = "QC")
public void receiveFollow(String jsonString, Channel channel){
if( jsonString==null||jsonString.length()==0){
log.error("消息为空");
}
Event event = JSONObject.parseObject(jsonString, Event.class);
if (event==null){
log.error("类型转换失败");
}
sendMessage(event);
}
public void sendMessage(Event event){
// 发送站内通知
Message message = new Message();
message.setFromId(SYSTEM_USER_ID);
message.setToId(event.getEntityUserId());
message.setConversationId(event.getTopic());
message.setCreateTime(new Date());
Map<String, Object> content = new HashMap<>();
content.put("userId", event.getUserId());
content.put("entityType", event.getEntityType());
content.put("entityId", event.getEntityId());
if (!event.getData().isEmpty()) {
for (Map.Entry<String, Object> entry : event.getData().entrySet()) {
content.put(entry.getKey(), entry.getValue());
}
}
message.setContent(JSONObject.toJSONString(content));
messageService.addMessage(message);
}
- 更新一些静态变量在CommunityConstant中
/**
* 主题: 评论
*/
String TOPIC_COMMENT = "comment";
/**
* 主题: 点赞
*/
String TOPIC_LIKE = "like";
/**
* 主题: 关注
*/
String TOPIC_FOLLOW = "follow";
1.CommentController 更新Controller层,我们要对关注、点赞、评论 三个业务层去修改方法,在其中增加事件
```java
@RequestMapping(path = "/add/{discussPostId}", method = RequestMethod.POST)
public String addComment(@PathVariable("discussPostId") int discussPostId, Comment comment) {
comment.setUserId(hostHolder.getUser().getId());
comment.setStatus(0);
comment.setCreateTime(new Date());
commentService.addComment(comment);
// 触发评论事件
Event event = new Event()
.setTopic(TOPIC_COMMENT)
.setUserId(hostHolder.getUser().getId())
.setEntityType(comment.getEntityType())
.setEntityId(comment.getEntityId())
.setData("postId", discussPostId);
if (comment.getEntityType() == ENTITY_TYPE_POST) {
DiscussPost target = discussPostService.getDiscussPostById(comment.getEntityId());
event.setEntityUserId(target.getUserId());
} else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) {
Comment target = commentService.findCommentById(comment.getEntityId());
event.setEntityUserId(target.getUserId());
}
eventProduce.send(event);
return "redirect:/discuss/detail/" + discussPostId;
}
```
2.LikeController
@RequestMapping(path = "/like", method = RequestMethod.POST)
@ResponseBody
//此处未限制未登录点赞,会抛异常 可以采用之前的全局异常注解,后期会对代码重构 增加SpringSecurity框架权限控制
public String like(int entityType, int entityId, int entityUserId,int postId) {
User user = hostHolder.getUser();
// 点赞
likeService.like(user.getId(), entityType, entityId, entityUserId);
// 数量
long likeCount = likeService.findEntityLikeCount(entityType, entityId);
// 状态
int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId);
// 返回的结果
Map<String, Object> map = new HashMap<>();
map.put("likeCount", likeCount);
map.put("likeStatus", likeStatus);
// 触发点赞事件
if (likeStatus == 1) {
Event event = new Event()
.setTopic(TOPIC_LIKE)
.setUserId(hostHolder.getUser().getId())
.setEntityType(entityType)
.setEntityId(entityId)
.setEntityUserId(entityUserId)
.setData("postId", postId);
eventProduce.send(event);
}
return CommunityUtil.getJSONString(0, null, map);
}
3.FollowController
@RequestMapping(path = "/follow", method = RequestMethod.POST)
@ResponseBody
public String follow(int entityType, int entityId) {
User user = hostHolder.getUser();
followService.follow(user.getId(), entityType, entityId);
// 触发关注事件
Event event = new Event()
.setTopic(TOPIC_FOLLOW)
.setUserId(hostHolder.getUser().getId())
.setEntityType(entityType)
.setEntityId(entityId)
.setEntityUserId(entityId);
eventProduce.send(event);
return CommunityUtil.getJSONString(0, "已关注!");
}
-
由于like事件触发时是对帖子,所以缺少一个PostId,所以我们在前端传参时需要传入PostId,在页面添加一下即可,js也要修改噢
以后的笔记中就不更新静态资源类 ,自取即可,写出来意义不大,浪费时间
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署