Browse Source

0722 整合redis

Qing 9 months ago
parent
commit
bffdac8d3a

+ 1 - 0
novel-demo/src/main/java/com/sf/config/SwaggerConfig.java

@@ -11,6 +11,7 @@ import org.springframework.context.annotation.Configuration;
 @Configuration
 public class SwaggerConfig {
 
+    // http://localhost:8888/swagger-ui.html
     @Bean
     public OpenAPI openAPI(){
         OpenAPI openAPI = new OpenAPI();

+ 10 - 2
novel-demo/src/main/java/com/sf/controller/BookCommentController.java

@@ -36,11 +36,19 @@ public class BookCommentController {
     @PostMapping("/api/front/user/comment")
     public RestResp<Void> addComment(@RequestBody UserCommentReqDto userCommentReqDto) {
         Long userId = UserHolder.getUserId();
-        if(userId == null){
-           return RestResp.fail("00005","用户登录失效了,请重新登录");
+        System.out.println("BookCommentController addComment: " + userId);
+        if (userId == null) {
+            return RestResp.fail("00005", "用户登录失效了,请重新登录");
         }
         userCommentReqDto.setUserId(userId);
         bookCommentService.saveComment(userCommentReqDto);
+
+        // 如果一个请求来了,但是又开了一个新线程,Threadlocal还能取到你说的全局id吗? 不能
+        // 因为ThreadLocal是对当前线程的备份 如果开启一个新的线程 获取不到之前线程的备份的
+//        new Thread(()->{
+//            Long threadUserId = UserHolder.getUserId();
+//            System.out.println("BookCommentController threadUserId: " + threadUserId);
+//        }).start();
         return RestResp.ok(null);
     }
 }

+ 54 - 6
novel-demo/src/main/java/com/sf/service/impl/HomeBookServiceImpl.java

@@ -20,6 +20,7 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -98,20 +99,65 @@ public class HomeBookServiceImpl extends ServiceImpl<HomeBookMapper, HomeBook> i
             list.add(homeBookRespDto);
         });
 
+        // 如果从mysql中取数据 再将数据存储到redis中
+        saveHomeBook(homeBookList, collected);
         return list;
     }
 
+    // 将数据存储到redis中
+    // 这里将已经从mysql中查到的数据传入 避免二次查询
+    public void saveHomeBook(List<HomeBook> homeBookList, Map<Long, BookInfo> bookInfoMap) {
+        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();
+            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 = bookInfoMap.get(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);
+    }
+
+    // 从redis中取数据
     public List<HomeBookRespDto> allHomeBookFromRedis() {
         List<HomeBookRespDto> homeBookRespDtoList = new ArrayList<>();
         ListOperations listOperations = redisTemplate.opsForList();
         HashOperations hashOperations = redisTemplate.opsForHash();
 
-        String key0 = "homeBookList0";
-        String key1 = "homeBookList1";
-        String key2 = "homeBookList2";
-        String key3 = "homeBookList3";
-        String key4 = "homeBookList4";
-        String hashKey = "bookHash";
+        // 对应5个类型的数据  比如homeBookList0 对应home_book表中type=0
+        String key0 = "book:homeBookList0";
+        String key1 = "book:homeBookList1";
+        String key2 = "book:homeBookList2";
+        String key3 = "book:homeBookList3";
+        String key4 = "book:homeBookList4";
+        String hashKey = "book:bookHash";
         List<String> bookIdList0 = listOperations.range(key0, 0, -1);
         List<String> bookIdList1 = listOperations.range(key1, 0, -1);
         List<String> bookIdList2 = listOperations.range(key2, 0, -1);
@@ -119,7 +165,9 @@ public class HomeBookServiceImpl extends ServiceImpl<HomeBookMapper, HomeBook> i
         List<String> bookIdList4 = listOperations.range(key4, 0, -1);
 
         List<String> current = bookIdList0;
+        // 兼容了数据为空的情况
         for (int i = 0; i < 5; i++) {
+            // 从第一个list 处理到第五个
             if (i == 1) current = bookIdList1;
             if (i == 2) current = bookIdList2;
             if (i == 3) current = bookIdList3;

+ 7 - 1
novel-demo/src/main/java/com/sf/service/impl/UserInfoServiceImpl.java

@@ -110,7 +110,13 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
         // 在存入数据库后 获取生成的id
         respDto.setUid(userInfo.getId());
 //        respDto.setToken("token_" + userInfo.getId());
-        respDto.setToken(jwtUtils.generateToken(userInfo.getId(), "front"));
+        String token = jwtUtils.generateToken(userInfo.getId(), "front");
+        respDto.setToken(token);
+        // 注册之后 自动登录 同样将token信息存储到redis中
+        // 当前的退出 是客户端处理的 没有登录状态的请求 不携带token信息
+        // 如果服务端也接收退出的请求  那么再从redis中删除此token
+        String tokenKey = "token_" + userInfo.getId();
+        redisTemplate.opsForValue().set(tokenKey, token, 10, TimeUnit.DAYS);
         return respDto;
     }
 

+ 2 - 0
novel-demo/src/main/java/com/sf/util/UserHolder.java

@@ -11,6 +11,8 @@ public class UserHolder {
     }
 
     public static Long getUserId() {
+        // 这里的threadLocal 是一个map结构
+        // map的key 是当前线程 value是当前线程的ThreadLocal
         return userHolder.get();
     }
 

+ 52 - 6
novel-demo/src/test/java/com/sf/RedisTests.java

@@ -1,6 +1,7 @@
 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;
@@ -86,6 +87,8 @@ public class RedisTests {
     @Autowired
     private Gson gson;
 
+    // homebook 数据初始化
+    // 使用了 list和hash的数据结构
     @Test
     public void testBook() {
         List<HomeBook> homeBookList = homeBookMapper.selectList(null);
@@ -100,6 +103,7 @@ public class RedisTests {
         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));
@@ -112,19 +116,61 @@ public class RedisTests {
             String json = gson.toJson(bookInfo);
             homeBookMap.put(bookId.toString(), json);
         }
-        String key0 = "homeBookList0";
-        String key1 = "homeBookList1";
-        String key2 = "homeBookList2";
-        String key3 = "homeBookList3";
-        String key4 = "homeBookList4";
+        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 = "bookHash";
+        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);
+    }
 }