feat: 新增小说内容查询接口

This commit is contained in:
xiongxiaoyang 2022-05-15 14:00:21 +08:00
parent da1df4fddb
commit b2446ff160
10 changed files with 289 additions and 23 deletions

View File

@ -2,6 +2,7 @@ package io.github.xxyopen.novel.controller.front;
import io.github.xxyopen.novel.core.common.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.common.constant.ApiRouterConsts;
import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.common.resp.RestResp;
import io.github.xxyopen.novel.dto.resp.BookContentRespDto;
import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto;
import io.github.xxyopen.novel.dto.resp.BookRankRespDto; import io.github.xxyopen.novel.dto.resp.BookRankRespDto;
import io.github.xxyopen.novel.service.BookService; import io.github.xxyopen.novel.service.BookService;
@ -30,8 +31,16 @@ public class BookController {
* 小说信息查询接口 * 小说信息查询接口
* */ * */
@GetMapping("{bookId}") @GetMapping("{bookId}")
public RestResp<BookInfoRespDto> getById(@PathVariable("bookId") Long bookId){ public RestResp<BookInfoRespDto> getBookById(@PathVariable("bookId") Long bookId){
return bookService.getById(bookId); return bookService.getBookById(bookId);
}
/**
* 小说章节内容查询接口
* */
@GetMapping("content/{chapterId}")
public RestResp<BookContentRespDto> getBookContent(@PathVariable("chapterId") Long chapterId){
return bookService.getBookContent(chapterId);
} }
/** /**

View File

@ -10,73 +10,88 @@ public class CacheConsts {
/** /**
* 本项目 Redis 缓存前缀 * 本项目 Redis 缓存前缀
* */ */
public static final String REDIS_CACHE_PREFIX = "Cache::Novel::"; public static final String REDIS_CACHE_PREFIX = "Cache::Novel::";
/** /**
* Caffeine 缓存管理器 * Caffeine 缓存管理器
* */ */
public static final String CAFFEINE_CACHE_MANAGER = "caffeineCacheManager"; public static final String CAFFEINE_CACHE_MANAGER = "caffeineCacheManager";
/** /**
* Redis 缓存管理器 * Redis 缓存管理器
* */ */
public static final String REDIS_CACHE_MANAGER = "redisCacheManager"; public static final String REDIS_CACHE_MANAGER = "redisCacheManager";
/** /**
* 首页小说推荐缓存 * 首页小说推荐缓存
* */ */
public static final String HOME_BOOK_CACHE_NAME = "homeBookCache"; public static final String HOME_BOOK_CACHE_NAME = "homeBookCache";
/** /**
* 最新新闻缓存 * 最新新闻缓存
* */ */
public static final String LATEST_NEWS_CACHE_NAME = "latestNewsCache"; public static final String LATEST_NEWS_CACHE_NAME = "latestNewsCache";
/** /**
* 小说点击榜缓存 * 小说点击榜缓存
* */ */
public static final String BOOK_VISIT_RANK_CACHE_NAME = "bookVisitRankCache"; public static final String BOOK_VISIT_RANK_CACHE_NAME = "bookVisitRankCache";
/** /**
* 小说新书榜缓存 * 小说新书榜缓存
* */ */
public static final String BOOK_NEWEST_RANK_CACHE_NAME = "bookNewestRankCache"; public static final String BOOK_NEWEST_RANK_CACHE_NAME = "bookNewestRankCache";
/** /**
* 小说更新榜缓存 * 小说更新榜缓存
* */ */
public static final String BOOK_UPDATE_RANK_CACHE_NAME = "bookUpdateRankCache"; public static final String BOOK_UPDATE_RANK_CACHE_NAME = "bookUpdateRankCache";
/** /**
* 首页友情链接缓存 * 首页友情链接缓存
* */ */
public static final String HOME_FRIEND_LINK_CACHE_NAME = "homeFriendLinkCache"; public static final String HOME_FRIEND_LINK_CACHE_NAME = "homeFriendLinkCache";
/**小说信息缓存*/ /**
* 小说信息缓存
*/
public static final String BOOK_INFO_CACHE_NAME = "bookInfoCache"; public static final String BOOK_INFO_CACHE_NAME = "bookInfoCache";
/**
* 小说章节缓存
*/
public static final String BOOK_CHAPTER_CACHE_NAME = "bookChapterCache";
/**
* 小说内容缓存
*/
public static final String BOOK_CONTENT_CACHE_NAME = "bookContentCache";
/** /**
* 缓存配置常量 * 缓存配置常量
*/ */
public enum CacheEnum { public enum CacheEnum {
HOME_BOOK_CACHE(0,HOME_BOOK_CACHE_NAME,60 * 60 * 24,1), HOME_BOOK_CACHE(0, HOME_BOOK_CACHE_NAME, 60 * 60 * 24, 1),
LATEST_NEWS_CACHE(0,LATEST_NEWS_CACHE_NAME,60 * 10,1), LATEST_NEWS_CACHE(0, LATEST_NEWS_CACHE_NAME, 60 * 10, 1),
BOOK_VISIT_RANK_CACHE(2,BOOK_VISIT_RANK_CACHE_NAME,60 * 60 * 6,1), BOOK_VISIT_RANK_CACHE(2, BOOK_VISIT_RANK_CACHE_NAME, 60 * 60 * 6, 1),
BOOK_NEWEST_RANK_CACHE(0,BOOK_NEWEST_RANK_CACHE_NAME,60 * 30,1), BOOK_NEWEST_RANK_CACHE(0, BOOK_NEWEST_RANK_CACHE_NAME, 60 * 30, 1),
BOOK_UPDATE_RANK_CACHE(0,BOOK_UPDATE_RANK_CACHE_NAME,60,1), BOOK_UPDATE_RANK_CACHE(0, BOOK_UPDATE_RANK_CACHE_NAME, 60, 1),
HOME_FRIEND_LINK_CACHE(2,HOME_FRIEND_LINK_CACHE_NAME,0,1), HOME_FRIEND_LINK_CACHE(2, HOME_FRIEND_LINK_CACHE_NAME, 0, 1),
BOOK_INFO_CACHE(0,BOOK_INFO_CACHE_NAME,60 * 60 * 18, 500) BOOK_INFO_CACHE(0, BOOK_INFO_CACHE_NAME, 60 * 60 * 18, 500),
;
BOOK_CHAPTER_CACHE(0,BOOK_CHAPTER_CACHE_NAME,60 * 60 * 6,5000),
BOOK_CONTENT_CACHE(2, BOOK_CONTENT_CACHE_NAME, 60 * 60 * 12, 3000);
/** /**
* 缓存类型 0-本地 1-本地和远程 2-远程 * 缓存类型 0-本地 1-本地和远程 2-远程

View File

@ -0,0 +1,49 @@
package io.github.xxyopen.novel.dto.resp;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 小说章节 响应DTO
* @author xiongxiaoyang
* @date 2022/5/15
*/
@Data
@Builder
public class BookChapterRespDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 小说ID
*/
private Long bookId;
/**
* 章节名
*/
private String chapterName;
/**
* 章节字数
*/
private Integer chapterWordCount;
/**
* 章节更新时间
* */
@JsonFormat(pattern = "yyyy/MM/dd HH:dd")
private LocalDateTime chapterUpdateTime;
/**
* 内容概要20字
*/
private String contentSummary;
}

View File

@ -0,0 +1,69 @@
package io.github.xxyopen.novel.dto.resp;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 小说内容 响应DTO
* @author xiongxiaoyang
* @date 2022/5/15
*/
@Data
@Builder
public class BookContentRespDto {
/**
* 小说 ID
*/
private Long bookId;
/**
* 类别ID
*/
private Long categoryId;
/**
* 类别名
*/
private String categoryName;
/**
* 小说名
*/
private String bookName;
/**
* 作家id
*/
private Long authorId;
/**
* 作家名
*/
private String authorName;
/**
* 章节名
*/
private String chapterName;
/**
* 章节字数
*/
private Integer chapterWordCount;
/**
* 章节更新时间
* */
@JsonFormat(pattern = "yyyy/MM/dd HH:dd")
private LocalDateTime chapterUpdateTime;
/**
* 章节内容
*/
private String content;
}

View File

@ -77,5 +77,10 @@ public class BookInfoRespDto {
* */ * */
private Long firstChapterId; private Long firstChapterId;
/**
* 最新章节ID
*/
private Long lastChapterId;
} }

View File

@ -0,0 +1,39 @@
package io.github.xxyopen.novel.manager;
import io.github.xxyopen.novel.core.constant.CacheConsts;
import io.github.xxyopen.novel.dao.entity.BookChapter;
import io.github.xxyopen.novel.dao.mapper.BookChapterMapper;
import io.github.xxyopen.novel.dto.resp.BookChapterRespDto;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
/**
* 小说章节 缓存管理类
*
* @author xiongxiaoyang
* @date 2022/5/12
*/
@Component
@RequiredArgsConstructor
public class BookChapterCacheManager {
private final BookChapterMapper bookChapterMapper;
/**
* 查询小说章节信息并放入缓存中
*/
@Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER
, value = CacheConsts.BOOK_CHAPTER_CACHE_NAME)
public BookChapterRespDto getChapter(Long chapterId) {
BookChapter bookChapter = bookChapterMapper.selectById(chapterId);
return BookChapterRespDto.builder()
.bookId(bookChapter.getBookId())
.chapterName(bookChapter.getChapterName())
.chapterWordCount(bookChapter.getWordCount())
.chapterUpdateTime(bookChapter.getUpdateTime())
.build();
}
}

