项目系统通知模块的设计

在互联网项目中,系统通知模块是必备的。主要功能是将系统的通知消息发送给用户,在不同项目中系统通知模块的实现也多有不同,以下我来举几个例子说明,不同项目下不同系统通知功能的实现。

1.前端pull类型:在一些对消息实时性要求不高的项目中,例如toB项目,系统通知中不涉及私信等用户间通信功能,主要是系统端向用户推送数据,此时对消息的实时性的要求并不高,我们可以让前端设置一个定时任务,按时向服务端发送请求来拉取消息通知。这样对于系统设计是最为简单的,当然占用资源也是最大的。

2.后端push类型,对于一些对于消息实时性要求搞的项目中,类似于IM场景,我们可以通过类似webSocket的双向通信协议,由后端向前端主动推送消息,使得消息实时性高,不会过多占用网络IO资源。当然这样对与系统的设计会出现更多挑战。

在Love中我使用的是pull+hold综合实现系统通知功能。主要借鉴WebQQ中系统通知的设计。前端像后端发起拉取通知的请求。后端不立即返回结果,而是将这个请求hold住,在此期间有消息推送的时候就会异步的将结果返回,这样能极大的减少网络IO资源的开销。这个方案中我使用了Spring提供的ReferredResult类,将请求阻塞在服务端中,设置超时返回并异步监听通知队列中的消息。

下面我来具体展示代码

  1. 拉取消息Controller层

new出一个DeferredResult对象,设置超时时间后返回暂无消息通知的response,将这个DeferredResult缓存到本地。

@Override
public DeferredResult<Result<?>> pullNotify(Long userId, PullNotifyRequest pullNotifyRequest, Long timeOut) {
    //使用DeferredResult来执行异步操作
    DeferredResult<Result<?>> deferredResult = new DeferredResult<>(timeOut);
    //超时情况下
    deferredResult.onTimeout(()->{
        //从MAP中删除
        userNotifyDeferredCache.remove(userId);
        Result result = new Result();
        result.setCode(206);
        result.setMsg("暂无新消息通知");
        deferredResult.setResult(result);
    });
    userNotifyDeferredCache.save(userId,deferredResult::setResult);
    return deferredResult;
}
  1. 发送系统消息类

这个类主要就是将消息发送到redis消息队列中。//TODO:使用Redis Stream消息队列来代替。在这里我简单的使用Redis List数据结构来做消息队列,使用一个监听器来监听这个消息队列

@Component
@RequiredArgsConstructor
@AutoConfiguration
public class UserNotifyProduction {

    private final StringRedisTemplate redisTemplate;

    /**
     * 系统通知消息生产者
     * @param noticeDTO
     */
    public void sendNotifyMessage(NoticeDTO noticeDTO){
        //判断一下目标用户是不是在线
//        Long userId = noticeDTO.getUserId();
//        if (userNotifyDeferredCache.isExist(userId)){
            redisTemplate.opsForList().rightPush(UserNotifyConstants.USER_NOTIFY_QUEUE, JSON.toJSONString(noticeDTO));
//        }else {
//            //存入数据库中
//            redisTemplate.opsForList().rightPush(UserNotifyConstants.USER_NOTIFY_TO_DB_QUEUE,JSON.toJSONString(noticeDTO));
//        }
    }
}
  1. 系统通知消息队列:系统每100ms到消息队列中拉取一次消息,得到消息后判断消息userId在DeferredResult的缓存中是否可以取到,如果可以取到则说明是在线用户可以直接将消息返回。如果取不到则存入数据库中,等待用户下次登入后则一并拉取所有目标通知数据。
package blossom.project.towelove.server.redisMQ;

import blossom.project.towelove.common.entity.notification.NoticeDTO;
import blossom.project.towelove.framework.redis.core.UserNotifyConstants;
import blossom.project.towelove.server.entity.Notice;
import blossom.project.towelove.server.mapper.NoticeMapper;
import blossom.project.towelove.server.service.impl.NotificationServiceImpl;
import com.alibaba.fastjson2.JSON;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.*;

/**
 * @projectName: Towelove
 * @package: blossom.project.towelove.server.redisMQ
 * @className: RedisListener
 * @author: Link Ji
 * @description: GOGO
 * @date: 2024/1/19 18:38
 * @version: 1.0
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class RedisListener implements InitializingBean {

    @Getter
    private final StringRedisTemplate redisTemplate;

    private final NotificationServiceImpl notificationService;

    private final NoticeMapper noticeMapper;

    private final UserNotifyDeferredCache userNotifyDeferredCache;

    ScheduledExecutorService scheduler =  Executors.newScheduledThreadPool(1, r -> new Thread(r,"notifyListener"));

    @Override
    public void afterPropertiesSet() {
        /**
         * 100毫秒到队列中读取一次
         */
        scheduler.scheduleAtFixedRate(() ->{
            String message = redisTemplate.opsForList().leftPop(UserNotifyConstants.USER_NOTIFY_QUEUE);
            NoticeDTO noticeDTO = JSON.parseObject(message, NoticeDTO.class);
            if (Objects.isNull(noticeDTO)) return;
            if (userNotifyDeferredCache.isExist(noticeDTO.getUserId())) {
                log.info("用户:{}在线收到一条通知消息:{}",noticeDTO.getUserId(),noticeDTO.getContent());
                notificationService.setDeferredResult(noticeDTO.getUserId(), noticeDTO.getContent());
            }else{
                log.info("用户:{}离线收到一条通知消息:{}",noticeDTO.getUserId(),noticeDTO.getContent());
                //存入DB中
                Notice notice = new Notice();
                notice.setType(1);
                notice.setUserId(noticeDTO.getUserId());
                notice.setContent(noticeDTO.getContent());
                noticeMapper.insert(notice);
            }
        },5,100, TimeUnit.MILLISECONDS);

