package com.sf.service.impl; import com.google.gson.Gson; import com.sf.cons.RedisKeyConst; import com.sf.dto.resp.BookRankRespDto; import com.sf.entity.BookInfo; import com.sf.mapper.BookInfoMapper; import com.sf.service.IBookRankService; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Service; import java.util.List; import java.util.Set; // 基于redis @Service("bookRankServiceByRedis") @RequiredArgsConstructor public class BookRankByRedisServiceImpl implements IBookRankService { // 数据初始化 private final BookInfoMapper bookInfoMapper; private final RedisTemplate redisTemplate; private final Gson gson; @Override public List listVisitRankBooks() { return getRankDataByRedis(RedisKeyConst.VISIT_ZSET); } @Override public List listNewestRankBooks() { return getRankDataByRedis(RedisKeyConst.NEW_ZSET); } @Override public List listUpdateRankBooks() { return getRankDataByRedis(RedisKeyConst.UPDATE_ZSET); } private List getRankDataByRedis(String key){ ZSetOperations zSetOperations = redisTemplate.opsForZSet(); Set set = zSetOperations.reverseRange(key, 0, 29); return set.stream().map(str -> { // 将map中的每一个元素 转化为BookRankRespDto BookInfo bookInfo = gson.fromJson(str, BookInfo.class); BookRankRespDto bookRankRespDto = new BookRankRespDto(); BeanUtils.copyProperties(bookInfo, bookRankRespDto); return bookRankRespDto; }).toList(); } // 数据初始化 // private void initData() { // List bookInfos = bookInfoMapper.selectList(null); // ZSetOperations zSetOperations = redisTemplate.opsForZSet(); // for (BookInfo bookInfo : bookInfos) { // Long visitCount = bookInfo.getVisitCount(); // String bookInfoJson = gson.toJson(bookInfo); // zSetOperations.add(RedisKeyConst.VISIT_ZSET, bookInfoJson, visitCount); // } // } // 这是实时榜单的处理逻辑 @Override public void updateVisitRank(Long bookId) { BookInfo bookInfo = bookInfoMapper.selectById(bookId); String json = gson.toJson(bookInfo); // 此时的问题 是json中包含了访问量参数 而访问量会频繁变化 ZSetOperations zSetOperations = redisTemplate.opsForZSet(); // 每一次更新访问量 就将旧的数据移除 新的数据添加进去 保证数据的统一 zSetOperations.remove(RedisKeyConst.VISIT_ZSET, json); bookInfo.setVisitCount(bookInfo.getVisitCount() + 1); zSetOperations.add(RedisKeyConst.VISIT_ZSET, gson.toJson(bookInfo), bookInfo.getVisitCount()); } }