『博客开发日记』之发布评论接口的实现

本文最后更新于 2026年1月14日 上午

发表评论接口的实现


发表评论接口的需求

用户要登录之后才能在文章里评论和对别人的评论进行回复

用户登录后可以在友链页面进行评论

用户不需要登录就能能在留言板进行评论

在CommentServiceImpl类中添加方法

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
79
80
81
82
83
84
85
    //添加评论
@Override
public ResponseResult addComment(Comment comment)
{
String type = comment.getType();

//校验评论内容
if (!StringUtils.hasText(comment.getContent())) {
return ResponseResult.errorResult(AppHttpCodeEnum.CONTENT_NOT_NULL);
}

comment.setType(type);
comment.setArticleId(comment.getArticleId());
comment.setContent(comment.getContent());
comment.setRootId(comment.getRootId() != null ? comment.getRootId() : -1L);
comment.setReplyToCommentId(comment.getReplyToCommentId());
comment.setReplyToUserId(comment.getReplyToUserId());

//根据评论类型进行权限校验
if (SystemConstants.COMMENT_TYPE_ARTICLE.equals(type) || SystemConstants.COMMENT_TYPE_LINK.equals(type))
{
//在文章评论和友链评论需要登录
if (!SecurityUtils.isLogin()) {
return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
}
LoginUser loginUser = SecurityUtils.getLoginUser();
User user = loginUser.getUser();
comment.setUserId(user.getId());
comment.setNickname(user.getNickname());
comment.setEmail(user.getEmail());
comment.setPersonalWebsite(comment.getPersonalWebsite());//添加个人网址
} else if (SystemConstants.COMMENT_TYPE_MESSAGE.equals(type)) {
//在留言板评论则不需要登录,但需要填写昵称和邮箱
if (SecurityUtils.isLogin()) {
//已登录用户使用登录信息
LoginUser loginUser = SecurityUtils.getLoginUser();
User user = loginUser.getUser();
comment.setUserId(user.getId());
comment.setNickname(user.getNickname());
comment.setEmail(user.getEmail());
comment.setPersonalWebsite(comment.getPersonalWebsite());
} else {
//未登录用户需要填写昵称和邮箱
if (!StringUtils.hasText(comment.getNickname())) {
return ResponseResult.errorResult(AppHttpCodeEnum.NICKNAME_NOT_NULL);
}
if (!StringUtils.hasText(comment.getEmail())) {
return ResponseResult.errorResult(AppHttpCodeEnum.EMAIL_NOT_NULL);
}
comment.setNickname(comment.getNickname());
comment.setEmail(comment.getEmail());
comment.setPersonalWebsite(comment.getPersonalWebsite());
}
}

//如果前端没有传头像,则根据邮箱生成
if (!StringUtils.hasText(comment.getAvatar())) {
comment.setAvatar(GravatarUtils.getGravatarUrl(comment.getEmail()));
}

//设置默认值
comment.setLikeCount(0);
comment.setStatus(SystemConstants.COMMENT_STATUS_NORMAL);
comment.setDelFlag("0");
comment.setCreateTime(new Date());

save(comment);

//封装成Vo返回,判断是否为博主(通过邮箱匹配)
CommentVo commentVo = BeanCopyUtils.copyBean(comment, CommentVo.class);
if (StringUtils.hasText(comment.getEmail())
&& comment.getEmail().equalsIgnoreCase(SystemConstants.BLOGGER_EMAIL)) {
commentVo.setUserType("1"); //博主标识
} else if (comment.getUserId() != null) {
//已登录用户,查询用户类型
User user = userMapper.selectById(comment.getUserId());
if (user != null) {
commentVo.setUserType(user.getUserType());
}
} else {
commentVo.setUserType("0"); //普通用户
}

return ResponseResult.okResult();
}

添加通过邮箱获取用户头像的工具类GravatarUtils

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
/**
* 头像工具类
* 支持 QQ 邮箱直接获取 QQ 头像,其他邮箱使用 Gravatar
*/
public class GravatarUtils
{

// 使用国内可访问的 Gravatar 镜像(loli.net 较稳定)或(https://cravatar.cn/avatar/)(https://gravatar.loli.net/avatar/)
private static final String GRAVATAR_URL = "https://cravatar.cn/avatar/";
// QQ 头像接口
private static final String QQ_AVATAR_URL = "https://q1.qlogo.cn/g?b=qq&nk=";
// 默认头像类型
private static final String DEFAULT_AVATAR = "identicon";
// 默认头像大小
private static final int DEFAULT_SIZE = 80;

/**
* 根据邮箱生成头像 URL
* QQ 邮箱直接获取 QQ 头像,其他邮箱使用 Gravatar
* @param email 邮箱地址
* @return 头像 URL
*/
public static String getGravatarUrl(String email) {
return getGravatarUrl(email, DEFAULT_SIZE);
}

/**
* 根据邮箱生成指定大小的头像 URL
* @param email 邮箱地址
* @param size 头像大小
* @return 头像 URL
*/
public static String getGravatarUrl(String email, int size) {
if (email == null || email.trim().isEmpty()) {
return GRAVATAR_URL + "00000000000000000000000000000000?d=" + DEFAULT_AVATAR + "&s=" + size;
}

String trimmedEmail = email.trim().toLowerCase();

// QQ 邮箱直接使用 QQ 头像
if (trimmedEmail.endsWith("@qq.com")) {
String qqNumber = trimmedEmail.replace("@qq.com", "");
// 验证是否为纯数字(QQ号)
if (qqNumber.matches("\\d+")) {
return QQ_AVATAR_URL + qqNumber + "&s=" + size;
}
}

// 其他邮箱使用 Gravatar
String hash = md5Hex(trimmedEmail);
return GRAVATAR_URL + hash + "?d=" + DEFAULT_AVATAR + "&s=" + size;
}

/**
* 计算字符串的 MD5 哈希值
* @param input 输入字符串
* @return MD5 哈希值(小写十六进制)
*/
private static String md5Hex(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("MD5 algorithm not found", e);
}
}
}

添加获取用户登录token安全认证的工具类SecurityUtils

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
/**
* 安全工具类 - 获取当前登录用户信息
*/
public class SecurityUtils
{

/**
* 获取当前登录用户
* @return LoginUser 或 null(未登录)
*/
public static LoginUser getLoginUser()
{
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
Object principal = authentication.getPrincipal();
if (principal instanceof LoginUser) {
return (LoginUser) principal;
}
return null;
}

/**
* 获取当前登录用户ID
* @return 用户ID 或 null
*/
public static Long getUserId() {
LoginUser loginUser = getLoginUser();
return loginUser != null ? loginUser.getUser().getId() : null;
}

/**
* 判断当前用户是否已登录
* @return true-已登录,false-未登录
*/
public static boolean isLogin() {
return getLoginUser() != null;
}
}

再在SystemConstants中添加几个关于四个类型评论的常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 /**
* 评论类型:友链评论
*/
public static final String COMMENT_TYPE_LINK = "1";
/**
* 评论类型:留言板评论
*/
public static final String COMMENT_TYPE_MESSAGE = "2";
/**
* 评论状态:正常文章评论
*/
public static final String COMMENT_STATUS_NORMAL = "0";
/**
* 博主邮箱(用于匿名评论时识别博主身份)
*/
public static final String BLOGGER_EMAIL = "2962933152@qq.com";



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

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


预告

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

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

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


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


『博客开发日记』之发布评论接口的实现
http://example.com/2026/01/12/『博客开发日记』之发布评论接口的实现/
作者
云梦泽
发布于
2026年1月12日
更新于
2026年1月14日
许可协议