Browse Source

0723 整合redis的set结构

Qing 9 months ago
parent
commit
27824d1472

+ 20 - 0
novel-demo/src/main/java/com/sf/controller/BookInfoController.java

@@ -1,5 +1,6 @@
 package com.sf.controller;
 
+import com.sf.dto.req.BookVisitReqDto;
 import com.sf.dto.resp.*;
 import com.sf.dto.RestResp;
 import com.sf.dto.req.BookSearchReqDto;
@@ -13,6 +14,8 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -113,4 +116,21 @@ public class BookInfoController {
         return RestResp.ok(chapterAboutRespDto);
     }
 
+    @Operation(summary = "增加小说点击量接口")
+    @PostMapping("/api/front/book/visit")
+    public RestResp<Void> addVisitCount(@Parameter(description = "小说ID")
+                                        @RequestBody BookVisitReqDto reqDto) {
+        bookInfoService.addVisitCount(Long.parseLong(reqDto.getBookId()));
+        return RestResp.ok(null);
+    }
+
+    // http://127.0.0.1:8888/api/front/book/rec_list
+    @Operation(summary = "推荐列表查询接口")
+    @GetMapping("/api/front/book/rec_list")
+    public RestResp<List<BookInfoRespDto>> listRecBooks(@Parameter(description = "小说ID") Long bookId) {
+        // 根据传递的书籍id 对应的书籍类型 找到同类型的书籍中 随机四本书
+        List<BookInfoRespDto> bookInfoRespDtos = bookInfoService.listRecBooks(bookId);
+        return RestResp.ok(bookInfoRespDtos);
+    }
+
 }

+ 8 - 0
novel-demo/src/main/java/com/sf/dto/req/BookVisitReqDto.java

@@ -0,0 +1,8 @@
+package com.sf.dto.req;
+
+import lombok.Data;
+
+@Data
+public class BookVisitReqDto {
+    private String bookId;
+}

+ 3 - 0
novel-demo/src/main/java/com/sf/mapper/BookInfoMapper.java

@@ -5,6 +5,7 @@ import com.sf.dto.req.BookSearchReqDto;
 import com.sf.entity.BookInfo;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -21,4 +22,6 @@ import java.util.List;
 public interface BookInfoMapper extends BaseMapper<BookInfo> {
 
     List<BookInfo> searchBooks(IPage page, BookSearchReqDto dto);
+
+    void addVisitCount(@Param("bookId") Long bookId);
 }

+ 3 - 0
novel-demo/src/main/java/com/sf/service/IBookInfoService.java

