|
@@ -0,0 +1,83 @@
|
|
|
+package com.sf.service.impl;
|
|
|
+
|
|
|
+import com.google.gson.Gson;
|
|
|
+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.beans.factory.annotation.Autowired;
|
|
|
+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<BookRankRespDto> listVisitRankBooks() {
|
|
|
+ // 将书籍对象的json放入zset的value中 点击量放入scores
|
|
|
+ String key = "book:visitZset";
|
|
|
+ // 当zset中已经有值时 只需要从zset中取数据
|
|
|
+ ZSetOperations zSetOperations = redisTemplate.opsForZSet();
|
|
|
+ Long size = zSetOperations.size(key);
|
|
|
+ if (size == 0) {
|
|
|
+ System.out.println("visitZset size:" + size);
|
|
|
+ initData();
|
|
|
+ }
|
|
|
+ Set set = zSetOperations.reverseRange(key, 0, 30);
|
|
|
+ return set.stream().map(obj -> {
|
|
|
+ // 将map中的每一个元素 转化为BookRankRespDto
|
|
|
+ String str = (String) obj;
|
|
|
+ BookInfo bookInfo = gson.fromJson(str, BookInfo.class);
|
|
|
+ BookRankRespDto bookRankRespDto = new BookRankRespDto();
|
|
|
+ BeanUtils.copyProperties(bookInfo, bookRankRespDto);
|
|
|
+ return bookRankRespDto;
|
|
|
+ }).toList();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 数据初始化
|
|
|
+ private void initData() {
|
|
|
+ String key = "book:visitZset";
|
|
|
+ List<BookInfo> bookInfos = bookInfoMapper.selectList(null);
|
|
|
+ ZSetOperations zSetOperations = redisTemplate.opsForZSet();
|
|
|
+ for (BookInfo bookInfo : bookInfos) {
|
|
|
+ Long visitCount = bookInfo.getVisitCount();
|
|
|
+ String bookInfoJson = gson.toJson(bookInfo);
|
|
|
+ zSetOperations.add(key, bookInfoJson, visitCount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<BookRankRespDto> listNewestRankBooks() {
|
|
|
+ return List.of();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<BookRankRespDto> listUpdateRankBooks() {
|
|
|
+ return List.of();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateVisitRank(Long bookId) {
|
|
|
+ String key = "book:visitZset";
|
|
|
+ BookInfo bookInfo = bookInfoMapper.selectById(bookId);
|
|
|
+ String json = gson.toJson(bookInfo);
|
|
|
+ // 此时的问题 是json中包含了访问量参数 而访问量会频繁变化
|
|
|
+ ZSetOperations zSetOperations = redisTemplate.opsForZSet();
|
|
|
+ // 每一次更新访问量 就将旧的数据移除 新的数据添加进去 保证数据的统一
|
|
|
+ zSetOperations.remove(key, json);
|
|
|
+ bookInfo.setVisitCount(bookInfo.getVisitCount() + 1);
|
|
|
+ zSetOperations.add(key, gson.toJson(bookInfo), bookInfo.getVisitCount());
|
|
|
+ }
|
|
|
+}
|