Bläddra i källkod

- 添加自定义缓存

tianyunperfect 3 år sedan
förälder
incheckning
2d0cb86964

+ 1 - 0
book-dao/src/main/java/com/book/dao/VO/QueryVO.java

@@ -17,4 +17,5 @@ public class QueryVO {
 
     Long id;
 
+    Long bookId;
 }

+ 11 - 4
book-server/src/main/java/com/book/server/controller/BookController.java

@@ -140,7 +140,7 @@ public class BookController extends BaseController {
      */
     @PostMapping("/content")
     public Result<BookContent> getBookContentByChapter(@RequestBody BookContentVO bookContentVO) {
-        return  bookService.getContentByContentId(bookContentVO);
+        return bookService.getContentByContentId(bookContentVO);
     }
 
     /**
@@ -156,6 +156,7 @@ public class BookController extends BaseController {
 
     /**
      * 获取指定书籍的阅读记录
+     *
      * @param userRecentlyRead
      * @return
      */
@@ -163,8 +164,10 @@ public class BookController extends BaseController {
     public Result<UserRecentlyRead> getRecentReadByUserIdAndBookId(@RequestBody UserRecentlyRead userRecentlyRead) {
         return Result.byObject(bookService.getRecentReadByUserIdAndBookId(userRecentlyRead));
     }
+
     /**
      * 获取指定用户的阅读记录
+     *
      * @param userRecentlyRead
      * @return
      */
@@ -175,6 +178,7 @@ public class BookController extends BaseController {
 
     /**
      * 获取购买章节列表
+     *
      * @param bookContentVO
      * @return
      */
@@ -185,19 +189,21 @@ public class BookController extends BaseController {
 
     /**
      * 自定义书籍上传
+     *
      * @param file
      * @param bookId
      * @return
      * @throws IOException
      */
     @PostMapping("/upload")
-    public Result uploadFile(@RequestParam("file") MultipartFile file,Long bookId) throws IOException {
+    public Result uploadFile(@RequestParam("file") MultipartFile file, Long bookId) throws IOException {
         if (file.isEmpty()) {
             return Result.failure();
         }
-        bookService.addFile(file,bookId);
+        bookService.addFile(file, bookId);
         return Result.success("添加成功");
     }
+
     /**
      * 后台-获取章节书籍内容
      *
@@ -206,11 +212,12 @@ public class BookController extends BaseController {
      */
     @PostMapping("/content-05863069-1AE0-435C-9283-2515A4A31BF7")
     public Result<BookContent> getBookContentByChapter2(@RequestBody BookContentVO bookContentVO) {
-        return  bookService.getContentByContentId2(bookContentVO);
+        return bookService.getContentByContentId2(bookContentVO);
     }
 
     /**
      * 后台-更新章节内容
+     *
      * @param bookContentVO
      * @return
      */

+ 185 - 19
book-server/src/main/java/com/book/server/service/impl/BookServiceImpl.java

@@ -30,6 +30,7 @@ import com.google.gson.JsonParser;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
@@ -74,8 +75,18 @@ public class BookServiceImpl implements BookService {
 
     @Override
     public List<BookRes> query(QueryVO queryVO) {
-        queryVO.setQuery("%" + queryVO.getQuery() + "%");
-        List<BookRes> bookResList = bookMapper2.queryBookRes(queryVO, queryVO.getPage() * queryVO.getSize(), queryVO.getSize());
+        List<BookRes> bookResList = new ArrayList<>();
+        if (queryVO.getBookId() != null) {
+            Book bookById = getBookById(queryVO.getBookId());
+            String categoryName = getCategoryName(bookById.getBookCategoryId());
+            BookRes bookRes = new BookRes();
+            BeanUtils.copyProperties(bookById, bookRes);
+            bookRes.setCategoryName(categoryName);
+            bookResList.add(bookRes);
+        } else {
+            queryVO.setQuery("%" + queryVO.getQuery() + "%");
+            bookResList = bookMapper2.queryBookRes(queryVO, queryVO.getPage() * queryVO.getSize(), queryVO.getSize());
+        }
         return bookResList;
     }
 
@@ -85,13 +96,44 @@ public class BookServiceImpl implements BookService {
         if (queryVO.getPage() == 5) {
             return bookRes;
         }
+        return getRecommendFromCache(queryVO);
+    }
+
+    public List<BookRes> getRecommendFromCache(QueryVO queryVO) {
+        String key = "recommend_" + queryVO.getSex() + "_" + queryVO.getPage() + "_" + queryVO.getSize();
+        Object o = redisUtil.get(key);
+        if (o == null) {
+            return setRecommendCache(key, queryVO);
+        } else {
+            return (List<BookRes>) o;
+        }
+    }
+
+    public synchronized List<BookRes> setRecommendCache(String key, QueryVO queryVO) {
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (List<BookRes>) o;
+        }
         List<BookRes> books = bookMapper2.novelEndRecommend(queryVO,
                 queryVO.getPage() * queryVO.getSize(), queryVO.getSize());
+        redisUtil.setWithTime(key, books);
         return books;
     }
 
     @Override
     public List<BlockRes> getBlockByPageId(Integer pageId) {
+        ArrayList<BlockRes> list = setBlockByPageIdCache(pageId);
+        return list;
+    }
+
+    private synchronized ArrayList<BlockRes> setBlockByPageIdCache(Integer pageId) {
+        //缓存
+        String key = pageId.toString();
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (ArrayList<BlockRes>) o;
+        }
+        //没有缓存
         ArrayList<BlockRes> list = new ArrayList<>();
         // 获取板块
         ManageBlockExample manageBlockExample = ManageBlockExample.newAndCreateCriteria()
@@ -100,7 +142,6 @@ public class BookServiceImpl implements BookService {
         manageBlockExample.orderBy(ManageBlock.Column.weigh.desc());
         List<ManageBlock> manageBlocks = manageBlockMapper.selectByExample(manageBlockExample);
 
-
         // 获取已有版本的所有书籍
         List<Integer> blockIds = manageBlocks.stream().map(ManageBlock::getId).collect(Collectors.toList());
         List<ManageBlockResourceRes> blockResourceResList = manageBlockResource2Mapper.getBooks(blockIds);
@@ -120,9 +161,11 @@ public class BookServiceImpl implements BookService {
             blockRes.setResources(map.getOrDefault(x.getId(), new TreeSet<>()));
             list.add(blockRes);
         });
+        redisUtil.setWithTime(key, list);
         return list;
     }
 
+
     @Override
     public void insertBooks() {
 
@@ -230,11 +273,29 @@ public class BookServiceImpl implements BookService {
 
     @Override
     public List<Chapter> getChaptersByBookId(Long bookId) {
-        List<Chapter> list = new ArrayList<>();
-
         if (bookId == null) {
             throw new IllegalArgumentException("bookId cannot be null or empty");
         }
+
+        //缓存
+        String key = "chaptersByBookId" + bookId;
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (List<Chapter>) o;
+        } else {
+            return setChaptersByBookIdCache(bookId);
+        }
+    }
+
+    private synchronized List<Chapter> setChaptersByBookIdCache(Long bookId) {
+        String key = "chaptersByBookId" + bookId;
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (List<Chapter>) o;
+        }
+
+        List<Chapter> list = new ArrayList<>();
+
         final String chaptersUrl = "http://new.emeixs.com/index.php/Home/Interface/chapters/bid/" + bookId;
         String result = HttpTool.sendGet(chaptersUrl, "");
         if (StringUtils.isEmpty(result)) {
@@ -263,22 +324,39 @@ public class BookServiceImpl implements BookService {
             chapter.setType(jsonObject.get("type").getAsString());
             chapter.setVolumeId(jsonObject.get("volume_id").getAsString());
             chapter.setWords(jsonObject.get("words").getAsString());
-            if (i + 1 == freeChapterNum) {
+            if (i + 1 <= freeChapterNum) {
                 chapter.setReadAble("0");
             }
             list.add(chapter);
         }
-
+        redisUtil.setWithTime(key, list);
         return list;
     }
 
     @Override
     public List<SearchKeyword> getSearchKeywordBySex(String sex) {
+        String key = "getSearchKeywordBySex" + sex;
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (List<SearchKeyword>) o;
+        } else {
+            return getSearchKeywordsCache(key, sex);
+        }
+    }
+
+    private List<SearchKeyword> getSearchKeywordsCache(String key, String sex) {
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (List<SearchKeyword>) o;
+        }
+
         SearchKeywordExample example = SearchKeywordExample.newAndCreateCriteria()
                 .andSexEqualTo(sex)
                 .example();
         example.orderBy(SearchKeyword.Column.weigh.desc());
         List<SearchKeyword> searchKeywords = searchKeywordMapper.selectByExample(example);
+
+        redisUtil.setWithTime(key, searchKeywords);
         return searchKeywords;
     }
 
@@ -288,9 +366,35 @@ public class BookServiceImpl implements BookService {
         return getRandom(bookRes);
     }
 
+    private synchronized List<BookRes> setTopRecommendCache(String key, QueryVO queryVO) {
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (List<BookRes>) o;
+        }
+        List<BookRes> bookRes = bookMapper2.topRecommend(queryVO, 0, 20);
+        redisUtil.setWithTime(key, bookRes);
+        return bookRes;
+    }
+
     @Override
     public List<BookRes> smartRecommand(QueryVO queryVO) {
+        String key = "smartRecommand_" + queryVO.getSex();
+        Object o = redisUtil.get(key);
+        if (o == null) {
+            List<BookRes> bookRes = setSmartRecommandCache(queryVO, key);
+            return bookRes;
+        } else {
+            return (List<BookRes>) o;
+        }
+    }
+
+    private synchronized List<BookRes> setSmartRecommandCache(QueryVO queryVO, String key) {
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (List<BookRes>) o;
+        }
         List<BookRes> bookRes = bookMapper2.smartRecommand(queryVO);
+        redisUtil.setWithTime(key, bookRes);
         return bookRes;
     }
 
@@ -356,7 +460,7 @@ public class BookServiceImpl implements BookService {
                     // 更新免费看点到 user
                     int i = userMapper.updateUserKandian(user, user.getKandian(), freeCount - book.getPrice(), DateUtils.getNow());
                     checkUpdate(i);
-                    updateUserById(user.getId());
+                    updateUserByIdCache(user.getId());
 
                 } else if (user.getKandian() + freeCount > book.getPrice()) { //免费+充值足够
                     Integer left = user.getKandian() + freeCount;
@@ -375,7 +479,7 @@ public class BookServiceImpl implements BookService {
                     // 更新到 user
                     int i = userMapper.updateUserKandian(user, kandian, 0, DateUtils.getNow());
                     checkUpdate(i);
-                    updateUserById(user.getId());
+                    updateUserByIdCache(user.getId());
 
                 } else {
                     return Result.failure(ResultCode.NOMONEY);
@@ -421,7 +525,23 @@ public class BookServiceImpl implements BookService {
     }
 
     private BookContent getBookContent(BookContentVO bookContentVO) {
+        String key = "" + bookContentVO.getBookId() + bookContentVO.getContentId();
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (BookContent) o;
+        } else {
+            return setBookContentCache(key, bookContentVO);
+        }
+    }
+
+    private synchronized BookContent setBookContentCache(String key, BookContentVO bookContentVO) {
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (BookContent) o;
+        }
+
         BookContent bookContent;
+        // 修改过的章节
         String content = getEditBookContentById(bookContentVO.getBookId(), bookContentVO.getContentId());
         if (content != null) {
             return getBookContentFromVO(bookContentVO, content);
@@ -433,6 +553,7 @@ public class BookServiceImpl implements BookService {
         } else {
             bookContent = getBookContentFromRemote(bookContentVO);
         }
+        redisUtil.setWithTime(key, bookContent);
         return bookContent;
     }
 
@@ -752,14 +873,23 @@ public class BookServiceImpl implements BookService {
         String key = "defaultFreeChapterNum";
         Object o = redisUtil.get(key);
         if (o == null) {
-            int book_free_chapter_num = Integer.parseInt(configMapper.selectByName("book_free_chapter_num").getValue());
-            redisUtil.set(key, book_free_chapter_num, 1, TimeUnit.HOURS);
+            int book_free_chapter_num = setBook_free_chapter_num(key);
             return book_free_chapter_num;
         } else {
             return (int) o;
         }
     }
 
+    private synchronized int setBook_free_chapter_num(String key) {
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (int) o;
+        }
+        int book_free_chapter_num = Integer.parseInt(configMapper.selectByName("book_free_chapter_num").getValue());
+        redisUtil.setWithTime(key, book_free_chapter_num);
+        return book_free_chapter_num;
+    }
+
     public Book getBookById(Long id) {
         String key = "book" + id;
         Object o = redisUtil.get(key);
@@ -770,10 +900,14 @@ public class BookServiceImpl implements BookService {
         }
     }
 
-    public Book updateBookByIdToRedis(Long id) {
+    public synchronized Book updateBookByIdToRedis(Long id) {
         String key = "book" + id;
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (Book) o;
+        }
         Book obj = bookMapper.selectByPrimaryKey(id);
-        redisUtil.set(key, obj, 15, TimeUnit.MINUTES);
+        redisUtil.setWithTime(key, obj);
         return obj;
     }
 
@@ -781,19 +915,52 @@ public class BookServiceImpl implements BookService {
         String key = "user" + id;
         Object o = redisUtil.get(key);
         if (o == null) {
-            return updateUserById(id);
+            return updateUserByIdCache(id);
         } else {
             return (User) o;
         }
     }
 
-    public User updateUserById(Long id) {
+    public synchronized User updateUserByIdCache(Long id) {
         String key = "user" + id;
+        Object o = redisUtil.get(key);
+        if (o != null) {
+            return (User) o;
+        }
         User obj = userMapper.selectByPrimaryKey(id);
-        redisUtil.set(key, obj, 30, TimeUnit.MINUTES);
+        redisUtil.setWithTime(key, obj);
         return obj;
     }
 
+    public String getCategoryName(Integer id) {
+        String key = "category";
+        Object o = redisUtil.hashGet(key, id);
+        if (o == null) {
+            String name = setCategoryCache(id, key);
+            return name;
+        } else {
+            return (String) o;
+        }
+    }
+
+    private synchronized String setCategoryCache(Integer id, String key) {
+        Object o = redisUtil.hashGet(key, id);
+        if (o != null) {
+            return (String) o;
+        }
+        List<BookCategory> bookCategories = bookCategoryMapper.selectByExample(BookCategoryExample.newAndCreateCriteria().example());
+        String name = "";
+        for (BookCategory x : bookCategories) {
+            redisUtil.hashSet(key, x.getId(), x.getName());
+            if (x.getId() == id) {
+                name = x.getName();
+            }
+        }
+        redisTemplate.expire(key, redisUtil.getRandomTime(), TimeUnit.MINUTES);
+        return name;
+    }
+
+
     @Autowired
     private RedisTemplate redisTemplate;
 
@@ -807,7 +974,7 @@ public class BookServiceImpl implements BookService {
         }
     }
 
-    public EditBook updateEditBookById(Long bookId, Long chapterId) {
+    public synchronized void updateEditBookById(Long bookId, Long chapterId) {
         String key = "edit_book" + bookId + chapterId;
         EditBook obj = editBookMapper.selectOneByExampleSelective(
                 EditBookExample.newAndCreateCriteria()
@@ -817,11 +984,10 @@ public class BookServiceImpl implements BookService {
                 EditBook.Column.content
         );
         redisUtil.set(key, obj);
-        return obj;
     }
 
     @PostConstruct
-    public void initUpdateEditBookIds() {
+    public void initUpdateEditBookIdsCache() {
         List<EditBook> editBooks = editBookMapper.selectByExampleSelective(EditBookExample.newAndCreateCriteria().example(),
                 EditBook.Column.bookId, EditBook.Column.chapterId, EditBook.Column.content);
         editBooks.forEach(x -> {

+ 43 - 21
book-server/src/main/java/com/book/server/utils/RedisUtil.java

@@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
 import java.io.Serializable;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 
 @Service
@@ -18,6 +19,7 @@ public class RedisUtil {
 
     /**
      * set value
+     *
      * @param key
      * @param value
      * @return
@@ -29,19 +31,20 @@ public class RedisUtil {
             operations.set(key, value);
             result = true;
         } catch (Exception e) {
-            log.error("set error: key {}, value {}",key,value,e);
+            log.error("set error: key {}, value {}", key, value, e);
         }
         return result;
     }
 
     /**
      * set value with expireTime
+     *
      * @param key
      * @param value
      * @param expireTime
      * @return
      */
-    public boolean set(final String key, Object value, int expireTime,TimeUnit timeUnit) {
+    public boolean set(final String key, Object value, int expireTime, TimeUnit timeUnit) {
         boolean result = false;
         try {
             ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
@@ -49,11 +52,19 @@ public class RedisUtil {
             redisTemplate.expire(key, expireTime, timeUnit);
             result = true;
         } catch (Exception e) {
-            log.error("set error: key {}, value {},expireTime {}",key,value,expireTime,e);
+            log.error("set error: key {}, value {},expireTime {}", key, value, expireTime, e);
         }
         return result;
     }
 
+    public boolean setWithTime(final String key, Object value) {
+        return set(key, value, getRandomTime(), TimeUnit.MINUTES);
+    }
+
+    public int getRandomTime() {
+        return 15 + ThreadLocalRandom.current().nextInt(15);
+    }
+
     /**
      * @param key
      * @return
@@ -75,6 +86,7 @@ public class RedisUtil {
 
     /**
      * remove single key
+     *
      * @param key
      */
     public void remove(final String key) {
@@ -85,6 +97,7 @@ public class RedisUtil {
 
     /**
      * batch delete
+     *
      * @param keys
      */
     public void remove(final String... keys) {
@@ -95,6 +108,7 @@ public class RedisUtil {
 
     /**
      * batch delete with pattern
+     *
      * @param pattern
      */
     public void removePattern(final String pattern) {
@@ -105,87 +119,95 @@ public class RedisUtil {
 
     /**
      * hash set
+     *
      * @param key
      * @param hashKey
      * @param value
      */
-    public void hashSet(String key, Object hashKey, Object value){
+    public void hashSet(String key, Object hashKey, Object value) {
         HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
-        hash.put(key,hashKey,value);
+        hash.put(key, hashKey, value);
     }
 
     /**
      * hash get
+     *
      * @param key
      * @param hashKey
      * @return
      */
-    public Object hashGet(String key, Object hashKey){
-        HashOperations<String, Object, Object>  hash = redisTemplate.opsForHash();
-        return hash.get(key,hashKey);
+    public Object hashGet(String key, Object hashKey) {
+        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
+        return hash.get(key, hashKey);
     }
 
     /**
-     *  list push
+     * list push
+     *
      * @param k
      * @param v
      */
-    public void push(String k,Object v){
+    public void push(String k, Object v) {
         ListOperations<String, Object> list = redisTemplate.opsForList();
-        list.rightPush(k,v);
+        list.rightPush(k, v);
     }
 
     /**
-     *  list range
+     * list range
+     *
      * @param k
      * @param l
      * @param l1
      * @return
      */
-    public List<Object> range(String k, long l, long l1){
+    public List<Object> range(String k, long l, long l1) {
         ListOperations<String, Object> list = redisTemplate.opsForList();
-        return list.range(k,l,l1);
+        return list.range(k, l, l1);
     }
 
     /**
-     *  set add
+     * set add
+     *
      * @param key
      * @param value
      */
-    public void setAdd(String key,Object value){
+    public void setAdd(String key, Object value) {
         SetOperations<String, Object> set = redisTemplate.opsForSet();
-        set.add(key,value);
+        set.add(key, value);
     }
 
     /**
      * set get
+     *
      * @param key
      * @return
      */
-    public Set<Object> setMembers(String key){
+    public Set<Object> setMembers(String key) {
         SetOperations<String, Object> set = redisTemplate.opsForSet();
         return set.members(key);
     }
 
     /**
      * ordered set add
+     *
      * @param key
      * @param value
      * @param scoure
      */
-    public void zAdd(String key,Object value,double scoure){
+    public void zAdd(String key, Object value, double scoure) {
         ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
-        zset.add(key,value,scoure);
+        zset.add(key, value, scoure);
     }
 
     /**
      * rangeByScore
+     *
      * @param key
      * @param scoure
      * @param scoure1
      * @return
      */
-    public Set<Object> rangeByScore(String key, double scoure, double scoure1){
+    public Set<Object> rangeByScore(String key, double scoure, double scoure1) {
         ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
         return zset.rangeByScore(key, scoure, scoure1);
     }