33.点赞功能

需求:

1.同一个用户只能点赞一次,再次点赞则取消点赞。

2.如果当前用户已经点赞,则点赞按钮高亮显示(前端实现,只需要根据Blog类中的isLike属性表示是否点赞过了)

sql 复制代码
CREATE TABLE `tb_blog` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `shop_id` bigint NOT NULL COMMENT '商户id',
  `user_id` bigint unsigned NOT NULL COMMENT '用户id',
  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '标题',
  `images` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '探店的照片,最多9张,多张以","隔开',
  `content` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '探店的文字描述',
  `liked` int unsigned DEFAULT '0' COMMENT '点赞数量',
  `comments` int unsigned DEFAULT NULL COMMENT '评论数量',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT;
java 复制代码
package com.xkj.org.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.time.LocalDateTime;

/**
 * @author xiankejin
 * @descrition
 * @date 2025/10/25
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_blog")
public class Blog {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private Long shopId;

    private Long userId;

    private String title;
    /**
     * 探店的照片,最多9张,多张以","隔开'
     */
    private String images;
    /**
     * 探店的文字描述
     */
    private String content;
    /**
     * 点赞数量
     */
    private Integer liked;
    /**
     * 评论数量
     */
    private Integer comments;

    private LocalDateTime createTime;

    private LocalDateTime updateTime;

    /**
     * 用户图标
     */
    @TableField(exist = false)
    private String icon;
    /**
     * 用户姓名
     */
    @TableField(exist = false)
    private String name;


    /**
     * 是否点赞过了
     */
    @TableField(exist = false)
    private Boolean isLike;

}
java 复制代码
@Override
    public List<Blog> queryHotBlog(Integer current) {
        //根据点赞数量倒序排列
        Page<Blog> page = query().orderByDesc("liked")
                .page(new Page<>(current, UserConstant.MAX_PAGE_SIZE));
        List<Blog> records = page.getRecords();
        //这里采用lambda表达式简写
        records.forEach(this::queryBlogUser);
        return records;
    }

    @Override
    public Blog detail(Integer id) {
        Blog blog = getById(id);
        queryBlogUser(blog);
        return blog;
    }

    @Override
    public void likeBlog(Integer id) {
        //1.判断当前用户是否已经点赞
        UserDTO user = UserHolder.getUser();
        //这里的userId一定要转成String类型,因为使用的是StringRedisTemplate
        String key = "blog:liked:" + id.toString();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, user.getId().toString());
        //如果未点赞,可以点赞
        //这里不要直接判断布尔值,而是使用工具类判断,防止isMember对象为null,报空指针异常
        if (BooleanUtil.isFalse(isMember)) {
            //数据库点赞数 + 1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //数据更新成功了在更新redis
            if (isSuccess) {
                //保存用户id到redis的set集合
                stringRedisTemplate.opsForSet().add(key, user.getId().toString());
            }
        } else {
            //如果点赞,则取消点赞
            //数据库点赞数 - 1
            boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update();
            //数据更新成功了在更新redis
            if (isSuccess) {
                //将用户id从redis的set集合中移除
                stringRedisTemplate.opsForSet().remove(key, user.getId().toString());
            }
        }

    }

    /**
     * 给BLog对象添加用户信息
     *
     * @param blog
     */
    private void queryBlogUser(Blog blog) {
        User user = userService.getById(blog.getUserId());
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
        //查询blog是否被点赞
        //1.判断当前用户是否已经点赞
        UserDTO currentUser = UserHolder.getUser();
        String key = "blog:liked:" + blog.getId().toString();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, currentUser.getId().toString());
        blog.setIsLike(BooleanUtil.isTrue(isMember));
    }
相关推荐
hellotutu几秒前
Java 读取 Excel 文件
java·开发语言·excel
野生风长6 分钟前
从零开始的c语言:指针高级应用(下)(回调函数,qsort函数模拟实现, strlen和sizeof)
java·c语言·开发语言·c++·算法
g***B7386 分钟前
Java 服务端架构的本质:从单体到云原生的演进与思维模式变革
java·云原生·架构
d111111111d9 分钟前
嵌入式面试问题:STM32中指针和数组的本质区别是什么,常用数组存储什么数据?
java·笔记·stm32·单片机·嵌入式硬件·学习
yivifu9 分钟前
Excel中Lookup函数实现临界点归入下一个等级的方法
java·前端·excel
大佐不会说日语~11 分钟前
Spring AI Alibaba 对话记忆丢失问题:Redis 缓存过期后如何恢复 AI 上下文
java·人工智能·spring boot·redis·spring·缓存
古城小栈15 分钟前
Spring AI 1.1:快速接入主流 LLM,实现智能问答与文本生成
java·人工智能·spring boot·spring
计算机学姐17 分钟前
基于SSM的宠物领养管理系统【2026最新】
java·vue.js·后端·java-ee·tomcat·mybatis·宠物
后端小张18 分钟前
【JAVA进阶】鸿蒙开发与SpringBoot深度融合:从接口设计到服务部署全解析
java·spring boot·spring·spring cloud·华为·harmonyos·鸿蒙
Qiuner18 分钟前
Spring Boot AOP(一) 入门与核心概念
java·spring boot·后端·spring·aop