5.11发送系统通知

定义对象,封装事件发生时候的一切信息。

1.在entity下新建 event事件,以封装事件对象

package com.nowcoder.community.entity;

import java.util.HashMap;
import java.util.Map;

public class Event {

    private String topic;//事件类型
    private int userId;//事件触发的人
    private int entityType;//记录实体类型 点赞,回复,还是关注
    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;
    }

}

2.开发事件的消费者

新建event包,在该包下新建EventProducer

package com.nowcoder.community.event;

import com.alibaba.fastjson.JSONObject;
import com.nowcoder.community.entity.Event;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

@Component
public class EventProducer {

    @Autowired
    private KafkaTemplate kafkaTemplate;

    // 处理事件
    public void fireEvent(Event event) {
        // 将事件发布到指定的主题
        kafkaTemplate.send(event.getTopic(), JSONObject.toJSONString(event));//消息的内容是JSON 字符串
    }

}

3有了生产者再去开发消费者

新建EventConsumer类
先在CommunityConstant 中新建几个主题常量
在这里插入图片描述
在这里插入图片描述

package com.nowcoder.community.event;

import com.alibaba.fastjson.JSONObject;
import com.nowcoder.community.entity.Event;
import com.nowcoder.community.entity.Message;
import com.nowcoder.community.service.MessageService;
import com.nowcoder.community.util.CommunityConstant;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class EventConsumer implements CommunityConstant {

    private static final Logger logger = LoggerFactory.getLogger(EventConsumer.class);//记录日志的组件

    @Autowired
    private MessageService messageService;

    @KafkaListener(topics = {TOPIC_COMMENT, TOPIC_LIKE, TOPIC_FOLLOW})//要消费这三个主题
    public void handleCommentMessage(ConsumerRecord record) {
        if (record == null || record.value() == null) {
            logger.error("消息的内容为空!");//记录日志
            return;
        }

        Event event = JSONObject.parseObject(record.value().toString(), Event.class);//将消息的内容(json字符串) 恢复成 消息字符串
        if (event == null) {
            logger.error("消息格式错误!");//有值,但是没有还原成功
            return;
        }

        // 发送站内通知,构造message数据,发送到message表里
        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());
        //这个content就是

        if (!event.getData().isEmpty()) {//判断事件对象中map有无值,event不为空,则将其中所有数据存到content字段中。
            for (Map.Entry<String, Object> entry : event.getData().entrySet()) {
                content.put(entry.getKey(), entry.getValue());
            }
        }

        message.setContent(JSONObject.toJSONString(content));//该JSON字符串是拼 这句话的各种条件
        messageService.addMessage(message);
    }
}

通知的形式特别相近,因此逻辑相近:
在这里插入图片描述
content就是如下这句话:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在评论、点赞、关注之后调用

在CommentController中

@Autowired
private EventProducer eventProducer;

在addComment后添加:

     // 触发评论事件
        Event event = new Event()//构造事件对象,把事件包含的内容包含进来。
                .setTopic(TOPIC_COMMENT)
                .setUserId(hostHolder.getUser().getId())//当前登录的人
                .setEntityType(comment.getEntityType())
                .setEntityId(comment.getEntityId())
                .setData("postId", discussPostId);//传一个帖子id,以连接到地址

        //实体的作者
        if (comment.getEntityType() == ENTITY_TYPE_POST) { //如果是帖子,查帖子表
            DiscussPost target = discussPostService.findDiscussPostById(comment.getEntityId());//评论的目标
            event.setEntityUserId(target.getUserId());
        } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { //如果是评论
            Comment target = commentService.findCommentById(comment.getEntityId());//评论的实体 便是目标
            event.setEntityUserId(target.getUserId());
        }
        eventProducer.fireEvent(event);

        return "redirect:/discuss/detail/" + discussPostId;

在commentMapper中添加:
在这里插入图片描述
在这里插入图片描述
在commentService中添加:
在这里插入图片描述

在LikeController中添加

    // 触发点赞事件
    if (likeStatus == 1) {//只有点赞的时候触发系统通知,取消点赞不会触发。满足if则是点赞
        Event event = new Event()
                .setTopic(TOPIC_LIKE)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(entityType)
                .setEntityId(entityId)
                .setEntityUserId(entityUserId)
                .setData("postId", postId);
        eventProducer.fireEvent(event);
    }

    return CommunityUtil.getJSONString(0, null, map);
}

在FollowController添加:

   // 触发关注事件
    Event event = new Event()
            .setTopic(TOPIC_FOLLOW)
            .setUserId(hostHolder.getUser().getId())
            .setEntityType(entityType)
            .setEntityId(entityId)
            .setEntityUserId(entityId);
    eventProducer.fireEvent(event);

    return CommunityUtil.getJSONString(0, "已关注!");
}

在这里插入图片描述
所以最后链接到某人的主页上,张三关注了我,那么最后链接到张三的主页上

在discuss-detail.html中

测试:

对某帖子评论:
在这里插入图片描述
然后查询message表格:
在这里插入图片描述
点赞后接着看:
在这里插入图片描述
在这里插入图片描述
接着点赞:
在这里插入图片描述
在这里插入图片描述
只不过类型不一样:
在这里插入图片描述
进行关注:
在这里插入图片描述
表里的数据:
在这里插入图片描述

附:message表格式如下:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值