『博客开发日记-后台』之全部已读通知接口的实现

本文最后更新于 2026年5月29日 晚上

全部已读通知接口的实现


全部已读通知接口的需求

先校验登录状态,如果是未登录返回需要登录

查询当前用户可见的已发布的通知

将通知在 sys_notice_user 中批量标记为已读

没有通知时直接返回

提取当前页可见通知ID

查询当前用户针对这些通知是否已经存在阅读记录

新增未读记录和更新已有未读记录分开来收集然后再批量入库

当前用户没有该通知的阅读记录,则新增一条已读记录

已有记录但状态不是已读,则更新为已读(防御性编程)


代码实现

在 NoticeController 中添加接口

1
2
3
4
5
6
7
@PutMapping("/read-all")
@SystemLog(businessName = "通知全部已读")
@ApiOperation(value = "通知全部已读接口", notes = "通知全部已读", response = String.class)
public ResponseResult readAllNotice()
{
return sysNoticeService.readAllNotice();
}

在 NoticeServiceImpl 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//通知全部已读
@Override
@Transactional
public ResponseResult readAllNotice()
{
//先校验登录状态,如果是未登录返回需要登录
Long userId = SecurityUtils.getUserId();
if (userId == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
}

//查询当前用户可见的已发布的通知
boolean isAdmin = SecurityUtils.isAdmin();
LambdaQueryWrapper<SysNotice> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysNotice::getStatus, SystemConstants.NOTICE_STATUS_PUBLISHED);

//将通知在 sys_notice_user 中批量标记为已读
if (!isAdmin) {
queryWrapper.and(wrapper -> wrapper.eq(SysNotice::getTargetType, SystemConstants.TARGET_TYPE_IS_ALL)
.or()
.apply("concat(',', target_user_ids, ',') like {0}", "%," + userId + ",%"));
}

//没有通知时直接返回
List<SysNotice> noticeList = sysNoticeService.list(queryWrapper);
if (noticeList.isEmpty()) {
return ResponseResult.okResult();
}

//提取当前页可见通知ID
List<Long> noticeIds = noticeList.stream().map(SysNotice::getId).toList();

//查询当前用户针对这些通知是否已经存在阅读记录
List<SysNoticeUser> noticeUserList = sysNoticeUserService.list(new LambdaQueryWrapper<SysNoticeUser>()
.eq(SysNoticeUser::getUserId, userId)
.in(SysNoticeUser::getNoticeId, noticeIds));

//把已存在的阅读记录转成Map方便后续操作
Map<Long, SysNoticeUser> noticeUserMap = noticeUserList.stream()
.collect(Collectors.toMap(SysNoticeUser::getNoticeId, item -> item, (oldVal, newVal) -> oldVal));

//新增未读记录和更新已有未读记录分开来收集然后再批量入库
List<SysNoticeUser> saveList = new ArrayList<>();
List<SysNoticeUser> updateList = new ArrayList<>();
Date now = new Date();
for (SysNotice notice : noticeList) {
SysNoticeUser noticeUser = noticeUserMap.get(notice.getId());
if (noticeUser == null) {
//当前用户没有该通知的阅读记录,则新增一条已读记录
SysNoticeUser newNoticeUser = new SysNoticeUser();
newNoticeUser.setNoticeId(notice.getId());
newNoticeUser.setUserId(userId);
newNoticeUser.setIsRead(SystemConstants.NOTICE_IS_READ);
newNoticeUser.setReadTime(now);
saveList.add(newNoticeUser);
} else if (!SystemConstants.NOTICE_IS_READ.equals(noticeUser.getIsRead())) {
//已有记录但状态不是已读,则更新为已读(防御性编程)
noticeUser.setIsRead(SystemConstants.NOTICE_IS_READ);
noticeUser.setReadTime(now);
updateList.add(noticeUser);
}
}

//批量保存新增的阅读记录
if (!saveList.isEmpty()) {
sysNoticeUserService.saveBatch(saveList);
}

//批量更新已存在的阅读记录
if (!updateList.isEmpty()) {
sysNoticeUserService.updateBatchById(updateList);
}

return ResponseResult.okResult();
}




PS:该系列只做为作者学习开发项目做的笔记用

不一定符合读者来学习,仅供参考


预告

后续会记录博客的开发过程

每次学习会做一份笔记来进行发表

“一花一世界,一叶一菩提”


版权所有 © 2026 云梦泽
欢迎访问我的个人网站:https://hgt12.github.io/


『博客开发日记-后台』之全部已读通知接口的实现
http://example.com/2026/05/29/『博客开发日记-后台』之全部已读通知接口的实现/
作者
云梦泽
发布于
2026年5月29日
更新于
2026年5月29日
许可协议