点赞功能开发

1.点赞收藏功能设计

1.示意图

img

2.描述
1.使用redis记录的数据
  • **hash类型:**hashkey:subjectId:userId,hashval:存的是点赞的状态 1 是点赞 0 是不点赞。
  • **string 类型:**key subjectId,val:我们的题目被点赞的数量
  • **string 类型:**key subjectId.userId,val:"1"记录题目被谁点过赞
2.数据库的设计
create table subject_liked
(
    id           bigint auto_increment comment '主键'
        primary key,
    subject_id   bigint                   null comment '题目id',
    like_user_id varchar(32)              null comment '点赞人id',
    status       int                      null comment '点赞状态 1点赞 0不点赞',
    created_by   varchar(32) charset utf8 null comment '创建人',
    created_time datetime                 null comment '创建时间',
    update_by    varchar(32) charset utf8 null comment '修改人',
    update_time  datetime                 null comment '修改时间',
    is_deleted   int default 0            null,
    constraint uniq_like
        unique (subject_id, like_user_id) comment '点赞唯一索引'
)
    comment '题目点赞表' collate = utf8mb4_bin;
3.功能设计
1.新增点赞

直接操作 redis,存 hash,存数量,存点赞的人与题目的 key

2.取消点赞

上面的反逻辑,数量会-1,hash 里面的状态会更新,点赞人与题目关联的 key 会被删除

3.查询当前题目被点赞的数量

直接与 redis 交互,读题目的被点赞数量的 key

4.查询当前题目被当前用户是否点过赞

直接查 redis 就可以了

5.我的点赞

直接查数据库做分页逻辑的展示

2.代码生成器的使用

1.找到代码生成器在磁盘的位置,直接复制到项目下

image-20240623135451683

2.导入模块
1.打开项目结构,选择导入模块

image-20240623135601572

image-20240623135633463

2.从已存在的资源中导入

image-20240623135709102

3.一直下一步即可

image-20240623135747788

4.导入成功

image-20240623135855599

5.右击pom.xml将其作为maven项目

image-20240623141337612

image-20240623141716529

6.发现刷新maven无法找到这个starter

image-20240623141605273

7.将jc-club-common-starter模块也导入进来
3.gen.yml 进行配置
1.替换数据库连接信息及对应表
# 数据库连接信息
jdbc:
  dbName: sun_club
  tableName: subject_liked
  url: 
  username: 
  password: 
  driver: com.mysql.cj.jdbc.Driver
2.使用的模板与生成文件映射给关系
mapperInfos: genCode/subjectLikedMapper.yml
3.全局参数
# 全局参数
params:
  # 作者
  author: sun
  # 模块
  module: subject
  # controller 通用前缀
  api: /subjectLiked
  # 生成对象是否移除前缀
  removePre: false
  # 使用内置函数赋值给变量  FunctionUtils 中替换
  genDate: now()
  # win 需要补充模板具体目录
  templateBasePath: D:/Intelij_IDEA_Project/sun-club/code-generate/src/main/resources/

3.点赞功能基本开发

1.sun-club-application-controller
1.SubjectLikedController.java 接受点赞题目id和点赞状态
/**
 * 新增点赞
 * @param subjectLikedDTO 点赞题目id、点赞状态0/1
 * @return
 */
@RequestMapping("add")
public Result<Boolean> add(@RequestBody SubjectLikedDTO subjectLikedDTO) {
    try {
        if (log.isInfoEnabled()) {
            log.info("SubjectLikedController.add.dto:{}", JSON.toJSONString(subjectLikedDTO));
        }
        Preconditions.checkNotNull(subjectLikedDTO.getSubjectId(), "题目id不能为空");
        Preconditions.checkNotNull(subjectLikedDTO.getStatus(), "点赞状态不能为空");
        // 获取点赞人的id
        String loginId = LoginUtil.getLoginId();
        subjectLikedDTO.setLikeUserId(loginId);
        Preconditions.checkNotNull(subjectLikedDTO.getLikeUserId(), "点赞人不能为空");
        SubjectLikedBO SubjectLikedBO = SubjectLikedDTOConverter.INSTANCE.convertDTOToBO(subjectLikedDTO);
        subjectLikedDomainService.add(SubjectLikedBO);
        return Result.ok(true);
    } catch (Exception e) {
        log.error("SubjectLikedController.register.error:{}", e.getMessage(), e);
        return Result.fail("新增题目点赞表失败");
    }
}
2.sun-club-common
1.SubjectLikedStatusEnum.java 题目点赞状态枚举
package com.sunxiansheng.subject.common.enums;

import lombok.Getter;

/**
 * Description: 题目点赞枚举
 * @Author sun
 * @Create 2024/5/24 9:53
 * @Version 1.0
 */
@Getter
public enum SubjectLikedStatusEnum {

    LIKED(1, "点赞"),
    UN_LIKED(0, "取消点赞"),
    ;

    public int code;
    public String desc;

    SubjectLikedStatusEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    /**
     * 根据code获取枚举
     * @param code
     * @return
     */
    public static SubjectLikedStatusEnum getByCode(int code) {
        for (SubjectLikedStatusEnum value : values()) {
            if (value.code == code) {
                return value;
            }
        }
        return null;
    }
}
3.sun-club-domain
1.SubjectLikedDomainService.java
/**
 * 添加 题目点赞表 信息
 */