//        scheduler.scheduleAtFixedRate(() ->{
//            String message = redisTemplate.opsForList().leftPop(UserNotifyConstants.USER_NOTIFY_TO_DB_QUEUE);
//            NoticeDTO noticeDTO = JSON.parseObject(message, NoticeDTO.class);
//            if (Objects.nonNull(noticeDTO)){
//                log.info("用户:{}离线收到一条通知消息:{}",noticeDTO.getUserId(),noticeDTO.getContent());
//                //存入DB中
//                Notice notice = new Notice();
//                notice.setType(1);
//                notice.setUserId(noticeDTO.getUserId());
//                notice.setContent(noticeDTO.getContent());
//                noticeMapper.insert(notice);
            }
//        },5,100,TimeUnit.MILLISECONDS);
        log.info("notifyListener start successfully");
    }
}
  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Spring Boot是一种构建Java应用程序的框架,它提供了开发Java应用程序所需的所有基础设施和工具。MyBatis是一种流行的持久性框架,通过它,我们可以轻松地与关系数据库交互。Vue是一种流行的JavaScript框架,用于构建用户界面。 校园任务与通知管理系统是一个基于Java Web前后端分离的系统,可以管理学生的任务和校园通知系统使用Spring Boot和MyBatis框架进行后端开发,使用Vue框架进行前端开发。系统具有以下主要功能: 1. 学生可以登录系统并查看他们的任务和通知。 2. 学生可以将任务标记为已完成,并且可以设置任务的截止日期。 3. 管理员可以发布通知,并可以随时更新和删除通知。 4. 管理员可以分配任务给学生,并可以在任务上设置截止日期和重要性级别。 5. 管理员可以查看所有任务和通知,并可以从中过滤和搜索。 整个系统采用前后端分离的设计方案,使得前端和后端具有独立性和灵活性。前端通过Vue与后端通信,后端通过Spring Boot和MyBatis提供数据和服务,确保系统的高效性和安全性。 总之,Spring Boot,MyBatis和Vue是构建校园任务和通知管理系统所需的必要技术。 这些技术的组合可以为系统带来高效性,可靠性和易扩展性。 ### 回答2: Spring Boot是一个基于Spring框架的快速开发的Web应用程序框架,可以简化Java web应用程序的开发流程。MyBatis是一种ORM框架,提供了许多常见的功能,如事务管理、缓存、SQL映射、连接池和一系列插件。Vue是一种现代化的JavaScript框架,用于构建交互式Web UI。这三个框架的结合可以提高Web应用程序的性能和开发效率。 校园任务与通知管理系统使用Spring Boot和MyBatis作为后端,提供数据的处理和管理。Vue作为前端框架,实现用户界面和用户交互。该系统能够实现对校园任务和通知的管理、发布和查看。 该系统的后端主要包括用户管理、任务管理和通知管理三个部分。用户管理模块用于实现对用户信息的管理,包括用户的注册、登录和权限管理等功能。任务管理模块可以实现对校园任务的发布、分配、执行和查看。通知管理模块能够实现对校园通知的发布、发送和查看。 前端使用Vue来实现用户界面和用户交互,通过Ajax请求后台API获取数据,实现前后端分离。Vue的特点是轻量级、易于学习和使用,可以大大提高系统的用户体验。 综上所述,采用Spring Boot、MyBatis和Vue开发的校园任务与通知管理系统是一种性能强、开发效率高、用户体验好的Java Web前后端分离系统,能够实现对校园任务和通知的管理、发布和查看,对学生和教师的教学工作有很大的帮助。 ### 回答3: 校园任务与通知管理系统是一个用于校园中任务分配和通知发布的管理系统。该系统采用了springboot,mybatis和vue进行前后端分离的开发。 学生、教师和管理员都可以登录该系统。学生可以查看自己的任务分配和通知,也可以通过系统进行任务完成情况的反馈。教师可以发布任务和通知,并管理学生完成任务的情况。管理员可以进行用户管理、任务管理和通知管理等操作。 该系统的后端使用springboot进行开发,采用了mybatis进行数据库的操作,实现了高效的数据管理和查询。前端使用vue进行开发,实现了良好的用户交互体验。前后端使用restful接口进行通信,实现了数据的高效传输和交互。 总的来说,校园任务与通知管理系统是一款高效可靠的管理系统,为校园的任务分配和通知发布提供了有效的支持。该系统采用前后端分离的开发模式,结合了springboot、mybatis和vue的优势,具有较好的性能和用户体验。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LinkJii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值