『博客开发日记-后台』之添加通知接口的实现

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

添加通知接口的实现


添加通知接口的需求

只处理通知内容中的临时图片,将其转为正式文件

将通知内容中的临时图片转正并同步文件表

同一通知里可能重复引用同一张临时图片,先去重

把目标用户ID列表转换成数据库存储格式

将元数据写入文件表


代码实现

在 NoticeController 中添加接口

1
2
3
4
5
6
7
8
 @PostMapping
@PreAuthorize("@ps.hasPermission('blog:notice:create')")
@SystemLog(businessName = "新增通知")
@ApiOperation(value = "新增通知接口", notes = "新增通知", response = String.class)
public ResponseResult addNotice(@Valid @RequestBody AddNoticeDto addNoticeDto)
{
return sysNoticeService.addNotice(addNoticeDto);
}

创建 AddNoticeDto

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
/**
* 添加通知请求DTO
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "添加通知请求对象")
public class AddNoticeDto
{
@NotBlank(message = "通知标题不能为空")
@ApiModelProperty(value = "通知标题", required = true, example = "测试通知标题")
private String title;

@NotBlank(message = "通知内容不能为空")
@ApiModelProperty(value = "通知内容(HTML格式/md格式)", required = true, example = "你好")
private String content;

@NotNull(message = "通知类型不能为空")
@ApiModelProperty(value = "通知类型(关联字典编码:notice_type)", required = true, example = "1")
private Integer type;

@NotNull(message = "通知等级不能为空")
@ApiModelProperty(value = "通知等级(LOW/MEDIUM/HIGH)(字典code:notice_level)", example = "H")
private String level;

@Pattern(regexp = "^$|^[012]$", message = "状态只能为0,1或2")
@ApiModelProperty(value = "状态(0: 未发布, 1: 已发布, 2: 已撤回)", example = "1")
private String status;

@ApiModelProperty(value = "目标人ID集合(多个使用英文逗号,分割)", example = "['1','2']")
private List<Long> targetUserIds;

@NotNull(message = "目标类型")
@Pattern(regexp = "^$|^[12]$", message = "目标类型只能为1或2")
@ApiModelProperty(value = "目标类型(1: 全体, 2: 指定)", example = "1")
private String targetType;
}

在 SysNoticeServiceImpl 中

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
76
77
78
//添加通知
@Override
@Transactional
public ResponseResult addNotice(AddNoticeDto addNoticeDto)
{
//只处理通知内容中的临时图片,将其转为正式文件
String content = addNoticeDto.getContent();
if (ImageUrlUtils.containsTempImages(content)) {
content = processContentImages(content, addNoticeDto.getTitle());
addNoticeDto.setContent(content);
}

//封装通知实体
SysNotice sysNotice = BeanCopyUtils.copyBean(addNoticeDto, SysNotice.class);
sysNotice.setTargetUserIds(convertTargetUserIds(addNoticeDto.getTargetUserIds()));
sysNotice.setPublisherId(SecurityUtils.getUserId());
sysNotice.setPublishTime(new Date());

//保存通知
boolean save = this.save(sysNotice);
if (!save) {
return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "添加通知失败");
}

return ResponseResult.okResult();
}

//将通知内容中的临时图片转正并同步文件表
private String processContentImages(String content, String noticeTitle)
{
List<String> tempImageUrls = ImageUrlUtils.extractTempImageUrls(content);
String result = content;

//同一通知里可能重复引用同一张临时图片,先去重
List<String> distinctTempImageUrls = tempImageUrls.stream().distinct().toList();

for (String tempUrl : distinctTempImageUrls) {
UploadFileMetaVo uploadFileMetaVo = ossFileService.moveTempToFormal(tempUrl);
if (uploadFileMetaVo == null || !StringUtils.hasText(uploadFileMetaVo.getUrl())) {
throw new RuntimeException("通知内容图片保存失败,无法保存通知记录: " + tempUrl);
}

result = ImageUrlUtils.replaceImageUrl(result, tempUrl, uploadFileMetaVo.getUrl());

if (StringUtils.hasText(uploadFileMetaVo.getFilePath())) {
saveFileRecord(uploadFileMetaVo.getName(),
uploadFileMetaVo.getFilePath(),
uploadFileMetaVo.getUrl(),
uploadFileMetaVo.getSize(),
uploadFileMetaVo.getMimeType(),
"通知《" + noticeTitle + "》中的图片");
}
}

return result;
}

//把目标用户ID列表转换成数据库存储格式
private String convertTargetUserIds(List<Long> targetUsers)
{
if (targetUsers == null || targetUsers.isEmpty()) {
return null;
}
return targetUsers.stream().map(String::valueOf).collect(Collectors.joining(","));
}

//将元数据写入文件表
private void saveFileRecord(String fileName, String filePath, String url, Long size, String mimeType, String fileSource)
{
SysFile sysFile = new SysFile();
sysFile.setName(fileName);
sysFile.setFilePath(filePath);
sysFile.setUrl(url);
sysFile.setSize(size);
sysFile.setMimeType(mimeType);
sysFile.setFileSource(fileSource);
sysFileService.save(sysFile);
}




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

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


预告

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

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

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


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


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