@@ -35,6 +35,9 @@ public interface IBookInfoService extends IService<BookInfo> {
      */
     BookInfoRespDto getBookInfo(Long id);
 
+    void addVisitCount(Long bookId);
+
+    List<BookInfoRespDto> listRecBooks(Long bookId);
 
     /**
      * 小说点击榜查询

+ 46 - 3
novel-demo/src/main/java/com/sf/service/impl/BookInfoServiceImpl.java

@@ -18,9 +18,13 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 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.SetOperations;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * <p>
@@ -42,6 +46,7 @@ public class BookInfoServiceImpl extends ServiceImpl<BookInfoMapper, BookInfo>
     private final BookInfoMapper bookInfoMapper;
     private final BookCategoryMapper bookCategoryMapper;
     private final BookChapterMapper bookChapterMapper;
+    private final RedisTemplate redisTemplate;
 
     // 分页的本质是limit  select * from book_info
     @Override
@@ -98,23 +103,61 @@ public class BookInfoServiceImpl extends ServiceImpl<BookInfoMapper, BookInfo>
         // 如果实体类的属性和dto的属性 名字相同
         BookInfoRespDto bookInfoRespDto = BookInfoRespDto.builder().build();
         // 拷贝属性  从bookInfo中拷贝同名属性 bookInfoRespDto
-        BeanUtils.copyProperties(bookInfo,bookInfoRespDto);
+        BeanUtils.copyProperties(bookInfo, bookInfoRespDto);
 
         // 增加首章id
         // select * from book_chapter where book_id='' and chapter_num=0
         LambdaQueryWrapper<BookChapter> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(BookChapter::getBookId, id);
-        queryWrapper.eq(BookChapter::getChapterNum,0);
+        queryWrapper.eq(BookChapter::getChapterNum, 0);
         // selectList 返回多条数据  selectOne是返回一条数据
         BookChapter bookChapter = bookChapterMapper.selectOne(queryWrapper);
         // 因为首章也可能没有
-        if(bookChapter != null){
+        if (bookChapter != null) {
             // ctrl + shift + ↑ / ↓
             bookInfoRespDto.setFirstChapterId(bookChapter.getId());
         }
         return bookInfoRespDto;
     }
 
+    @Override
+    public void addVisitCount(Long bookId) {
+        bookInfoMapper.addVisitCount(bookId);
+    }
+
+    @Override
+    public List<BookInfoRespDto> listRecBooks(Long bookId) {
+        // 推荐作为依据的书籍
+        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
+        Long categoryId = bookInfo.getCategoryId();
+
+        LambdaQueryWrapper<BookInfo> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(BookInfo::getCategoryId, categoryId);
+        // 返回的书籍列表中 包含初始的书籍
+        List<BookInfo> bookInfos = bookInfoMapper.selectList(queryWrapper);
+
+        String key = "book:myRecBooksSet" + bookInfo.getCategoryId();
+        SetOperations setOperations = redisTemplate.opsForSet();
+        for (BookInfo info : bookInfos) {
+            setOperations.add(key, info.getId());
+        }
+        setOperations.remove(key, bookInfo.getId());
+        // 随机不重复的元素
+        Set distinctRandomMembers = setOperations.distinctRandomMembers(key, 4);
+
+        List<BookInfoRespDto> bookInfoRespDtos = new ArrayList<>();
+        for (Object randomMember : distinctRandomMembers) {
+            Long randomMemberId = (Long) randomMember;
+            BookInfo selected = bookInfoMapper.selectById(randomMemberId);
+
+            BookInfoRespDto bookInfoRespDto = new BookInfoRespDto();
+            BeanUtils.copyProperties(selected, bookInfoRespDto);
+            bookInfoRespDtos.add(bookInfoRespDto);
+        }
+
+        return bookInfoRespDtos;
+    }
+
     @Override
     public List<BookRankRespDto> listVisitRankBooks() {
         LambdaQueryWrapper<BookInfo> bookInfoQueryWrapper = new LambdaQueryWrapper<>();

+ 6 - 0
novel-demo/src/main/resources/mapper/BookInfoMapper.xml

@@ -39,4 +39,10 @@
             order by ${dto.sort}
         </if>
     </select>
+
+    <update id="addVisitCount">
+        update book_info
+        set visit_count = visit_count + 1
+        where id = #{bookId}
+    </update>
 </mapper>

+ 122 - 0
novel-demo/src/test/java/com/sf/BookDataTests.java

@@ -0,0 +1,122 @@
+package com.sf;
+
+import com.google.gson.Gson;
+import com.sf.dto.resp.HomeBookRespDto;
+import com.sf.entity.BookInfo;
+import com.sf.entity.HomeBook;
+import com.sf.mapper.BookInfoMapper;
+import com.sf.mapper.HomeBookMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.ListOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SpringBootTest
+public class BookDataTests {
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    @Autowired
+    private HomeBookMapper homeBookMapper;
+
+    @Autowired
+    private BookInfoMapper bookInfoMapper;
+
+    @Autowired
+    private Gson gson;
+
+    // homebook 数据初始化
+    // 使用了 list和hash的数据结构
+    @Test
+    public void testBook() {
+        List<HomeBook> homeBookList = homeBookMapper.selectList(null);
+        ListOperations listOperations = redisTemplate.opsForList();
+        HashOperations hashOperations = redisTemplate.opsForHash();
+
+        List<String> bookIdList0 = new ArrayList<>();
+        List<String> bookIdList1 = new ArrayList<>();
+        List<String> bookIdList2 = new ArrayList<>();
+        List<String> bookIdList3 = new ArrayList<>();
+        List<String> bookIdList4 = new ArrayList<>();
+        Map<String, String> homeBookMap = new HashMap<>();
+        for (HomeBook homeBook : homeBookList) {
+            Long bookId = homeBook.getBookId();
+            // 根据type的类型不同 放入不同的list中
+            switch (homeBook.getType().intValue()) {
+                case 0 -> bookIdList0.add(String.valueOf(bookId));
+                case 1 -> bookIdList1.add(String.valueOf(bookId));
+                case 2 -> bookIdList2.add(String.valueOf(bookId));
+                case 3 -> bookIdList3.add(String.valueOf(bookId));
+                case 4 -> bookIdList4.add(String.valueOf(bookId));
+            }
+
+            BookInfo bookInfo = bookInfoMapper.selectById(bookId);
+            String json = gson.toJson(bookInfo);
+            homeBookMap.put(bookId.toString(), json);
+        }
+        String key0 = "book:homeBookList0";
+        String key1 = "book:homeBookList1";
+        String key2 = "book:homeBookList2";
+        String key3 = "book:homeBookList3";
+        String key4 = "book:homeBookList4";
+        listOperations.rightPushAll(key0, bookIdList0);
+        listOperations.rightPushAll(key1, bookIdList1);
+        listOperations.rightPushAll(key2, bookIdList2);
+        listOperations.rightPushAll(key3, bookIdList3);
+        listOperations.rightPushAll(key4, bookIdList4);
+
+        String hashKey = "book:bookHash";
+        hashOperations.putAll(hashKey, homeBookMap);
+
+    }
+
+
+    @Test
+    public void testBook1() {
+        List<HomeBook> homeBookList = homeBookMapper.selectList(null);
+        ListOperations listOperations = redisTemplate.opsForList();
+        HashOperations hashOperations = redisTemplate.opsForHash();
+        List<String> homeBookRedisList = new ArrayList<>();
+        for (HomeBook homeBook : homeBookList) {
+            Integer type = (int) homeBook.getType();
+            Long bookId = homeBook.getBookId();
+            String value = type + "," + bookId;
+            homeBookRedisList.add(value);
+        }
+        String key = "book:homeBookList";
+        listOperations.rightPushAll(key, homeBookRedisList);
+
+
+        List<HomeBookRespDto> homeBookRespDtoList = new ArrayList<>();
+        String hashKey = "book:bookHash";
+        List<String> range = listOperations.range(key, 0, -1);
+        for (String value : range) {
+            String[] split = value.split(",");
+            Integer type = Integer.parseInt(split[0]);
+            Long bookId = Long.parseLong(split[1]);
+            String json = (String) hashOperations.get(hashKey, bookId.toString());
+            // 通过gson转化成对象
+            BookInfo bookInfo = gson.fromJson(json, BookInfo.class);
+            if (bookInfo != null) {
+                HomeBookRespDto homeBookRespDto = HomeBookRespDto.builder()
+                        .type(type)  // byte -> int
+                        .bookId(bookId)
+                        .picUrl(bookInfo.getPicUrl())
+                        .bookName(bookInfo.getBookName())
+                        .authorName(bookInfo.getAuthorName())
+                        .bookDesc(bookInfo.getBookDesc())
+                        .build();
+                homeBookRespDtoList.add(homeBookRespDto);
+            }
+        }
+        System.out.println(homeBookRespDtoList);
+    }
+}

+ 42 - 96
novel-demo/src/test/java/com/sf/RedisTests.java

@@ -1,18 +1,9 @@
 package com.sf;
 
-import com.google.gson.Gson;
-import com.sf.dto.resp.HomeBookRespDto;
-import com.sf.entity.BookInfo;
-import com.sf.entity.HomeBook;
-import com.sf.mapper.BookInfoMapper;
-import com.sf.mapper.HomeBookMapper;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.data.redis.core.HashOperations;
-import org.springframework.data.redis.core.ListOperations;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.data.redis.core.*;
 
 import java.util.*;
 
@@ -78,99 +69,54 @@ public class RedisTests {
     }
 
 
-    @Autowired
-    private HomeBookMapper homeBookMapper;
+    @Test
+    public void testSet() {
+        // 对集合的操作
+        SetOperations setOperations = redisTemplate.opsForSet();
+        String key = "testSet:myset1";
+        Long add = setOperations.add(key, "12", "13", "14", "15");
+        System.out.println(add);
 
-    @Autowired
-    private BookInfoMapper bookInfoMapper;
+        Long size = setOperations.size(key);
+        System.out.println(size);
 
-    @Autowired
-    private Gson gson;
+        Boolean isMember = setOperations.isMember(key, "12");
+        System.out.println(isMember);
 
-    // homebook 数据初始化
-    // 使用了 list和hash的数据结构
-    @Test
-    public void testBook() {
-        List<HomeBook> homeBookList = homeBookMapper.selectList(null);
-        ListOperations listOperations = redisTemplate.opsForList();
-        HashOperations hashOperations = redisTemplate.opsForHash();
+        Object object = setOperations.randomMember(key);
+        System.out.println(object);
 
-        List<String> bookIdList0 = new ArrayList<>();
-        List<String> bookIdList1 = new ArrayList<>();
-        List<String> bookIdList2 = new ArrayList<>();
-        List<String> bookIdList3 = new ArrayList<>();
-        List<String> bookIdList4 = new ArrayList<>();
-        Map<String, String> homeBookMap = new HashMap<>();
-        for (HomeBook homeBook : homeBookList) {
-            Long bookId = homeBook.getBookId();
-            // 根据type的类型不同 放入不同的list中
-            switch (homeBook.getType().intValue()) {
-                case 0 -> bookIdList0.add(String.valueOf(bookId));
-                case 1 -> bookIdList1.add(String.valueOf(bookId));
-                case 2 -> bookIdList2.add(String.valueOf(bookId));
-                case 3 -> bookIdList3.add(String.valueOf(bookId));
-                case 4 -> bookIdList4.add(String.valueOf(bookId));
-            }
-
-            BookInfo bookInfo = bookInfoMapper.selectById(bookId);
-            String json = gson.toJson(bookInfo);
-            homeBookMap.put(bookId.toString(), json);
-        }
-        String key0 = "book:homeBookList0";
-        String key1 = "book:homeBookList1";
-        String key2 = "book:homeBookList2";
-        String key3 = "book:homeBookList3";
-        String key4 = "book:homeBookList4";
-        listOperations.rightPushAll(key0, bookIdList0);
-        listOperations.rightPushAll(key1, bookIdList1);
-        listOperations.rightPushAll(key2, bookIdList2);
-        listOperations.rightPushAll(key3, bookIdList3);
-        listOperations.rightPushAll(key4, bookIdList4);
-
-        String hashKey = "book:bookHash";
-        hashOperations.putAll(hashKey, homeBookMap);
+        Set set = setOperations.distinctRandomMembers(key, 8);
+        System.out.println(set);
 
-    }
+        Object pop = setOperations.pop(key);
+        System.out.println(pop);
 
+        Set members = setOperations.members(key);
+        System.out.println(members);
+    }
 
     @Test
-    public void testBook1() {
-        List<HomeBook> homeBookList = homeBookMapper.selectList(null);
-        ListOperations listOperations = redisTemplate.opsForList();
-        HashOperations hashOperations = redisTemplate.opsForHash();
-        List<String> homeBookRedisList = new ArrayList<>();
-        for (HomeBook homeBook : homeBookList) {
-            Integer type = (int) homeBook.getType();
-            Long bookId = homeBook.getBookId();
-            String value = type + "," + bookId;
-            homeBookRedisList.add(value);
-        }
-        String key = "book:homeBookList";
-        listOperations.rightPushAll(key, homeBookRedisList);
-
-
-        List<HomeBookRespDto> homeBookRespDtoList = new ArrayList<>();
-        String hashKey = "book:bookHash";
-        List<String> range = listOperations.range(key, 0, -1);
-        for (String value : range) {
-            String[] split = value.split(",");
-            Integer type = Integer.parseInt(split[0]);
-            Long bookId = Long.parseLong(split[1]);
-            String json = (String) hashOperations.get(hashKey, bookId.toString());
-            // 通过gson转化成对象
-            BookInfo bookInfo = gson.fromJson(json, BookInfo.class);
-            if (bookInfo != null) {
-                HomeBookRespDto homeBookRespDto = HomeBookRespDto.builder()
-                        .type(type)  // byte -> int
-                        .bookId(bookId)
-                        .picUrl(bookInfo.getPicUrl())
-                        .bookName(bookInfo.getBookName())
-                        .authorName(bookInfo.getAuthorName())
-                        .bookDesc(bookInfo.getBookDesc())
-                        .build();
-                homeBookRespDtoList.add(homeBookRespDto);
-            }
-        }
-        System.out.println(homeBookRespDtoList);
+    public void testZSet() {
+        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
+        String key = "testSet:myzset";
+        zSetOperations.add(key,"zhangsan",90);
+        zSetOperations.add(key,"lisi",80);
+        zSetOperations.add(key,"wangwu",70);
+        zSetOperations.add(key,"zhaoliu",60);
+
+        Set range = zSetOperations.range(key, 0, -1);
+        System.out.println(range);
+
+        Set set = zSetOperations.rangeWithScores(key, 0, -1);
+        System.out.println(set);
+
+        Long rank = zSetOperations.rank(key, "lisi");
+        System.out.println(rank);
+        Long reverseRank = zSetOperations.reverseRank(key, "lisi");
+        System.out.println(reverseRank);
+
     }
+
+
 }