提示:今日是2024年的6月30日,未来的你看到这篇文章,希望你依旧快乐
文章目录
前言
首先在这里前缀部分我就不做要求了,比如说登录信息什么的
数据库表格
这里实现点赞功能,主要是围绕论坛项目完成的
user_info代表用户信息表
forum_article代表着文章信息表
user_message代表着点赞或者评论点赞发送信息表
like_record代表着用户点赞表
user_info用户信息表
forum_article文章信息表
user_message点赞评论信息发送表
like_record点赞信息表
表格准备完毕
代码实现
Controller层
/**
* 实现文章点赞功能。
* 通过请求映射 "/doLike",该方法处理用户对文章的点赞操作。
* 使用@GlobalInterceptor注解,表明该方法受全局拦截器影响,会检查参数有效性及用户登录状态。
*
* @param session 用户会话对象,用于获取会话中的用户信息。
* @param articleId 需要点赞的文章ID,通过@VerifyParam注解确保其为非空,保证操作的有效性。
* @return 返回操作成功的响应对象。
*/
@RequestMapping("/doLike")
@GlobalInterceptor(checkParams = true, checkLogin = true)
public ResponseVO likeArticle(HttpSession session, @VerifyParam(required = true) String articleId) {
// 从会话中获取用户信息
SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
// 调用点赞服务,记录用户的点赞行为
likeRecordService.doLike(articleId, sessionWebUserDto.getUserId(), sessionWebUserDto.getNickName(), OperRecordOpTypeEnum.ARTICLE_LIKE);
// 返回操作成功的响应
return getSuccessResponseVO(null);
}
//枚举
package com.easybbs.entity.enums;
public enum OperRecordOpTypeEnum {
ARTICLE_LIKE(0, "文章点赞"),
COMMENT_LIKE(1, "评论点赞");
private Integer type;
private String desc;
OperRecordOpTypeEnum(Integer type, String desc) {
this.type = type;
this.desc = desc;
}
public Integer getType() {
return type;
}
public String getDesc() {
return desc;
}
}
至于这里的参数校验和登录校验我就不作详细解释了,相信未来的你也一定可以看懂
Service接口层
//点赞
void doLike(String objectId, String userId, String nickName, OperRecordOpTypeEnum opTypeEnum);
Service接口实现层
/**
* 用户点赞操作。
* 实现对文章或评论的点赞功能,并记录用户的点赞行为。
* @param objectId 点赞对象的ID,可以是文章ID或评论ID。
* @param userId 点赞用户的ID。
* @param nickName 点赞用户的昵称。
* @param opTypeEnum 点赞操作的类型,区分是文章点赞还是评论点赞。
* @throws BusinessException 如果文章不存在,则抛出业务异常。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void doLike(String objectId, String userId, String nickName, OperRecordOpTypeEnum opTypeEnum) {
// 创建用户消息对象,用于记录点赞行为。
UserMessage userMessage = new UserMessage();
userMessage.setCreateTime(new Date());
// 根据点赞类型执行不同的操作。
switch (opTypeEnum){
case ARTICLE_LIKE:
// 根据文章ID查询文章信息,如果文章不存在,则抛出异常。
ForumArticle forumArticle = forumArticleMapper.selectByArticleId(objectId);
if(forumArticle == null){
throw new BusinessException("文章不存在");
}
// 执行文章点赞逻辑。
articleLike(objectId,forumArticle,userId,opTypeEnum);
// 设置用户消息的相关信息,如文章ID、文章标题等。
userMessage.setArticleId(objectId);
userMessage.setArticleTitle(forumArticle.getTitle());
userMessage.setMessageType(MessageTypeEnum.ARTICLE_LIKE.getType());
userMessage.setCommentId(Constants.ZERO);
userMessage.setReceivedUserId(forumArticle.getUserId());
break;
case COMMENT_LIKE:
// 评论点赞的逻辑实现。
break;
}
// 设置用户消息的发送者信息。
userMessage.setSendUserId(userId);
userMessage.setSendNickName(nickName);
userMessage.setStatus(MessageStatusEnum.NO_READ.getStatus());
// 判断是否为给自己的点赞,若是,则不记录点赞消息。
// 判断是否已经点赞
if(!userId.equals(userMessage.getReceivedUserId())){
// 根据文章ID、评论ID、发送者ID和消息类型查询是否已存在相同的点赞记录。
UserMessage dbInfo = userMessageMapper.selectByArticleIdAndCommentIdAndSendUserIdAndMessageType(userMessage.getArticleId(),userMessage.getCommentId()
,userMessage.getSendUserId(),userMessage.getMessageType());
// 如果不存在相同的点赞记录,则插入新的点赞消息。
if(dbInfo == null ){
userMessageMapper.insert(userMessage);
}
}
}
/**
* 用户对文章进行点赞或取消点赞操作。
*
* @param objId 对象ID,即文章的唯一标识。
* @param forumArticle 文章对象,用于获取文章的作者信息。
* @param userId 用户ID,执行点赞操作的用户。
* @param opTypeEnum 操作类型枚举,表示点赞或取消点赞。
* @return 返回点赞记录,如果用户之前点赞过,则返回非空;否则返回空。
*/
public LikeRecord articleLike(String objId, ForumArticle forumArticle, String userId, OperRecordOpTypeEnum opTypeEnum) {
// 根据对象ID、用户ID和操作类型查询点赞记录,判断用户是否已经点赞过。
LikeRecord record = this.likeRecordMapper.selectByObjectIdAndUserIdAndOpType(objId, userId, opTypeEnum.getType());
if (record != null) {
// 如果用户之前点赞过,则取消点赞。
this.likeRecordMapper.deleteByObjectIdAndUserIdAndOpType(objId, userId, opTypeEnum.getType());
// 更新文章的点赞数,减少1。
forumArticleMapper.updateArticleCount(UpdateArticleCountTypeEnum.GOOD_COUNT.getType(), -1, objId);
} else {
// 如果用户未点赞,则创建新的点赞记录。
LikeRecord likeRecord = new LikeRecord();
likeRecord.setObjectId(objId);
likeRecord.setUserId(userId);
likeRecord.setOpType(opTypeEnum.getType());
likeRecord.setCreateTime(new Date());
// 设置点赞记录的作者用户ID为文章的作者用户ID。
likeRecord.setAuthorUserId(forumArticle.getUserId());
// 插入新的点赞记录。
this.likeRecordMapper.insert(likeRecord);
// 更新文章的点赞数,增加1。
forumArticleMapper.updateArticleCount(UpdateArticleCountTypeEnum.GOOD_COUNT.getType(), 1, objId);
}
// 返回点赞记录,无论是否新点赞或取消点赞。
return record;
}
Mapper层
<!-- 根据PrimaryKey获取对象-->
<select id="selectByArticleId" resultMap="base_result_map" >
select <include refid="base_column_list" />,content,markdown_content from forum_article where article_id=#{articleId}
</select>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByArticleIdAndCommentIdAndSendUserIdAndMessageType" resultMap="base_result_map" >
select <include refid="base_column_list" /> from user_message where article_id=#{articleId} and comment_id=#{commentId} and send_user_id=#{sendUserId} and message_type=#{messageType}
</select>
<!-- 根据ObjectIdAndUserIdAndOpType删除-->
<delete id="deleteByObjectIdAndUserIdAndOpType">
delete from like_record where object_id=#{objectId} and user_id=#{userId} and op_type=#{opType}
</delete>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByObjectIdAndUserIdAndOpType" resultMap="base_result_map" >
select <include refid="base_column_list" /> from like_record where object_id=#{objectId} and user_id=#{userId} and op_type=#{opType}
</select>
总结
当然上面只是一些代码的展示,但其实主要的是思路,那接下来我就说明一下我实现的思路
文章点赞功能,首先文章点赞传到Controller层的时候,肯定需要把文章id传送过去,在Controller接受到文章id之后,再从登录信息里面传递出来用户的id,用户的名称,是文章点赞还是评论点赞呢,传递过去之后,创建发送消息的对象,根据点赞类型进行分开,如果是文章点赞的话,首先根据用户id,文章id,点赞类型去查找点赞的记录表,如果说找到了的话,取消点赞,实际上也就是删除点赞信息,删除一条点赞信息表里面的语句,如果说没有点赞的话,创建一个点赞对象,点赞的人是这个用户,名称是这个用户,点赞的文章是文章id,点赞的类型是文章点赞,还需要额外设置点赞是给哪一个用户点赞,肯定是根据文章信息找到发送文章的人,然后插入新的点赞记录,更改文章的点赞数,如果说取消点赞也需要更改文章点赞类型,
点赞完成之后去继续完善用户发送信息表,比如说设置文章id,文章标题,文章点赞类型,接收人用户id是谁,发送人用户id是谁,发送人名字是谁,发送的是未读状态,
接下来首先需要判断不是自己给自己点赞,自己给自己点赞是肯定不会发送消息的,如果说根据文章id,评论的id发送者id,点赞类型查找如果说没有查找到的话,添加一条记录消息,总不能每次点赞完成之后都发送一次消息吧,发送的肯定是一次消息,大概逻辑就是这样