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));
    }
相关推荐
洛克大航海3 小时前
9-SpringCloud-服务网关 Gateway-高级特性之 Filter-2
java·spring cloud·gateway·filter
勿忘,瞬间3 小时前
内部类和Object类
java
大头an3 小时前
Java项目打包完整指南:从JAR到Docker全方位解析
java
日月星辰Ace3 小时前
JDK 工具学习系列(二):jar 命令实用教程与常见问题
java
九转成圣3 小时前
JWT 全面解析与 Spring Boot 实战教程
java·spring boot·后端
青云交4 小时前
Java 大视界 -- Java 大数据机器学习模型在遥感图像土地利用分类中的优化与应用
java·机器学习·分布式计算·数据预处理·遥感图像·模型融合·土地利用分类
=>>漫反射=>>4 小时前
【Spring Boot Starter 设计思考:分离模式是否适用于所有场景】
java·spring boot·后端·设计规范·自动装配
Jack电子实验室4 小时前
深入理解C语言函数指针:从基础到实战应用
java·c语言·算法
小马哥编程4 小时前
【软考架构】案例分析-系统设计与建模:数据流图DFD与数据字典
java·数据库·架构·统一建模语言