SpringBoot实现文章点赞功能

提示:今日是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,点赞类型查找如果说没有查找到的话,添加一条记录消息,总不能每次点赞完成之后都发送一次消息吧,发送的肯定是一次消息,大概逻辑就是这样

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/760286.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

20240630每日一题-组合数学-平均分组问题

更多资源请关注纽扣编程微信公众号 将6个小球&#xff0c;其中1个红球&#xff0c;2个黑球&#xff0c;3个白球拍成一列&#xff0c;相同颜色的球没区别&#xff0c;那么有多少种排法&#xff1f; 答案 60种 分析 相同颜色的小球可以看作平均分组&#xff0c;去除对应排序的…

Zookeeper:Zookeeper JavaAPI操作与分布式锁

文章目录 一、Zookeeper JavaAPI操作1、Curator介绍2、创建、查询、修改、删除节点3、Watch事件监听 二、Zookeeper分布式锁原理 一、Zookeeper JavaAPI操作 1、Curator介绍 Curator是Apache Zookeeper的Java客户端。常见的Zookeeper Java API&#xff1a; 原生Java API。ZkC…

基于PHP的酒店管理系统(改进版)

有需要请加文章底部Q哦 可远程调试 基于PHP的酒店管理系统(改进版) 一 介绍 此酒店管理系统(改进版)基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端jquery插件美化。系统角色分为用户和管理员。系统在原有基础上增加了注册登录注销功能&#xff0c;增加预订房间图片…

临时文件上传系统Plik

什么是 Plik &#xff1f; Plik 是一个基于 Go 语言的可扩展且用户友好的临时文件上传系统&#xff08;类似于 Wetransfer&#xff09;。 软件主要特点&#xff1a; 强大的命令行客户端易于使用的 Web 用户界面多个数据后端&#xff1a;文件、OpenStack Swift、S3、Google Clo…

Swift中的二分查找:全面指南

Swift中的二分查找&#xff1a;全面指南 简介 二分查找是计算机科学中的经典算法&#xff0c;被广泛用于在已排序的数组中高效地搜索目标值。与线性查找逐个检查每个元素不同&#xff0c;二分查找不断将搜索区间减半&#xff0c;因此在处理大数据集时要快得多。 在这篇博客中…

java基于ssm+jsp 固定资产管理系统

1前台首页功能模块 固定资产管理系统&#xff0c;在系统首页可以查看首页、设备信息、论坛信息、我的、跳转到后台等内容&#xff0c;如图1所示。 图1前台首页功能界面图 注册&#xff0c;在注册页面可以填写用户名、密码、姓名、性别、头像、身份证、手机等详细内容&#xff…

基于Ollama Python的本地多模态大模型

0&#xff0c;背景 最近测试Ollama&#xff0c;发现之前直接下载开源模型在我电脑上都跑不动的模型&#xff0c;居然也能运行了&#xff08;AMD 7840HS核显/32GB内存&#xff09;&#xff0c;突发奇想那些多模态大模型能不能基于Python接口使用&#xff0c;所以决定尝试一下。…

Qt之Pdb生成及Dump崩溃文件生成与调试(含注释和源码)

文章目录 一、Pdb生成及Dump文件使用示例图1.Pdb文件生成2.Dump文件调试3.参数不全Pdb生成的Dump文件调试 二、个人理解1.生成Pdb文件的方式2.Dump文件不生产的情况 三、源码Pro文件mian.cppMainWindowUi文件 总结 一、Pdb生成及Dump文件使用示例图 1.Pdb文件生成 下图先通过…

Springboot+vue电商平台

管理员权限操作的功能包括管理商家&#xff0c;管理商家星级信息&#xff0c;管理用户&#xff0c;管理商品等。 商家权限操作的功能包括管理商品&#xff0c;回复商品评价&#xff0c;管理商品订单等。 用户权限操作的功能包括查看商家&#xff0c;购买商品&#xff0c;提交…

Django之邮箱注册

目录 一、邮箱验证-环境搭建 1.1、注册流程 1.2、环境搭建 二、封装工具类 三、发送邮件接口开发 四、用户调用发送邮件接口 4.1、Fetch API 4.1.1、GET请求 4.1.2、POST请求 五、完成注册功能 一、邮箱验证-环境搭建 1.1、注册流程 1.2、环境搭建 创建项目 django-a…

