• 仿牛客网项目---消息队列的实现


    本篇文章讲一讲我们的项目中用到的消息队列。

     

    1.阻塞队列

    2.kafka

    我的项目为什么要用消息队列?

    如果采用消息队列,那么评论、点赞、关注三类不同的事,可以定义三类不同的主题(评论、点赞、关注),发生相应的事件可以将其包装成一条消息放入对应的队列里。那么当前的线程可以继续处理下一条消息,不用处理后续的业务(后续由消费者线程处理)。面向事件驱动编程。

    3.发布系统通知

    下面讲讲怎么发布系统通知。

    在entity包下创建event类:

    1. public class Event {
    2. private String topic; //表示事件的主题的字符串
    3. private int userId; //表示与事件相关的用户的ID
    4. private int entityType; //表示与事件相关的实体类型
    5. private int entityId; //表示与事件相关的实体的ID
    6. private int entityUserId; //表示与实体相关的用户的ID
    7. private Map data = new HashMap<>(); //一个Map对象,用于存储与事件相关的附加数据
    8. //省略了很多get()方法和set()方法
    9. }

    通过使用这个Event类,我就可以创建一个事件对象,并设置事件的主题、用户ID、实体类型、实体ID、实体用户ID以及其他相关的附加数据。

    接着在在community的event目录下创建EventProducer、EventCnsumer类。

    1. @Component
    2. public class EventProducer {
    3. @Autowired
    4. private KafkaTemplate kafkaTemplate;
    5. // 处理事件
    6. public void fireEvent(Event event) {
    7. // 将事件发布到指定的主题
    8. kafkaTemplate.send(event.getTopic(), JSONObject.toJSONString(event));
    9. }
    10. }

    通过调用fireEvent方法,我们就可以将一个事件对象发送到Kafka消息队列中的指定主题。这样,消费者可以从该主题订阅事件,并对事件进行相应的处理逻辑。

    1. @Component
    2. public class EventConsumer implements CommunityConstant {
    3. private static final Logger logger = LoggerFactory.getLogger(EventConsumer.class);
    4. @Autowired
    5. private MessageService messageService;
    6. @KafkaListener(topics = {TOPIC_COMMENT, TOPIC_LIKE, TOPIC_FOLLOW})
    7. public void handleCommentMessage(ConsumerRecord record) {
    8. if (record == null || record.value() == null) {
    9. logger.error("消息的内容为空!");
    10. return;
    11. }
    12. Event event = JSONObject.parseObject(record.value().toString(), Event.class);
    13. if (event == null) {
    14. logger.error("消息格式错误!");
    15. return;
    16. }
    17. // 发送站内通知
    18. Message message = new Message();
    19. message.setFromId(SYSTEM_USER_ID);
    20. message.setToId(event.getEntityUserId());
    21. message.setConversationId(event.getTopic());
    22. message.setCreateTime(new Date());
    23. Map content = new HashMap<>();
    24. content.put("userId", event.getUserId());
    25. content.put("entityType", event.getEntityType());
    26. content.put("entityId", event.getEntityId());
    27. if (!event.getData().isEmpty()) {
    28. for (Map.Entry entry : event.getData().entrySet()) {
    29. content.put(entry.getKey(), entry.getValue());
    30. }
    31. }
    32. message.setContent(JSONObject.toJSONString(content));
    33. messageService.addMessage(message);
    34. }
    35. }

    handleCommentMessage方法中,首先检查接收到的消息是否为空,然后将消息内容解析为Event对象。如果解析失败,会记录错误并返回。

    接下来,根据接收到的事件信息,构建一个站内通知的Message对象。设置发送者ID为系统用户ID,接收者ID为事件关联的实体用户ID,会话ID为事件主题,创建时间为当前时间。

    然后,构建一个存储事件相关信息的content映射。

    最后,将content转换为JSON字符串,并将其设置为站内通知的内容。

    说了一堆乱七八糟的,反正就是这段代码提供了一个事件消费者类,用于订阅和处理从Kafka消息队列中接收到的指定事件主题的消息。它可以根据事件的类型执行相应的处理操作,例如发送站内通知等。

    在评论、点赞、关注视图层增加方法。

    CommentController。LikeController。Followcontroller。

    4.显示系统通知

    消息未读使用拦截器实现,因为每个请求都需要记录次数。

    1. @Component
    2. public class MessageInterceptor implements HandlerInterceptor {
    3. @Autowired
    4. private HostHolder hostHolder;
    5. @Autowired
    6. private MessageService messageService;
    7. @Override
    8. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    9. User user = hostHolder.getUser();
    10. if (user != null && modelAndView != null) {
    11. int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null);
    12. int noticeUnreadCount = messageService.findNoticeUnreadCount(user.getId(), null);
    13. modelAndView.addObject("allUnreadCount", letterUnreadCount + noticeUnreadCount);
    14. }
    15. }
    16. }

    上面的这段代码提供了一个消息拦截器类,用于在请求处理完成后,对返回的ModelAndView对象进行拦截和处理,以实现消息的统计和展示功能。

  • 相关阅读:
    C++ 学习 ::【基础篇:05】:C++ 函数重载认识及使用、简单介绍:C++ 支持函数重载的原因
    2、24 个常见的 Docker 疑难杂症处理技巧(二)
    LeetCode_266_回文排列
    万物数创CTO黄一:别人批判我的代码是件有趣的事 | 对话MVP
    【英语:基础进阶_听口实战运用】D5.听力对话训练
    soapui
    Python中的函数式编程是什么?
    数据库系统原理与应用教程(063)—— MySQL 练习题:操作题 39-50(七)
    C# WPF入门学习主线篇(七)—— Label常见属性和事件
    ISCSLP 2022 | AccentSpeech—从众包数据中学习口音来构建目标说话人的口音语音合成系统
  • 原文地址:https://blog.csdn.net/qq_54432917/article/details/136543947