void add(SubjectLikedBO subjectLikedBO);
2.SubjectLikedDomainServiceImpl.java
/*
与redis交互
 */
@Resource
private RedisUtil redisUtil;

/*
点赞 hash结构:大key
 */
public static final String SUBJECT_LIKE_KEY = "subject.liked";

/*
题目点赞计数 string结构:key
 */
public static final String SUBJECT_LIKE_COUNT_KEY = "subject.liked.count";

/*
题目被谁点过赞 string结构:key
*/
public static final String SUBJECT_LIKE_DETAIL_KEY = "subject.liked.detail";

/**
 * 构建新增点赞时redis中的hashKey(小key)
 * @param subjectId
 * @param userId
 * @return
 */
private String buildSubjectLikedKey(String subjectId, String userId) {
    return subjectId + ":" + userId;
}

@Override
public void add(SubjectLikedBO subjectLikedBO) {
    // 获取信息
    Long subjectId = subjectLikedBO.getSubjectId();
    String likeUserId = subjectLikedBO.getLikeUserId();
    Integer status = subjectLikedBO.getStatus();
    // 构建hashKey
    String hashKey = buildSubjectLikedKey(String.valueOf(subjectId), likeUserId);
    // 存储点赞信息
    redisUtil.putHash(SUBJECT_LIKE_KEY, hashKey, status);
    // 题目点赞计数
    String countKey = SUBJECT_LIKE_COUNT_KEY + "." + subjectId;
    // 题目被谁点过赞
    String detailKey = SUBJECT_LIKE_DETAIL_KEY + "." + subjectId + "." + likeUserId;
    // 如果是点赞,则增加一
    if (SubjectLikedStatusEnum.LIKED.getCode() == status) {
        // 记录该题目被谁点过赞
        redisUtil.set(detailKey, "1");
        redisUtil.increment(countKey, 1);
    } else {
        // 如果说是取消点赞,则要判断是否已经是0了
        Integer count = redisUtil.getInt(countKey);
        // 如果是0,就直接返回,不是0则减一
        if (Objects.isNull(count) || count <= 0) {
            return;
        }
        redisUtil.increment(countKey, -1);
        // 取消点赞,也要删除点赞细节
        redisUtil.del(detailKey);
    }
}
3.RedisUtil.java 新增hash结构api
/**
 * 向Redis中的hash结构存储数据
 * @param key 一个hash结构的key
 * @param hashKey hash中的小key
 * @param hashVal hash中的小value
 */
public void putHash(String key, String hashKey, Object hashVal) {
    redisTemplate.opsForHash().put(key, hashKey, hashVal);
}

/**
 * Redis中的String类型,获取value时将其转换为int类型
 * @param key
 * @return
 */
public Integer getInt(String key) {
    return (Integer) redisTemplate.opsForValue().get(key);
}

/**
 * Redis中的String类型,将value增加一
 * @param key
 * @param count
 * @return
 */
public void increment(String key, Integer count) {
    redisTemplate.opsForValue().increment(key, count);
}
4.测试
1.点赞

image-20240623160707690

2.Redis

image-20240623160728623

image-20240623160733922

image-20240623160739429

3.题目详情增加点赞数据

1.sun-club-application-controller
1.SubjectInfoDTO.java 新增字段
/**
 * 是否被当前用户点赞
 */
private Boolean liked;

/**
 * 当前题目点赞的数量
 */
private Integer likedCount;
2.sun-club-domain
1.SubjectInfoBO.java 新增字段
/**
 * 是否被当前用户点赞
 */
private Boolean liked;

/**
 * 当前题目点赞的数量
 */
private Integer likedCount;
2.SubjectLikedDomainService.java
/**
 * 获取当前是否被点赞过
 */
Boolean isLiked(String subjectId, String userId);

/**
 * 获取点赞数量
 */
Integer getLikedCount(Long subjectId);
3.SubjectLikedDomainServiceImpl.java
@Override
public Boolean isLiked(String subjectId, String userId) {
    String detailKey = SUBJECT_LIKE_DETAIL_KEY + "." + subjectId + "." + userId;
    // 如果存在这个key,就说明该题目被这个用户点过赞了
    return redisUtil.exist(detailKey);
}

@Override
public Integer getLikedCount(Long subjectId) {
    String countKey = SUBJECT_LIKE_COUNT_KEY + "." + subjectId;
    Integer count = redisUtil.getInt(countKey);
    // 如果为空或0,直接返回0
    if (Objects.isNull(count) || count <= 0) {
        return 0;
    }
    return count;
}
4.SubjectInfoDomainServiceImpl.java 在查询题目信息时查询点赞信息
// ========== redis查询点赞信息 ==========
bo.setLiked(subjectLikedDomainService.isLiked(String.valueOf(subjectInfoBO.getId()), LoginUtil.getLoginId()));
bo.setLikedCount(subjectLikedDomainService.getLikedCount(subjectInfoBO.getId()));
// ========== redis查询点赞信息 ==========
3.测试
1.给508题目点赞

image-20240623164317097

2.查询508题目详情,发现被当前用户点赞了

image-20240623164239496

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

S-X-S

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值