View File

@ -0,0 +1,36 @@
package io.github.xxyopen.novel.manager;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.github.xxyopen.novel.core.constant.CacheConsts;
import io.github.xxyopen.novel.dao.entity.BookContent;
import io.github.xxyopen.novel.dao.mapper.BookContentMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
/**
* 小说内容 缓存管理类
*
* @author xiongxiaoyang
* @date 2022/5/12
*/
@Component
@RequiredArgsConstructor
public class BookContentCacheManager {
private final BookContentMapper bookContentMapper;
/**
* 查询小说内容并放入缓存中
*/
@Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER
, value = CacheConsts.BOOK_CONTENT_CACHE_NAME)
public String getBookContent(Long chapterId) {
QueryWrapper<BookContent> contentQueryWrapper = new QueryWrapper<>();
contentQueryWrapper.eq("chapter_id",chapterId).last("limit 1");
BookContent bookContent = bookContentMapper.selectOne(contentQueryWrapper);
return bookContent.getContent();
}
}

View File

@ -33,7 +33,7 @@ public class BookInfoCacheManager {
public BookInfoRespDto getBookInfo(Long id) { public BookInfoRespDto getBookInfo(Long id) {
// 查询基础信息 // 查询基础信息
BookInfo bookInfo = bookInfoMapper.selectById(id); BookInfo bookInfo = bookInfoMapper.selectById(id);
// 查询最新章节ID // 查询首章ID
QueryWrapper<BookChapter> queryWrapper = new QueryWrapper<>(); QueryWrapper<BookChapter> queryWrapper = new QueryWrapper<>();
queryWrapper queryWrapper
.eq("book_id", id) .eq("book_id", id)
@ -52,6 +52,7 @@ public class BookInfoCacheManager {
.categoryName(bookInfo.getCategoryName()) .categoryName(bookInfo.getCategoryName())
.commentCount(bookInfo.getCommentCount()) .commentCount(bookInfo.getCommentCount())
.firstChapterId(firstBookChapter.getId()) .firstChapterId(firstBookChapter.getId())
.lastChapterId(bookInfo.getLastChapterId())
.picUrl(bookInfo.getPicUrl()) .picUrl(bookInfo.getPicUrl())
.visitCount(bookInfo.getVisitCount()) .visitCount(bookInfo.getVisitCount())
.wordCount(bookInfo.getWordCount()) .wordCount(bookInfo.getWordCount())

View File

@ -1,6 +1,7 @@
package io.github.xxyopen.novel.service; package io.github.xxyopen.novel.service;
import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.common.resp.RestResp;
import io.github.xxyopen.novel.dto.resp.BookContentRespDto;
import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto;
import io.github.xxyopen.novel.dto.resp.BookRankRespDto; import io.github.xxyopen.novel.dto.resp.BookRankRespDto;
@ -32,5 +33,10 @@ public interface BookService {
/** /**
* 小说信息查询 * 小说信息查询
* */ * */
RestResp<BookInfoRespDto> getById(Long bookId); RestResp<BookInfoRespDto> getBookById(Long bookId);
/**
* 小说章节内容查询
* */
RestResp<BookContentRespDto> getBookContent(Long chapterId);
} }

View File

@ -1,8 +1,13 @@
package io.github.xxyopen.novel.service.impl; package io.github.xxyopen.novel.service.impl;
import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.common.resp.RestResp;
import io.github.xxyopen.novel.dao.mapper.BookChapterMapper;
import io.github.xxyopen.novel.dto.resp.BookChapterRespDto;
import io.github.xxyopen.novel.dto.resp.BookContentRespDto;
import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto;
import io.github.xxyopen.novel.dto.resp.BookRankRespDto; import io.github.xxyopen.novel.dto.resp.BookRankRespDto;
import io.github.xxyopen.novel.manager.BookChapterCacheManager;
import io.github.xxyopen.novel.manager.BookContentCacheManager;
import io.github.xxyopen.novel.manager.BookInfoCacheManager; import io.github.xxyopen.novel.manager.BookInfoCacheManager;
import io.github.xxyopen.novel.manager.BookRankCacheManager; import io.github.xxyopen.novel.manager.BookRankCacheManager;
import io.github.xxyopen.novel.service.BookService; import io.github.xxyopen.novel.service.BookService;
@ -25,6 +30,12 @@ public class BookServiceImpl implements BookService {
private final BookInfoCacheManager bookInfoCacheManager; private final BookInfoCacheManager bookInfoCacheManager;
private final BookChapterCacheManager bookChapterCacheManager;
private final BookContentCacheManager bookContentCacheManager;
private final BookChapterMapper bookChapterMapper;
@Override @Override
public RestResp<List<BookRankRespDto>> listVisitRankBooks() { public RestResp<List<BookRankRespDto>> listVisitRankBooks() {
return RestResp.ok(bookRankCacheManager.listVisitRankBooks()); return RestResp.ok(bookRankCacheManager.listVisitRankBooks());
@ -41,7 +52,33 @@ public class BookServiceImpl implements BookService {
} }
@Override @Override
public RestResp<BookInfoRespDto> getById(Long bookId) { public RestResp<BookInfoRespDto> getBookById(Long bookId) {
return RestResp.ok(bookInfoCacheManager.getBookInfo(bookId)); return RestResp.ok(bookInfoCacheManager.getBookInfo(bookId));
} }
@Override
public RestResp<BookContentRespDto> getBookContent(Long chapterId) {
// 查询章节信息
BookChapterRespDto bookChapter = bookChapterCacheManager.getChapter(chapterId);
// 查询章节内容
String content = bookContentCacheManager.getBookContent(chapterId);
// 查询小说信息
BookInfoRespDto bookInfo = bookInfoCacheManager.getBookInfo(bookChapter.getBookId());
// 组装数据并返回
return RestResp.ok(BookContentRespDto.builder()
.authorId(bookInfo.getAuthorId())
.bookName(bookInfo.getBookName())
.authorName(bookInfo.getAuthorName())
.bookId(bookInfo.getId())
.content(content)
.categoryId(bookInfo.getCategoryId())
.categoryName(bookInfo.getCategoryName())
.chapterName(bookChapter.getChapterName())
.chapterUpdateTime(bookChapter.getChapterUpdateTime())
.chapterWordCount(bookChapter.getChapterWordCount())
.build());
}
} }