Variables Reference for vscode

Predefined variables Visual Studio Code 支持在调试、任务配置文件以及一些特定的设置中使用变量替换。这些变量可以使用 ${variableName} 语法在 launch.json 和 tasks.json 文件的某些键和值字符串中使用。 Predefined variables Visual Studio Code 支持以下预定义变量…

【分布式计算框架 MapReduce】高级编程—多任务数据分析

目录 一、对于 sogou_500w_utf 数据&#xff0c;使用 MapReduce 编程模型完成对以下数据的分析任务。 1. 统计搜索的关键字查询频度&#xff0c;找出搜索次数超过 20 次的关键字的个数。 ① 运行截图 ② 源代码 二、改造 WordCount 程序&#xff0c;使得结果的排序规则为按…

APP逆向 day7 JAVA基础2

一.前言 昨天我们讲了点java基础&#xff0c;大家是不是觉得就特别简单&#xff0c;今天讲点稍微难一丢丢的基础&#xff0c;也就是java基础2.0&#xff0c;今天我要和大家说的内容十分的重要&#xff0c;直接关乎到下一节的内容&#xff0c;所以&#xff0c;好好学&#xff0…

React 打包时如何关闭源代码混淆

React 开发中&#xff0c;使用 npm build 命令进行生产代码打包&#xff0c;为了压缩代码并尽量保证代码的安全性&#xff0c;React 打包时会代码进行压缩和混淆&#xff0c;但是有时我们需要 debug 生产环境的源代码&#xff0c;例如当我们调试 SSR 的项目时&#xff0c;需要禁…

<电力行业> - 《第10课:变电》

1 变电 变电环节&#xff0c;顾名思义就是改变电压的环节&#xff0c;主要是在变电站和变电所完成的。变电站和变电所主要区别在于&#xff1a;变电站比变电所更大。 发电厂的变压器和配电变压器也属于“变电”&#xff0c;但我们在说电网环节时&#xff0c;变电特指电网公司…

Android常用加解密算法总结

Android开发中对于数据的传输和保存一定会使用加密技术&#xff0c;加密算法是最普遍的安保手段&#xff0c;多数情况数据加密后在需要使用源数据时需要再进行解密&#xff0c;但凡是都有例外。下面从可逆加密、不可逆、不纯粹加密三种方式记录一下常见的加解密算法。 加密技术…

计算机毕业设计Thinkphp/Laravel校园体育器材管理系统

校园体育器材管理系统在流畅性&#xff0c;续航能力&#xff0c;等方方面面都有着很大的优势。这就意味着校园体育器材管理系统的设计可以比其他系统更为出色的能力&#xff0c;可以更高效的完成最新的体育器材、器材借用、器材归还、器材损坏、采购入库、器材报废、维修记录等…

局域网必备文件传输神器,吾爱再出精品,支持电脑、手机无缝对接!

今天给大家带来的不是一般的干货&#xff0c;而是一款让阿星我爱不释手的局域网文件传输神器&#xff0c;而且是吾爱大佬出品。无论是工作还是生活&#xff0c;它都能给你带来极大的便利。这年头&#xff0c;谁还没个跨设备传输文件的需求呢&#xff1f; 手机、电脑、平板&…

AI agent是什么,什么技术栈

AI agent&#xff0c;也称为会话代理或聊天机器人&#xff0c; 是一种通过文本或语音模拟人类对话的计算机程序。 它们旨在以自然且引人入胜的方式理解和响应用户输入。 AI agent 被广泛用于各种应用中&#xff0c;包括客户服务、营销、 销售和教育。 有两种主要类型的 AI agen…

Webpack: 前端资深构建工具

概述 如果你是一名前端工程师&#xff0c;相信之前或多或少听过、用过 Webpack 这一构建工具&#xff0c;它能够融合多种工程化工具&#xff0c;将开发阶段的应用代码编译、打包成适合网络分发、客户端运行的应用产物如今&#xff0c;Webpack 已经深深渗入到前端工程的方方面面…