From e537240c7342e7326b5f7d7a3698afb0074ebac0 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 27 May 2022 16:04:26 +0800 Subject: [PATCH 001/112] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E5=B0=8F?= =?UTF-8?q?=E8=AF=B4=E6=90=9C=E7=B4=A2=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/front/BookController.java | 15 +------- .../controller/front/SearchController.java | 35 +++++++++++++++++++ .../novel/core/constant/ApiRouterConsts.java | 10 ++++++ 3 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java b/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java index 46327cd..b39322d 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java @@ -1,12 +1,9 @@ package io.github.xxyopen.novel.controller.front; -import io.github.xxyopen.novel.core.common.resp.PageRespDto; -import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.common.resp.RestResp; -import io.github.xxyopen.novel.dto.req.BookSearchReqDto; +import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.dto.resp.*; import io.github.xxyopen.novel.service.BookService; -import io.github.xxyopen.novel.service.SearchService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -26,8 +23,6 @@ public class BookController { private final BookService bookService; - private final SearchService searchService; - /** * 小说分类列表查询接口 */ @@ -36,14 +31,6 @@ public class BookController { return bookService.listCategory(workDirection); } - /** - * 小说搜索接口 - */ - @GetMapping("search_list") - public RestResp> searchBooks(BookSearchReqDto condition) { - return searchService.searchBooks(condition); - } - /** * 小说信息查询接口 */ diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java b/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java new file mode 100644 index 0000000..3d5ad4e --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java @@ -0,0 +1,35 @@ +package io.github.xxyopen.novel.controller.front; + +import io.github.xxyopen.novel.core.common.resp.PageRespDto; +import io.github.xxyopen.novel.core.common.resp.RestResp; +import io.github.xxyopen.novel.core.constant.ApiRouterConsts; +import io.github.xxyopen.novel.dto.req.BookSearchReqDto; +import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; +import io.github.xxyopen.novel.service.SearchService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 前台门户-搜索模块 API 控制器 + * + * @author xiongxiaoyang + * @date 2022/5/27 + */ +@RestController +@RequestMapping(ApiRouterConsts.API_FRONT_SEARCH_URL_PREFIX) +@RequiredArgsConstructor +public class SearchController { + + private final SearchService searchService; + + /** + * 小说搜索接口 + */ + @GetMapping("books") + public RestResp> searchBooks(BookSearchReqDto condition) { + return searchService.searchBooks(condition); + } + +} diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/ApiRouterConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/ApiRouterConsts.java index 881f95f..621cdcf 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/ApiRouterConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/ApiRouterConsts.java @@ -57,6 +57,11 @@ public class ApiRouterConsts { * */ public static final String RESOURCE_URL_PREFIX = "/resource"; + /** + * 搜索模块请求路径前缀 + * */ + public static final String SEARCH_URL_PREFIX = "/search"; + /** * 前台门户首页API请求路径前缀 */ @@ -82,4 +87,9 @@ public class ApiRouterConsts { */ public static final String API_FRONT_RESOURCE_URL_PREFIX = API_FRONT_URL_PREFIX + RESOURCE_URL_PREFIX; + /** + * 前台门户搜索相关API请求路径前缀 + * */ + public static final String API_FRONT_SEARCH_URL_PREFIX = API_FRONT_URL_PREFIX + SEARCH_URL_PREFIX; + } -- Gitee From 80e7264afabb8ca5537bb2bb64a563dd3506e8e4 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 27 May 2022 17:34:10 +0800 Subject: [PATCH 002/112] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20Token=20?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E6=8B=A6=E6=88=AA=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/core/config/WebConfig.java | 10 ++++- .../interceptor/TokenParseInterceptor.java | 43 +++++++++++++++++++ .../novel/service/impl/BookServiceImpl.java | 1 + 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java diff --git a/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java index 2bb0fae..58a06d4 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java @@ -4,6 +4,7 @@ import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.core.interceptor.AuthInterceptor; import io.github.xxyopen.novel.core.interceptor.FileInterceptor; +import io.github.xxyopen.novel.core.interceptor.TokenParseInterceptor; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -25,6 +26,8 @@ public class WebConfig implements WebMvcConfigurer { private final FileInterceptor fileInterceptor; + private final TokenParseInterceptor tokenParseInterceptor; + @Override public void addInterceptors(InterceptorRegistry registry) { // 文件访问拦截 @@ -42,7 +45,12 @@ public class WebConfig implements WebMvcConfigurer { // 放行登录注册相关请求接口 .excludePathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/register" , ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/login" - ,ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login"); + , ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login"); + + // Token 解析拦截器 + registry.addInterceptor(tokenParseInterceptor) + // 拦截小说内容查询接口,需要解析 token 以判断该用户是否有权阅读该章节(付费章节是否已购买) + .addPathPatterns(ApiRouterConsts.API_FRONT_BOOK_URL_PREFIX + "/content/*"); } } diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java new file mode 100644 index 0000000..15514cf --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java @@ -0,0 +1,43 @@ +package io.github.xxyopen.novel.core.interceptor; + +import io.github.xxyopen.novel.core.auth.UserHolder; +import io.github.xxyopen.novel.core.constant.SystemConfigConsts; +import io.github.xxyopen.novel.core.util.JwtUtils; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +/** + * Token 解析拦截器 + * + * @author xiongxiaoyang + * @date 2022/5/27 + */ +@Component +@RequiredArgsConstructor +public class TokenParseInterceptor implements HandlerInterceptor { + + private final JwtUtils jwtUtils; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // 获取登录 JWT + String token = request.getHeader(SystemConfigConsts.HTTP_AUTH_HEADER_NAME); + if (StringUtils.hasText(token)) { + // 解析 token 并保存 + UserHolder.setUserId(jwtUtils.parseToken(token, SystemConfigConsts.NOVEL_FRONT_KEY)); + } + return HandlerInterceptor.super.preHandle(request, response, handler); + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + // 清理当前线程保存的用户数据 + UserHolder.clear(); + HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); + } +} diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index ff694ba..c377cb0 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -346,6 +346,7 @@ public class BookServiceImpl implements BookService { @Override public RestResp getBookContentAbout(Long chapterId) { + log.debug("userId:{}",UserHolder.getUserId()); // 查询章节信息 BookChapterRespDto bookChapter = bookChapterCacheManager.getChapter(chapterId); -- Gitee From cdd99834a60b6f2ec3930cae25ee5de6573a749a Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sat, 28 May 2022 07:23:08 +0800 Subject: [PATCH 003/112] docs: update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 82f2c61..36880a6 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,9 @@ git clone https://gitee.com/novel_dev_team/novel-front-web.git 关注公众号接收项目最新动态,获取`Spring Boot 3`学习笔记! -加微信群交流,公众号后台回复「**微信群**」即可。 +加微信群学习交流,公众号后台回复「**微信群**」即可。 + +发送「**资料**」获取`JAVA 面试参考`、`海量简历模板`、`技术电子书`等学习面试资料。 ![微信公众号](https://youdoc.github.io/img/qrcode_for_gh.jpg) -- Gitee From 3019093dc3c2a3f05412351978ca4360a6055c28 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sat, 28 May 2022 18:51:47 +0800 Subject: [PATCH 004/112] =?UTF-8?q?style:=20=E6=8D=A2=E8=A1=8C/=E5=91=BD?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/core/config/WebConfig.java | 12 +++++------ .../manager/cache/AuthorInfoCacheManager.java | 10 +++++----- .../cache/BookCategoryCacheManager.java | 4 ++-- .../cache/BookChapterCacheManager.java | 4 ++-- .../cache/BookContentCacheManager.java | 4 ++-- .../manager/cache/BookInfoCacheManager.java | 15 +++++++------- .../manager/cache/BookRankCacheManager.java | 20 +++++++++---------- .../manager/cache/FriendLinkCacheManager.java | 4 ++-- .../manager/cache/HomeBookCacheManager.java | 4 ++-- .../novel/manager/cache/NewsCacheManager.java | 4 ++-- .../manager/cache/UserInfoCacheManager.java | 6 +++--- .../manager/redis/VerifyCodeManager.java | 8 +++----- .../service/impl/DbSearchServiceImpl.java | 4 ++-- .../service/impl/EsSearchServiceImpl.java | 14 ++++++------- 14 files changed, 55 insertions(+), 58 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java index 58a06d4..18f9276 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java @@ -37,15 +37,15 @@ public class WebConfig implements WebMvcConfigurer { // 权限认证拦截 registry.addInterceptor(authInterceptor) // 拦截会员中心相关请求接口 - .addPathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/**" + .addPathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/**", // 拦截作家后台相关请求接口 - , ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/**" + ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/**", // 拦截平台后台相关请求接口 - , ApiRouterConsts.API_ADMIN_URL_PREFIX + "/**") + ApiRouterConsts.API_ADMIN_URL_PREFIX + "/**") // 放行登录注册相关请求接口 - .excludePathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/register" - , ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/login" - , ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login"); + .excludePathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/register", + ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/login", + ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login"); // Token 解析拦截器 registry.addInterceptor(tokenParseInterceptor) diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/AuthorInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/AuthorInfoCacheManager.java index c48ac8c..7aeb1cb 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/AuthorInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/AuthorInfoCacheManager.java @@ -28,8 +28,8 @@ public class AuthorInfoCacheManager { /** * 查询作家信息,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER - , value = CacheConsts.AUTHOR_INFO_CACHE_NAME, unless = "#result == null") + @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, + value = CacheConsts.AUTHOR_INFO_CACHE_NAME, unless = "#result == null") public AuthorInfoDto getAuthor(Long userId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper @@ -45,9 +45,9 @@ public class AuthorInfoCacheManager { .status(authorInfo.getStatus()).build(); } - @CacheEvict(cacheManager = CacheConsts.REDIS_CACHE_MANAGER - , value = CacheConsts.AUTHOR_INFO_CACHE_NAME) - public void evictAuthorCache(){ + @CacheEvict(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, + value = CacheConsts.AUTHOR_INFO_CACHE_NAME) + public void evictAuthorCache() { // 调用此方法自动清除作家信息的缓存 } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookCategoryCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookCategoryCacheManager.java index a592a4a..817b8fe 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookCategoryCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookCategoryCacheManager.java @@ -27,8 +27,8 @@ public class BookCategoryCacheManager { /** * 根据作品方向查询小说分类列表,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.BOOK_CATEGORY_LIST_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_CATEGORY_LIST_CACHE_NAME) public List listCategory(Integer workDirection) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookCategoryTable.COLUMN_WORK_DIRECTION, workDirection); diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java index fe45fbe..83a0665 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java @@ -23,8 +23,8 @@ public class BookChapterCacheManager { /** * 查询小说章节信息,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.BOOK_CHAPTER_CACHE_NAME) + @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() diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java index ea21719..3f8fa50 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java @@ -24,8 +24,8 @@ public class BookContentCacheManager { /** * 查询小说内容,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER - , value = CacheConsts.BOOK_CONTENT_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, + value = CacheConsts.BOOK_CONTENT_CACHE_NAME) public String getBookContent(Long chapterId) { QueryWrapper contentQueryWrapper = new QueryWrapper<>(); contentQueryWrapper.eq(DatabaseConsts.BookContentTable.COLUMN_CHAPTER_ID, chapterId) diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java index ba509c5..82f4365 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java @@ -32,17 +32,17 @@ public class BookInfoCacheManager { /** * 从缓存中查询小说信息(先判断缓存中是否已存在,存在则直接从缓存中取,否则执行方法体中的逻辑后缓存结果) */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.BOOK_INFO_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_INFO_CACHE_NAME) public BookInfoRespDto getBookInfo(Long id) { return cachePutBookInfo(id); } /** * 缓存小说信息(不管缓存中是否存在都执行方法体中的逻辑,然后缓存起来) - * */ - @CachePut(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.BOOK_INFO_CACHE_NAME) + */ + @CachePut(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_INFO_CACHE_NAME) public BookInfoRespDto cachePutBookInfo(Long id) { // 查询基础信息 BookInfo bookInfo = bookInfoMapper.selectById(id); @@ -73,12 +73,11 @@ public class BookInfoCacheManager { } - /** * 查询每个类别下最新更新的 500 个小说ID列表,并放入缓存中 1 个小时 */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.LAST_UPDATE_BOOK_ID_LIST_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.LAST_UPDATE_BOOK_ID_LIST_CACHE_NAME) public List getLastUpdateIdList(Long categoryId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookTable.COLUMN_CATEGORY_ID, categoryId) diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java index e616d52..a98cad9 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java @@ -27,39 +27,39 @@ public class BookRankCacheManager { /** * 查询小说点击榜列表,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER - , value = CacheConsts.BOOK_VISIT_RANK_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, + value = CacheConsts.BOOK_VISIT_RANK_CACHE_NAME) public List listVisitRankBooks() { QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); bookInfoQueryWrapper.orderByDesc(DatabaseConsts.BookTable.COLUMN_VISIT_COUNT); - return getBookRankRespDtos(bookInfoQueryWrapper); + return listRankBooks(bookInfoQueryWrapper); } /** * 查询小说新书榜列表,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.BOOK_NEWEST_RANK_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_NEWEST_RANK_CACHE_NAME) public List listNewestRankBooks() { QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); bookInfoQueryWrapper .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()); - return getBookRankRespDtos(bookInfoQueryWrapper); + return listRankBooks(bookInfoQueryWrapper); } /** * 查询小说更新榜列表,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.BOOK_UPDATE_RANK_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_UPDATE_RANK_CACHE_NAME) public List listUpdateRankBooks() { QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); bookInfoQueryWrapper .orderByDesc(DatabaseConsts.CommonColumnEnum.UPDATE_TIME.getName()); - return getBookRankRespDtos(bookInfoQueryWrapper); + return listRankBooks(bookInfoQueryWrapper); } - private List getBookRankRespDtos(QueryWrapper bookInfoQueryWrapper) { + private List listRankBooks(QueryWrapper bookInfoQueryWrapper) { bookInfoQueryWrapper.last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); return bookInfoMapper.selectList(bookInfoQueryWrapper).stream().map(v -> { BookRankRespDto respDto = new BookRankRespDto(); diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/FriendLinkCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/FriendLinkCacheManager.java index b1876d8..d0eba3c 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/FriendLinkCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/FriendLinkCacheManager.java @@ -27,8 +27,8 @@ public class FriendLinkCacheManager { /** * 友情链接列表查询,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER - , value = CacheConsts.HOME_FRIEND_LINK_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, + value = CacheConsts.HOME_FRIEND_LINK_CACHE_NAME) public List listFriendLinks() { // 从友情链接表中查询出友情链接列表 QueryWrapper queryWrapper = new QueryWrapper<>(); diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/HomeBookCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/HomeBookCacheManager.java index c94a95a..5e648f8 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/HomeBookCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/HomeBookCacheManager.java @@ -36,8 +36,8 @@ public class HomeBookCacheManager { /** * 查询首页小说推荐,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.HOME_BOOK_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.HOME_BOOK_CACHE_NAME) public List listHomeBooks() { // 从首页小说推荐表中查询出需要推荐的小说 QueryWrapper queryWrapper = new QueryWrapper<>(); diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/NewsCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/NewsCacheManager.java index 6ffc5c8..65fd458 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/NewsCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/NewsCacheManager.java @@ -27,8 +27,8 @@ public class NewsCacheManager { /** * 最新新闻列表查询,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER - , value = CacheConsts.LATEST_NEWS_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.LATEST_NEWS_CACHE_NAME) public List listLatestNews() { // 从新闻信息表中查询出最新发布的两条新闻 QueryWrapper queryWrapper = new QueryWrapper<>(); diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/UserInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/UserInfoCacheManager.java index 050db89..90ee1eb 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/UserInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/UserInfoCacheManager.java @@ -25,11 +25,11 @@ public class UserInfoCacheManager { /** * 查询用户信息,并放入缓存中 */ - @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER - , value = CacheConsts.USER_INFO_CACHE_NAME) + @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, + value = CacheConsts.USER_INFO_CACHE_NAME) public UserInfoDto getUser(Long userId) { UserInfo userInfo = userInfoMapper.selectById(userId); - if(Objects.isNull(userInfo)){ + if (Objects.isNull(userInfo)) { return null; } return UserInfoDto.builder() diff --git a/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java b/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java index d6578c2..78100b3 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java @@ -30,8 +30,8 @@ public class VerifyCodeManager { public String genImgVerifyCode(String sessionId) throws IOException { String verifyCode = ImgVerifyCodeUtils.getRandomVerifyCode(4); String img = ImgVerifyCodeUtils.genVerifyCodeImg(verifyCode); - stringRedisTemplate.opsForValue().set(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId - , verifyCode, Duration.ofMinutes(5)); + stringRedisTemplate.opsForValue().set(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId, + verifyCode, Duration.ofMinutes(5)); return img; } @@ -39,9 +39,7 @@ public class VerifyCodeManager { * 校验图片验证码 */ public boolean imgVerifyCodeOk(String sessionId, String verifyCode) { - return Objects.equals( - stringRedisTemplate.opsForValue().get(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId) - , verifyCode); + return Objects.equals(stringRedisTemplate.opsForValue().get(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId), verifyCode); } /** diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java index 4418344..052886a 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java @@ -35,8 +35,8 @@ public class DbSearchServiceImpl implements SearchService { page.setCurrent(condition.getPageNum()); page.setSize(condition.getPageSize()); List bookInfos = bookInfoMapper.searchBooks(page, condition); - return RestResp.ok(PageRespDto.of(condition.getPageNum(), condition.getPageSize(), page.getTotal() - , bookInfos.stream().map(v -> BookInfoRespDto.builder() + return RestResp.ok(PageRespDto.of(condition.getPageNum(), condition.getPageSize(), page.getTotal(), + bookInfos.stream().map(v -> BookInfoRespDto.builder() .id(v.getId()) .bookName(v.getBookName()) .categoryId(v.getCategoryId()) diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java index b03dcb8..0c67460 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java @@ -64,10 +64,10 @@ public class EsSearchServiceImpl implements SearchService { searchBuilder.from((condition.getPageNum() - 1) * condition.getPageSize()) .size(condition.getPageSize()); // 设置高亮显示 - searchBuilder.highlight(h -> h.fields(EsConsts.BookIndex.FIELD_BOOK_NAME - , t -> t.preTags("").postTags("")) - .fields(EsConsts.BookIndex.FIELD_AUTHOR_NAME - , t -> t.preTags("").postTags(""))); + searchBuilder.highlight(h -> h.fields(EsConsts.BookIndex.FIELD_BOOK_NAME, + t -> t.preTags("").postTags("")) + .fields(EsConsts.BookIndex.FIELD_AUTHOR_NAME, + t -> t.preTags("").postTags(""))); return searchBuilder; }, @@ -113,9 +113,9 @@ public class EsSearchServiceImpl implements SearchService { if (!StringUtils.isBlank(condition.getKeyword())) { // 关键词匹配 b.must((q -> q.multiMatch(t -> t - .fields(EsConsts.BookIndex.FIELD_BOOK_NAME + "^2" - , EsConsts.BookIndex.FIELD_AUTHOR_NAME + "^1.8" - , EsConsts.BookIndex.FIELD_BOOK_DESC + "^0.1") + .fields(EsConsts.BookIndex.FIELD_BOOK_NAME + "^2", + EsConsts.BookIndex.FIELD_AUTHOR_NAME + "^1.8", + EsConsts.BookIndex.FIELD_BOOK_DESC + "^0.1") .query(condition.getKeyword()) ) )); -- Gitee From 8a0105cfa4a837796f11d58eb0689837298464e7 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 05:52:49 +0800 Subject: [PATCH 005/112] =?UTF-8?q?style:=20=E6=8D=A2=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/service/impl/EsSearchServiceImpl.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java index 0c67460..705f467 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java @@ -54,10 +54,9 @@ public class EsSearchServiceImpl implements SearchService { buildSearchCondition(condition, searchBuilder); // 排序 if (!StringUtils.isBlank(condition.getSort())) { - searchBuilder.sort(o -> - o.field(f -> f.field(StringUtils - .underlineToCamel(condition.getSort().split(" ")[0])) - .order(SortOrder.Desc)) + searchBuilder.sort(o -> o.field(f -> f + .field(StringUtils.underlineToCamel(condition.getSort().split(" ")[0])) + .order(SortOrder.Desc)) ); } // 分页 -- Gitee From d2cadda291e15dfff5aa625eb3e947066874da8d Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 09:17:36 +0800 Subject: [PATCH 006/112] docs: update README.md --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 36880a6..33ee6b9 100644 --- a/README.md +++ b/README.md @@ -28,22 +28,22 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 ## 后端技术选型 -| 技术 | 版本 | 说明 | 官网 | 学习 | -|:----------------|:--------------:|---------------------| --------------------------------------- | :-------------------------------------------------: | -| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | -| Mybatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | -| MyBatis-Plus | 3.5.1 | Mybatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | -| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | -| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | -| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | -| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | -| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | -| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | -| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | -| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | -| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | -| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | -| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | +| 技术 | 版本 | 说明 | 官网 | 学习 | +|:--------------|:--------------:|---------------------| --------------------------------------- | :-------------------------------------------------: | +| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | +| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | +| MyBatis-Plus | 3.5.1 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | +| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | +| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | +| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | +| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | +| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | +| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | +| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | +| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | +| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | +| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | +| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | **注:更多热门新技术待集成。** ## 前端技术选型 -- Gitee From 1151ed3f9ff82a6b4c48fb937e7c0038f822b722 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 09:53:12 +0800 Subject: [PATCH 007/112] docs: update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 33ee6b9..2a9aa1f 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 ## 项目地址 - 后端项目(更新中):[GitHub](https://github.com/201206030/novel) | [码云](https://gitee.com/novel_dev_team/novel) -- 后端微服务版本项目(待更新):[GitHub](https://github.com/201206030/novel-cloud) | [码云](https://gitee.com/novel_dev_team/novel-cloud) - 前端项目(更新中):[GitHub](https://github.com/201206030/novel-front-web) | [码云](https://gitee.com/novel_dev_team/novel-front-web) - 线上应用版:[GitHub](https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus) |[演示地址](http://47.106.243.172:8888/) +- 微服务版:[GitHub](https://github.com/201206030/novel-cloud) | [码云](https://gitee.com/novel_dev_team/novel-cloud) ## 开发环境 -- Gitee From fa47081398db014bc9b9166433a55c054d7504df Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 12:31:10 +0800 Subject: [PATCH 008/112] =?UTF-8?q?feat:=20=E5=A2=9E=E8=82=8C=E5=B0=8F?= =?UTF-8?q?=E8=AF=B4=E5=8F=91=E5=B8=83=E5=88=97=E8=A1=A8=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/author/AuthorController.java | 17 +++++-- .../novel/core/constant/DatabaseConsts.java | 2 + .../xxyopen/novel/service/BookService.java | 28 ++++++++--- .../novel/service/impl/BookServiceImpl.java | 46 +++++++++++++++---- 4 files changed, 72 insertions(+), 21 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index f311881..c215395 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -1,22 +1,23 @@ package io.github.xxyopen.novel.controller.author; import io.github.xxyopen.novel.core.auth.UserHolder; +import io.github.xxyopen.novel.core.common.req.PageReqDto; +import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.dto.req.AuthorRegisterReqDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; +import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.service.AuthorService; import io.github.xxyopen.novel.service.BookService; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; /** * 作家后台-作家模块 API 控制器 + * * @author xiongxiaoyang * @date 2022/5/23 */ @@ -46,6 +47,14 @@ public class AuthorController { return bookService.saveBook(dto); } + /** + * 小说发布列表查询接口 + */ + @GetMapping("books") + public RestResp> listBooks(PageReqDto dto) { + return bookService.listAuthorBooks(dto); + } + /** * 小说章节发布接口 */ diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java index 49533d7..a950b85 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java @@ -89,6 +89,8 @@ public class DatabaseConsts { public static final String COLUMN_CATEGORY_ID = "category_id"; + public static final String AUTHOR_ID = "author_id"; + public static final String COLUMN_VISIT_COUNT = "visit_count"; public static final String COLUMN_LAST_CHAPTER_UPDATE_TIME = "last_chapter_update_time"; diff --git a/src/main/java/io/github/xxyopen/novel/service/BookService.java b/src/main/java/io/github/xxyopen/novel/service/BookService.java index 98e9059..916391a 100644 --- a/src/main/java/io/github/xxyopen/novel/service/BookService.java +++ b/src/main/java/io/github/xxyopen/novel/service/BookService.java @@ -1,5 +1,7 @@ package io.github.xxyopen.novel.service; +import io.github.xxyopen.novel.core.common.req.PageReqDto; +import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; @@ -128,32 +130,44 @@ public interface BookService { /** * 删除评论 - * @param userId 评论用户ID + * + * @param userId 评论用户ID * @param commentId 评论ID * @return void - * */ + */ RestResp deleteComment(Long userId, Long commentId); /** * 修改评论 - * @param userId 用户ID - * @param id 评论ID + * + * @param userId 用户ID + * @param id 评论ID * @param content 修改后的评论内容 * @return void - * */ + */ RestResp updateComment(Long userId, Long id, String content); /** * 小说信息保存 + * * @param dto 小说信息 * @return void - * */ + */ RestResp saveBook(BookAddReqDto dto); /** * 小说章节信息保存 + * * @param dto 章节信息 * @return void - * */ + */ RestResp saveBookChapter(ChapterAddReqDto dto); + + /** + * 查询作家发布小说列表 + * + * @param dto 分页请求参数 + * @return 小说分页列表数据 + */ + RestResp> listAuthorBooks(PageReqDto dto); } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index c377cb0..82fe2e5 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -1,8 +1,12 @@ package io.github.xxyopen.novel.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.github.xxyopen.novel.core.auth.UserHolder; import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum; +import io.github.xxyopen.novel.core.common.req.PageReqDto; +import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.dao.entity.*; @@ -199,9 +203,9 @@ public class BookServiceImpl implements BookService { public RestResp saveComment(UserCommentReqDto dto) { // 校验用户是否已发表评论 QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID,dto.getUserId()) - .eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID,dto.getBookId()); - if(bookCommentMapper.selectCount(queryWrapper) > 0){ + queryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, dto.getUserId()) + .eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID, dto.getBookId()); + if (bookCommentMapper.selectCount(queryWrapper) > 0) { // 用户已发表评论 return RestResp.fail(ErrorCodeEnum.USER_COMMENTED); } @@ -254,8 +258,8 @@ public class BookServiceImpl implements BookService { public RestResp deleteComment(Long userId, Long commentId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), commentId) - .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID,userId); - bookCommentMapper.delete(queryWrapper); + .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId); + bookCommentMapper.delete(queryWrapper); return RestResp.ok(); } @@ -263,10 +267,10 @@ public class BookServiceImpl implements BookService { public RestResp updateComment(Long userId, Long id, String content) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), id) - .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID,userId); + .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId); BookComment bookComment = new BookComment(); bookComment.setCommentContent(content); - bookCommentMapper.update(bookComment,queryWrapper); + bookCommentMapper.update(bookComment, queryWrapper); return RestResp.ok(); } @@ -300,11 +304,11 @@ public class BookServiceImpl implements BookService { // a) 查询最新章节号 int chapterNum = 0; QueryWrapper chapterQueryWrapper = new QueryWrapper<>(); - chapterQueryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID,dto.getBookId()) + chapterQueryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, dto.getBookId()) .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); BookChapter bookChapter = bookChapterMapper.selectOne(chapterQueryWrapper); - if(Objects.nonNull(bookChapter)){ + if (Objects.nonNull(bookChapter)) { chapterNum = bookChapter.getChapterNum() + 1; } // b) 设置章节相关信息并保存 @@ -344,9 +348,31 @@ public class BookServiceImpl implements BookService { return RestResp.ok(); } + @Override + public RestResp> listAuthorBooks(PageReqDto dto) { + IPage page = new Page<>(); + page.setCurrent(dto.getPageNum()); + page.setSize(dto.getPageSize()); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(DatabaseConsts.BookTable.AUTHOR_ID, UserHolder.getAuthorId()) + .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()); + IPage bookInfoPage = bookInfoMapper.selectPage(page, queryWrapper); + return RestResp.ok(PageRespDto.of(dto.getPageNum(), dto.getPageSize(), page.getTotal(), + bookInfoPage.getRecords().stream().map(v -> BookInfoRespDto.builder() + .id(v.getId()) + .bookName(v.getBookName()) + .picUrl(v.getPicUrl()) + .categoryId(v.getCategoryId()) + .categoryName(v.getCategoryName()) + .wordCount(v.getWordCount()) + .visitCount(v.getVisitCount()) + .lastChapterName(v.getLastChapterName()) + .build()).toList())); + } + @Override public RestResp getBookContentAbout(Long chapterId) { - log.debug("userId:{}",UserHolder.getUserId()); + log.debug("userId:{}", UserHolder.getUserId()); // 查询章节信息 BookChapterRespDto bookChapter = bookChapterCacheManager.getChapter(chapterId); -- Gitee From 066dd0f13ed576ed158e229d2cabe13629f44712 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 12:58:15 +0800 Subject: [PATCH 009/112] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=B0=8F?= =?UTF-8?q?=E8=AF=B4=E5=8F=91=E5=B8=83=E7=AB=A0=E8=8A=82=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/author/AuthorController.java | 9 +++++++++ .../xxyopen/novel/service/BookService.java | 9 +++++++++ .../novel/service/impl/BookServiceImpl.java | 17 +++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index c215395..38dea2c 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -8,6 +8,7 @@ import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.dto.req.AuthorRegisterReqDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; +import io.github.xxyopen.novel.dto.resp.BookChapterRespDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.service.AuthorService; import io.github.xxyopen.novel.service.BookService; @@ -63,4 +64,12 @@ public class AuthorController { return bookService.saveBookChapter(dto); } + /** + * 小说发布章节列表查询接口 + */ + @GetMapping("book/chapters/{bookId}") + public RestResp> listBookChapters(@PathVariable("bookId") Long bookId, PageReqDto dto) { + return bookService.listBookChapters(bookId, dto); + } + } diff --git a/src/main/java/io/github/xxyopen/novel/service/BookService.java b/src/main/java/io/github/xxyopen/novel/service/BookService.java index 916391a..4779dc1 100644 --- a/src/main/java/io/github/xxyopen/novel/service/BookService.java +++ b/src/main/java/io/github/xxyopen/novel/service/BookService.java @@ -170,4 +170,13 @@ public interface BookService { * @return 小说分页列表数据 */ RestResp> listAuthorBooks(PageReqDto dto); + + /** + * 查询小说发布章节列表 + * + * @param bookId 小说ID + * @param dto 分页请求参数 + * @return 章节分页列表数据 + */ + RestResp> listBookChapters(Long bookId, PageReqDto dto); } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index 82fe2e5..87f9a13 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -370,6 +370,23 @@ public class BookServiceImpl implements BookService { .build()).toList())); } + @Override + public RestResp> listBookChapters(Long bookId, PageReqDto dto) { + IPage page = new Page<>(); + page.setCurrent(dto.getPageNum()); + page.setSize(dto.getPageSize()); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId) + .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM); + IPage bookChapterPage = bookChapterMapper.selectPage(page, queryWrapper); + return RestResp.ok(PageRespDto.of(dto.getPageNum(), dto.getPageSize(), page.getTotal(), + bookChapterPage.getRecords().stream().map(v -> BookChapterRespDto.builder() + .id(v.getId()) + .chapterName(v.getChapterName()) + .chapterUpdateTime(v.getUpdateTime()) + .build()).toList())); + } + @Override public RestResp getBookContentAbout(Long chapterId) { log.debug("userId:{}", UserHolder.getUserId()); -- Gitee From f33c66c5d267dce9a3703973322c78630fe2ac48 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 15:23:37 +0800 Subject: [PATCH 010/112] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E4=BD=9C?= =?UTF-8?q?=E5=AE=B6=E7=8A=B6=E6=80=81=E6=9F=A5=E8=AF=A2=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../novel/controller/author/AuthorController.java | 10 +++++++++- .../xxyopen/novel/core/auth/AuthorAuthStrategy.java | 5 ++++- .../io/github/xxyopen/novel/service/AuthorService.java | 7 +++++++ .../xxyopen/novel/service/impl/AuthorServiceImpl.java | 6 ++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index 38dea2c..dbe95b2 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -40,6 +40,14 @@ public class AuthorController { return authorService.register(dto); } + /** + * 查询作家状态接口 + * */ + @GetMapping("status") + public RestResp getStatus(){ + return authorService.getStatus(UserHolder.getUserId()); + } + /** * 小说发布接口 */ @@ -65,7 +73,7 @@ public class AuthorController { } /** - * 小说发布章节列表查询接口 + * 小说章节发布列表查询接口 */ @GetMapping("book/chapters/{bookId}") public RestResp> listBookChapters(@PathVariable("bookId") Long bookId, PageReqDto dto) { diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java b/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java index d6abcd6..599bfbf 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java @@ -32,7 +32,10 @@ public class AuthorAuthStrategy implements AuthStrategy { /** * 不需要进行作家权限认证的 URI * */ - private static final List EXCLUDE_URI = List.of(ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/register"); + private static final List EXCLUDE_URI = List.of( + ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/register", + ApiRouterConsts.API_AUTHOR_URL_PREFIX +"/status" + ); @Override public void auth(String token, String requestUri) throws BusinessException { diff --git a/src/main/java/io/github/xxyopen/novel/service/AuthorService.java b/src/main/java/io/github/xxyopen/novel/service/AuthorService.java index 672daa7..bf7c95a 100644 --- a/src/main/java/io/github/xxyopen/novel/service/AuthorService.java +++ b/src/main/java/io/github/xxyopen/novel/service/AuthorService.java @@ -18,4 +18,11 @@ public interface AuthorService { * @return void */ RestResp register(AuthorRegisterReqDto dto); + + /** + * 查询作家状态 + * @param userId 用户ID + * @return 作家状态 + * */ + RestResp getStatus(Long userId); } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/AuthorServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/AuthorServiceImpl.java index 6c731bb..faa5bbf 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/AuthorServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/AuthorServiceImpl.java @@ -54,4 +54,10 @@ public class AuthorServiceImpl implements AuthorService { return RestResp.ok(); } + @Override + public RestResp getStatus(Long userId) { + AuthorInfoDto author = authorInfoCacheManager.getAuthor(userId); + return Objects.isNull(author) ? RestResp.ok(null) : RestResp.ok(author.getStatus()); + } + } -- Gitee From ad907063d94cb9e9c4a271e3f89cdafe5afd4631 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 18:03:30 +0800 Subject: [PATCH 011/112] =?UTF-8?q?feat:=20=E5=B0=8F=E8=AF=B4=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=A2=9E=E5=8A=A0=E6=9B=B4=E6=96=B0=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/xxyopen/novel/dto/resp/BookInfoRespDto.java | 9 +++++++++ .../xxyopen/novel/service/impl/BookServiceImpl.java | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookInfoRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookInfoRespDto.java index 55ba809..011939f 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookInfoRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookInfoRespDto.java @@ -1,7 +1,10 @@ package io.github.xxyopen.novel.dto.resp; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.*; +import java.time.LocalDateTime; + /** * 小说信息 响应DTO * @@ -89,5 +92,11 @@ public class BookInfoRespDto { */ private String lastChapterName; + /** + * 最新章节更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime updateTime; + } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index 87f9a13..4a31b2e 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -362,11 +362,10 @@ public class BookServiceImpl implements BookService { .id(v.getId()) .bookName(v.getBookName()) .picUrl(v.getPicUrl()) - .categoryId(v.getCategoryId()) .categoryName(v.getCategoryName()) .wordCount(v.getWordCount()) .visitCount(v.getVisitCount()) - .lastChapterName(v.getLastChapterName()) + .updateTime(v.getUpdateTime()) .build()).toList())); } -- Gitee From 785646b4c456af0ac9ef8c865a59d709cb43cf78 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 19:48:47 +0800 Subject: [PATCH 012/112] =?UTF-8?q?fix:=20=E7=AB=A0=E8=8A=82=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../novel/controller/author/AuthorController.java | 9 +++++---- .../github/xxyopen/novel/dto/req/ChapterAddReqDto.java | 1 - .../xxyopen/novel/service/impl/BookServiceImpl.java | 6 +++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index dbe95b2..935da7c 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -42,9 +42,9 @@ public class AuthorController { /** * 查询作家状态接口 - * */ + */ @GetMapping("status") - public RestResp getStatus(){ + public RestResp getStatus() { return authorService.getStatus(UserHolder.getUserId()); } @@ -67,8 +67,9 @@ public class AuthorController { /** * 小说章节发布接口 */ - @PostMapping("book/chapter") - public RestResp publishBookChapter(@Valid @RequestBody ChapterAddReqDto dto) { + @PostMapping("book/chapter/{bookId}") + public RestResp publishBookChapter(@PathVariable("bookId") Long bookId, @Valid @RequestBody ChapterAddReqDto dto) { + dto.setBookId(bookId); return bookService.saveBookChapter(dto); } diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/ChapterAddReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/ChapterAddReqDto.java index b7ec4ec..6505ace 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/ChapterAddReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/ChapterAddReqDto.java @@ -17,7 +17,6 @@ public class ChapterAddReqDto { /** * 小说ID */ - @NotNull private Long bookId; /** diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index 4a31b2e..8a7fa20 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -300,6 +300,11 @@ public class BookServiceImpl implements BookService { @Transactional(rollbackFor = Exception.class) @Override public RestResp saveBookChapter(ChapterAddReqDto dto) { + // 校验该作品是否属于当前作家 + BookInfoRespDto bookInfo = bookInfoCacheManager.getBookInfo(dto.getBookId()); + if (!Objects.equals(bookInfo.getAuthorId(), UserHolder.getAuthorId())) { + return RestResp.fail(ErrorCodeEnum.USER_UN_AUTH); + } // 1) 保存章节相关信息到小说章节表 // a) 查询最新章节号 int chapterNum = 0; @@ -332,7 +337,6 @@ public class BookServiceImpl implements BookService { // 3) 更新小说表最新章节信息和小说总字数信息 // a) 更新小说表关于最新章节的信息 - BookInfoRespDto bookInfo = bookInfoCacheManager.getBookInfo(dto.getBookId()); BookInfo newBookInfo = new BookInfo(); newBookInfo.setId(dto.getBookId()); newBookInfo.setLastChapterId(newBookChapter.getId()); -- Gitee From ed882abbd1a465c0d0d5b32a8453547453a80950 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 20:36:31 +0800 Subject: [PATCH 013/112] =?UTF-8?q?fix:=20=E5=90=8C=E7=B1=BB=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E8=BF=87=E6=BB=A4=E6=97=A0=E7=AB=A0=E8=8A=82=E5=B0=8F?= =?UTF-8?q?=E8=AF=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/xxyopen/novel/core/constant/DatabaseConsts.java | 2 ++ .../xxyopen/novel/manager/cache/BookInfoCacheManager.java | 7 +++++++ .../github/xxyopen/novel/service/impl/BookServiceImpl.java | 6 +++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java index a950b85..3f0fafa 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java @@ -93,6 +93,8 @@ public class DatabaseConsts { public static final String COLUMN_VISIT_COUNT = "visit_count"; + public static final String COLUMN_WORD_COUNT = "word_count"; + public static final String COLUMN_LAST_CHAPTER_UPDATE_TIME = "last_chapter_update_time"; } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java index 82f4365..18dfc9a 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java @@ -9,6 +9,7 @@ import io.github.xxyopen.novel.dao.mapper.BookChapterMapper; import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; @@ -72,6 +73,11 @@ public class BookInfoCacheManager { .build(); } + @CacheEvict(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_INFO_CACHE_NAME) + public void evictBookInfoCache(Long ignoredId) { + // 调用此方法自动清除小说信息的缓存 + } /** * 查询每个类别下最新更新的 500 个小说ID列表,并放入缓存中 1 个小时 @@ -81,6 +87,7 @@ public class BookInfoCacheManager { public List getLastUpdateIdList(Long categoryId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookTable.COLUMN_CATEGORY_ID, categoryId) + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT,0) .orderByDesc(DatabaseConsts.BookTable.COLUMN_LAST_CHAPTER_UPDATE_TIME) .last(DatabaseConsts.SqlEnum.LIMIT_500.getSql()); return bookInfoMapper.selectList(queryWrapper).stream().map(BookInfo::getId).toList(); diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index 8a7fa20..79c0b35 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -301,7 +301,7 @@ public class BookServiceImpl implements BookService { @Override public RestResp saveBookChapter(ChapterAddReqDto dto) { // 校验该作品是否属于当前作家 - BookInfoRespDto bookInfo = bookInfoCacheManager.getBookInfo(dto.getBookId()); + BookInfo bookInfo = bookInfoMapper.selectById(dto.getBookId()); if (!Objects.equals(bookInfo.getAuthorId(), UserHolder.getAuthorId())) { return RestResp.fail(ErrorCodeEnum.USER_UN_AUTH); } @@ -345,8 +345,8 @@ public class BookServiceImpl implements BookService { newBookInfo.setWordCount(bookInfo.getWordCount() + newBookChapter.getWordCount()); newBookChapter.setUpdateTime(LocalDateTime.now()); bookInfoMapper.updateById(newBookInfo); - // b) 刷新小说信息缓存 - bookInfoCacheManager.cachePutBookInfo(dto.getBookId()); + // b) 清除小说信息缓存 + bookInfoCacheManager.evictBookInfoCache(dto.getBookId()); // c) 发送小说信息更新的 MQ 消息 amqpMsgManager.sendBookChangeMsg(dto.getBookId()); return RestResp.ok(); -- Gitee From 121ec01fa260ddbca52abbfd470ed3c5b3ba48ac Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 29 May 2022 20:47:45 +0800 Subject: [PATCH 014/112] =?UTF-8?q?fix:=20=E4=BD=9C=E5=AE=B6=E5=B0=8F?= =?UTF-8?q?=E8=AF=B4=E5=8F=91=E5=B8=83=E6=A0=A1=E9=AA=8C=E4=BD=9C=E5=93=81?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../novel/core/common/constant/ErrorCodeEnum.java | 11 +++++++++++ .../xxyopen/novel/core/constant/DatabaseConsts.java | 2 ++ .../xxyopen/novel/service/impl/BookServiceImpl.java | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java b/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java index e69e7d4..0f53844 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java @@ -92,6 +92,17 @@ public enum ErrorCodeEnum { * */ USER_COMMENTED("A2001","用户已发表评论"), + /** + * 作家发布异常 + * */ + AUTHOR_PUBLISH("A3000","作家发布异常"), + + /** + * 小说名已存在 + * */ + AUTHOR_BOOK_NAME_EXIST("A3001","小说名已存在"), + + /** * 用户上传文件异常 * */ diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java index 3f0fafa..01b0e63 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java @@ -89,6 +89,8 @@ public class DatabaseConsts { public static final String COLUMN_CATEGORY_ID = "category_id"; + public static final String COLUMN_BOOK_NAME = "book_name"; + public static final String AUTHOR_ID = "author_id"; public static final String COLUMN_VISIT_COUNT = "visit_count"; diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index 79c0b35..e3d9bb3 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -276,6 +276,12 @@ public class BookServiceImpl implements BookService { @Override public RestResp saveBook(BookAddReqDto dto) { + // 校验小说名是否已存在 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(DatabaseConsts.BookTable.COLUMN_BOOK_NAME, dto.getBookName()); + if (bookInfoMapper.selectCount(queryWrapper) > 0) { + return RestResp.fail(ErrorCodeEnum.AUTHOR_BOOK_NAME_EXIST); + } BookInfo bookInfo = new BookInfo(); // 设置作家信息 AuthorInfoDto author = authorInfoCacheManager.getAuthor(UserHolder.getUserId()); -- Gitee From b6a07d3a0cb5e4b2186c3b5de77e8f2ac5e21b13 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Mon, 30 May 2022 06:40:30 +0800 Subject: [PATCH 015/112] =?UTF-8?q?fix:=20=E6=8E=92=E8=A1=8C=E6=A6=9C?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E6=97=A0=E7=AB=A0=E8=8A=82=E5=B0=8F=E8=AF=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/manager/cache/BookRankCacheManager.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java index a98cad9..6f28752 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java @@ -43,6 +43,7 @@ public class BookRankCacheManager { public List listNewestRankBooks() { QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); bookInfoQueryWrapper + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT,0) .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()); return listRankBooks(bookInfoQueryWrapper); } @@ -55,12 +56,15 @@ public class BookRankCacheManager { public List listUpdateRankBooks() { QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); bookInfoQueryWrapper + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT,0) .orderByDesc(DatabaseConsts.CommonColumnEnum.UPDATE_TIME.getName()); return listRankBooks(bookInfoQueryWrapper); } private List listRankBooks(QueryWrapper bookInfoQueryWrapper) { - bookInfoQueryWrapper.last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); + bookInfoQueryWrapper + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT,0) + .last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); return bookInfoMapper.selectList(bookInfoQueryWrapper).stream().map(v -> { BookRankRespDto respDto = new BookRankRespDto(); respDto.setId(v.getId()); -- Gitee From 4d71aa33b1320cf47a4fd07717b1bdc7d2ac5397 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Mon, 30 May 2022 06:48:41 +0800 Subject: [PATCH 016/112] =?UTF-8?q?feat:=20=E7=AB=A0=E8=8A=82=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E8=BF=94=E5=9B=9E=20isVip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java | 5 +++++ .../github/xxyopen/novel/service/impl/BookServiceImpl.java | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java index 8d4b5d8..b648831 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java @@ -52,4 +52,9 @@ public class BookChapterRespDto implements Serializable { @JsonFormat(pattern = "yyyy/MM/dd HH:dd") private LocalDateTime chapterUpdateTime; + /** + * 是否收费;1-收费 0-免费 + */ + private Integer isVip; + } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index e3d9bb3..31d07e2 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -191,6 +191,7 @@ public class BookServiceImpl implements BookService { return RestResp.ok(bookChapterMapper.selectList(queryWrapper).stream().map(v -> BookChapterRespDto.builder() .id(v.getId()) .chapterName(v.getChapterName()) + .isVip(v.getIsVip()) .build()).toList()); } @@ -393,6 +394,7 @@ public class BookServiceImpl implements BookService { .id(v.getId()) .chapterName(v.getChapterName()) .chapterUpdateTime(v.getUpdateTime()) + .isVip(v.getIsVip()) .build()).toList())); } -- Gitee From 220068cd3ae993dabaf15f00bcefbc53d5ca2ba6 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 31 May 2022 14:03:43 +0800 Subject: [PATCH 017/112] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90=E5=88=86?= =?UTF-8?q?=E5=B8=83=E5=BC=8F=E4=BB=BB=E5=8A=A1=E8=B0=83=E5=BA=A6=20XXL-JO?= =?UTF-8?q?B=EF=BC=8C=20=E4=BC=98=E5=8C=96=20Elasticsearch=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=90=8C=E6=AD=A5=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 ++ .../novel/core/config/XxlJobConfig.java | 44 +++++++++++ .../core/listener/RabbitQueueListener.java | 2 +- .../xxyopen/novel/core/task/BookToEsTask.java | 78 ++++++++++--------- .../service/impl/EsSearchServiceImpl.java | 6 ++ src/main/resources/application.yml | 15 ++++ 6 files changed, 115 insertions(+), 37 deletions(-) create mode 100644 src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java diff --git a/pom.xml b/pom.xml index 47b6466..675e55a 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,7 @@ 6.0.0-SNAPSHOT 0.11.5 8.2.0 + 2.3.1 @@ -116,6 +117,12 @@ spring-boot-starter-amqp + + com.xuxueli + xxl-job-core + ${xxl-job.version} + + mysql mysql-connector-java diff --git a/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java new file mode 100644 index 0000000..4084cf2 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java @@ -0,0 +1,44 @@ +package io.github.xxyopen.novel.core.config; + +import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * XXL-JOB 配置类 + * + * @author xiongxiaoyang + * @date 2022/5/31 + */ +@Configuration +@Slf4j +public class XxlJobConfig { + + @Value("${xxl.job.admin.addresses}") + private String adminAddresses; + + @Value("${xxl.job.accessToken}") + private String accessToken; + + @Value("${xxl.job.executor.appname}") + private String appname; + + @Value("${xxl.job.executor.logpath}") + private String logPath; + + @Bean + public XxlJobSpringExecutor xxlJobExecutor() { + log.info(">>>>>>>>>>> xxl-job config init."); + XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); + xxlJobSpringExecutor.setAdminAddresses(adminAddresses); + xxlJobSpringExecutor.setAccessToken(accessToken); + xxlJobSpringExecutor.setAppname(appname); + xxlJobSpringExecutor.setLogPath(logPath); + return xxlJobSpringExecutor; + } + +} \ No newline at end of file diff --git a/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java b/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java index 55d82f2..1d0971f 100644 --- a/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java +++ b/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Component; * @date 2022/5/25 */ @Component -@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "true") +@ConditionalOnProperty(prefix = "spring", name = {"elasticsearch.enable","amqp.enable"}, havingValue = "true") @RequiredArgsConstructor @Slf4j public class RabbitQueueListener { diff --git a/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java b/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java index a456e38..69704c5 100644 --- a/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java +++ b/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java @@ -6,6 +6,8 @@ import co.elastic.clients.elasticsearch.core.BulkRequest; import co.elastic.clients.elasticsearch.core.BulkResponse; import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.annotation.XxlJob; import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.core.constant.EsConsts; import io.github.xxyopen.novel.dao.entity.BookInfo; @@ -15,7 +17,6 @@ import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.List; @@ -40,49 +41,54 @@ public class BookToEsTask { * 每月凌晨做一次全量数据同步 */ @SneakyThrows - @Scheduled(cron = "0 0 0 1 * ?") - public void saveToEs() { + @XxlJob("saveToEsJobHandler") + public ReturnT saveToEs() { - QueryWrapper queryWrapper = new QueryWrapper<>(); - List bookInfos; - long maxId = 0; - for(;;) { - queryWrapper.clear(); - queryWrapper - .orderByAsc(DatabaseConsts.CommonColumnEnum.ID.getName()) - .gt(DatabaseConsts.CommonColumnEnum.ID.getName(), maxId) - .last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); - bookInfos = bookInfoMapper.selectList(queryWrapper); - if (bookInfos.isEmpty()) { - break; - } - BulkRequest.Builder br = new BulkRequest.Builder(); + try { + QueryWrapper queryWrapper = new QueryWrapper<>(); + List bookInfos; + long maxId = 0; + for (; ; ) { + queryWrapper.clear(); + queryWrapper + .orderByAsc(DatabaseConsts.CommonColumnEnum.ID.getName()) + .gt(DatabaseConsts.CommonColumnEnum.ID.getName(), maxId) + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT, 0) + .last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); + bookInfos = bookInfoMapper.selectList(queryWrapper); + if (bookInfos.isEmpty()) { + break; + } + BulkRequest.Builder br = new BulkRequest.Builder(); - for (BookInfo book : bookInfos) { - br.operations(op -> op - .index(idx -> idx - .index(EsConsts.BookIndex.INDEX_NAME) - .id(book.getId().toString()) - .document(EsBookDto.build(book)) - ) - ).timeout(Time.of(t -> t.time("10s"))); - maxId = book.getId(); - } + for (BookInfo book : bookInfos) { + br.operations(op -> op + .index(idx -> idx + .index(EsConsts.BookIndex.INDEX_NAME) + .id(book.getId().toString()) + .document(EsBookDto.build(book)) + ) + ).timeout(Time.of(t -> t.time("10s"))); + maxId = book.getId(); + } - BulkResponse result = elasticsearchClient.bulk(br.build()); + BulkResponse result = elasticsearchClient.bulk(br.build()); - // Log errors, if any - if (result.errors()) { - log.error("Bulk had errors"); - for (BulkResponseItem item : result.items()) { - if (item.error() != null) { - log.error(item.error().reason()); + // Log errors, if any + if (result.errors()) { + log.error("Bulk had errors"); + for (BulkResponseItem item : result.items()) { + if (item.error() != null) { + log.error(item.error().reason()); + } } } } - + return ReturnT.SUCCESS; + } catch (Exception e) { + log.error(e.getMessage(), e); + return ReturnT.FAIL; } - } } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java index 705f467..d977947 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java @@ -109,6 +109,12 @@ public class EsSearchServiceImpl implements SearchService { BoolQuery boolQuery = BoolQuery.of(b -> { + // 只查有字数的小说 + b.must(RangeQuery.of(m -> m + .field(EsConsts.BookIndex.FIELD_WORD_COUNT) + .gt(JsonData.of(0)) + )._toQuery()); + if (!StringUtils.isBlank(condition.getKeyword())) { // 关键词匹配 b.must((q -> q.multiMatch(t -> t diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 41e220b..2492763 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -58,6 +58,21 @@ spring: # 第一次和第二次重试之间的持续时间 initial-interval: "3s" +# XXL-JOB 配置 +xxl: + job: + admin: + ### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册; + addresses: http://127.0.0.1:8080/xxl-job-admin + executor: + ### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册 + appname: xxl-job-executor-novel + ### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径; + logpath: logs/xxl-job/jobhandler + ### xxl-job, access token + accessToken: 123 + + --- spring: config: -- Gitee From 9eb967402a8b3e151b892ed105534d01e8bfb20a Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 31 May 2022 14:16:26 +0800 Subject: [PATCH 018/112] docs: update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2a9aa1f..ad6b5a6 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 - Redis 7.0 - Elasticsearch 8.2.0(可选) - RabbitMQ 3.10.2(可选) +- XXL-JOB 2.3.1(可选) - JDK 17 - Maven 3.8 - IntelliJ IDEA 2021.3(可选) @@ -40,6 +41,7 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | | Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | | RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | +| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | | Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | | Docker | - | 应用容器引擎 | https://www.docker.com/ | - | | Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | -- Gitee From d7a7580c4e7732efe400e91ebcfda77af88c742c Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 31 May 2022 21:17:04 +0800 Subject: [PATCH 019/112] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20XXL-JOB=20?= =?UTF-8?q?=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/github/xxyopen/novel/core/config/XxlJobConfig.java | 2 ++ src/main/resources/application.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java index 4084cf2..c722bed 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java @@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -15,6 +16,7 @@ import org.springframework.context.annotation.Configuration; * @date 2022/5/31 */ @Configuration +@ConditionalOnProperty(prefix = "xxl.job", name = "enable", havingValue = "true") @Slf4j public class XxlJobConfig { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2492763..5db5605 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -61,6 +61,8 @@ spring: # XXL-JOB 配置 xxl: job: + # 是否开启 XXL-JOB:true-开启 false-不开启 + enable: false admin: ### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册; addresses: http://127.0.0.1:8080/xxl-job-admin -- Gitee From 9894814fe40e1efb2e8e272f3ce99c59651dc10a Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 31 May 2022 21:31:42 +0800 Subject: [PATCH 020/112] docs: update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ad6b5a6..57372f4 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 - IntelliJ IDEA 2021.3(可选) - Node 16.14 +**注:Elasticsearch、RabbitMQ 和 XXL-JOB 默认关闭,可通过 application.yml 配置文件中相应的`enable`配置属性开启。** + ## 后端技术选型 | 技术 | 版本 | 说明 | 官网 | 学习 | -- Gitee From c628104a30cd6c29c0dadc6b37b2251a2af4f0fc Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Wed, 1 Jun 2022 13:40:17 +0800 Subject: [PATCH 021/112] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90=20Sentinel?= =?UTF-8?q?=20=E5=AE=9E=E7=8E=B0=E6=8E=A5=E5=8F=A3=E9=98=B2=E5=88=B7?= =?UTF-8?q?=E5=92=8C=E9=99=90=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 15 ++- .../core/common/constant/ErrorCodeEnum.java | 14 ++- .../xxyopen/novel/core/config/WebConfig.java | 18 +++- .../interceptor/FlowLimitInterceptor.java | 98 +++++++++++++++++++ 4 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java diff --git a/pom.xml b/pom.xml index 675e55a..21eb3da 100644 --- a/pom.xml +++ b/pom.xml @@ -111,18 +111,31 @@ jackson-databind - + org.springframework.boot spring-boot-starter-amqp + com.xuxueli xxl-job-core ${xxl-job.version} + + + com.alibaba.csp + sentinel-core + 1.8.4 + + + com.alibaba.csp + sentinel-parameter-flow-control + 1.8.4 + + mysql mysql-connector-java diff --git a/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java b/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java index 0f53844..8d10836 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java @@ -82,6 +82,16 @@ public enum ErrorCodeEnum { * */ USER_UN_AUTH("A0301","访问未授权"), + /** + * 用户请求服务异常 + * */ + USER_REQ_EXCEPTION("A0500","用户请求服务异常"), + + /** + * 请求超出限制 + * */ + USER_REQ_MANY("A0501","请求超出限制"), + /** * 用户评论异常 * */ @@ -137,11 +147,11 @@ public enum ErrorCodeEnum { /** * 错误码 * */ - private String code; + private final String code; /** * 中文描述 * */ - private String message; + private final String message; } diff --git a/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java index 18f9276..a456df2 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java @@ -4,6 +4,7 @@ import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.core.interceptor.AuthInterceptor; import io.github.xxyopen.novel.core.interceptor.FileInterceptor; +import io.github.xxyopen.novel.core.interceptor.FlowLimitInterceptor; import io.github.xxyopen.novel.core.interceptor.TokenParseInterceptor; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; @@ -22,6 +23,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { + private final FlowLimitInterceptor flowLimitInterceptor; + private final AuthInterceptor authInterceptor; private final FileInterceptor fileInterceptor; @@ -30,9 +33,16 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { + + // 流量限制拦截器 + registry.addInterceptor(flowLimitInterceptor) + .addPathPatterns("/**") + .order(0); + // 文件访问拦截 registry.addInterceptor(fileInterceptor) - .addPathPatterns(SystemConfigConsts.IMAGE_UPLOAD_DIRECTORY + "**"); + .addPathPatterns(SystemConfigConsts.IMAGE_UPLOAD_DIRECTORY + "**") + .order(1); // 权限认证拦截 registry.addInterceptor(authInterceptor) @@ -45,12 +55,14 @@ public class WebConfig implements WebMvcConfigurer { // 放行登录注册相关请求接口 .excludePathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/register", ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/login", - ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login"); + ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login") + .order(2); // Token 解析拦截器 registry.addInterceptor(tokenParseInterceptor) // 拦截小说内容查询接口,需要解析 token 以判断该用户是否有权阅读该章节(付费章节是否已购买) - .addPathPatterns(ApiRouterConsts.API_FRONT_BOOK_URL_PREFIX + "/content/*"); + .addPathPatterns(ApiRouterConsts.API_FRONT_BOOK_URL_PREFIX + "/content/*") + .order(3); } } diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java new file mode 100644 index 0000000..f8c22f2 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java @@ -0,0 +1,98 @@ +package io.github.xxyopen.novel.core.interceptor; + +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.slots.block.RuleConstant; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum; +import io.github.xxyopen.novel.core.common.resp.RestResp; +import io.github.xxyopen.novel.core.common.util.IpUtils; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 流量限制 拦截器 + * 实现接口防刷和限流 + * + * @author xiongxiaoyang + * @date 2022/6/1 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class FlowLimitInterceptor implements HandlerInterceptor { + + private final ObjectMapper objectMapper; + + /** + * 定义一个对所有的请求进行统一限制的资源 + */ + private static final String ALL_LIMIT_RESOURCE = "allLimitResource"; + + static { + // 接口限流规则:所有的请求,限制每秒最多只能通过 2000 个,超出限制匀速排队 + List rules = new ArrayList<>(); + FlowRule rule1 = new FlowRule(); + rule1.setResource(ALL_LIMIT_RESOURCE); + rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); + // Set limit QPS to 2000. + rule1.setCount(2000); + rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER); + rules.add(rule1); + FlowRuleManager.loadRules(rules); + + // 接口防刷规则 1:所有的请求,限制每个 IP 每秒最多只能通过 50 个,超出限制直接拒绝 + ParamFlowRule rule2 = new ParamFlowRule(ALL_LIMIT_RESOURCE) + .setParamIdx(0) + .setCount(50); + // 接口防刷规则 2:所有的请求,限制每个 IP 每分钟最多只能通过 1000 个,超出限制直接拒绝 + ParamFlowRule rule3 = new ParamFlowRule(ALL_LIMIT_RESOURCE) + .setParamIdx(0) + .setCount(1000) + .setDurationInSec(60); + ParamFlowRuleManager.loadRules(Arrays.asList(rule2, rule3)); + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String ip = IpUtils.getRealIp(request); + Entry entry = null; + try { + // 若需要配置例外项,则传入的参数只支持基本类型。 + // EntryType 代表流量类型,其中系统规则只对 IN 类型的埋点生效 + // count 大多数情况都填 1,代表统计为一次调用。 + entry = SphU.entry(ALL_LIMIT_RESOURCE, EntryType.IN, 1, ip); + // Your logic here. + return HandlerInterceptor.super.preHandle(request, response, handler); + } catch (BlockException ex) { + // Handle request rejection. + log.info("IP:{}被限流了!", ip); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.getWriter().write(objectMapper.writeValueAsString(RestResp.fail(ErrorCodeEnum.USER_REQ_MANY))); + } finally { + // 注意:exit 的时候也一定要带上对应的参数,否则可能会有统计错误。 + if (entry != null) { + entry.exit(1, ip); + } + } + return false; + } + +} -- Gitee From 7f0d6c842a662708b8431814699abfc710e1e37f Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Wed, 1 Jun 2022 13:59:41 +0800 Subject: [PATCH 022/112] =?UTF-8?q?chore:=20=E4=BE=9D=E8=B5=96=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 21eb3da..5c6cc65 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,7 @@ 0.11.5 8.2.0 2.3.1 + 1.8.4 @@ -128,12 +129,12 @@ com.alibaba.csp sentinel-core - 1.8.4 + ${sentinel.version} com.alibaba.csp sentinel-parameter-flow-control - 1.8.4 + ${sentinel.version} -- Gitee From c4fabe2ca12cf9fd157ba2510cff450af9e0aa6a Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Wed, 1 Jun 2022 14:11:58 +0800 Subject: [PATCH 023/112] docs: update README.md --- README.md | 3 ++- .../novel/core/interceptor/FlowLimitInterceptor.java | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 57372f4..32811be 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | | Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | | RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | -| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | +| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | +| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | | Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | | Docker | - | 应用容器引擎 | https://www.docker.com/ | - | | Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java index f8c22f2..0ca5ee2 100644 --- a/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java @@ -41,15 +41,15 @@ public class FlowLimitInterceptor implements HandlerInterceptor { private final ObjectMapper objectMapper; /** - * 定义一个对所有的请求进行统一限制的资源 + * novel 项目所有的资源 */ - private static final String ALL_LIMIT_RESOURCE = "allLimitResource"; + private static final String NOVEL_RESOURCE = "novelResource"; static { // 接口限流规则:所有的请求,限制每秒最多只能通过 2000 个,超出限制匀速排队 List rules = new ArrayList<>(); FlowRule rule1 = new FlowRule(); - rule1.setResource(ALL_LIMIT_RESOURCE); + rule1.setResource(NOVEL_RESOURCE); rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); // Set limit QPS to 2000. rule1.setCount(2000); @@ -58,11 +58,11 @@ public class FlowLimitInterceptor implements HandlerInterceptor { FlowRuleManager.loadRules(rules); // 接口防刷规则 1:所有的请求,限制每个 IP 每秒最多只能通过 50 个,超出限制直接拒绝 - ParamFlowRule rule2 = new ParamFlowRule(ALL_LIMIT_RESOURCE) + ParamFlowRule rule2 = new ParamFlowRule(NOVEL_RESOURCE) .setParamIdx(0) .setCount(50); // 接口防刷规则 2:所有的请求,限制每个 IP 每分钟最多只能通过 1000 个,超出限制直接拒绝 - ParamFlowRule rule3 = new ParamFlowRule(ALL_LIMIT_RESOURCE) + ParamFlowRule rule3 = new ParamFlowRule(NOVEL_RESOURCE) .setParamIdx(0) .setCount(1000) .setDurationInSec(60); @@ -77,7 +77,7 @@ public class FlowLimitInterceptor implements HandlerInterceptor { // 若需要配置例外项,则传入的参数只支持基本类型。 // EntryType 代表流量类型,其中系统规则只对 IN 类型的埋点生效 // count 大多数情况都填 1,代表统计为一次调用。 - entry = SphU.entry(ALL_LIMIT_RESOURCE, EntryType.IN, 1, ip); + entry = SphU.entry(NOVEL_RESOURCE, EntryType.IN, 1, ip); // Your logic here. return HandlerInterceptor.super.preHandle(request, response, handler); } catch (BlockException ex) { -- Gitee From 320b985ce602b6ac2611f3dcb62f25d4c5a19c91 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Thu, 2 Jun 2022 06:58:18 +0800 Subject: [PATCH 024/112] docs: update README.md --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 32811be..4dc8d26 100644 --- a/README.md +++ b/README.md @@ -252,13 +252,15 @@ git clone https://gitee.com/novel_dev_team/novel-front-web.git ## 公众号 -关注公众号接收项目最新动态,获取`Spring Boot 3`学习笔记! +- 关注公众号接收`项目`和`文档`的更新动态 -加微信群学习交流,公众号后台回复「**微信群**」即可。 +- 加微信群学习交流,公众号后台回复「**微信群**」即可 -发送「**资料**」获取`JAVA 面试参考`、`海量简历模板`、`技术电子书`等学习面试资料。 +- 回复「**资料**」获取`Java 学习面试资料` -![微信公众号](https://youdoc.github.io/img/qrcode_for_gh.jpg) +- 回复「**笔记**」获取`Spring Boot 3 学习笔记` + +![IT进阶](https://youdoc.gitee.io/img/qrcode_for_gh.jpg) ## 赞赏支持 -- Gitee From 520faff51f61aa0543c4e839349dffc241500c75 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Thu, 2 Jun 2022 12:15:21 +0800 Subject: [PATCH 025/112] =?UTF-8?q?docs:=20=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/manager/redis/VerifyCodeManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java b/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java index 78100b3..e42adda 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java @@ -25,7 +25,7 @@ public class VerifyCodeManager { private final StringRedisTemplate stringRedisTemplate; /** - * 生成图片验证码,并放入缓存中 + * 生成图形验证码,并放入 Redis 中 */ public String genImgVerifyCode(String sessionId) throws IOException { String verifyCode = ImgVerifyCodeUtils.getRandomVerifyCode(4); @@ -36,14 +36,14 @@ public class VerifyCodeManager { } /** - * 校验图片验证码 + * 校验图形验证码 */ public boolean imgVerifyCodeOk(String sessionId, String verifyCode) { return Objects.equals(stringRedisTemplate.opsForValue().get(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId), verifyCode); } /** - * 删除验证码 + * 从 Redis 中删除验证码 */ public void removeImgVerifyCode(String sessionId) { stringRedisTemplate.delete(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId); -- Gitee From 21f30df237904ca2bec8d7a79403e36ebb1e5da3 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Thu, 2 Jun 2022 12:16:34 +0800 Subject: [PATCH 026/112] =?UTF-8?q?build:=20=E4=BF=AE=E6=94=B9=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5c6cc65..ea01fdf 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ io.github.xxyopen novel - 3.1.0 + 3.2.0 novel Spring Boot 3 + Vue 3 构建的前后端分离小说系统 -- Gitee From 5e995cd63ebb85b826e28aff5809636b27d9ebc3 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 3 Jun 2022 09:22:07 +0800 Subject: [PATCH 027/112] docs: update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4dc8d26..098a553 100644 --- a/README.md +++ b/README.md @@ -260,7 +260,7 @@ git clone https://gitee.com/novel_dev_team/novel-front-web.git - 回复「**笔记**」获取`Spring Boot 3 学习笔记` -![IT进阶](https://youdoc.gitee.io/img/qrcode_for_gh.jpg) +![xxyopen](https://youdoc.gitee.io/img/qrcode_for_gh.jpg) ## 赞赏支持 -- Gitee From bf60ba30c93b7976675676a7b581bf991db81fd6 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 3 Jun 2022 18:52:35 +0800 Subject: [PATCH 028/112] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E5=88=86=E8=A1=A8=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/20220603.sql | 171 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 doc/sql/20220603.sql diff --git a/doc/sql/20220603.sql b/doc/sql/20220603.sql new file mode 100644 index 0000000..b2daf19 --- /dev/null +++ b/doc/sql/20220603.sql @@ -0,0 +1,171 @@ +DROP PROCEDURE IF EXISTS createBookChapterTable; +-- 创建小说章节表的存储过程 +CREATE PROCEDURE createBookChapterTable() +BEGIN + + -- 定义变量 + DECLARE i int DEFAULT 0; + DECLARE tableName char(13) DEFAULT NULL; + + while i < 10 do + + set tableName = concat('book_chapter',i); + + set @stmt = concat('create table ',tableName,'( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `book_id` bigint(20) unsigned NOT NULL COMMENT \'小说ID\', + `chapter_num` smallint(5) unsigned NOT NULL COMMENT \'章节号\', + `chapter_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'章节名\', + `word_count` int(10) unsigned NOT NULL COMMENT \'章节字数\', + `is_vip` tinyint(3) unsigned NOT NULL DEFAULT \'0\' COMMENT \'是否收费;1-收费 0-免费\', + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_bookId_chapterNum` (`book_id`,`chapter_num`) USING BTREE, + UNIQUE KEY `pk_id` (`id`) USING BTREE, + KEY `idx_bookId` (`book_id`) USING BTREE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=\'小说章节\''); + prepare stmt from @stmt; + execute stmt; + deallocate prepare stmt; + + set i = i + 1; + + end while; + +END; +call createBookChapterTable(); + + +DROP PROCEDURE IF EXISTS createBookContentTable; +-- 创建小说内容表的存储过程 +CREATE PROCEDURE createBookContentTable() +BEGIN + + -- 定义变量 + DECLARE i int DEFAULT 0; + DECLARE tableName char(13) DEFAULT NULL; + + while i < 10 do + + set tableName = concat('book_content',i); + + set @stmt = concat('create table ',tableName,'( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT \'主键\', + `chapter_id` bigint(20) unsigned NOT NULL COMMENT \'章节ID\', + `content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'小说章节内容\', + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_chapterId` (`chapter_id`) USING BTREE, + UNIQUE KEY `pk_id` (`id`) USING BTREE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=\'小说内容\''); + prepare stmt from @stmt; + execute stmt; + deallocate prepare stmt; + + set i = i + 1; + + end while; + +END; +call createBookContentTable(); + + +DROP PROCEDURE IF EXISTS copyBookChapterData; +-- 迁移小说章节数据的存储过程 +CREATE PROCEDURE copyBookChapterData() +BEGIN + + -- 定义变量 + DECLARE s int DEFAULT 0; + DECLARE chapterId bigint; + DECLARE bookId bigint; + DECLARE chapterNum smallint; + DECLARE chapterName varchar(100); + DECLARE wordCount int DEFAULT 0; + DECLARE isVip tinyint(64) DEFAULT 0; + DECLARE createTime datetime DEFAULT NULL; + DECLARE updateTime datetime DEFAULT NULL; + DECLARE tableNumber int DEFAULT 0; + DECLARE tableName char(13) DEFAULT NULL; + + + -- 定义游标 + DECLARE report CURSOR FOR select id,book_id,chapter_num, chapter_name, word_count, is_vip,create_time,update_time from book_chapter; + + -- 声明当游标遍历完后将标志变量置成某个值 + DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1; + + -- 打开游标 + open report; + + -- 将游标中的值赋值给变量,注意:变量名不要和返回的列名同名,变量顺序要和sql结果列的顺序一致 + fetch report into chapterId,bookId,chapterNum, chapterName, wordCount,isVip,createTime,updateTime; + + -- 循环遍历 + while s<>1 do + -- 执行业务逻辑 + set tableNumber = bookId % 10; + set tableName = concat('book_chapter',tableNumber); + set @stmt = concat('insert into ',tableName,'(`id`, `book_id`, `chapter_num`, `chapter_name`, `word_count`, `is_vip`, `create_time`, `update_time`) VALUES (',chapterId,', ',bookId,', ',chapterNum,', \'',chapterName,'\', ',wordCount,', ',isVip,', \'',createTime,'\', \'',updateTime,'\')'); + prepare stmt from @stmt; + execute stmt; + deallocate prepare stmt; + + fetch report into chapterId,bookId,chapterNum, chapterName, wordCount,isVip,createTime,updateTime; + end while; + -- 关闭游标 + close report; + +END; +call copyBookChapterData(); + + +DROP PROCEDURE IF EXISTS copyBookContentData; +-- 迁移小说内容数据的存储过程 +CREATE PROCEDURE copyBookContentData() +BEGIN + + -- 定义变量 + DECLARE s int DEFAULT 0; + DECLARE contentId bigint; + DECLARE chapterId bigint; + DECLARE bookContent mediumtext; + DECLARE createTime datetime DEFAULT NULL; + DECLARE updateTime datetime DEFAULT NULL; + DECLARE tableNumber int DEFAULT 0; + DECLARE tableName char(13) DEFAULT NULL; + + + -- 定义游标 + DECLARE report CURSOR FOR select id,chapter_id,content,create_time,update_time from book_content; + + -- 声明当游标遍历完后将标志变量置成某个值 + DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1; + + -- 打开游标 + open report; + + -- 将游标中的值赋值给变量,注意:变量名不要和返回的列名同名,变量顺序要和sql结果列的顺序一致 + fetch report into contentId,chapterId,bookContent,createTime,updateTime; + + -- 循环遍历 + while s<>1 do + -- 执行业务逻辑 + set tableNumber = chapterId % 10; + set tableName = concat('book_content',tableNumber); + set bookContent = REPLACE(bookContent,'\'',"\\'"); + set @stmt = concat('insert into ',tableName,'(`id`, `chapter_id`, `content`) VALUES (',contentId,', ',chapterId,',\'',bookContent,'\')'); + + prepare stmt from @stmt; + execute stmt; + deallocate prepare stmt; + + fetch report into contentId,chapterId,bookContent,createTime,updateTime; + end while; + -- 关闭游标 + close report; + +END; +call copyBookContentData(); \ No newline at end of file -- Gitee From 5d0ac13ae68cbe279e3b9ed412ba49c3f3708972 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 3 Jun 2022 20:57:23 +0800 Subject: [PATCH 029/112] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90=20ShardingSp?= =?UTF-8?q?here-JDBC=20=E6=9C=80=E6=96=B0=E7=89=88=EF=BC=8C=E5=88=86?= =?UTF-8?q?=E8=A1=A8=E5=AD=98=E5=82=A8=E5=B0=8F=E8=AF=B4=E5=86=85=E5=AE=B9?= =?UTF-8?q?=EF=BC=88=E9=BB=98=E8=AE=A4=E5=85=B3=E9=97=AD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 默认关闭分库分表,通过配置属性 shardingsphere.enabled 来开启 --- pom.xml | 8 +++++++ src/main/resources/application.yml | 38 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/pom.xml b/pom.xml index ea01fdf..552c38f 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ 8.2.0 2.3.1 1.8.4 + 5.1.1 @@ -137,6 +138,13 @@ ${sentinel.version} + + + org.apache.shardingsphere + shardingsphere-jdbc-core-spring-boot-starter + ${shardingsphere-jdbc.version} + + mysql mysql-connector-java diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5db5605..7a06a9e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -20,6 +20,44 @@ spring: url: jdbc:mysql://localhost:3306/novel_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: test123456 + # 分库分表配置 + shardingsphere: + datasource: + names: ds_0 + ds_0: + type: com.zaxxer.hikari.HikariDataSource + driverClassName: com.mysql.cj.jdbc.Driver + jdbcUrl: jdbc:mysql://localhost:3306/novel_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: test123456 + rules: + sharding: + tables: + # book_content表 + book_content: + # 数据节点 + actual-data-nodes: ds_$->{0}.book_content$->{0..9} + # 分表策略 + table-strategy: + standard: + # 分片列名称 + sharding-column: chapter_id + # 分片算法名称 + sharding-algorithm-name: bookContentSharding + sharding-algorithms: + bookContentSharding: + # 行表达式分片算法,使用 Groovy 的表达式,提供对 SQL 语句中的 = 和 IN 的分片操作支持 + type: INLINE + props: + # 分片算法的行表达式 + algorithm-expression: book_content$->{chapter_id % 10} + props: + # 是否在日志中打印 SQL + sql-show: true + # 是否开启分库分表 + enabled: false + + config: activate: on-profile: dev -- Gitee From 78b366716aefd0114ba52f1cc11e4bf15a8fdd71 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 3 Jun 2022 21:49:30 +0800 Subject: [PATCH 030/112] docs: update README.md --- README.md | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 098a553..d63ab44 100644 --- a/README.md +++ b/README.md @@ -31,24 +31,25 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 ## 后端技术选型 -| 技术 | 版本 | 说明 | 官网 | 学习 | -|:--------------|:--------------:|---------------------| --------------------------------------- | :-------------------------------------------------: | -| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | -| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | -| MyBatis-Plus | 3.5.1 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | -| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | -| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | -| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | -| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | -| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | -| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | -| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | -| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | -| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | -| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | -| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | -| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | -| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | +| 技术 | 版本 | 说明 | 官网 | 学习 | +|:-------------------------------|:--------------:|---------------------| --------------------------------------- |:----------------------------------------------------------------------------------------:| +| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | +| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | +| MyBatis-Plus | 3.5.1 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | +| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | +| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | +| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | +| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | +| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | +| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org/index_zh.html | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | +| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | +| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | +| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | +| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | +| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | +| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | +| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | +| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | **注:更多热门新技术待集成。** ## 前端技术选型 -- Gitee From 08237e11e9f714d6f3b5a8b79bd1353081ad2273 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 3 Jun 2022 22:07:30 +0800 Subject: [PATCH 031/112] docs: update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d63ab44..b97240c 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | | Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | | MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | -| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org/index_zh.html | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | +| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | | Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | | RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | | XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | -- Gitee From d5e45e74c9410c00fd613261e3ad25c6a4a3dac4 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sat, 4 Jun 2022 07:54:46 +0800 Subject: [PATCH 032/112] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0=20ShardingS?= =?UTF-8?q?phere-JDBC=20=E7=9A=84=E6=A8=A1=E5=BC=8F=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 32 ++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7a06a9e..fa82642 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -20,8 +20,28 @@ spring: url: jdbc:mysql://localhost:3306/novel_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: test123456 - # 分库分表配置 + # ShardingSphere-JDBC 配置 + # 配置是 ShardingSphere-JDBC 中唯一与应用开发者交互的模块, + # 通过它可以快速清晰的理解 ShardingSphere-JDBC 所提供的功能。 shardingsphere: + # 是否开启分库分表 + enabled: false + props: + # 是否在日志中打印 SQL + sql-show: true + # 模式配置 + mode: + # 单机模式 + type: Standalone + repository: + # 文件持久化 + type: File + props: + # 元数据存储路径 + path: .shardingsphere + # 使用本地配置覆盖持久化配置 + overwrite: true + # 数据源配置 datasource: names: ds_0 ds_0: @@ -30,10 +50,12 @@ spring: jdbcUrl: jdbc:mysql://localhost:3306/novel_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: test123456 + # 规则配置 rules: + # 数据分片 sharding: tables: - # book_content表 + # book_content 表 book_content: # 数据节点 actual-data-nodes: ds_$->{0}.book_content$->{0..9} @@ -51,12 +73,6 @@ spring: props: # 分片算法的行表达式 algorithm-expression: book_content$->{chapter_id % 10} - props: - # 是否在日志中打印 SQL - sql-show: true - # 是否开启分库分表 - enabled: false - config: activate: -- Gitee From 0a8808b418e854694d2f0d5261ec88f41917c794 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Mon, 6 Jun 2022 21:43:31 +0800 Subject: [PATCH 033/112] =?UTF-8?q?build:=20=E9=9B=86=E6=88=90=20Spring=20?= =?UTF-8?q?Boot=20Admin=EF=BC=8C=E5=AE=9E=E7=8E=B0=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=92=8C=E7=9B=91=E6=8E=A7=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 22 ++++++++++++++ src/main/resources/application.yml | 42 ++++++++++++++++++++++++++- src/main/resources/logback-spring.xml | 4 +-- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 552c38f..c3ca758 100644 --- a/pom.xml +++ b/pom.xml @@ -145,6 +145,17 @@ ${shardingsphere-jdbc.version} + + + org.springframework.boot + spring-boot-starter-actuator + + + de.codecentric + spring-boot-admin-starter-client + 3.0.0-M1 + + mysql mysql-connector-java @@ -200,6 +211,17 @@ false + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + true + + + false + + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index fa82642..5b97094 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,7 +1,6 @@ spring: profiles: active: dev - # 将所有数字转为 String 类型返回,避免前端数据精度丢失的问题 jackson: generator: @@ -10,6 +9,8 @@ spring: # 上传文件最大大小 multipart: max-file-size: 5MB + application: + name: novel server: port: 8888 @@ -129,6 +130,45 @@ xxl: accessToken: 123 +--- +spring: + config: + activate: + on-profile: dev +# Spring Boot 应用管理和监控 + boot: + admin: + client: + # 是否开启 Spring Boot Admin 客户端 + enabled: false + # Spring Boot Admin 服务端注册地址 + url: http://localhost:8080 + # Spring Boot Admin 服务端认证用户名 + username: novel + # Spring Boot Admin 服务端认证密码 + password: novel + + +management: + endpoints: + web: + exposure: + include: "*" + endpoint: + logfile: + enabled: true + external-file: logs/novel.log + + info: + env: + enabled: true + health: + rabbit: + enabled: false + elasticsearch: + enabled: false + + --- spring: config: diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 40569f6..a7883d6 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -53,26 +53,26 @@ + + - - -- Gitee From 7012b7b8ea9eb321c270e34250d352b3769da152 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 7 Jun 2022 08:24:40 +0800 Subject: [PATCH 034/112] docs: update README.md --- README.md | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index b97240c..b5ebf5d 100644 --- a/README.md +++ b/README.md @@ -31,25 +31,26 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 ## 后端技术选型 -| 技术 | 版本 | 说明 | 官网 | 学习 | -|:-------------------------------|:--------------:|---------------------| --------------------------------------- |:----------------------------------------------------------------------------------------:| -| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | -| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | -| MyBatis-Plus | 3.5.1 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | -| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | -| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | -| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | -| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | -| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | -| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | -| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | -| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | -| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | -| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | -| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | -| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | -| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | -| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | +| 技术 | 版本 | 说明 | 官网 | 学习 | +|-------------------------------|:--------------:|---------------------| --------------------------------------- |:---------------------------------------------------------------------------------------:| +| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | +| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | +| MyBatis-Plus | 3.5.1 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | +| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | +| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | +| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | +| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | +| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | +| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | +| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | +| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | +| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | +| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | +| Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | +| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | +| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | +| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | +| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | **注:更多热门新技术待集成。** ## 前端技术选型 -- Gitee From 925da99d0b9cdca934795dd3404be6073b56ad8d Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 7 Jun 2022 18:17:08 +0800 Subject: [PATCH 035/112] =?UTF-8?q?perf:=20Actuator=20Endpoints=20?= =?UTF-8?q?=E4=BF=9D=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 ++ .../xxyopen/novel/NovelApplication.java | 45 ++++++++++++------- src/main/resources/application.yml | 18 +++++++- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/pom.xml b/pom.xml index c3ca758..04b3c58 100644 --- a/pom.xml +++ b/pom.xml @@ -155,6 +155,10 @@ spring-boot-admin-starter-client 3.0.0-M1 + + org.springframework.boot + spring-boot-starter-security + mysql diff --git a/src/main/java/io/github/xxyopen/novel/NovelApplication.java b/src/main/java/io/github/xxyopen/novel/NovelApplication.java index 5f5d082..c0e7072 100644 --- a/src/main/java/io/github/xxyopen/novel/NovelApplication.java +++ b/src/main/java/io/github/xxyopen/novel/NovelApplication.java @@ -4,12 +4,16 @@ import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; +import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.util.matcher.AnyRequestMatcher; import java.util.Map; @@ -20,21 +24,30 @@ import java.util.Map; @Slf4j public class NovelApplication { - public static void main(String[] args) { - SpringApplication.run(NovelApplication.class, args); - } - - @Bean - public CommandLineRunner commandLineRunner(ApplicationContext context){ - return args -> { - Map beans = context.getBeansOfType(CacheManager.class); - log.info("加载了如下缓存管理器:"); - beans.forEach((k,v)->{ - log.info("{}:{}",k,v.getClass().getName()); - log.info("缓存:{}",v.getCacheNames()); - }); - - }; - } + public static void main(String[] args) { + SpringApplication.run(NovelApplication.class, args); + } + + @Bean + public CommandLineRunner commandLineRunner(ApplicationContext context) { + return args -> { + Map beans = context.getBeansOfType(CacheManager.class); + log.info("加载了如下缓存管理器:"); + beans.forEach((k, v) -> { + log.info("{}:{}", k, v.getClass().getName()); + log.info("缓存:{}", v.getCacheNames()); + }); + + }; + } + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.csrf().disable() + .requestMatcher(EndpointRequest.toAnyEndpoint()) + .authorizeRequests(requests -> requests.anyRequest().hasRole("ENDPOINT_ADMIN")); + http.httpBasic(); + return http.build(); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5b97094..baf43a2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -147,28 +147,44 @@ spring: username: novel # Spring Boot Admin 服务端认证密码 password: novel + security: + user: + name: ENDPOINT_ADMIN + password: ENDPOINT_ADMIN + roles: ENDPOINT_ADMIN - +# Actuator 端点管理 management: + # 端点公开配置 endpoints: + # 通过 HTTP 公开的 Web 端点 web: exposure: + # 公开所有的 Web 端点 include: "*" + + # 端点启用配置 endpoint: logfile: + # 启用返回日志文件内容的端点 enabled: true + # 外部日志文件路径 external-file: logs/novel.log info: env: + # 公开所有以 info. 开头的环境属性 enabled: true health: rabbit: + # 关闭 rabbitmq 的健康检查 enabled: false elasticsearch: + # 关闭 elasticsearch 的健康检查 enabled: false + --- spring: config: -- Gitee From fc0f3bee1d8afa3de703052a39d59caf9fa86b1d Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 7 Jun 2022 20:57:06 +0800 Subject: [PATCH 036/112] =?UTF-8?q?perf:=20=E5=A2=9E=E5=8A=A0=20Spring=20B?= =?UTF-8?q?oot=20Admin=20=E7=9A=84=20SBA=20Client=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index baf43a2..53924df 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -147,6 +147,11 @@ spring: username: novel # Spring Boot Admin 服务端认证密码 password: novel + instance: + metadata: + # SBA Client + user.name: ${spring.security.user.name} + user.password: ${spring.security.user.password} security: user: name: ENDPOINT_ADMIN -- Gitee From 8199b3d4af1552db1c2b3456d500227bd4026f31 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Thu, 9 Jun 2022 11:52:47 +0800 Subject: [PATCH 037/112] docs: update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b5ebf5d..7bedbc3 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Github forks](https://img.shields.io/github/forks/201206030/novel?logo=github)](https://github.com/201206030/novel) [![Gitee star](https://gitee.com/novel_dev_team/novel/badge/star.svg?theme=gitee)](https://gitee.com/novel_dev_team/novel) [![Gitee fork](https://gitee.com/novel_dev_team/novel/badge/fork.svg?theme=gitee)](https://gitee.com/novel_dev_team/novel) +visitors ## 项目简介 novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离的**学习型**小说项目,配备详细的项目教程手把手教你**从零开始**开发上线一个生产级别的 Java 系统,由小说门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成。包括小说推荐、作品检索、小说排行榜、小说阅读、小说评论、充值订阅、新闻发布等功能。 -- Gitee From cfafc6450b35e54c841e4d75dd4344532488a192 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 10 Jun 2022 17:31:22 +0800 Subject: [PATCH 038/112] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0=20xxl=5Fjob?= =?UTF-8?q?=20=E7=9A=84=E8=84=9A=E6=9C=AC=EF=BC=8C=E5=BC=80=E5=90=AF=20xxl?= =?UTF-8?q?-job=20=E5=8A=9F=E8=83=BD=E6=89=8D=E9=9C=80=E8=A6=81=E6=89=A7?= =?UTF-8?q?=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/xxl-job.sql | 190 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 doc/sql/xxl-job.sql diff --git a/doc/sql/xxl-job.sql b/doc/sql/xxl-job.sql new file mode 100644 index 0000000..ceed371 --- /dev/null +++ b/doc/sql/xxl-job.sql @@ -0,0 +1,190 @@ +# +# XXL-JOB v2.4.0-SNAPSHOT +# Copyright (c) 2015-present, xuxueli. + +CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci; +use `xxl_job`; + +SET NAMES utf8mb4; + +CREATE TABLE `xxl_job_info` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `job_group` int(11) NOT NULL COMMENT '执行器主键ID', + `job_desc` varchar(255) NOT NULL, + `add_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + `author` varchar(64) DEFAULT NULL COMMENT '作者', + `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件', + `schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型', + `schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型', + `misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略', + `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略', + `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', + `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数', + `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略', + `executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒', + `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数', + `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型', + `glue_source` mediumtext COMMENT 'GLUE源代码', + `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注', + `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间', + `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔', + `trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行', + `trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间', + `trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_log` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `job_group` int(11) NOT NULL COMMENT '执行器主键ID', + `job_id` int(11) NOT NULL COMMENT '任务,主键ID', + `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址', + `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', + `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数', + `executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2', + `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数', + `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间', + `trigger_code` int(11) NOT NULL COMMENT '调度-结果', + `trigger_msg` text COMMENT '调度-日志', + `handle_time` datetime DEFAULT NULL COMMENT '执行-时间', + `handle_code` int(11) NOT NULL COMMENT '执行-状态', + `handle_msg` text COMMENT '执行-日志', + `alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败', + PRIMARY KEY (`id`), + KEY `I_trigger_time` (`trigger_time`), + KEY `I_handle_code` (`handle_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_log_report` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `trigger_day` datetime DEFAULT NULL COMMENT '调度-时间', + `running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量', + `suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量', + `fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量', + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_logglue` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `job_id` int(11) NOT NULL COMMENT '任务,主键ID', + `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型', + `glue_source` mediumtext COMMENT 'GLUE源代码', + `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注', + `add_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_registry` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `registry_group` varchar(50) NOT NULL, + `registry_key` varchar(255) NOT NULL, + `registry_value` varchar(255) NOT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_group` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `app_name` varchar(64) NOT NULL COMMENT '执行器AppName', + `title` varchar(12) NOT NULL COMMENT '执行器名称', + `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入', + `address_list` text COMMENT '执行器地址列表,多地址逗号分隔', + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL COMMENT '账号', + `password` varchar(50) NOT NULL COMMENT '密码', + `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员', + `permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割', + PRIMARY KEY (`id`), + UNIQUE KEY `i_username` (`username`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_lock` ( + `lock_name` varchar(50) NOT NULL COMMENT '锁名称', + PRIMARY KEY (`lock_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' ); +INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', ''); +INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL); +INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock'); + +commit; + + +-- 增加 novel 任务执行器和同步小说数据到 Elasticsearch 的任务 +-- 增加 novel 任务执行器和同步小说数据到 Elasticsearch 的任务 +INSERT INTO `xxl_job`.`xxl_job_group` ( `app_name`, `title`, `address_type`, `address_list`, `update_time` ) +VALUES + ( + 'xxl-job-executor-novel', + 'novel 任务执行器', + 0, + NULL, + now() + ); +INSERT INTO `xxl_job`.`xxl_job_info` ( + `job_group`, + `job_desc`, + `add_time`, + `update_time`, + `author`, + `alarm_email`, + `schedule_type`, + `schedule_conf`, + `misfire_strategy`, + `executor_route_strategy`, + `executor_handler`, + `executor_param`, + `executor_block_strategy`, + `executor_timeout`, + `executor_fail_retry_count`, + `glue_type`, + `glue_source`, + `glue_remark`, + `glue_updatetime`, + `child_jobid`, + `trigger_status`, + `trigger_last_time`, + `trigger_next_time` +) +VALUES + ( + (SELECT + id + FROM + xxl_job_group + WHERE + app_name = 'xxl-job-executor-novel'), + '同步小说数据到 Elasticsearch', + now(), + now(), + 'xxyopen', + '', + 'CRON', + '0 0 0 1 * ?', + 'DO_NOTHING', + 'FIRST', + 'saveToEsJobHandler', + '', + 'SERIAL_EXECUTION', + 0, + 0, + 'BEAN', + '', + 'GLUE代码初始化', + now(), + '', + 0, + 0, + 0 + ); \ No newline at end of file -- Gitee From 37811bf173aef33566045d85fc2bc36650b0c442 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 10 Jun 2022 17:33:58 +0800 Subject: [PATCH 039/112] =?UTF-8?q?chore:=20=E4=BF=AE=E6=94=B9=20ShardingS?= =?UTF-8?q?phere-JDBC=20=20=E7=9A=84=E6=95=B0=E6=8D=AE=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=90=8D=EF=BC=8C=E5=BC=80=E5=90=AF=20Shardi?= =?UTF-8?q?ngSphere-JDBC=20=E5=8A=9F=E8=83=BD=E6=89=8D=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/{20220603.sql => shardingsphere-jdbc.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/sql/{20220603.sql => shardingsphere-jdbc.sql} (100%) diff --git a/doc/sql/20220603.sql b/doc/sql/shardingsphere-jdbc.sql similarity index 100% rename from doc/sql/20220603.sql rename to doc/sql/shardingsphere-jdbc.sql -- Gitee From 8e9f31a240209668db5c692c1b323ef59f4115ef Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 10 Jun 2022 18:12:21 +0800 Subject: [PATCH 040/112] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E8=84=9A=E6=9C=AC=E6=96=87=E4=BB=B6=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/readme | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 doc/sql/readme diff --git a/doc/sql/readme b/doc/sql/readme new file mode 100644 index 0000000..e604e2b --- /dev/null +++ b/doc/sql/readme @@ -0,0 +1,5 @@ +1. 初始状态下,MYSQL 只需要执行 novel.sql 文件即可正常运行本系统 +2. 代码更新后再执行以日期命名的增量 SQL 文件 +3. 只有开启 XXL-JOB 的功能,才需要执行 xxl-job.sql 和以 xxl-job 开头日期结尾的增量 SQL 文件 +4. 只有开启 ShardingSphere-JDBC 的功能,才需要执行 shardingsphere-jdbc.sql 和以 shardingsphere-jdbc 开头日期结尾的增量 SQL 文件 + -- Gitee From ac1628aa2a34a98aed7e745eeaa4149e0b3f49fb Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sun, 19 Jun 2022 07:57:28 +0800 Subject: [PATCH 041/112] =?UTF-8?q?refactor:=20=E4=BD=BF=E7=94=A8=20`@Conf?= =?UTF-8?q?igurationProperties`=20record?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/core/config/CorsConfig.java | 2 +- .../xxyopen/novel/core/config/CorsProperties.java | 8 +------- .../xxyopen/novel/core/config/XssProperties.java | 14 +------------- .../xxyopen/novel/core/filter/XssFilter.java | 4 ++-- 4 files changed, 5 insertions(+), 23 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/config/CorsConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/CorsConfig.java index a14e497..a31692d 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/CorsConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/CorsConfig.java @@ -25,7 +25,7 @@ public class CorsConfig { public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); // 允许的域,不要写*,否则cookie就无法使用了 - for (String allowOrigin : corsProperties.getAllowOrigins()) { + for (String allowOrigin : corsProperties.allowOrigins()) { config.addAllowedOrigin(allowOrigin); } // 允许的头信息 diff --git a/src/main/java/io/github/xxyopen/novel/core/config/CorsProperties.java b/src/main/java/io/github/xxyopen/novel/core/config/CorsProperties.java index 51f5cfe..7f3f8f7 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/CorsProperties.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/CorsProperties.java @@ -1,6 +1,5 @@ package io.github.xxyopen.novel.core.config; -import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.List; @@ -12,11 +11,6 @@ import java.util.List; * @date 2022/5/17 */ @ConfigurationProperties(prefix = "novel.cors") -@Data -public class CorsProperties { +public record CorsProperties(List allowOrigins) { - /** - * 允许跨域的域名 - * */ - private List allowOrigins; } diff --git a/src/main/java/io/github/xxyopen/novel/core/config/XssProperties.java b/src/main/java/io/github/xxyopen/novel/core/config/XssProperties.java index 613e090..58a1317 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/XssProperties.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/XssProperties.java @@ -1,6 +1,5 @@ package io.github.xxyopen.novel.core.config; -import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.List; @@ -12,17 +11,6 @@ import java.util.List; * @date 2022/5/17 */ @ConfigurationProperties(prefix = "novel.xss") -@Data -public class XssProperties { - - /** - * 过滤开关 - * */ - private Boolean enabled; - - /** - * 排除链接 - * */ - private List excludes; +public record XssProperties(Boolean enabled,List excludes) { } diff --git a/src/main/java/io/github/xxyopen/novel/core/filter/XssFilter.java b/src/main/java/io/github/xxyopen/novel/core/filter/XssFilter.java index b1f3942..17a7b5b 100644 --- a/src/main/java/io/github/xxyopen/novel/core/filter/XssFilter.java +++ b/src/main/java/io/github/xxyopen/novel/core/filter/XssFilter.java @@ -48,11 +48,11 @@ public class XssFilter implements Filter { } private boolean handleExcludeUrl(HttpServletRequest request) { - if (CollectionUtils.isEmpty(xssProperties.getExcludes())) { + if (CollectionUtils.isEmpty(xssProperties.excludes())) { return false; } String url = request.getServletPath(); - for (String pattern : xssProperties.getExcludes()) { + for (String pattern : xssProperties.excludes()) { Pattern p = Pattern.compile("^" + pattern); Matcher m = p.matcher(url); if (m.find()) { -- Gitee From 9bd95d3f28a5cb622019815d21e7b0d8c77d4354 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Mon, 20 Jun 2022 13:20:00 +0800 Subject: [PATCH 042/112] =?UTF-8?q?feat:=20Spring=20AOP=20+=20Redisson=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=88=86=E5=B8=83=E5=BC=8F=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 49 ++++++----- pom.xml | 14 ++++ .../xxyopen/novel/core/annotation/Key.java | 21 +++++ .../xxyopen/novel/core/annotation/Lock.java | 31 +++++++ .../xxyopen/novel/core/aspect/LockAspect.java | 81 +++++++++++++++++++ .../novel/core/config/RedissonConfig.java | 26 ++++++ .../novel/service/impl/BookServiceImpl.java | 5 +- src/main/resources/redisson.yml | 3 + 8 files changed, 208 insertions(+), 22 deletions(-) create mode 100644 src/main/java/io/github/xxyopen/novel/core/annotation/Key.java create mode 100644 src/main/java/io/github/xxyopen/novel/core/annotation/Lock.java create mode 100644 src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java create mode 100644 src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java create mode 100644 src/main/resources/redisson.yml diff --git a/README.md b/README.md index 7bedbc3..ae93bcf 100644 --- a/README.md +++ b/README.md @@ -32,26 +32,27 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 ## 后端技术选型 -| 技术 | 版本 | 说明 | 官网 | 学习 | -|-------------------------------|:--------------:|---------------------| --------------------------------------- |:---------------------------------------------------------------------------------------:| -| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | -| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | -| MyBatis-Plus | 3.5.1 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | -| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | -| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | -| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | -| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | -| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | -| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | -| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | -| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | -| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | -| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | -| Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | -| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | -| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | -| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | -| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | +| 技术 | 版本 | 说明 | 官网 | 学习 | +|---------------------|:--------------:|---------------------| --------------------------------------- |:---------------------------------------------------------------------------------------:| +| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | +| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | +| MyBatis-Plus | 3.5.1 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | +| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | +| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | +| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | +| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | +| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | +| Redisson | 3.17.4 | 分布式锁实现 | https://github.com/redisson/redisson | [进入](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | +| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | +| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | +| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | +| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | +| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | +| Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | +| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | +| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | +| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | +| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | **注:更多热门新技术待集成。** ## 前端技术选型 @@ -203,7 +204,7 @@ git clone https://gitee.com/novel_dev_team/novel.git password: test123456 ``` - 2. 修改`src/resources/application.yml`配置文件中的`redis`连接配置 + 2. 修改`src/resources/application.yml` 和 `src/resources/redisson.yml` 配置文件中的`redis`连接配置 ``` spring: @@ -213,6 +214,12 @@ git clone https://gitee.com/novel_dev_team/novel.git password: 123456 ``` + ``` + singleServerConfig: + address: "redis://127.0.0.1:6379" + password: 123456 + ``` + 3. 项目根目录下运行如下命令来启动后端服务(有安装 IDE 的可以导入源码到 IDE 中运行) ``` diff --git a/pom.xml b/pom.xml index 04b3c58..9b69ada 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ 2.3.1 1.8.4 5.1.1 + 3.17.4 @@ -160,6 +161,19 @@ spring-boot-starter-security + + + org.redisson + redisson + ${redisson.version} + + + + + org.springframework.boot + spring-boot-starter-aop + + mysql mysql-connector-java diff --git a/src/main/java/io/github/xxyopen/novel/core/annotation/Key.java b/src/main/java/io/github/xxyopen/novel/core/annotation/Key.java new file mode 100644 index 0000000..7a1e2a8 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/annotation/Key.java @@ -0,0 +1,21 @@ +package io.github.xxyopen.novel.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * 分布式锁-Key 注解 + * + * @author xiongxiaoyang + * @date 2022/6/20 + */ +@Documented +@Retention(RUNTIME) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +public @interface Key { + String expr() default ""; +} diff --git a/src/main/java/io/github/xxyopen/novel/core/annotation/Lock.java b/src/main/java/io/github/xxyopen/novel/core/annotation/Lock.java new file mode 100644 index 0000000..a5e5be2 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/annotation/Lock.java @@ -0,0 +1,31 @@ +package io.github.xxyopen.novel.core.annotation; + +import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * 分布式锁 注解 + * + * @author xiongxiaoyang + * @date 2022/6/20 + */ +@Documented +@Retention(RUNTIME) +@Target(METHOD) +public @interface Lock { + + String prefix(); + + boolean isWait() default false; + + long waitTime() default 3L; + + ErrorCodeEnum failCode() default ErrorCodeEnum.OK; + +} diff --git a/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java b/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java new file mode 100644 index 0000000..a003edd --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java @@ -0,0 +1,81 @@ +package io.github.xxyopen.novel.core.aspect; + +import io.github.xxyopen.novel.core.annotation.Lock; +import io.github.xxyopen.novel.core.common.exception.BusinessException; +import lombok.SneakyThrows; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.common.TemplateParserContext; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +/** + * 分布式锁 切面 + * + * @author xiongxiaoyang + * @date 2022/6/20 + */ +@Aspect +@Component +public record LockAspect(RedissonClient redissonClient) { + + private static final String KEY_PREFIX = "Lock"; + + private static final String KEY_SEPARATOR = "::"; + + @Around(value = "@annotation(io.github.xxyopen.novel.core.annotation.Lock)") + @SneakyThrows + public Object doAround(ProceedingJoinPoint joinPoint) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method targetMethod = methodSignature.getMethod(); + Lock lock = targetMethod.getAnnotation(Lock.class); + String lockKey = KEY_PREFIX + buildLockKey(lock.prefix(), targetMethod, + joinPoint.getArgs()); + RLock rLock = redissonClient.getLock(lockKey); + if (lock.isWait() ? rLock.tryLock(lock.waitTime(), TimeUnit.SECONDS) : rLock.tryLock()) { + try { + return joinPoint.proceed(); + } finally { + rLock.unlock(); + } + } + throw new BusinessException(lock.failCode()); + } + + private String buildLockKey(String prefix, Method method, Object[] args) { + StringBuilder builder = new StringBuilder(); + if (Objects.nonNull(prefix) && !prefix.isEmpty()) { + builder.append(KEY_SEPARATOR).append(prefix); + } + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + builder.append(KEY_SEPARATOR); + if (parameters[i].isAnnotationPresent(io.github.xxyopen.novel.core.annotation.Key.class)) { + io.github.xxyopen.novel.core.annotation.Key key = parameters[i].getAnnotation(io.github.xxyopen.novel.core.annotation.Key.class); + builder.append(parseKeyExpr(key.expr(), args[i])); + } + } + return builder.toString(); + } + + private String parseKeyExpr(String expr, Object arg) { + if (Objects.isNull(expr) || expr.isEmpty()) { + return arg.toString(); + } + ExpressionParser parser = new SpelExpressionParser(); + Expression expression = parser.parseExpression(expr, new TemplateParserContext()); + return expression.getValue(arg, String.class); + } + +} diff --git a/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java new file mode 100644 index 0000000..68136d5 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java @@ -0,0 +1,26 @@ +package io.github.xxyopen.novel.core.config; + +import lombok.SneakyThrows; +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Redisson 配置类 + * + * @author xiongxiaoyang + * @date 2022/6/20 + */ +@Configuration +public class RedissonConfig { + + @Bean + @SneakyThrows + public RedissonClient redissonClient(){ + Config config = Config.fromYAML(getClass().getResource("/redisson.yml")); + return Redisson.create(config); + } + +} diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index 31d07e2..dc0c996 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -3,6 +3,8 @@ package io.github.xxyopen.novel.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.github.xxyopen.novel.core.annotation.Key; +import io.github.xxyopen.novel.core.annotation.Lock; import io.github.xxyopen.novel.core.auth.UserHolder; import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum; import io.github.xxyopen.novel.core.common.req.PageReqDto; @@ -200,8 +202,9 @@ public class BookServiceImpl implements BookService { return RestResp.ok(bookCategoryCacheManager.listCategory(workDirection)); } + @Lock(prefix = "userComment") @Override - public RestResp saveComment(UserCommentReqDto dto) { + public RestResp saveComment(@Key(expr = "#{userId + '::' + bookId}") UserCommentReqDto dto) { // 校验用户是否已发表评论 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, dto.getUserId()) diff --git a/src/main/resources/redisson.yml b/src/main/resources/redisson.yml new file mode 100644 index 0000000..bfe1a47 --- /dev/null +++ b/src/main/resources/redisson.yml @@ -0,0 +1,3 @@ +singleServerConfig: + address: "redis://127.0.0.1:6379" + password: 123456 -- Gitee From 57793c444449f12af5238a56056161ce32e91350 Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Tue, 21 Jun 2022 06:44:49 +0800 Subject: [PATCH 043/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae93bcf..29480c5 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,8 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | | Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | | Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | -| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | | Redisson | 3.17.4 | 分布式锁实现 | https://github.com/redisson/redisson | [进入](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | +| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | | ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | | Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | | RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | -- Gitee From d7a9416c57403c311709bac6eb3bacb98b2d5371 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 21 Jun 2022 07:33:25 +0800 Subject: [PATCH 044/112] =?UTF-8?q?perf:=20LockAspect=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/xxyopen/novel/core/aspect/LockAspect.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java b/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java index a003edd..bf10bb4 100644 --- a/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java +++ b/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.core.aspect; +import io.github.xxyopen.novel.core.annotation.Key; import io.github.xxyopen.novel.core.annotation.Lock; import io.github.xxyopen.novel.core.common.exception.BusinessException; import lombok.SneakyThrows; @@ -14,10 +15,10 @@ import org.springframework.expression.ExpressionParser; import org.springframework.expression.common.TemplateParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import java.lang.reflect.Method; import java.lang.reflect.Parameter; -import java.util.Objects; import java.util.concurrent.TimeUnit; /** @@ -55,14 +56,14 @@ public record LockAspect(RedissonClient redissonClient) { private String buildLockKey(String prefix, Method method, Object[] args) { StringBuilder builder = new StringBuilder(); - if (Objects.nonNull(prefix) && !prefix.isEmpty()) { + if (StringUtils.hasText(prefix)) { builder.append(KEY_SEPARATOR).append(prefix); } Parameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { builder.append(KEY_SEPARATOR); - if (parameters[i].isAnnotationPresent(io.github.xxyopen.novel.core.annotation.Key.class)) { - io.github.xxyopen.novel.core.annotation.Key key = parameters[i].getAnnotation(io.github.xxyopen.novel.core.annotation.Key.class); + if (parameters[i].isAnnotationPresent(Key.class)) { + Key key = parameters[i].getAnnotation(Key.class); builder.append(parseKeyExpr(key.expr(), args[i])); } } @@ -70,7 +71,7 @@ public record LockAspect(RedissonClient redissonClient) { } private String parseKeyExpr(String expr, Object arg) { - if (Objects.isNull(expr) || expr.isEmpty()) { + if (!StringUtils.hasText(expr)) { return arg.toString(); } ExpressionParser parser = new SpelExpressionParser(); -- Gitee From 154b009c050410d78a5343e06ebfa33a765cf2c0 Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Tue, 21 Jun 2022 07:48:12 +0800 Subject: [PATCH 045/112] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 29480c5..a47e49f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ [![index]( https://s1.ax1x.com/2022/05/17/O5tgbR.png )]( https://curl.qcloud.com/kgMaOjoq ) +[![JDK 17](https://img.shields.io/badge/JDK%2017-%234479A1.svg?logo=java)](https://docs.oracle.com/en/java/javase/17/) +[![Spring Boot 3](https://img.shields.io/badge/Spring%20Boot%203-%23000000.svg?logo=springboot)](https://docs.spring.io/spring-boot/docs/3.0.0-SNAPSHOT/reference/html/) +[![Vue 3](https://img.shields.io/badge/Vue%203%20-%232b3847.svg?logo=vue.js)](https://staging-cn.vuejs.org/) [![Github stars](https://img.shields.io/github/stars/201206030/novel?logo=github)](https://github.com/201206030/novel) [![Github forks](https://img.shields.io/github/forks/201206030/novel?logo=github)](https://github.com/201206030/novel) [![Gitee star](https://gitee.com/novel_dev_team/novel/badge/star.svg?theme=gitee)](https://gitee.com/novel_dev_team/novel) @@ -59,7 +62,7 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | 技术 | 版本 | 说明 | 官网 | 学习 | | :----------------- | :-----: | -------------------------- | --------------------------------------- | :-------------------------------------------------: | -| Vue.js | 3.2.13 | 渐进式 JavaScript 框架 | https://v3.cn.vuejs.org | [进入](https://v3.cn.vuejs.org/guide/introduction.html) | +| Vue.js | 3.2.13 | 渐进式 JavaScript 框架 | https://vuejs.org/ | [进入](https://staging-cn.vuejs.org/guide/introduction.html) | | Vue Router | 4.0.15 | Vue.js 的官方路由 | https://router.vuejs.org/zh/index.html | [进入](https://router.vuejs.org/zh/guide/) | | axios | 0.27.2 | 基于 promise 的网络请求库 | https://axios-http.com/zh | [进入](https://axios-http.com/zh/docs/intro) | | element-plus | 2.2.0 | 基于 Vue 3,面向设计师和开发者的组件库 | https://element-plus.org/zh-CN/ | [进入](https://element-plus.org/zh-CN/guide/design.html) | -- Gitee From 5dceb7ac96f592f7a631e9242cdbe75d6e48bbb1 Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Tue, 21 Jun 2022 07:51:29 +0800 Subject: [PATCH 046/112] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a47e49f..39fc960 100644 --- a/README.md +++ b/README.md @@ -62,10 +62,10 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | 技术 | 版本 | 说明 | 官网 | 学习 | | :----------------- | :-----: | -------------------------- | --------------------------------------- | :-------------------------------------------------: | -| Vue.js | 3.2.13 | 渐进式 JavaScript 框架 | https://vuejs.org/ | [进入](https://staging-cn.vuejs.org/guide/introduction.html) | -| Vue Router | 4.0.15 | Vue.js 的官方路由 | https://router.vuejs.org/zh/index.html | [进入](https://router.vuejs.org/zh/guide/) | -| axios | 0.27.2 | 基于 promise 的网络请求库 | https://axios-http.com/zh | [进入](https://axios-http.com/zh/docs/intro) | -| element-plus | 2.2.0 | 基于 Vue 3,面向设计师和开发者的组件库 | https://element-plus.org/zh-CN/ | [进入](https://element-plus.org/zh-CN/guide/design.html) | +| Vue.js | 3.2.13 | 渐进式 JavaScript 框架 | https://vuejs.org | [进入](https://staging-cn.vuejs.org/guide/introduction.html) | +| Vue Router | 4.0.15 | Vue.js 的官方路由 | https://router.vuejs.org | [进入](https://router.vuejs.org/zh/guide/) | +| axios | 0.27.2 | 基于 promise 的网络请求库 | https://axios-http.com | [进入](https://axios-http.com/zh/docs/intro) | +| element-plus | 2.2.0 | 基于 Vue 3,面向设计师和开发者的组件库 | https://element-plus.org | [进入](https://element-plus.org/zh-CN/guide/design.html) | ## 编码规范 -- Gitee From fdc74bb7da1bdaed5bfbc8fc4a067f1bbbf8360c Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Tue, 21 Jun 2022 08:04:16 +0800 Subject: [PATCH 047/112] Update README.md --- README.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 39fc960..406dd96 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ [![index]( https://s1.ax1x.com/2022/05/17/O5tgbR.png )]( https://curl.qcloud.com/kgMaOjoq ) -[![JDK 17](https://img.shields.io/badge/JDK%2017-%234479A1.svg?logo=java)](https://docs.oracle.com/en/java/javase/17/) -[![Spring Boot 3](https://img.shields.io/badge/Spring%20Boot%203-%23000000.svg?logo=springboot)](https://docs.spring.io/spring-boot/docs/3.0.0-SNAPSHOT/reference/html/) -[![Vue 3](https://img.shields.io/badge/Vue%203%20-%232b3847.svg?logo=vue.js)](https://staging-cn.vuejs.org/) -[![Github stars](https://img.shields.io/github/stars/201206030/novel?logo=github)](https://github.com/201206030/novel) -[![Github forks](https://img.shields.io/github/forks/201206030/novel?logo=github)](https://github.com/201206030/novel) -[![Gitee star](https://gitee.com/novel_dev_team/novel/badge/star.svg?theme=gitee)](https://gitee.com/novel_dev_team/novel) -[![Gitee fork](https://gitee.com/novel_dev_team/novel/badge/fork.svg?theme=gitee)](https://gitee.com/novel_dev_team/novel) -visitors +

+ JDK 17 + Spring Boot 3 + Vue 3 + Github stars + Github forks + Gitee stars + Gitee forks + visitors +

+ ## 项目简介 novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离的**学习型**小说项目,配备详细的项目教程手把手教你**从零开始**开发上线一个生产级别的 Java 系统,由小说门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成。包括小说推荐、作品检索、小说排行榜、小说阅读、小说评论、充值订阅、新闻发布等功能。 -- Gitee From d9202c76faebf014ea8477eac9f731c7f5950190 Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Tue, 21 Jun 2022 08:08:04 +0800 Subject: [PATCH 048/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 406dd96..df3bfa9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

JDK 17 Spring Boot 3 - Vue 3 + Vue 3
Github stars Github forks Gitee stars -- Gitee From c572650107429740710d3bfb761f0fc6fce8be93 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Thu, 23 Jun 2022 20:58:38 +0800 Subject: [PATCH 049/112] =?UTF-8?q?refactor:=20=E4=BD=BF=E7=94=A8=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E6=8E=A8=E6=96=AD=20var?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/github/xxyopen/novel/core/config/CacheConfig.java | 6 ++++-- .../xxyopen/novel/service/impl/EsSearchServiceImpl.java | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/config/CacheConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/CacheConfig.java index 8a13fbe..5493a94 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/CacheConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/CacheConfig.java @@ -37,7 +37,8 @@ public class CacheConfig { SimpleCacheManager cacheManager = new SimpleCacheManager(); List caches = new ArrayList<>(CacheConsts.CacheEnum.values().length); - for (CacheConsts.CacheEnum c : CacheConsts.CacheEnum.values()) { + // 类型推断 var 非常适合 for 循环,JDK 10 引入,JDK 11 改进 + for (var c : CacheConsts.CacheEnum.values()) { if (c.isLocal()) { Caffeine caffeine = Caffeine.newBuilder().recordStats().maximumSize(c.getMaxSize()); if (c.getTtl() > 0) { @@ -62,7 +63,8 @@ public class CacheConfig { .disableCachingNullValues().prefixCacheNameWith(CacheConsts.REDIS_CACHE_PREFIX); Map cacheMap = new LinkedHashMap<>(CacheConsts.CacheEnum.values().length); - for (CacheConsts.CacheEnum c : CacheConsts.CacheEnum.values()) { + // 类型推断 var 非常适合 for 循环,JDK 10 引入,JDK 11 改进 + for (var c : CacheConsts.CacheEnum.values()) { if (c.isRemote()) { if (c.getTtl() > 0) { cacheMap.put(c.getName(), RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues() diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java index d977947..271c94f 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java @@ -77,7 +77,8 @@ public class EsSearchServiceImpl implements SearchService { List list = new ArrayList<>(); List> hits = response.hits().hits(); - for (Hit hit : hits) { + // 类型推断 var 非常适合 for 循环,JDK 10 引入,JDK 11 改进 + for (var hit : hits) { EsBookDto book = hit.source(); assert book != null; if (!CollectionUtils.isEmpty(hit.highlight().get(EsConsts.BookIndex.FIELD_BOOK_NAME))) { -- Gitee From dec50ab0a0bc0f0992633353327a6591ff0c72b7 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Mon, 27 Jun 2022 11:17:49 +0800 Subject: [PATCH 050/112] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90=20springdoc-?= =?UTF-8?q?openapi=20=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90=20API=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 19 ++++++++++ .../xxyopen/novel/NovelApplication.java | 10 ++++- .../controller/author/AuthorController.java | 20 ++++++++-- .../controller/front/BookController.java | 37 ++++++++++++++----- .../controller/front/HomeController.java | 5 +++ .../controller/front/NewsController.java | 8 +++- .../controller/front/ResourceController.java | 8 +++- .../controller/front/SearchController.java | 7 +++- .../controller/front/UserController.java | 25 +++++++++++-- .../novel/core/common/req/PageReqDto.java | 4 ++ .../novel/core/common/resp/RestResp.java | 4 ++ .../novel/dto/req/AuthorRegisterReqDto.java | 20 ++++++---- .../xxyopen/novel/dto/req/BookAddReqDto.java | 8 ++++ .../novel/dto/req/BookSearchReqDto.java | 10 +++++ .../novel/dto/req/ChapterAddReqDto.java | 5 +++ .../novel/dto/req/UserCommentReqDto.java | 3 ++ .../novel/dto/req/UserInfoUptReqDto.java | 4 ++ .../novel/dto/req/UserLoginReqDto.java | 3 ++ .../novel/dto/req/UserRegisterReqDto.java | 5 +++ .../novel/dto/resp/BookCategoryRespDto.java | 3 ++ .../dto/resp/BookChapterAboutRespDto.java | 3 ++ .../novel/dto/resp/BookChapterRespDto.java | 8 ++++ .../novel/dto/resp/BookCommentRespDto.java | 9 +++++ .../dto/resp/BookContentAboutRespDto.java | 4 ++ .../novel/dto/resp/BookInfoRespDto.java | 17 +++++++++ .../novel/dto/resp/BookRankRespDto.java | 11 ++++++ .../novel/dto/resp/HomeBookRespDto.java | 7 ++++ .../novel/dto/resp/HomeFriendLinkRespDto.java | 3 ++ .../novel/dto/resp/ImgVerifyCodeRespDto.java | 3 ++ .../novel/dto/resp/NewsInfoRespDto.java | 8 ++++ .../novel/dto/resp/UserInfoRespDto.java | 4 ++ .../novel/dto/resp/UserLoginRespDto.java | 4 ++ .../novel/dto/resp/UserRegisterRespDto.java | 3 ++ 33 files changed, 264 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 9b69ada..73fbb17 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,7 @@ 5.1.1 3.17.4 + org.springframework.boot @@ -174,6 +175,13 @@ spring-boot-starter-aop + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.0.0-M4-SNAPSHOT + + mysql mysql-connector-java @@ -240,6 +248,17 @@ false + + sonatype-nexus-snapshots-2 + Sonatype Nexus Snapshots 2 + https://s01.oss.sonatype.org/content/repositories/snapshots/ + + true + + + false + + diff --git a/src/main/java/io/github/xxyopen/novel/NovelApplication.java b/src/main/java/io/github/xxyopen/novel/NovelApplication.java index c0e7072..cf31ddd 100644 --- a/src/main/java/io/github/xxyopen/novel/NovelApplication.java +++ b/src/main/java/io/github/xxyopen/novel/NovelApplication.java @@ -1,5 +1,12 @@ package io.github.xxyopen.novel; +import io.github.xxyopen.novel.core.constant.SystemConfigConsts; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.info.License; +import io.swagger.v3.oas.annotations.security.SecurityScheme; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.CommandLineRunner; @@ -13,10 +20,11 @@ import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AnyRequestMatcher; import java.util.Map; +@OpenAPIDefinition(info = @Info(title = "novel 项目接口文档", version = "v3.2.0", license = @License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0"))) +@SecurityScheme(type = SecuritySchemeType.APIKEY, in = SecuritySchemeIn.HEADER, name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME, description = "登录 token") @SpringBootApplication @MapperScan("io.github.xxyopen.novel.dao.mapper") @EnableCaching diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index 935da7c..f681a30 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -5,6 +5,7 @@ import io.github.xxyopen.novel.core.common.req.PageReqDto; import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.ApiRouterConsts; +import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.dto.req.AuthorRegisterReqDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; @@ -12,8 +13,13 @@ import io.github.xxyopen.novel.dto.resp.BookChapterRespDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.service.AuthorService; import io.github.xxyopen.novel.service.BookService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springdoc.core.annotations.ParameterObject; import org.springframework.web.bind.annotation.*; /** @@ -22,6 +28,8 @@ import org.springframework.web.bind.annotation.*; * @author xiongxiaoyang * @date 2022/5/23 */ +@Tag(name = "author", description = "作家后台-作者模块") +@SecurityRequirement(name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME) @RestController @RequestMapping(ApiRouterConsts.API_AUTHOR_URL_PREFIX) @RequiredArgsConstructor @@ -34,6 +42,7 @@ public class AuthorController { /** * 作家注册接口 */ + @Operation(description = "作家注册接口") @PostMapping("register") public RestResp register(@Valid @RequestBody AuthorRegisterReqDto dto) { dto.setUserId(UserHolder.getUserId()); @@ -43,6 +52,7 @@ public class AuthorController { /** * 查询作家状态接口 */ + @Operation(description = "作家状态查询接口") @GetMapping("status") public RestResp getStatus() { return authorService.getStatus(UserHolder.getUserId()); @@ -51,6 +61,7 @@ public class AuthorController { /** * 小说发布接口 */ + @Operation(description = "小说发布接口") @PostMapping("book") public RestResp publishBook(@Valid @RequestBody BookAddReqDto dto) { return bookService.saveBook(dto); @@ -59,16 +70,18 @@ public class AuthorController { /** * 小说发布列表查询接口 */ + @Operation(description = "小说发布列表查询接口") @GetMapping("books") - public RestResp> listBooks(PageReqDto dto) { + public RestResp> listBooks(@ParameterObject PageReqDto dto) { return bookService.listAuthorBooks(dto); } /** * 小说章节发布接口 */ + @Operation(description = "小说章节发布接口") @PostMapping("book/chapter/{bookId}") - public RestResp publishBookChapter(@PathVariable("bookId") Long bookId, @Valid @RequestBody ChapterAddReqDto dto) { + public RestResp publishBookChapter(@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId, @Valid @RequestBody ChapterAddReqDto dto) { dto.setBookId(bookId); return bookService.saveBookChapter(dto); } @@ -76,8 +89,9 @@ public class AuthorController { /** * 小说章节发布列表查询接口 */ + @Operation(description = "小说章节发布列表查询接口") @GetMapping("book/chapters/{bookId}") - public RestResp> listBookChapters(@PathVariable("bookId") Long bookId, PageReqDto dto) { + public RestResp> listBookChapters(@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId, PageReqDto dto) { return bookService.listBookChapters(bookId, dto); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java b/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java index b39322d..06bbd46 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java @@ -4,6 +4,9 @@ import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.dto.resp.*; import io.github.xxyopen.novel.service.BookService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -16,6 +19,7 @@ import java.util.List; * @author xiongxiaoyang * @date 2022/5/14 */ +@Tag(name = "book", description = "前台门户-小说模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_BOOK_URL_PREFIX) @RequiredArgsConstructor @@ -26,78 +30,88 @@ public class BookController { /** * 小说分类列表查询接口 */ + @Operation(description = "小说分类列表查询接口") @GetMapping("category/list") - public RestResp> listCategory(Integer workDirection) { + public RestResp> listCategory(@Parameter(description = "作品方向",required = true) Integer workDirection) { return bookService.listCategory(workDirection); } /** * 小说信息查询接口 */ + @Operation(description = "小说信息查询接口") @GetMapping("{id}") - public RestResp getBookById(@PathVariable("id") Long bookId) { + public RestResp getBookById(@Parameter(description = "小说 ID") @PathVariable("id") Long bookId) { return bookService.getBookById(bookId); } /** * 增加小说点击量接口 */ + @Operation(description = "增加小说点击量接口") @PostMapping("visit") - public RestResp addVisitCount(Long bookId) { + public RestResp addVisitCount(@Parameter(description = "小说ID") Long bookId) { return bookService.addVisitCount(bookId); } /** * 小说最新章节相关信息查询接口 */ + @Operation(description = "小说最新章节相关信息查询接口") @GetMapping("last_chapter/about") - public RestResp getLastChapterAbout(Long bookId) { + public RestResp getLastChapterAbout(@Parameter(description = "小说ID") Long bookId) { return bookService.getLastChapterAbout(bookId); } /** * 小说推荐列表查询接口 */ + @Operation(description = "小说推荐列表查询接口") @GetMapping("rec_list") - public RestResp> listRecBooks(Long bookId) throws NoSuchAlgorithmException { + public RestResp> listRecBooks(@Parameter(description = "小说ID") Long bookId) throws NoSuchAlgorithmException { return bookService.listRecBooks(bookId); } /** * 小说章节列表查询接口 */ + @Operation(description = "小说章节列表查询接口") @GetMapping("chapter/list") - public RestResp> listChapters(Long bookId) { + public RestResp> listChapters(@Parameter(description = "小说ID") Long bookId) { return bookService.listChapters(bookId); } /** * 小说内容相关信息查询接口 */ + @Operation(description = "小说内容相关信息查询接口") @GetMapping("content/{chapterId}") - public RestResp getBookContentAbout(@PathVariable("chapterId") Long chapterId) { + public RestResp getBookContentAbout(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getBookContentAbout(chapterId); } /** * 获取上一章节ID接口 */ + @Operation(description = "获取上一章节ID接口") @GetMapping("pre_chapter_id/{chapterId}") - public RestResp getPreChapterId(@PathVariable("chapterId") Long chapterId) { + public RestResp getPreChapterId(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getPreChapterId(chapterId); } /** * 获取下一章节ID接口 */ + @Operation(description = "获取下一章节ID接口") @GetMapping("next_chapter_id/{chapterId}") - public RestResp getNextChapterId(@PathVariable("chapterId") Long chapterId) { + public RestResp getNextChapterId(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getNextChapterId(chapterId); } /** * 小说点击榜查询接口 */ + @Operation(description = "小说点击榜查询接口") @GetMapping("visit_rank") public RestResp> listVisitRankBooks() { return bookService.listVisitRankBooks(); @@ -106,6 +120,7 @@ public class BookController { /** * 小说新书榜查询接口 */ + @Operation(description = "小说新书榜查询接口") @GetMapping("newest_rank") public RestResp> listNewestRankBooks() { return bookService.listNewestRankBooks(); @@ -114,6 +129,7 @@ public class BookController { /** * 小说更新榜查询接口 */ + @Operation(description = "小说更新榜查询接口") @GetMapping("update_rank") public RestResp> listUpdateRankBooks() { return bookService.listUpdateRankBooks(); @@ -122,8 +138,9 @@ public class BookController { /** * 小说最新评论查询接口 */ + @Operation(description = "小说最新评论查询接口") @GetMapping("comment/newest_list") - public RestResp listNewestComments(Long bookId) { + public RestResp listNewestComments(@Parameter(description = "小说ID") Long bookId) { return bookService.listNewestComments(bookId); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/HomeController.java b/src/main/java/io/github/xxyopen/novel/controller/front/HomeController.java index 9dddca2..94f14f3 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/HomeController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/HomeController.java @@ -5,6 +5,8 @@ import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.dto.resp.HomeBookRespDto; import io.github.xxyopen.novel.dto.resp.HomeFriendLinkRespDto; import io.github.xxyopen.novel.service.HomeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,6 +20,7 @@ import java.util.List; * @author xiongxiaoyang * @date 2022/5/12 */ +@Tag(name = "home", description = "前台门户-首页模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_HOME_URL_PREFIX) @RequiredArgsConstructor @@ -28,6 +31,7 @@ public class HomeController { /** * 首页小说推荐查询接口 */ + @Operation(description = "首页小说推荐查询接口") @GetMapping("books") public RestResp> listHomeBooks() { return homeService.listHomeBooks(); @@ -36,6 +40,7 @@ public class HomeController { /** * 首页友情链接列表查询接口 */ + @Operation(description = "首页友情链接列表查询接口") @GetMapping("friend_Link/list") public RestResp> listHomeFriendLinks() { return homeService.listHomeFriendLinks(); diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java b/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java index db7bac3..eb4eaf0 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java @@ -4,6 +4,9 @@ import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.dto.resp.NewsInfoRespDto; import io.github.xxyopen.novel.service.NewsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -18,6 +21,7 @@ import java.util.List; * @author xiongxiaoyang * @date 2022/5/12 */ +@Tag(name = "news", description = "前台门户-新闻模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_NEWS_URL_PREFIX) @RequiredArgsConstructor @@ -28,6 +32,7 @@ public class NewsController { /** * 最新新闻列表查询接口 */ + @Operation(description = "最新新闻列表查询接口") @GetMapping("latest_list") public RestResp> listLatestNews() { return newsService.listLatestNews(); @@ -36,8 +41,9 @@ public class NewsController { /** * 新闻信息查询接口 */ + @Operation(description = "新闻信息查询接口") @GetMapping("{id}") - public RestResp getNews(@PathVariable Long id) { + public RestResp getNews(@Parameter(description = "新闻ID") @PathVariable Long id) { return newsService.getNews(id); } } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java b/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java index edec679..b58654d 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java @@ -4,6 +4,9 @@ import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.dto.resp.ImgVerifyCodeRespDto; import io.github.xxyopen.novel.service.ResourceService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -16,6 +19,7 @@ import java.io.IOException; * @author xiongxiaoyang * @date 2022/5/17 */ +@Tag(name = "resource", description = "前台门户-资源模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_RESOURCE_URL_PREFIX) @RequiredArgsConstructor @@ -26,6 +30,7 @@ public class ResourceController { /** * 获取图片验证码接口 */ + @Operation(description = "获取图片验证码接口") @GetMapping("img_verify_code") public RestResp getImgVerifyCode() throws IOException { return resourceService.getImgVerifyCode(); @@ -34,8 +39,9 @@ public class ResourceController { /** * 图片上传接口 * */ + @Operation(description = "图片上传接口") @PostMapping("/image") - RestResp uploadImage(@RequestParam("file") MultipartFile file) { + RestResp uploadImage(@Parameter(description = "上传文件") @RequestParam("file") MultipartFile file) { return resourceService.uploadImage(file); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java b/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java index 3d5ad4e..e8a17a7 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java @@ -6,7 +6,10 @@ import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.dto.req.BookSearchReqDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.service.SearchService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import org.springdoc.core.annotations.ParameterObject; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -17,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController; * @author xiongxiaoyang * @date 2022/5/27 */ +@Tag(name = "search", description = "前台门户-搜索模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_SEARCH_URL_PREFIX) @RequiredArgsConstructor @@ -27,8 +31,9 @@ public class SearchController { /** * 小说搜索接口 */ + @Operation(description = "小说搜索接口") @GetMapping("books") - public RestResp> searchBooks(BookSearchReqDto condition) { + public RestResp> searchBooks(@ParameterObject BookSearchReqDto condition) { return searchService.searchBooks(condition); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java b/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java index 39f597a..f5936ab 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java @@ -3,6 +3,7 @@ package io.github.xxyopen.novel.controller.front; import io.github.xxyopen.novel.core.auth.UserHolder; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.ApiRouterConsts; +import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.dto.req.UserCommentReqDto; import io.github.xxyopen.novel.dto.req.UserInfoUptReqDto; import io.github.xxyopen.novel.dto.req.UserLoginReqDto; @@ -12,6 +13,10 @@ import io.github.xxyopen.novel.dto.resp.UserLoginRespDto; import io.github.xxyopen.novel.dto.resp.UserRegisterRespDto; import io.github.xxyopen.novel.service.BookService; import io.github.xxyopen.novel.service.UserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -22,6 +27,8 @@ import org.springframework.web.bind.annotation.*; * @author xiongxiaoyang * @date 2022/5/17 */ +@Tag(name = "user", description = "前台门户-会员模块") +@SecurityRequirement(name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME) @RestController @RequestMapping(ApiRouterConsts.API_FRONT_USER_URL_PREFIX) @RequiredArgsConstructor @@ -34,6 +41,7 @@ public class UserController { /** * 用户注册接口 */ + @Operation(description = "用户注册接口") @PostMapping("register") public RestResp register(@Valid @RequestBody UserRegisterReqDto dto) { return userService.register(dto); @@ -42,6 +50,7 @@ public class UserController { /** * 用户登录接口 */ + @Operation(description = "用户登录接口") @PostMapping("login") public RestResp login(@Valid @RequestBody UserLoginReqDto dto) { return userService.login(dto); @@ -50,6 +59,7 @@ public class UserController { /** * 用户信息查询接口 */ + @Operation(description = "用户信息查询接口") @GetMapping public RestResp getUserInfo() { return userService.getUserInfo(UserHolder.getUserId()); @@ -58,6 +68,7 @@ public class UserController { /** * 用户信息修改接口 */ + @Operation(description = "用户信息修改接口") @PutMapping public RestResp updateUserInfo(@Valid @RequestBody UserInfoUptReqDto dto) { dto.setUserId(UserHolder.getUserId()); @@ -67,6 +78,7 @@ public class UserController { /** * 用户反馈提交接口 */ + @Operation(description = "用户反馈提交接口") @PostMapping("feedback") public RestResp submitFeedback(@RequestBody String content) { return userService.saveFeedback(UserHolder.getUserId(), content); @@ -75,14 +87,16 @@ public class UserController { /** * 用户反馈删除接口 */ + @Operation(description = "用户反馈删除接口") @DeleteMapping("feedback/{id}") - public RestResp deleteFeedback(@PathVariable Long id) { + public RestResp deleteFeedback(@Parameter(description = "反馈ID") @PathVariable Long id) { return userService.deleteFeedback(UserHolder.getUserId(), id); } /** * 发表评论接口 */ + @Operation(description = "发表评论接口") @PostMapping("comment") public RestResp comment(@Valid @RequestBody UserCommentReqDto dto) { dto.setUserId(UserHolder.getUserId()); @@ -92,16 +106,18 @@ public class UserController { /** * 修改评论接口 */ + @Operation(description = "修改评论接口") @PutMapping("comment/{id}") - public RestResp updateComment(@PathVariable Long id, String content) { + public RestResp updateComment(@Parameter(description = "评论ID") @PathVariable Long id, String content) { return bookService.updateComment(UserHolder.getUserId(), id, content); } /** * 删除评论接口 */ + @Operation(description = "删除评论接口") @DeleteMapping("comment/{id}") - public RestResp deleteComment(@PathVariable Long id) { + public RestResp deleteComment(@Parameter(description = "评论ID") @PathVariable Long id) { return bookService.deleteComment(UserHolder.getUserId(), id); } @@ -110,8 +126,9 @@ public class UserController { * 0-不在书架 * 1-已在书架 */ + @Operation(description = "查询书架状态接口") @GetMapping("bookshelf_status") - public RestResp getBookshelfStatus(@RequestBody String bookId) { + public RestResp getBookshelfStatus(@Parameter(description = "小说ID") String bookId) { return userService.getBookshelfStatus(UserHolder.getUserId(), bookId); } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/req/PageReqDto.java b/src/main/java/io/github/xxyopen/novel/core/common/req/PageReqDto.java index 3d67116..b881301 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/req/PageReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/req/PageReqDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.core.common.req; +import io.swagger.v3.oas.annotations.Parameter; import lombok.Data; /** @@ -14,17 +15,20 @@ public class PageReqDto { /** * 请求页码,默认第 1 页 * */ + @Parameter(description = "请求页码,默认第 1 页") private int pageNum = 1; /** * 每页大小,默认每页 10 条 * */ + @Parameter(description = "每页大小,默认每页 10 条") private int pageSize = 10; /** * 是否查询所有,默认不查所有 * 为 true 时,pageNum 和 pageSize 无效 * */ + @Parameter(hidden = true) private boolean fetchAll = false; } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/resp/RestResp.java b/src/main/java/io/github/xxyopen/novel/core/common/resp/RestResp.java index f07af5e..3a6ee8e 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/resp/RestResp.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/resp/RestResp.java @@ -1,6 +1,7 @@ package io.github.xxyopen.novel.core.common.resp; import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import java.util.Objects; @@ -17,16 +18,19 @@ public class RestResp { /** * 响应码 */ + @Schema(description = "错误码,00000-没有错误") private String code; /** * 响应消息 */ + @Schema(description = "响应消息") private String message; /** * 响应数据 */ + @Schema(description = "响应数据") private T data; private RestResp() { diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/AuthorRegisterReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/AuthorRegisterReqDto.java index 2517b11..8fbea2b 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/AuthorRegisterReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/AuthorRegisterReqDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.req; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.*; import lombok.Data; @@ -17,33 +18,38 @@ public class AuthorRegisterReqDto { /** * 笔名 */ - @NotBlank(message="笔名不能为空!") + @Schema(description = "笔名", required = true) + @NotBlank(message = "笔名不能为空!") private String penName; /** * 手机号码 */ - @NotBlank(message="手机号不能为空!") - @Pattern(regexp="^1[3|4|5|6|7|8|9][0-9]{9}$",message="手机号格式不正确!") + @Schema(description = "手机号码", required = true) + @NotBlank(message = "手机号不能为空!") + @Pattern(regexp = "^1[3|4|5|6|7|8|9][0-9]{9}$", message = "手机号格式不正确!") private String telPhone; /** * QQ或微信账号 */ - @NotBlank(message="QQ或微信账号不能为空!") + @Schema(description = "QQ或微信账号", required = true) + @NotBlank(message = "QQ或微信账号不能为空!") private String chatAccount; /** * 电子邮箱 */ - @NotBlank(message="电子邮箱不能为空!") - @Email(message="邮箱格式不正确!") + @Schema(description = "电子邮箱", required = true) + @NotBlank(message = "电子邮箱不能为空!") + @Email(message = "邮箱格式不正确!") private String email; /** * 作品方向;0-男频 1-女频 */ - @NotNull(message="作品方向不能为空!") + @Schema(description = "作品方向;0-男频 1-女频", required = true) + @NotNull(message = "作品方向不能为空!") @Min(0) @Max(1) private Integer workDirection; diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/BookAddReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/BookAddReqDto.java index f4ae0fa..f89f9ec 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/BookAddReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/BookAddReqDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.req; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -16,42 +17,49 @@ public class BookAddReqDto { /** * 作品方向;0-男频 1-女频 */ + @Schema(description = "作品方向;0-男频 1-女频", required = true) @NotNull private Integer workDirection; /** * 类别ID */ + @Schema(description = "类别ID", required = true) @NotNull private Long categoryId; /** * 类别名 */ + @Schema(description = "类别名", required = true) @NotBlank private String categoryName; /** * 小说封面地址 */ + @Schema(description = "小说封面地址", required = true) @NotBlank private String picUrl; /** * 小说名 */ + @Schema(description = "小说名", required = true) @NotBlank private String bookName; /** * 书籍描述 */ + @Schema(description = "书籍描述", required = true) @NotBlank private String bookDesc; /** * 是否收费;1-收费 0-免费 */ + @Schema(description = "是否收费;1-收费 0-免费", required = true) @NotNull private Integer isVip; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/BookSearchReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/BookSearchReqDto.java index 0c34248..015427c 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/BookSearchReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/BookSearchReqDto.java @@ -2,6 +2,7 @@ package io.github.xxyopen.novel.dto.req; import com.fasterxml.jackson.annotation.JsonFormat; import io.github.xxyopen.novel.core.common.req.PageReqDto; +import io.swagger.v3.oas.annotations.Parameter; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; @@ -19,36 +20,43 @@ public class BookSearchReqDto extends PageReqDto { /** * 搜索关键字 */ + @Parameter(description = "搜索关键字") private String keyword; /** * 作品方向 */ + @Parameter(description = "作品方向") private Integer workDirection; /** * 分类ID */ + @Parameter(description = "分类ID") private Integer categoryId; /** * 是否收费,1:收费,0:免费 */ + @Parameter(description = "是否收费,1:收费,0:免费") private Integer isVip; /** * 小说更新状态,0:连载中,1:已完结 */ + @Parameter(description = "小说更新状态,0:连载中,1:已完结") private Integer bookStatus; /** * 字数最小值 */ + @Parameter(description = "字数最小值") private Integer wordCountMin; /** * 字数最大值 */ + @Parameter(description = "字数最大值") private Integer wordCountMax; /** @@ -57,6 +65,7 @@ public class BookSearchReqDto extends PageReqDto { * 如果使用Post请求,@RequestBody接收请求体参数,默认解析日期格式为yyyy-MM-dd HH:mm:ss , * 如果需要接收其他格式的参数,则可以使用@JsonFormat注解 * */ + @Parameter(description = "最小更新时间") @DateTimeFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd") private Date updateTimeMin; @@ -64,5 +73,6 @@ public class BookSearchReqDto extends PageReqDto { /** * 排序字段 */ + @Parameter(description = "排序字段") private String sort; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/ChapterAddReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/ChapterAddReqDto.java index 6505ace..cc07f5c 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/ChapterAddReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/ChapterAddReqDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.req; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -17,17 +18,20 @@ public class ChapterAddReqDto { /** * 小说ID */ + @Schema(description = "小说ID", required = true) private Long bookId; /** * 章节名 */ @NotBlank + @Schema(description = "章节名", required = true) private String chapterName; /** * 章节内容 */ + @Schema(description = "章节内容", required = true) @NotBlank @Length(min = 50) private String chapterContent; @@ -35,6 +39,7 @@ public class ChapterAddReqDto { /** * 是否收费;1-收费 0-免费 */ + @Schema(description = "是否收费;1-收费 0-免费", required = true) @NotNull private Integer isVip; diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/UserCommentReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/UserCommentReqDto.java index bf9ef3b..1ebdd2e 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/UserCommentReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/UserCommentReqDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.req; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -15,9 +16,11 @@ public class UserCommentReqDto { private Long userId; + @Schema(description = "小说ID", required = true) @NotNull(message="小说ID不能为空!") private Long bookId; + @Schema(description = "评论内容", required = true) @NotBlank(message="评论不能为空!") @Length(min = 10,max = 512) private String commentContent; diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/UserInfoUptReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/UserInfoUptReqDto.java index 2366a71..ac0020c 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/UserInfoUptReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/UserInfoUptReqDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.req; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.Pattern; @@ -16,12 +17,15 @@ public class UserInfoUptReqDto { private Long userId; + @Schema(description = "昵称") @Length(min = 2,max = 10) private String nickName; + @Schema(description = "头像地址") @Pattern(regexp="^/[^\s]{10,}\\.(png|PNG|jpg|JPG|jpeg|JPEG|gif|GIF|bpm|BPM)$") private String userPhoto; + @Schema(description = "性别") @Min(value = 0) @Max(value = 1) private Integer userSex; diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/UserLoginReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/UserLoginReqDto.java index 1c88be3..ab92e1d 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/UserLoginReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/UserLoginReqDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.req; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import lombok.Data; @@ -13,10 +14,12 @@ import lombok.Data; @Data public class UserLoginReqDto { + @Schema(description = "手机号", required = true) @NotBlank(message="手机号不能为空!") @Pattern(regexp="^1[3|4|5|6|7|8|9][0-9]{9}$",message="手机号格式不正确!") private String username; + @Schema(description = "密码", required = true) @NotBlank(message="密码不能为空!") private String password; diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/UserRegisterReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/UserRegisterReqDto.java index d2793ba..0fa7e15 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/UserRegisterReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/UserRegisterReqDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.req; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import lombok.Data; @@ -14,13 +15,16 @@ import org.hibernate.validator.constraints.Length; @Data public class UserRegisterReqDto { + @Schema(description = "手机号", required = true) @NotBlank(message="手机号不能为空!") @Pattern(regexp="^1[3|4|5|6|7|8|9][0-9]{9}$",message="手机号格式不正确!") private String username; + @Schema(description = "密码", required = true) @NotBlank(message="密码不能为空!") private String password; + @Schema(description = "验证码", required = true) @NotBlank(message="验证码不能为空!") @Pattern(regexp="^\\d{4}$",message="验证码格式不正确!") private String velCode; @@ -28,6 +32,7 @@ public class UserRegisterReqDto { /** * 请求会话标识,用来标识图形验证码属于哪个会话 * */ + @Schema(description = "sessionId", required = true) @NotBlank @Length(min = 32,max = 32) private String sessionId; diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookCategoryRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookCategoryRespDto.java index 410a4b9..e9e9a49 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookCategoryRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookCategoryRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -16,11 +17,13 @@ public class BookCategoryRespDto { /** * 类别ID */ + @Schema(description = "类别ID") private Long id; /** * 类别名 */ + @Schema(description = "类别名") private String name; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterAboutRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterAboutRespDto.java index 50b87c8..bef9170 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterAboutRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterAboutRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -18,11 +19,13 @@ public class BookChapterAboutRespDto { /** * 章节总数 */ + @Schema(description = "章节总数") private Long chapterTotal; /** * 内容概要(30字) */ + @Schema(description = " 内容概要(30字)") private String contentSummary; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java index b648831..665a129 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java @@ -1,6 +1,7 @@ package io.github.xxyopen.novel.dto.resp; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -24,37 +25,44 @@ public class BookChapterRespDto implements Serializable { /** * 章节ID * */ + @Schema(description = "章节ID") private Long id; /** * 小说ID */ + @Schema(description = "小说ID") private Long bookId; /** * 章节号 */ + @Schema(description = "章节号") private Integer chapterNum; /** * 章节名 */ + @Schema(description = "章节名") private String chapterName; /** * 章节字数 */ + @Schema(description = "章节字数") private Integer chapterWordCount; /** * 章节更新时间 */ + @Schema(description = "章节更新时间") @JsonFormat(pattern = "yyyy/MM/dd HH:dd") private LocalDateTime chapterUpdateTime; /** * 是否收费;1-收费 0-免费 */ + @Schema(description = "是否收费;1-收费 0-免费") private Integer isVip; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookCommentRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookCommentRespDto.java index a632fdc..f32ce3f 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookCommentRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookCommentRespDto.java @@ -3,6 +3,7 @@ package io.github.xxyopen.novel.dto.resp; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.github.xxyopen.novel.core.json.serializer.UsernameSerializer; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -18,25 +19,33 @@ import java.util.List; @Builder public class BookCommentRespDto { + @Schema(description = "评论总数") private Long commentTotal; + @Schema(description = "评论列表") private List comments; @Data @Builder public static class CommentInfo { + @Schema(description = "评论ID") private Long id; + @Schema(description = "评论内容") private String commentContent; + @Schema(description = "评论用户") @JsonSerialize(using = UsernameSerializer.class) private String commentUser; + @Schema(description = "评论用户ID") private Long commentUserId; + @Schema(description = "评论用户头像") private String commentUserPhoto; + @Schema(description = "评论时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime commentTime; diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookContentAboutRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookContentAboutRespDto.java index bb8c01c..96477f3 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookContentAboutRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookContentAboutRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -16,16 +17,19 @@ public class BookContentAboutRespDto { /** * 小说信息 */ + @Schema(description = "小说信息") private BookInfoRespDto bookInfo; /** * 章节信息 */ + @Schema(description = "章节信息") private BookChapterRespDto chapterInfo; /** * 章节内容 */ + @Schema(description = "章节内容") private String bookContent; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookInfoRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookInfoRespDto.java index 011939f..6483bb1 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookInfoRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookInfoRespDto.java @@ -1,6 +1,7 @@ package io.github.xxyopen.novel.dto.resp; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.time.LocalDateTime; @@ -20,81 +21,97 @@ public class BookInfoRespDto { /** * ID */ + @Schema(description = "小说ID") private Long id; /** * 类别ID */ + @Schema(description = "类别ID") private Long categoryId; /** * 类别名 */ + @Schema(description = "类别名") private String categoryName; /** * 小说封面地址 */ + @Schema(description = "小说封面地址") private String picUrl; /** * 小说名 */ + @Schema(description = "小说名") private String bookName; /** * 作家id */ + @Schema(description = "作家id") private Long authorId; /** * 作家名 */ + @Schema(description = "作家名") private String authorName; /** * 书籍描述 */ + @Schema(description = "书籍描述") private String bookDesc; /** * 书籍状态;0-连载中 1-已完结 */ + @Schema(description = "书籍状态;0-连载中 1-已完结") private Integer bookStatus; /** * 点击量 */ + @Schema(description = "点击量") private Long visitCount; /** * 总字数 */ + @Schema(description = "总字数") private Integer wordCount; /** * 评论数 */ + @Schema(description = "评论数") private Integer commentCount; /** * 首章节ID */ + @Schema(description = "首章节ID") private Long firstChapterId; /** * 最新章节ID */ + @Schema(description = "最新章节ID") private Long lastChapterId; /** * 最新章节名 */ + @Schema(description = "最新章节名") private String lastChapterName; /** * 最新章节更新时间 */ + @Schema(description = "最新章节更新时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm") private LocalDateTime updateTime; diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookRankRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookRankRespDto.java index 27c5f3d..475b903 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookRankRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookRankRespDto.java @@ -1,6 +1,7 @@ package io.github.xxyopen.novel.dto.resp; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serial; @@ -22,51 +23,61 @@ public class BookRankRespDto implements Serializable { /** * ID */ + @Schema(description = "小说ID") private Long id; /** * 类别ID */ + @Schema(description = "类别ID") private Long categoryId; /** * 类别名 */ + @Schema(description = "类别名") private String categoryName; /** * 小说封面地址 */ + @Schema(description = "小说封面地址") private String picUrl; /** * 小说名 */ + @Schema(description = "小说名") private String bookName; /** * 作家名 */ + @Schema(description = "作家名") private String authorName; /** * 书籍描述 */ + @Schema(description = "书籍描述") private String bookDesc; /** * 总字数 */ + @Schema(description = "总字数") private Integer wordCount; /** * 最新章节名 */ + @Schema(description = "最新章节名") private String lastChapterName; /** * 最新章节更新时间 */ + @Schema(description = "最新章节更新时间") @JsonFormat(pattern = "MM/dd HH:mm") private LocalDateTime lastChapterUpdateTime; diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/HomeBookRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/HomeBookRespDto.java index 8a98e0b..1808e0d 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/HomeBookRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/HomeBookRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** @@ -14,31 +15,37 @@ public class HomeBookRespDto { /** * 类型;0-轮播图 1-顶部栏 2-本周强推 3-热门推荐 4-精品推荐 */ + @Schema(description = "类型;0-轮播图 1-顶部栏 2-本周强推 3-热门推荐 4-精品推荐") private Integer type; /** * 推荐小说ID */ + @Schema(description = "小说ID") private Long bookId; /** * 小说封面地址 */ + @Schema(description = "小说封面地址") private String picUrl; /** * 小说名 */ + @Schema(description = "小说名") private String bookName; /** * 作家名 */ + @Schema(description = "作家名") private String authorName; /** * 书籍描述 */ + @Schema(description = "书籍描述") private String bookDesc; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/HomeFriendLinkRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/HomeFriendLinkRespDto.java index 8478b71..7143ddf 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/HomeFriendLinkRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/HomeFriendLinkRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serial; @@ -20,10 +21,12 @@ public class HomeFriendLinkRespDto implements Serializable { /** * 链接名 */ + @Schema(description = "链接名") private String linkName; /** * 链接url */ + @Schema(description = "链接url") private String linkUrl; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/ImgVerifyCodeRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/ImgVerifyCodeRespDto.java index 635bd2a..0c477b6 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/ImgVerifyCodeRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/ImgVerifyCodeRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -15,11 +16,13 @@ public class ImgVerifyCodeRespDto { /** * 当前会话ID,用于标识改图形验证码属于哪个会话 * */ + @Schema(description = "sessionId") private String sessionId; /** * Base64 编码的验证码图片 * */ + @Schema(description = "Base64 编码的验证码图片") private String img; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/NewsInfoRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/NewsInfoRespDto.java index 91d2e54..635b30c 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/NewsInfoRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/NewsInfoRespDto.java @@ -1,6 +1,7 @@ package io.github.xxyopen.novel.dto.resp; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -19,37 +20,44 @@ public class NewsInfoRespDto { /** * ID */ + @Schema(description = "新闻ID") private Long id; /** * 类别ID */ + @Schema(description = "类别ID") private Long categoryId; /** * 类别名 */ + @Schema(description = "类别名") private String categoryName; /** * 新闻来源 */ + @Schema(description = "新闻来源") private String sourceName; /** * 新闻标题 */ + @Schema(description = "新闻标题") private String title; /** * 更新时间 */ + @Schema(description = "更新时间") @JsonFormat(pattern = "yyyy-MM-dd") private LocalDateTime updateTime; /** * 新闻内容 * */ + @Schema(description = "新闻内容") private String content; diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/UserInfoRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/UserInfoRespDto.java index c6f5213..753a65a 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/UserInfoRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/UserInfoRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -16,15 +17,18 @@ public class UserInfoRespDto { /** * 昵称 * */ + @Schema(description = "昵称") private String nickName; /** * 用户头像 * */ + @Schema(description = "用户头像") private String userPhoto; /** * 用户性别 * */ + @Schema(description = "用户性别") private Integer userSex; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/UserLoginRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/UserLoginRespDto.java index ad05e24..c0d6066 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/UserLoginRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/UserLoginRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -12,9 +13,12 @@ import lombok.Data; @Builder public class UserLoginRespDto { + @Schema(description = "用户ID") private Long uid; + @Schema(description = "用户昵称") private String nickName; + @Schema(description = "用户token") private String token; } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/UserRegisterRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/UserRegisterRespDto.java index e6cb65c..8edf125 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/UserRegisterRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/UserRegisterRespDto.java @@ -1,5 +1,6 @@ package io.github.xxyopen.novel.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -12,7 +13,9 @@ import lombok.Data; @Builder public class UserRegisterRespDto { + @Schema(description = "用户ID") private Long uid; + @Schema(description = "用户token") private String token; } -- Gitee From 80480bc0265331765faa107e459bfe0ef13f72a1 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Mon, 27 Jun 2022 12:41:13 +0800 Subject: [PATCH 051/112] Update README.md --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index df3bfa9..1082408 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | | XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | | Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | +| Springdoc-openapi | 2.0.0-M4-SNAPSHOT | API 文档自动生成 | https://github.com/springdoc/springdoc-openapi | [进入](https://springdoc.org/) | | Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | | Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | | Docker | - | 应用容器引擎 | https://www.docker.com/ | - | @@ -177,6 +178,10 @@ io ![img](https://oscimg.oschina.net/oscnet/up-f849960f4c1303fea77d26e64fc505a7180.png) +11. 接口文档 + +![img](https://youdoc.github.io/img/novel/SwaggerUI.png) + ## 安装步骤 @@ -226,13 +231,15 @@ git clone https://gitee.com/novel_dev_team/novel.git password: 123456 ``` - 3. 项目根目录下运行如下命令来启动后端服务(有安装 IDE 的可以导入源码到 IDE 中运行) + 3. 根据前后端的实际部署情况,修改`application.yml`中的跨域配置(默认情况可忽略此步骤) + + 4. 项目根目录下运行如下命令来启动后端服务(有安装 IDE 的可以导入源码到 IDE 中运行) ``` mvn spring-boot:run ``` - - 4. 根据前后端的实际部署情况,修改`application.yml`中的跨域配置(默认情况可忽略此步骤) + 5. 接口文档访问地址:http://server:port/swagger-ui/index.html + - 下载前端前台门户系统源码 -- Gitee From e795d26aa52615db77b97d490502d3e23e5a8851 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Mon, 27 Jun 2022 18:33:44 +0800 Subject: [PATCH 052/112] =?UTF-8?q?docs:=20=E6=8E=A5=E5=8F=A3=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/author/AuthorController.java | 16 +++++------ .../controller/front/BookController.java | 28 +++++++++---------- .../controller/front/HomeController.java | 6 ++-- .../controller/front/NewsController.java | 6 ++-- .../controller/front/ResourceController.java | 6 ++-- .../controller/front/SearchController.java | 4 +-- .../controller/front/UserController.java | 22 +++++++-------- 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index f681a30..b979efe 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -28,7 +28,7 @@ import org.springframework.web.bind.annotation.*; * @author xiongxiaoyang * @date 2022/5/23 */ -@Tag(name = "author", description = "作家后台-作者模块") +@Tag(name = "AuthorController", description = "作家后台-作者模块") @SecurityRequirement(name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME) @RestController @RequestMapping(ApiRouterConsts.API_AUTHOR_URL_PREFIX) @@ -42,7 +42,7 @@ public class AuthorController { /** * 作家注册接口 */ - @Operation(description = "作家注册接口") + @Operation(summary = "作家注册接口") @PostMapping("register") public RestResp register(@Valid @RequestBody AuthorRegisterReqDto dto) { dto.setUserId(UserHolder.getUserId()); @@ -52,7 +52,7 @@ public class AuthorController { /** * 查询作家状态接口 */ - @Operation(description = "作家状态查询接口") + @Operation(summary = "作家状态查询接口") @GetMapping("status") public RestResp getStatus() { return authorService.getStatus(UserHolder.getUserId()); @@ -61,7 +61,7 @@ public class AuthorController { /** * 小说发布接口 */ - @Operation(description = "小说发布接口") + @Operation(summary = "小说发布接口") @PostMapping("book") public RestResp publishBook(@Valid @RequestBody BookAddReqDto dto) { return bookService.saveBook(dto); @@ -70,7 +70,7 @@ public class AuthorController { /** * 小说发布列表查询接口 */ - @Operation(description = "小说发布列表查询接口") + @Operation(summary = "小说发布列表查询接口") @GetMapping("books") public RestResp> listBooks(@ParameterObject PageReqDto dto) { return bookService.listAuthorBooks(dto); @@ -79,7 +79,7 @@ public class AuthorController { /** * 小说章节发布接口 */ - @Operation(description = "小说章节发布接口") + @Operation(summary = "小说章节发布接口") @PostMapping("book/chapter/{bookId}") public RestResp publishBookChapter(@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId, @Valid @RequestBody ChapterAddReqDto dto) { dto.setBookId(bookId); @@ -89,9 +89,9 @@ public class AuthorController { /** * 小说章节发布列表查询接口 */ - @Operation(description = "小说章节发布列表查询接口") + @Operation(summary = "小说章节发布列表查询接口") @GetMapping("book/chapters/{bookId}") - public RestResp> listBookChapters(@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId, PageReqDto dto) { + public RestResp> listBookChapters(@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId,@ParameterObject PageReqDto dto) { return bookService.listBookChapters(bookId, dto); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java b/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java index 06bbd46..ff7d9ea 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java @@ -19,7 +19,7 @@ import java.util.List; * @author xiongxiaoyang * @date 2022/5/14 */ -@Tag(name = "book", description = "前台门户-小说模块") +@Tag(name = "BookController", description = "前台门户-小说模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_BOOK_URL_PREFIX) @RequiredArgsConstructor @@ -30,7 +30,7 @@ public class BookController { /** * 小说分类列表查询接口 */ - @Operation(description = "小说分类列表查询接口") + @Operation(summary = "小说分类列表查询接口") @GetMapping("category/list") public RestResp> listCategory(@Parameter(description = "作品方向",required = true) Integer workDirection) { return bookService.listCategory(workDirection); @@ -39,7 +39,7 @@ public class BookController { /** * 小说信息查询接口 */ - @Operation(description = "小说信息查询接口") + @Operation(summary = "小说信息查询接口") @GetMapping("{id}") public RestResp getBookById(@Parameter(description = "小说 ID") @PathVariable("id") Long bookId) { return bookService.getBookById(bookId); @@ -48,7 +48,7 @@ public class BookController { /** * 增加小说点击量接口 */ - @Operation(description = "增加小说点击量接口") + @Operation(summary = "增加小说点击量接口") @PostMapping("visit") public RestResp addVisitCount(@Parameter(description = "小说ID") Long bookId) { return bookService.addVisitCount(bookId); @@ -57,7 +57,7 @@ public class BookController { /** * 小说最新章节相关信息查询接口 */ - @Operation(description = "小说最新章节相关信息查询接口") + @Operation(summary = "小说最新章节相关信息查询接口") @GetMapping("last_chapter/about") public RestResp getLastChapterAbout(@Parameter(description = "小说ID") Long bookId) { return bookService.getLastChapterAbout(bookId); @@ -66,7 +66,7 @@ public class BookController { /** * 小说推荐列表查询接口 */ - @Operation(description = "小说推荐列表查询接口") + @Operation(summary = "小说推荐列表查询接口") @GetMapping("rec_list") public RestResp> listRecBooks(@Parameter(description = "小说ID") Long bookId) throws NoSuchAlgorithmException { return bookService.listRecBooks(bookId); @@ -75,7 +75,7 @@ public class BookController { /** * 小说章节列表查询接口 */ - @Operation(description = "小说章节列表查询接口") + @Operation(summary = "小说章节列表查询接口") @GetMapping("chapter/list") public RestResp> listChapters(@Parameter(description = "小说ID") Long bookId) { return bookService.listChapters(bookId); @@ -84,7 +84,7 @@ public class BookController { /** * 小说内容相关信息查询接口 */ - @Operation(description = "小说内容相关信息查询接口") + @Operation(summary = "小说内容相关信息查询接口") @GetMapping("content/{chapterId}") public RestResp getBookContentAbout(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getBookContentAbout(chapterId); @@ -93,7 +93,7 @@ public class BookController { /** * 获取上一章节ID接口 */ - @Operation(description = "获取上一章节ID接口") + @Operation(summary = "获取上一章节ID接口") @GetMapping("pre_chapter_id/{chapterId}") public RestResp getPreChapterId(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getPreChapterId(chapterId); @@ -102,7 +102,7 @@ public class BookController { /** * 获取下一章节ID接口 */ - @Operation(description = "获取下一章节ID接口") + @Operation(summary = "获取下一章节ID接口") @GetMapping("next_chapter_id/{chapterId}") public RestResp getNextChapterId(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getNextChapterId(chapterId); @@ -111,7 +111,7 @@ public class BookController { /** * 小说点击榜查询接口 */ - @Operation(description = "小说点击榜查询接口") + @Operation(summary = "小说点击榜查询接口") @GetMapping("visit_rank") public RestResp> listVisitRankBooks() { return bookService.listVisitRankBooks(); @@ -120,7 +120,7 @@ public class BookController { /** * 小说新书榜查询接口 */ - @Operation(description = "小说新书榜查询接口") + @Operation(summary = "小说新书榜查询接口") @GetMapping("newest_rank") public RestResp> listNewestRankBooks() { return bookService.listNewestRankBooks(); @@ -129,7 +129,7 @@ public class BookController { /** * 小说更新榜查询接口 */ - @Operation(description = "小说更新榜查询接口") + @Operation(summary = "小说更新榜查询接口") @GetMapping("update_rank") public RestResp> listUpdateRankBooks() { return bookService.listUpdateRankBooks(); @@ -138,7 +138,7 @@ public class BookController { /** * 小说最新评论查询接口 */ - @Operation(description = "小说最新评论查询接口") + @Operation(summary = "小说最新评论查询接口") @GetMapping("comment/newest_list") public RestResp listNewestComments(@Parameter(description = "小说ID") Long bookId) { return bookService.listNewestComments(bookId); diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/HomeController.java b/src/main/java/io/github/xxyopen/novel/controller/front/HomeController.java index 94f14f3..bb8074b 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/HomeController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/HomeController.java @@ -20,7 +20,7 @@ import java.util.List; * @author xiongxiaoyang * @date 2022/5/12 */ -@Tag(name = "home", description = "前台门户-首页模块") +@Tag(name = "HomeController", description = "前台门户-首页模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_HOME_URL_PREFIX) @RequiredArgsConstructor @@ -31,7 +31,7 @@ public class HomeController { /** * 首页小说推荐查询接口 */ - @Operation(description = "首页小说推荐查询接口") + @Operation(summary = "首页小说推荐查询接口") @GetMapping("books") public RestResp> listHomeBooks() { return homeService.listHomeBooks(); @@ -40,7 +40,7 @@ public class HomeController { /** * 首页友情链接列表查询接口 */ - @Operation(description = "首页友情链接列表查询接口") + @Operation(summary = "首页友情链接列表查询接口") @GetMapping("friend_Link/list") public RestResp> listHomeFriendLinks() { return homeService.listHomeFriendLinks(); diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java b/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java index eb4eaf0..d9bf427 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java @@ -21,7 +21,7 @@ import java.util.List; * @author xiongxiaoyang * @date 2022/5/12 */ -@Tag(name = "news", description = "前台门户-新闻模块") +@Tag(name = "NewsController", description = "前台门户-新闻模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_NEWS_URL_PREFIX) @RequiredArgsConstructor @@ -32,7 +32,7 @@ public class NewsController { /** * 最新新闻列表查询接口 */ - @Operation(description = "最新新闻列表查询接口") + @Operation(summary = "最新新闻列表查询接口") @GetMapping("latest_list") public RestResp> listLatestNews() { return newsService.listLatestNews(); @@ -41,7 +41,7 @@ public class NewsController { /** * 新闻信息查询接口 */ - @Operation(description = "新闻信息查询接口") + @Operation(summary = "新闻信息查询接口") @GetMapping("{id}") public RestResp getNews(@Parameter(description = "新闻ID") @PathVariable Long id) { return newsService.getNews(id); diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java b/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java index b58654d..ade6d97 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java @@ -19,7 +19,7 @@ import java.io.IOException; * @author xiongxiaoyang * @date 2022/5/17 */ -@Tag(name = "resource", description = "前台门户-资源模块") +@Tag(name = "ResourceController", description = "前台门户-资源模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_RESOURCE_URL_PREFIX) @RequiredArgsConstructor @@ -30,7 +30,7 @@ public class ResourceController { /** * 获取图片验证码接口 */ - @Operation(description = "获取图片验证码接口") + @Operation(summary = "获取图片验证码接口") @GetMapping("img_verify_code") public RestResp getImgVerifyCode() throws IOException { return resourceService.getImgVerifyCode(); @@ -39,7 +39,7 @@ public class ResourceController { /** * 图片上传接口 * */ - @Operation(description = "图片上传接口") + @Operation(summary = "图片上传接口") @PostMapping("/image") RestResp uploadImage(@Parameter(description = "上传文件") @RequestParam("file") MultipartFile file) { return resourceService.uploadImage(file); diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java b/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java index e8a17a7..82a6601 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java @@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.RestController; * @author xiongxiaoyang * @date 2022/5/27 */ -@Tag(name = "search", description = "前台门户-搜索模块") +@Tag(name = "SearchController", description = "前台门户-搜索模块") @RestController @RequestMapping(ApiRouterConsts.API_FRONT_SEARCH_URL_PREFIX) @RequiredArgsConstructor @@ -31,7 +31,7 @@ public class SearchController { /** * 小说搜索接口 */ - @Operation(description = "小说搜索接口") + @Operation(summary = "小说搜索接口") @GetMapping("books") public RestResp> searchBooks(@ParameterObject BookSearchReqDto condition) { return searchService.searchBooks(condition); diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java b/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java index f5936ab..1528b05 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java @@ -27,7 +27,7 @@ import org.springframework.web.bind.annotation.*; * @author xiongxiaoyang * @date 2022/5/17 */ -@Tag(name = "user", description = "前台门户-会员模块") +@Tag(name = "UserController", description = "前台门户-会员模块") @SecurityRequirement(name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME) @RestController @RequestMapping(ApiRouterConsts.API_FRONT_USER_URL_PREFIX) @@ -41,7 +41,7 @@ public class UserController { /** * 用户注册接口 */ - @Operation(description = "用户注册接口") + @Operation(summary = "用户注册接口") @PostMapping("register") public RestResp register(@Valid @RequestBody UserRegisterReqDto dto) { return userService.register(dto); @@ -50,7 +50,7 @@ public class UserController { /** * 用户登录接口 */ - @Operation(description = "用户登录接口") + @Operation(summary = "用户登录接口") @PostMapping("login") public RestResp login(@Valid @RequestBody UserLoginReqDto dto) { return userService.login(dto); @@ -59,7 +59,7 @@ public class UserController { /** * 用户信息查询接口 */ - @Operation(description = "用户信息查询接口") + @Operation(summary = "用户信息查询接口") @GetMapping public RestResp getUserInfo() { return userService.getUserInfo(UserHolder.getUserId()); @@ -68,7 +68,7 @@ public class UserController { /** * 用户信息修改接口 */ - @Operation(description = "用户信息修改接口") + @Operation(summary = "用户信息修改接口") @PutMapping public RestResp updateUserInfo(@Valid @RequestBody UserInfoUptReqDto dto) { dto.setUserId(UserHolder.getUserId()); @@ -78,7 +78,7 @@ public class UserController { /** * 用户反馈提交接口 */ - @Operation(description = "用户反馈提交接口") + @Operation(summary = "用户反馈提交接口") @PostMapping("feedback") public RestResp submitFeedback(@RequestBody String content) { return userService.saveFeedback(UserHolder.getUserId(), content); @@ -87,7 +87,7 @@ public class UserController { /** * 用户反馈删除接口 */ - @Operation(description = "用户反馈删除接口") + @Operation(summary = "用户反馈删除接口") @DeleteMapping("feedback/{id}") public RestResp deleteFeedback(@Parameter(description = "反馈ID") @PathVariable Long id) { return userService.deleteFeedback(UserHolder.getUserId(), id); @@ -96,7 +96,7 @@ public class UserController { /** * 发表评论接口 */ - @Operation(description = "发表评论接口") + @Operation(summary = "发表评论接口") @PostMapping("comment") public RestResp comment(@Valid @RequestBody UserCommentReqDto dto) { dto.setUserId(UserHolder.getUserId()); @@ -106,7 +106,7 @@ public class UserController { /** * 修改评论接口 */ - @Operation(description = "修改评论接口") + @Operation(summary = "修改评论接口") @PutMapping("comment/{id}") public RestResp updateComment(@Parameter(description = "评论ID") @PathVariable Long id, String content) { return bookService.updateComment(UserHolder.getUserId(), id, content); @@ -115,7 +115,7 @@ public class UserController { /** * 删除评论接口 */ - @Operation(description = "删除评论接口") + @Operation(summary = "删除评论接口") @DeleteMapping("comment/{id}") public RestResp deleteComment(@Parameter(description = "评论ID") @PathVariable Long id) { return bookService.deleteComment(UserHolder.getUserId(), id); @@ -126,7 +126,7 @@ public class UserController { * 0-不在书架 * 1-已在书架 */ - @Operation(description = "查询书架状态接口") + @Operation(summary = "查询书架状态接口") @GetMapping("bookshelf_status") public RestResp getBookshelfStatus(@Parameter(description = "小说ID") String bookId) { return userService.getBookshelfStatus(UserHolder.getUserId(), bookId); -- Gitee From 76677ea8b81f96154495d9360731f276b7352b11 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Mon, 27 Jun 2022 18:51:24 +0800 Subject: [PATCH 053/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1082408..d01a8e0 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | | XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | | Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | -| Springdoc-openapi | 2.0.0-M4-SNAPSHOT | API 文档自动生成 | https://github.com/springdoc/springdoc-openapi | [进入](https://springdoc.org/) | +| Springdoc-openapi | 2.0.0-M4-SNAPSHOT | Swagger 3 接口文档自动生成 | https://github.com/springdoc/springdoc-openapi | [进入](https://springdoc.org/) | | Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | | Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | | Docker | - | 应用容器引擎 | https://www.docker.com/ | - | -- Gitee From 6d2fa7423795bd948d94c363843ea4454611fe79 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Thu, 30 Jun 2022 19:11:02 +0800 Subject: [PATCH 054/112] =?UTF-8?q?docs:=20=E4=BF=AE=E6=94=B9=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/dto/req/AuthorRegisterReqDto.java | 1 + .../github/xxyopen/novel/dto/req/UserLoginReqDto.java | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/AuthorRegisterReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/AuthorRegisterReqDto.java index 8fbea2b..a4547c3 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/AuthorRegisterReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/AuthorRegisterReqDto.java @@ -13,6 +13,7 @@ import lombok.Data; @Data public class AuthorRegisterReqDto { + @Schema(hidden = true) private Long userId; /** diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/UserLoginReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/UserLoginReqDto.java index ab92e1d..d0f7754 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/req/UserLoginReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/req/UserLoginReqDto.java @@ -14,13 +14,13 @@ import lombok.Data; @Data public class UserLoginReqDto { - @Schema(description = "手机号", required = true) - @NotBlank(message="手机号不能为空!") - @Pattern(regexp="^1[3|4|5|6|7|8|9][0-9]{9}$",message="手机号格式不正确!") + @Schema(description = "手机号", required = true, example = "18888888888") + @NotBlank(message = "手机号不能为空!") + @Pattern(regexp = "^1[3|4|5|6|7|8|9][0-9]{9}$", message = "手机号格式不正确!") private String username; - @Schema(description = "密码", required = true) - @NotBlank(message="密码不能为空!") + @Schema(description = "密码", required = true, example = "123456") + @NotBlank(message = "密码不能为空!") private String password; } -- Gitee From 9b93d90270478b1feda1c23e1a89f5fa840edda8 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Thu, 30 Jun 2022 21:34:54 +0800 Subject: [PATCH 055/112] =?UTF-8?q?style:=20=E4=BB=A3=E7=A0=81=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/README.md | 6 + doc/sql/readme | 5 - doc/style/README.md | 3 + doc/style/intellij-java-google-style.xml | 598 ++++++++++++++++++ .../xxyopen/novel/NovelApplication.java | 7 +- .../controller/author/AuthorController.java | 15 +- .../controller/front/BookController.java | 44 +- .../controller/front/NewsController.java | 8 +- .../controller/front/ResourceController.java | 14 +- .../controller/front/SearchController.java | 3 +- .../controller/front/UserController.java | 16 +- .../xxyopen/novel/core/annotation/Key.java | 6 +- .../xxyopen/novel/core/aspect/LockAspect.java | 9 +- .../xxyopen/novel/core/auth/AuthStrategy.java | 8 +- .../novel/core/auth/AuthorAuthStrategy.java | 13 +- .../novel/core/auth/FrontAuthStrategy.java | 2 +- .../xxyopen/novel/core/auth/UserHolder.java | 6 +- .../core/common/constant/CommonConsts.java | 18 +- .../core/common/constant/ErrorCodeEnum.java | 115 ++-- .../exception/CommonExceptionHandler.java | 18 +- .../novel/core/common/req/PageReqDto.java | 9 +- .../novel/core/common/resp/PageRespDto.java | 9 +- .../core/common/util/ImgVerifyCodeUtils.java | 11 +- .../novel/core/common/util/IpUtils.java | 1 + .../novel/core/config/CacheConfig.java | 34 +- .../xxyopen/novel/core/config/CorsConfig.java | 2 +- .../xxyopen/novel/core/config/EsConfig.java | 2 +- .../novel/core/config/RedissonConfig.java | 2 +- .../xxyopen/novel/core/config/WebConfig.java | 41 +- .../novel/core/config/XssProperties.java | 5 +- .../novel/core/constant/AmqpConsts.java | 10 +- .../novel/core/constant/ApiRouterConsts.java | 20 +- .../novel/core/constant/CacheConsts.java | 19 +- .../novel/core/constant/DatabaseConsts.java | 1 - .../xxyopen/novel/core/constant/EsConsts.java | 12 +- .../core/constant/SystemConfigConsts.java | 12 +- .../xxyopen/novel/core/filter/XssFilter.java | 23 +- .../core/interceptor/AuthInterceptor.java | 27 +- .../core/interceptor/FileInterceptor.java | 13 +- .../interceptor/FlowLimitInterceptor.java | 28 +- .../interceptor/TokenParseInterceptor.java | 6 +- .../deserializer/GlobalJsonDeserializer.java | 13 +- .../json/serializer/UsernameSerializer.java | 6 +- .../core/listener/RabbitQueueListener.java | 11 +- .../xxyopen/novel/core/task/BookToEsTask.java | 21 +- .../xxyopen/novel/core/util/JwtUtils.java | 25 +- .../wrapper/XssHttpServletRequestWrapper.java | 6 +- .../manager/cache/AuthorInfoCacheManager.java | 17 +- .../cache/BookCategoryCacheManager.java | 13 +- .../cache/BookChapterCacheManager.java | 16 +- .../cache/BookContentCacheManager.java | 4 +- .../manager/cache/BookInfoCacheManager.java | 69 +- .../manager/cache/BookRankCacheManager.java | 21 +- .../manager/cache/FriendLinkCacheManager.java | 5 +- .../manager/cache/HomeBookCacheManager.java | 19 +- .../novel/manager/cache/NewsCacheManager.java | 21 +- .../manager/cache/UserInfoCacheManager.java | 9 +- .../novel/manager/dao/UserDaoManager.java | 11 +- .../novel/manager/mq/AmqpMsgManager.java | 19 +- .../manager/redis/VerifyCodeManager.java | 12 +- .../xxyopen/novel/service/AuthorService.java | 3 +- .../novel/service/impl/BookServiceImpl.java | 160 +++-- .../service/impl/DbSearchServiceImpl.java | 24 +- .../service/impl/EsSearchServiceImpl.java | 113 ++-- .../novel/service/impl/NewsServiceImpl.java | 15 +- .../service/impl/ResourceServiceImpl.java | 29 +- .../novel/service/impl/UserServiceImpl.java | 48 +- 67 files changed, 1292 insertions(+), 619 deletions(-) create mode 100644 doc/sql/README.md delete mode 100644 doc/sql/readme create mode 100644 doc/style/README.md create mode 100644 doc/style/intellij-java-google-style.xml diff --git a/doc/sql/README.md b/doc/sql/README.md new file mode 100644 index 0000000..add482c --- /dev/null +++ b/doc/sql/README.md @@ -0,0 +1,6 @@ +1. 初始状态下,MySQL 只需要执行 `novel.sql` 文件即可正常运行本系统 +2. 代码更新后再执行以日期命名的增量 SQL 文件 +3. 只有开启 XXL-JOB 的功能,才需要执行 `xxl-job.sql` 和以 xxl-job 开头日期结尾的增量 SQL 文件 +4. 只有开启 ShardingSphere-JDBC 的功能,才需要执行 `shardingsphere-jdbc.sql` 和以 shardingsphere-jdbc 开头日期结尾的增量 SQL + 文件 + diff --git a/doc/sql/readme b/doc/sql/readme deleted file mode 100644 index e604e2b..0000000 --- a/doc/sql/readme +++ /dev/null @@ -1,5 +0,0 @@ -1. 初始状态下,MYSQL 只需要执行 novel.sql 文件即可正常运行本系统 -2. 代码更新后再执行以日期命名的增量 SQL 文件 -3. 只有开启 XXL-JOB 的功能,才需要执行 xxl-job.sql 和以 xxl-job 开头日期结尾的增量 SQL 文件 -4. 只有开启 ShardingSphere-JDBC 的功能,才需要执行 shardingsphere-jdbc.sql 和以 shardingsphere-jdbc 开头日期结尾的增量 SQL 文件 - diff --git a/doc/style/README.md b/doc/style/README.md new file mode 100644 index 0000000..41b2635 --- /dev/null +++ b/doc/style/README.md @@ -0,0 +1,3 @@ +IntelliJ IDEA 中导入 `intellij-java-google-style.xml` 文件: + +`Preferences` => `Editor` => `Code Style` => `Java` => `Schema` => `Import Schema` \ No newline at end of file diff --git a/doc/style/intellij-java-google-style.xml b/doc/style/intellij-java-google-style.xml new file mode 100644 index 0000000..67b3517 --- /dev/null +++ b/doc/style/intellij-java-google-style.xml @@ -0,0 +1,598 @@ + + + + + +

+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .*:.*Style + + http://schemas.android.com/apk/res/android + + + BY_NAME + +
+
+ + + + .*:layout_width + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_height + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_weight + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_margin + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginTop + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginBottom + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginStart + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginEnd + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginLeft + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginRight + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_.* + + http://schemas.android.com/apk/res/android + + + BY_NAME + +
+
+ + + + .*:padding + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingTop + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingBottom + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingStart + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingEnd + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingLeft + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingRight + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .* + http://schemas.android.com/apk/res/android + + + BY_NAME + +
+
+ + + + .* + http://schemas.android.com/apk/res-auto + + + BY_NAME + +
+
+ + + + .* + http://schemas.android.com/tools + + + BY_NAME + +
+
+ + + + .* + .* + + + BY_NAME + +
+ + + + + + + + + + diff --git a/src/main/java/io/github/xxyopen/novel/NovelApplication.java b/src/main/java/io/github/xxyopen/novel/NovelApplication.java index cf31ddd..7b6dae1 100644 --- a/src/main/java/io/github/xxyopen/novel/NovelApplication.java +++ b/src/main/java/io/github/xxyopen/novel/NovelApplication.java @@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.security.SecurityScheme; +import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.CommandLineRunner; @@ -21,8 +22,6 @@ import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; -import java.util.Map; - @OpenAPIDefinition(info = @Info(title = "novel 项目接口文档", version = "v3.2.0", license = @License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0"))) @SecurityScheme(type = SecuritySchemeType.APIKEY, in = SecuritySchemeIn.HEADER, name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME, description = "登录 token") @SpringBootApplication @@ -52,8 +51,8 @@ public class NovelApplication { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf().disable() - .requestMatcher(EndpointRequest.toAnyEndpoint()) - .authorizeRequests(requests -> requests.anyRequest().hasRole("ENDPOINT_ADMIN")); + .requestMatcher(EndpointRequest.toAnyEndpoint()) + .authorizeRequests(requests -> requests.anyRequest().hasRole("ENDPOINT_ADMIN")); http.httpBasic(); return http.build(); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index b979efe..4c8be34 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -20,7 +20,12 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; /** * 作家后台-作家模块 API 控制器 @@ -81,7 +86,9 @@ public class AuthorController { */ @Operation(summary = "小说章节发布接口") @PostMapping("book/chapter/{bookId}") - public RestResp publishBookChapter(@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId, @Valid @RequestBody ChapterAddReqDto dto) { + public RestResp publishBookChapter( + @Parameter(description = "小说ID") @PathVariable("bookId") Long bookId, + @Valid @RequestBody ChapterAddReqDto dto) { dto.setBookId(bookId); return bookService.saveBookChapter(dto); } @@ -91,7 +98,9 @@ public class AuthorController { */ @Operation(summary = "小说章节发布列表查询接口") @GetMapping("book/chapters/{bookId}") - public RestResp> listBookChapters(@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId,@ParameterObject PageReqDto dto) { + public RestResp> listBookChapters( + @Parameter(description = "小说ID") @PathVariable("bookId") Long bookId, + @ParameterObject PageReqDto dto) { return bookService.listBookChapters(bookId, dto); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java b/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java index ff7d9ea..a299b28 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/BookController.java @@ -2,16 +2,25 @@ package io.github.xxyopen.novel.controller.front; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.ApiRouterConsts; -import io.github.xxyopen.novel.dto.resp.*; +import io.github.xxyopen.novel.dto.resp.BookCategoryRespDto; +import io.github.xxyopen.novel.dto.resp.BookChapterAboutRespDto; +import io.github.xxyopen.novel.dto.resp.BookChapterRespDto; +import io.github.xxyopen.novel.dto.resp.BookCommentRespDto; +import io.github.xxyopen.novel.dto.resp.BookContentAboutRespDto; +import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; +import io.github.xxyopen.novel.dto.resp.BookRankRespDto; import io.github.xxyopen.novel.service.BookService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; - import java.security.NoSuchAlgorithmException; import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; /** * 前台门户-小说模块 API 控制器 @@ -32,7 +41,8 @@ public class BookController { */ @Operation(summary = "小说分类列表查询接口") @GetMapping("category/list") - public RestResp> listCategory(@Parameter(description = "作品方向",required = true) Integer workDirection) { + public RestResp> listCategory( + @Parameter(description = "作品方向", required = true) Integer workDirection) { return bookService.listCategory(workDirection); } @@ -41,7 +51,8 @@ public class BookController { */ @Operation(summary = "小说信息查询接口") @GetMapping("{id}") - public RestResp getBookById(@Parameter(description = "小说 ID") @PathVariable("id") Long bookId) { + public RestResp getBookById( + @Parameter(description = "小说 ID") @PathVariable("id") Long bookId) { return bookService.getBookById(bookId); } @@ -59,7 +70,8 @@ public class BookController { */ @Operation(summary = "小说最新章节相关信息查询接口") @GetMapping("last_chapter/about") - public RestResp getLastChapterAbout(@Parameter(description = "小说ID") Long bookId) { + public RestResp getLastChapterAbout( + @Parameter(description = "小说ID") Long bookId) { return bookService.getLastChapterAbout(bookId); } @@ -68,7 +80,8 @@ public class BookController { */ @Operation(summary = "小说推荐列表查询接口") @GetMapping("rec_list") - public RestResp> listRecBooks(@Parameter(description = "小说ID") Long bookId) throws NoSuchAlgorithmException { + public RestResp> listRecBooks( + @Parameter(description = "小说ID") Long bookId) throws NoSuchAlgorithmException { return bookService.listRecBooks(bookId); } @@ -77,7 +90,8 @@ public class BookController { */ @Operation(summary = "小说章节列表查询接口") @GetMapping("chapter/list") - public RestResp> listChapters(@Parameter(description = "小说ID") Long bookId) { + public RestResp> listChapters( + @Parameter(description = "小说ID") Long bookId) { return bookService.listChapters(bookId); } @@ -86,7 +100,8 @@ public class BookController { */ @Operation(summary = "小说内容相关信息查询接口") @GetMapping("content/{chapterId}") - public RestResp getBookContentAbout(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { + public RestResp getBookContentAbout( + @Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getBookContentAbout(chapterId); } @@ -95,7 +110,8 @@ public class BookController { */ @Operation(summary = "获取上一章节ID接口") @GetMapping("pre_chapter_id/{chapterId}") - public RestResp getPreChapterId(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { + public RestResp getPreChapterId( + @Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getPreChapterId(chapterId); } @@ -104,7 +120,8 @@ public class BookController { */ @Operation(summary = "获取下一章节ID接口") @GetMapping("next_chapter_id/{chapterId}") - public RestResp getNextChapterId(@Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { + public RestResp getNextChapterId( + @Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { return bookService.getNextChapterId(chapterId); } @@ -140,7 +157,8 @@ public class BookController { */ @Operation(summary = "小说最新评论查询接口") @GetMapping("comment/newest_list") - public RestResp listNewestComments(@Parameter(description = "小说ID") Long bookId) { + public RestResp listNewestComments( + @Parameter(description = "小说ID") Long bookId) { return bookService.listNewestComments(bookId); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java b/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java index d9bf427..e05716c 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/NewsController.java @@ -1,20 +1,19 @@ package io.github.xxyopen.novel.controller.front; -import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.common.resp.RestResp; +import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.dto.resp.NewsInfoRespDto; import io.github.xxyopen.novel.service.NewsService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - /** * 前台门户-新闻模块 API 控制器 * @@ -43,7 +42,8 @@ public class NewsController { */ @Operation(summary = "新闻信息查询接口") @GetMapping("{id}") - public RestResp getNews(@Parameter(description = "新闻ID") @PathVariable Long id) { + public RestResp getNews( + @Parameter(description = "新闻ID") @PathVariable Long id) { return newsService.getNews(id); } } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java b/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java index ade6d97..93e173d 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java @@ -7,12 +7,15 @@ import io.github.xxyopen.novel.service.ResourceService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import java.io.IOException; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; - /** * 前台门户-资源(图片/视频/文档)模块 API 控制器 * @@ -38,10 +41,11 @@ public class ResourceController { /** * 图片上传接口 - * */ + */ @Operation(summary = "图片上传接口") @PostMapping("/image") - RestResp uploadImage(@Parameter(description = "上传文件") @RequestParam("file") MultipartFile file) { + RestResp uploadImage( + @Parameter(description = "上传文件") @RequestParam("file") MultipartFile file) { return resourceService.uploadImage(file); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java b/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java index 82a6601..ff3ee90 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/SearchController.java @@ -33,7 +33,8 @@ public class SearchController { */ @Operation(summary = "小说搜索接口") @GetMapping("books") - public RestResp> searchBooks(@ParameterObject BookSearchReqDto condition) { + public RestResp> searchBooks( + @ParameterObject BookSearchReqDto condition) { return searchService.searchBooks(condition); } diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java b/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java index 1528b05..c25c4ae 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java @@ -19,7 +19,14 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; /** * 前台门户-会员模块 API 控制器 @@ -108,7 +115,8 @@ public class UserController { */ @Operation(summary = "修改评论接口") @PutMapping("comment/{id}") - public RestResp updateComment(@Parameter(description = "评论ID") @PathVariable Long id, String content) { + public RestResp updateComment(@Parameter(description = "评论ID") @PathVariable Long id, + String content) { return bookService.updateComment(UserHolder.getUserId(), id, content); } @@ -122,9 +130,7 @@ public class UserController { } /** - * 查询书架状态接口 - * 0-不在书架 - * 1-已在书架 + * 查询书架状态接口 0-不在书架 1-已在书架 */ @Operation(summary = "查询书架状态接口") @GetMapping("bookshelf_status") diff --git a/src/main/java/io/github/xxyopen/novel/core/annotation/Key.java b/src/main/java/io/github/xxyopen/novel/core/annotation/Key.java index 7a1e2a8..8f9812b 100644 --- a/src/main/java/io/github/xxyopen/novel/core/annotation/Key.java +++ b/src/main/java/io/github/xxyopen/novel/core/annotation/Key.java @@ -1,12 +1,12 @@ package io.github.xxyopen.novel.core.annotation; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - /** * 分布式锁-Key 注解 * @@ -17,5 +17,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; @Retention(RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) public @interface Key { + String expr() default ""; + } diff --git a/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java b/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java index bf10bb4..0b19ccf 100644 --- a/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java +++ b/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java @@ -3,6 +3,9 @@ package io.github.xxyopen.novel.core.aspect; import io.github.xxyopen.novel.core.annotation.Key; import io.github.xxyopen.novel.core.annotation.Lock; import io.github.xxyopen.novel.core.common.exception.BusinessException; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.concurrent.TimeUnit; import lombok.SneakyThrows; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -17,10 +20,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.util.concurrent.TimeUnit; - /** * 分布式锁 切面 * @@ -42,7 +41,7 @@ public record LockAspect(RedissonClient redissonClient) { Method targetMethod = methodSignature.getMethod(); Lock lock = targetMethod.getAnnotation(Lock.class); String lockKey = KEY_PREFIX + buildLockKey(lock.prefix(), targetMethod, - joinPoint.getArgs()); + joinPoint.getArgs()); RLock rLock = redissonClient.getLock(lockKey); if (lock.isWait() ? rLock.tryLock(lock.waitTime(), TimeUnit.SECONDS) : rLock.tryLock()) { try { diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/AuthStrategy.java b/src/main/java/io/github/xxyopen/novel/core/auth/AuthStrategy.java index 8d394c8..99fbe12 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/AuthStrategy.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/AuthStrategy.java @@ -6,9 +6,8 @@ import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.core.util.JwtUtils; import io.github.xxyopen.novel.dto.UserInfoDto; import io.github.xxyopen.novel.manager.cache.UserInfoCacheManager; -import org.springframework.util.StringUtils; - import java.util.Objects; +import org.springframework.util.StringUtils; /** * 策略模式实现用户认证授权功能 @@ -21,7 +20,7 @@ public interface AuthStrategy { /** * 请求用户认证 * - * @param token 登录 token + * @param token 登录 token * @param requestUri 请求的 URI * @throws BusinessException 认证失败则抛出业务异常 */ @@ -35,7 +34,8 @@ public interface AuthStrategy { * @param token token 登录 token * @return 用户ID */ - default Long authSSO(JwtUtils jwtUtils, UserInfoCacheManager userInfoCacheManager, String token) { + default Long authSSO(JwtUtils jwtUtils, UserInfoCacheManager userInfoCacheManager, + String token) { if (!StringUtils.hasText(token)) { // token 为空 throw new BusinessException(ErrorCodeEnum.USER_LOGIN_EXPIRED); diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java b/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java index 599bfbf..71e5ff1 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java @@ -7,11 +7,10 @@ import io.github.xxyopen.novel.core.util.JwtUtils; import io.github.xxyopen.novel.dto.AuthorInfoDto; import io.github.xxyopen.novel.manager.cache.AuthorInfoCacheManager; import io.github.xxyopen.novel.manager.cache.UserInfoCacheManager; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - import java.util.List; import java.util.Objects; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; /** * 作家后台管理系统 认证策略 @@ -31,17 +30,17 @@ public class AuthorAuthStrategy implements AuthStrategy { /** * 不需要进行作家权限认证的 URI - * */ + */ private static final List EXCLUDE_URI = List.of( - ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/register", - ApiRouterConsts.API_AUTHOR_URL_PREFIX +"/status" + ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/register", + ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/status" ); @Override public void auth(String token, String requestUri) throws BusinessException { // 统一账号认证 Long userId = authSSO(jwtUtils, userInfoCacheManager, token); - if(EXCLUDE_URI.contains(requestUri)){ + if (EXCLUDE_URI.contains(requestUri)) { // 该请求不需要进行作家权限认证 return; } diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java b/src/main/java/io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java index 2c69fb2..4e1b807 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java @@ -23,6 +23,6 @@ public class FrontAuthStrategy implements AuthStrategy { @Override public void auth(String token, String requestUri) throws BusinessException { // 统一账号认证 - authSSO(jwtUtils,userInfoCacheManager,token); + authSSO(jwtUtils, userInfoCacheManager, token); } } \ No newline at end of file diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/UserHolder.java b/src/main/java/io/github/xxyopen/novel/core/auth/UserHolder.java index 350d3db..7ab8775 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/UserHolder.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/UserHolder.java @@ -13,12 +13,12 @@ public class UserHolder { /** * 当前线程用户ID - * */ + */ private static final ThreadLocal userIdTL = new ThreadLocal<>(); /** * 当前线程作家ID - * */ + */ private static final ThreadLocal authorIdTL = new ThreadLocal<>(); public void setUserId(Long userId) { @@ -37,7 +37,7 @@ public class UserHolder { return authorIdTL.get(); } - public void clear(){ + public void clear() { userIdTL.remove(); authorIdTL.remove(); } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/constant/CommonConsts.java b/src/main/java/io/github/xxyopen/novel/core/common/constant/CommonConsts.java index e2fae0a..b943f28 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/constant/CommonConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/constant/CommonConsts.java @@ -11,33 +11,33 @@ public class CommonConsts { /** * 是 - * */ + */ public static final Integer YES = 1; public static final String TRUE = "true"; /** * 否 - * */ + */ public static final Integer NO = 0; public static final String FALSE = "false"; /** * 性别常量 - * */ - public enum SexEnum{ + */ + public enum SexEnum { /** * 男 - * */ - MALE(0,"男"), + */ + MALE(0, "男"), /** * 女 - * */ - FEMALE(1,"女"); + */ + FEMALE(1, "女"); - SexEnum(int code,String desc){ + SexEnum(int code, String desc) { this.code = code; this.desc = desc; } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java b/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java index 8d10836..918cf30 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java @@ -5,15 +5,12 @@ import lombok.Getter; /** * 错误码枚举类。 - * - * 错误码为字符串类型,共 5 位,分成两个部分:错误产生来源+四位数字编号。 - * 错误产生来源分为 A/B/C, A 表示错误来源于用户,比如参数错误,用户安装版本过低,用户支付 - * 超时等问题; B 表示错误来源于当前系统,往往是业务逻辑出错,或程序健壮性差等问题; C 表示错误来源 - * 于第三方服务,比如 CDN 服务出错,消息投递超时等问题;四位数字编号从 0001 到 9999,大类之间的 + *

+ * 错误码为字符串类型,共 5 位,分成两个部分:错误产生来源+四位数字编号。 错误产生来源分为 A/B/C, A 表示错误来源于用户,比如参数错误,用户安装版本过低,用户支付 超时等问题; B + * 表示错误来源于当前系统,往往是业务逻辑出错,或程序健壮性差等问题; C 表示错误来源 于第三方服务,比如 CDN 服务出错,消息投递超时等问题;四位数字编号从 0001 到 9999,大类之间的 * 步长间距预留 100。 - * - * 错误码分为一级宏观错误码、二级宏观错误码、三级宏观错误码。 - * 在无法更加具体确定的错误场景中,可以直接使用一级宏观错误码。 + *

+ * 错误码分为一级宏观错误码、二级宏观错误码、三级宏观错误码。 在无法更加具体确定的错误场景中,可以直接使用一级宏观错误码。 * * @author xiongxiaoyang * @date 2022/5/11 @@ -24,134 +21,132 @@ public enum ErrorCodeEnum { /** * 正确执行后的返回 - * */ - OK("00000","一切 ok"), + */ + OK("00000", "一切 ok"), /** * 一级宏观错误码,用户端错误 - * */ - USER_ERROR("A0001","用户端错误"), + */ + USER_ERROR("A0001", "用户端错误"), /** * 二级宏观错误码,用户注册错误 - * */ - USER_REGISTER_ERROR("A0100","用户注册错误"), + */ + USER_REGISTER_ERROR("A0100", "用户注册错误"), /** * 用户未同意隐私协议 - * */ - USER_NO_AGREE_PRIVATE_ERROR("A0101","用户未同意隐私协议"), + */ + USER_NO_AGREE_PRIVATE_ERROR("A0101", "用户未同意隐私协议"), /** * 注册国家或地区受限 - * */ - USER_REGISTER_AREA_LIMIT_ERROR("A0102","注册国家或地区受限"), + */ + USER_REGISTER_AREA_LIMIT_ERROR("A0102", "注册国家或地区受限"), /** * 用户验证码错误 - * */ - USER_VERIFY_CODE_ERROR("A0240","用户验证码错误"), + */ + USER_VERIFY_CODE_ERROR("A0240", "用户验证码错误"), /** * 用户名已存在 - * */ - USER_NAME_EXIST("A0111","用户名已存在"), + */ + USER_NAME_EXIST("A0111", "用户名已存在"), /** * 用户账号不存在 - * */ - USER_ACCOUNT_NOT_EXIST("A0201","用户账号不存在"), + */ + USER_ACCOUNT_NOT_EXIST("A0201", "用户账号不存在"), /** * 用户密码错误 - * */ - USER_PASSWORD_ERROR("A0210","用户密码错误"), + */ + USER_PASSWORD_ERROR("A0210", "用户密码错误"), /** * 二级宏观错误码,用户请求参数错误 - * */ - USER_REQUEST_PARAM_ERROR("A0400","用户请求参数错误"), + */ + USER_REQUEST_PARAM_ERROR("A0400", "用户请求参数错误"), /** * 用户登录已过期 - * */ - USER_LOGIN_EXPIRED("A0230","用户登录已过期"), + */ + USER_LOGIN_EXPIRED("A0230", "用户登录已过期"), /** * 访问未授权 - * */ - USER_UN_AUTH("A0301","访问未授权"), + */ + USER_UN_AUTH("A0301", "访问未授权"), /** * 用户请求服务异常 - * */ - USER_REQ_EXCEPTION("A0500","用户请求服务异常"), + */ + USER_REQ_EXCEPTION("A0500", "用户请求服务异常"), /** * 请求超出限制 - * */ - USER_REQ_MANY("A0501","请求超出限制"), + */ + USER_REQ_MANY("A0501", "请求超出限制"), /** * 用户评论异常 - * */ - USER_COMMENT("A2000","用户评论异常"), + */ + USER_COMMENT("A2000", "用户评论异常"), /** * 用户评论异常 - * */ - USER_COMMENTED("A2001","用户已发表评论"), + */ + USER_COMMENTED("A2001", "用户已发表评论"), /** * 作家发布异常 - * */ - AUTHOR_PUBLISH("A3000","作家发布异常"), + */ + AUTHOR_PUBLISH("A3000", "作家发布异常"), /** * 小说名已存在 - * */ - AUTHOR_BOOK_NAME_EXIST("A3001","小说名已存在"), - + */ + AUTHOR_BOOK_NAME_EXIST("A3001", "小说名已存在"), /** * 用户上传文件异常 - * */ - USER_UPLOAD_FILE_ERROR("A0700","用户上传文件异常"), + */ + USER_UPLOAD_FILE_ERROR("A0700", "用户上传文件异常"), /** * 用户上传文件类型不匹配 - * */ - USER_UPLOAD_FILE_TYPE_NOT_MATCH("A0701","用户上传文件类型不匹配"), + */ + USER_UPLOAD_FILE_TYPE_NOT_MATCH("A0701", "用户上传文件类型不匹配"), /** * 一级宏观错误码,系统执行出错 - * */ - SYSTEM_ERROR("B0001","系统执行出错"), + */ + SYSTEM_ERROR("B0001", "系统执行出错"), /** * 二级宏观错误码,系统执行超时 - * */ - SYSTEM_TIMEOUT_ERROR("B0100","系统执行超时"), + */ + SYSTEM_TIMEOUT_ERROR("B0100", "系统执行超时"), /** * 一级宏观错误码,调用第三方服务出错 - * */ - THIRD_SERVICE_ERROR("C0001","调用第三方服务出错"), + */ + THIRD_SERVICE_ERROR("C0001", "调用第三方服务出错"), /** * 一级宏观错误码,中间件服务出错 - * */ - MIDDLEWARE_SERVICE_ERROR("C0100","中间件服务出错") - ; + */ + MIDDLEWARE_SERVICE_ERROR("C0100", "中间件服务出错"); /** * 错误码 - * */ + */ private final String code; /** * 中文描述 - * */ + */ private final String message; } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/exception/CommonExceptionHandler.java b/src/main/java/io/github/xxyopen/novel/core/common/exception/CommonExceptionHandler.java index 7b9e43f..3104c82 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/exception/CommonExceptionHandler.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/exception/CommonExceptionHandler.java @@ -19,28 +19,28 @@ public class CommonExceptionHandler { /** * 处理数据校验异常 - * */ + */ @ExceptionHandler(BindException.class) - public RestResp handlerBindException(BindException e){ - log.error(e.getMessage(),e); + public RestResp handlerBindException(BindException e) { + log.error(e.getMessage(), e); return RestResp.fail(ErrorCodeEnum.USER_REQUEST_PARAM_ERROR); } /** * 处理业务异常 - * */ + */ @ExceptionHandler(BusinessException.class) - public RestResp handlerBusinessException(BusinessException e){ - log.error(e.getMessage(),e); + public RestResp handlerBusinessException(BusinessException e) { + log.error(e.getMessage(), e); return RestResp.fail(e.getErrorCodeEnum()); } /** * 处理系统异常 - * */ + */ @ExceptionHandler(Exception.class) - public RestResp handlerException(Exception e){ - log.error(e.getMessage(),e); + public RestResp handlerException(Exception e) { + log.error(e.getMessage(), e); return RestResp.error(); } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/req/PageReqDto.java b/src/main/java/io/github/xxyopen/novel/core/common/req/PageReqDto.java index b881301..31c92c9 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/req/PageReqDto.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/req/PageReqDto.java @@ -14,20 +14,19 @@ public class PageReqDto { /** * 请求页码,默认第 1 页 - * */ + */ @Parameter(description = "请求页码,默认第 1 页") private int pageNum = 1; /** * 每页大小,默认每页 10 条 - * */ + */ @Parameter(description = "每页大小,默认每页 10 条") private int pageSize = 10; /** - * 是否查询所有,默认不查所有 - * 为 true 时,pageNum 和 pageSize 无效 - * */ + * 是否查询所有,默认不查所有 为 true 时,pageNum 和 pageSize 无效 + */ @Parameter(hidden = true) private boolean fetchAll = false; diff --git a/src/main/java/io/github/xxyopen/novel/core/common/resp/PageRespDto.java b/src/main/java/io/github/xxyopen/novel/core/common/resp/PageRespDto.java index 65c954c..689fe6a 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/resp/PageRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/resp/PageRespDto.java @@ -1,8 +1,7 @@ package io.github.xxyopen.novel.core.common.resp; -import lombok.Getter; - import java.util.List; +import lombok.Getter; /** * 分页响应数据格式封装 @@ -34,8 +33,7 @@ public class PageRespDto { private final List list; /** - * 该构造函数用于通用分页查询的场景 - * 接收普通分页数据和普通集合 + * 该构造函数用于通用分页查询的场景 接收普通分页数据和普通集合 */ public PageRespDto(long pageNum, long pageSize, long total, List list) { this.pageNum = pageNum; @@ -50,7 +48,7 @@ public class PageRespDto { /** * 获取分页数 - * */ + */ public long getPages() { if (this.pageSize == 0L) { return 0L; @@ -59,7 +57,6 @@ public class PageRespDto { if (this.total % this.pageSize != 0L) { ++pages; } - return pages; } } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/util/ImgVerifyCodeUtils.java b/src/main/java/io/github/xxyopen/novel/core/common/util/ImgVerifyCodeUtils.java index 073a3cb..2e230d4 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/util/ImgVerifyCodeUtils.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/util/ImgVerifyCodeUtils.java @@ -1,14 +1,15 @@ package io.github.xxyopen.novel.core.common.util; -import lombok.experimental.UtilityClass; - -import javax.imageio.ImageIO; -import java.awt.*; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Base64; import java.util.Random; +import javax.imageio.ImageIO; +import lombok.experimental.UtilityClass; /** * 图片验证码工具类 @@ -79,7 +80,7 @@ public class ImgVerifyCodeUtils { for (int i = 1; i <= verifyCode.length(); i++) { g.setFont(getFont()); g.setColor(new Color(random.nextInt(101), random.nextInt(111), random - .nextInt(121))); + .nextInt(121))); g.translate(random.nextInt(3), random.nextInt(3)); g.drawString(String.valueOf(verifyCode.charAt(i - 1)), 13 * i, 23); } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/util/IpUtils.java b/src/main/java/io/github/xxyopen/novel/core/common/util/IpUtils.java index 6d5f2f2..0d628c8 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/util/IpUtils.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/util/IpUtils.java @@ -16,6 +16,7 @@ public class IpUtils { /** * 获取真实IP + * * @return 真实IP */ public String getRealIp(HttpServletRequest request) { diff --git a/src/main/java/io/github/xxyopen/novel/core/config/CacheConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/CacheConfig.java index 5493a94..ac6a643 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/CacheConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/CacheConfig.java @@ -2,6 +2,11 @@ package io.github.xxyopen.novel.core.config; import com.github.benmanes.caffeine.cache.Caffeine; import io.github.xxyopen.novel.core.constant.CacheConsts; +import java.time.Duration; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import org.springframework.cache.CacheManager; import org.springframework.cache.caffeine.CaffeineCache; import org.springframework.cache.support.SimpleCacheManager; @@ -13,12 +18,6 @@ import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; -import java.time.Duration; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - /** * 缓存配置类 * @@ -40,7 +39,8 @@ public class CacheConfig { // 类型推断 var 非常适合 for 循环,JDK 10 引入,JDK 11 改进 for (var c : CacheConsts.CacheEnum.values()) { if (c.isLocal()) { - Caffeine caffeine = Caffeine.newBuilder().recordStats().maximumSize(c.getMaxSize()); + Caffeine caffeine = Caffeine.newBuilder().recordStats() + .maximumSize(c.getMaxSize()); if (c.getTtl() > 0) { caffeine.expireAfterWrite(Duration.ofSeconds(c.getTtl())); } @@ -57,26 +57,32 @@ public class CacheConfig { */ @Bean public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory) { - RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter( + connectionFactory); RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig() - .disableCachingNullValues().prefixCacheNameWith(CacheConsts.REDIS_CACHE_PREFIX); + .disableCachingNullValues().prefixCacheNameWith(CacheConsts.REDIS_CACHE_PREFIX); - Map cacheMap = new LinkedHashMap<>(CacheConsts.CacheEnum.values().length); + Map cacheMap = new LinkedHashMap<>( + CacheConsts.CacheEnum.values().length); // 类型推断 var 非常适合 for 循环,JDK 10 引入,JDK 11 改进 for (var c : CacheConsts.CacheEnum.values()) { if (c.isRemote()) { if (c.getTtl() > 0) { - cacheMap.put(c.getName(), RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues() - .prefixCacheNameWith(CacheConsts.REDIS_CACHE_PREFIX).entryTtl(Duration.ofSeconds(c.getTtl()))); + cacheMap.put(c.getName(), + RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues() + .prefixCacheNameWith(CacheConsts.REDIS_CACHE_PREFIX) + .entryTtl(Duration.ofSeconds(c.getTtl()))); } else { - cacheMap.put(c.getName(), RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues() + cacheMap.put(c.getName(), + RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues() .prefixCacheNameWith(CacheConsts.REDIS_CACHE_PREFIX)); } } } - RedisCacheManager redisCacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, cacheMap); + RedisCacheManager redisCacheManager = new RedisCacheManager(redisCacheWriter, + defaultCacheConfig, cacheMap); redisCacheManager.setTransactionAware(true); redisCacheManager.initializeCaches(); return redisCacheManager; diff --git a/src/main/java/io/github/xxyopen/novel/core/config/CorsConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/CorsConfig.java index a31692d..1346aa7 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/CorsConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/CorsConfig.java @@ -37,7 +37,7 @@ public class CorsConfig { UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource(); // 添加映射路径,拦截一切请求 - configurationSource.registerCorsConfiguration("/**",config); + configurationSource.registerCorsConfiguration("/**", config); return new CorsFilter(configurationSource); } diff --git a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java index 0603fe4..df33e09 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java @@ -26,7 +26,7 @@ public class EsConfig { // Create the transport with a Jackson mapper ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper()); + restClient, new JacksonJsonpMapper()); // And create the API client return new ElasticsearchClient(transport); diff --git a/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java index 68136d5..ad85852 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java @@ -18,7 +18,7 @@ public class RedissonConfig { @Bean @SneakyThrows - public RedissonClient redissonClient(){ + public RedissonClient redissonClient() { Config config = Config.fromYAML(getClass().getResource("/redisson.yml")); return Redisson.create(config); } diff --git a/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java index a456df2..e01823d 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/WebConfig.java @@ -12,9 +12,8 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** - * Spring Web Mvc 相关配置 - * 不要加 @EnableWebMvc 注解,否则会导致 jackson 的全局配置失效 - * 类上添加 @EnableWebMvc 会导致 WebMvcAutoConfiguration 中的自动配置全部失效 + * Spring Web Mvc 相关配置不要加 @EnableWebMvc 注解,否则会导致 jackson 的全局配置失效。因为 @EnableWebMvc 注解会导致 + * WebMvcAutoConfiguration 自动配置失效 * * @author xiongxiaoyang * @date 2022/5/18 @@ -36,33 +35,33 @@ public class WebConfig implements WebMvcConfigurer { // 流量限制拦截器 registry.addInterceptor(flowLimitInterceptor) - .addPathPatterns("/**") - .order(0); + .addPathPatterns("/**") + .order(0); // 文件访问拦截 registry.addInterceptor(fileInterceptor) - .addPathPatterns(SystemConfigConsts.IMAGE_UPLOAD_DIRECTORY + "**") - .order(1); + .addPathPatterns(SystemConfigConsts.IMAGE_UPLOAD_DIRECTORY + "**") + .order(1); // 权限认证拦截 registry.addInterceptor(authInterceptor) - // 拦截会员中心相关请求接口 - .addPathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/**", - // 拦截作家后台相关请求接口 - ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/**", - // 拦截平台后台相关请求接口 - ApiRouterConsts.API_ADMIN_URL_PREFIX + "/**") - // 放行登录注册相关请求接口 - .excludePathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/register", - ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/login", - ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login") - .order(2); + // 拦截会员中心相关请求接口 + .addPathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/**", + // 拦截作家后台相关请求接口 + ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/**", + // 拦截平台后台相关请求接口 + ApiRouterConsts.API_ADMIN_URL_PREFIX + "/**") + // 放行登录注册相关请求接口 + .excludePathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/register", + ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/login", + ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login") + .order(2); // Token 解析拦截器 registry.addInterceptor(tokenParseInterceptor) - // 拦截小说内容查询接口,需要解析 token 以判断该用户是否有权阅读该章节(付费章节是否已购买) - .addPathPatterns(ApiRouterConsts.API_FRONT_BOOK_URL_PREFIX + "/content/*") - .order(3); + // 拦截小说内容查询接口,需要解析 token 以判断该用户是否有权阅读该章节(付费章节是否已购买) + .addPathPatterns(ApiRouterConsts.API_FRONT_BOOK_URL_PREFIX + "/content/*") + .order(3); } } diff --git a/src/main/java/io/github/xxyopen/novel/core/config/XssProperties.java b/src/main/java/io/github/xxyopen/novel/core/config/XssProperties.java index 58a1317..e6d814e 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/XssProperties.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/XssProperties.java @@ -1,8 +1,7 @@ package io.github.xxyopen.novel.core.config; -import org.springframework.boot.context.properties.ConfigurationProperties; - import java.util.List; +import org.springframework.boot.context.properties.ConfigurationProperties; /** * Xss 过滤配置属性 @@ -11,6 +10,6 @@ import java.util.List; * @date 2022/5/17 */ @ConfigurationProperties(prefix = "novel.xss") -public record XssProperties(Boolean enabled,List excludes) { +public record XssProperties(Boolean enabled, List excludes) { } diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/AmqpConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/AmqpConsts.java index 7292bda..7ccf861 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/AmqpConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/AmqpConsts.java @@ -10,22 +10,22 @@ public class AmqpConsts { /** * 小说信息改变 MQ - * */ - public static class BookChangeMq{ + */ + public static class BookChangeMq { /** * 小说信息改变交换机 - * */ + */ public static final String EXCHANGE_NAME = "EXCHANGE-BOOK-CHANGE"; /** * Elasticsearch book 索引更新的队列 - * */ + */ public static final String QUEUE_ES_UPDATE = "QUEUE-ES-BOOK-UPDATE"; /** * Redis book 缓存更新的队列 - * */ + */ public static final String QUEUE_REDIS_UPDATE = "QUEUE-REDIS-BOOK-UPDATE"; } diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/ApiRouterConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/ApiRouterConsts.java index 621cdcf..4a62610 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/ApiRouterConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/ApiRouterConsts.java @@ -34,32 +34,32 @@ public class ApiRouterConsts { /** * 首页模块请求路径前缀 - * */ + */ public static final String HOME_URL_PREFIX = "/home"; /** * 首页模块请求路径前缀 - * */ + */ public static final String NEWS_URL_PREFIX = "/news"; /** * 小说模块请求路径前缀 - * */ + */ public static final String BOOK_URL_PREFIX = "/book"; /** * 会员模块请求路径前缀 - * */ + */ public static final String USER_URL_PREFIX = "/user"; /** * 资源(图片/视频/文档)模块请求路径前缀 - * */ + */ public static final String RESOURCE_URL_PREFIX = "/resource"; /** * 搜索模块请求路径前缀 - * */ + */ public static final String SEARCH_URL_PREFIX = "/search"; /** @@ -85,11 +85,13 @@ public class ApiRouterConsts { /** * 前台门户资源(图片/视频/文档)相关API请求路径前缀 */ - public static final String API_FRONT_RESOURCE_URL_PREFIX = API_FRONT_URL_PREFIX + RESOURCE_URL_PREFIX; + public static final String API_FRONT_RESOURCE_URL_PREFIX = + API_FRONT_URL_PREFIX + RESOURCE_URL_PREFIX; /** * 前台门户搜索相关API请求路径前缀 - * */ - public static final String API_FRONT_SEARCH_URL_PREFIX = API_FRONT_URL_PREFIX + SEARCH_URL_PREFIX; + */ + public static final String API_FRONT_SEARCH_URL_PREFIX = + API_FRONT_URL_PREFIX + SEARCH_URL_PREFIX; } diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/CacheConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/CacheConsts.java index d7eabd4..f5164c9 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/CacheConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/CacheConsts.java @@ -56,7 +56,7 @@ public class CacheConsts { /** * 小说分类列表缓存 - * */ + */ public static final String BOOK_CATEGORY_LIST_CACHE_NAME = "bookCategoryListCache"; /** @@ -76,13 +76,14 @@ public class CacheConsts { /** * 最近更新小说ID列表缓存 - * */ + */ public static final String LAST_UPDATE_BOOK_ID_LIST_CACHE_NAME = "lastUpdateBookIdListCache"; /** * 图片验证码缓存 KEY - * */ - public static final String IMG_VERIFY_CODE_CACHE_KEY = REDIS_CACHE_PREFIX + "imgVerifyCodeCache::"; + */ + public static final String IMG_VERIFY_CODE_CACHE_KEY = + REDIS_CACHE_PREFIX + "imgVerifyCodeCache::"; /** * 用户信息缓存 @@ -111,19 +112,19 @@ public class CacheConsts { HOME_FRIEND_LINK_CACHE(2, HOME_FRIEND_LINK_CACHE_NAME, 0, 1), - BOOK_CATEGORY_LIST_CACHE(0,BOOK_CATEGORY_LIST_CACHE_NAME,0,2), + BOOK_CATEGORY_LIST_CACHE(0, BOOK_CATEGORY_LIST_CACHE_NAME, 0, 2), 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_CHAPTER_CACHE(0, BOOK_CHAPTER_CACHE_NAME, 60 * 60 * 6, 5000), BOOK_CONTENT_CACHE(2, BOOK_CONTENT_CACHE_NAME, 60 * 60 * 12, 3000), - LAST_UPDATE_BOOK_ID_LIST_CACHE(0,LAST_UPDATE_BOOK_ID_LIST_CACHE_NAME,60 * 60, 10), + LAST_UPDATE_BOOK_ID_LIST_CACHE(0, LAST_UPDATE_BOOK_ID_LIST_CACHE_NAME, 60 * 60, 10), - USER_INFO_CACHE(2,USER_INFO_CACHE_NAME,60 * 60 * 24, 10000), + USER_INFO_CACHE(2, USER_INFO_CACHE_NAME, 60 * 60 * 24, 10000), - AUTHOR_INFO_CACHE(2,AUTHOR_INFO_CACHE_NAME,60 * 60 * 48, 1000); + AUTHOR_INFO_CACHE(2, AUTHOR_INFO_CACHE_NAME, 60 * 60 * 48, 1000); /** * 缓存类型 0-本地 1-本地和远程 2-远程 diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java index 01b0e63..32c89f4 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/DatabaseConsts.java @@ -10,7 +10,6 @@ import lombok.Getter; */ public class DatabaseConsts { - /** * 用户信息表 */ diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/EsConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/EsConsts.java index 5527098..da8c52d 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/EsConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/EsConsts.java @@ -14,8 +14,8 @@ public class EsConsts { /** * 小说索引 - * */ - public static class BookIndex{ + */ + public static class BookIndex { private BookIndex() { throw new IllegalStateException(SystemConfigConsts.CONST_INSTANCE_EXCEPTION_MSG); @@ -23,18 +23,18 @@ public class EsConsts { /** * 索引名 - * */ + */ public static final String INDEX_NAME = "book"; /** * id */ - public static final String FIELD_ID = "id"; + public static final String FIELD_ID = "id"; /** * 作品方向;0-男频 1-女频 */ - public static final String FIELD_WORK_DIRECTION = "workDirection"; + public static final String FIELD_WORK_DIRECTION = "workDirection"; /** * 类别ID @@ -110,7 +110,7 @@ public class EsConsts { * 是否收费;1-收费 0-免费 */ public static final String FIELD_IS_VIP = "isVip"; - + } } diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/SystemConfigConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/SystemConfigConsts.java index 3d7b94d..858aefa 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/SystemConfigConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/SystemConfigConsts.java @@ -14,32 +14,32 @@ public class SystemConfigConsts { /** * Http 请求认证 Header - * */ + */ public static final String HTTP_AUTH_HEADER_NAME = "Authorization"; /** * 前台门户系统标识 - * */ + */ public static final String NOVEL_FRONT_KEY = "front"; /** * 作家管理系统标识 - * */ + */ public static final String NOVEL_AUTHOR_KEY = "author"; /** * 后台管理系统标识 - * */ + */ public static final String NOVEL_ADMIN_KEY = "admin"; /** * 图片上传目录 - * */ + */ public static final String IMAGE_UPLOAD_DIRECTORY = "/image/"; /** * 常量类实例化异常信息 - * */ + */ public static final String CONST_INSTANCE_EXCEPTION_MSG = "Constant class"; } diff --git a/src/main/java/io/github/xxyopen/novel/core/filter/XssFilter.java b/src/main/java/io/github/xxyopen/novel/core/filter/XssFilter.java index 17a7b5b..709cab6 100644 --- a/src/main/java/io/github/xxyopen/novel/core/filter/XssFilter.java +++ b/src/main/java/io/github/xxyopen/novel/core/filter/XssFilter.java @@ -3,18 +3,22 @@ package io.github.xxyopen.novel.core.filter; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import io.github.xxyopen.novel.core.config.XssProperties; import io.github.xxyopen.novel.core.wrapper.XssHttpServletRequestWrapper; -import jakarta.servlet.*; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import jakarta.servlet.annotation.WebFilter; import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.stereotype.Component; -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * 防止 XSS 攻击的过滤器 * @@ -22,13 +26,12 @@ import java.util.regex.Pattern; * @date 2022/5/17 */ @Component -@ConditionalOnProperty(value = "novel.xss.enabled",havingValue = "true") +@ConditionalOnProperty(value = "novel.xss.enabled", havingValue = "true") @WebFilter(urlPatterns = "/*", filterName = "xssFilter") @EnableConfigurationProperties(value = {XssProperties.class}) @RequiredArgsConstructor public class XssFilter implements Filter { - private final XssProperties xssProperties; @Override @@ -37,13 +40,15 @@ public class XssFilter implements Filter { } @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, + FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) servletRequest; if (handleExcludeUrl(req)) { filterChain.doFilter(servletRequest, servletResponse); return; } - XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest); + XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper( + (HttpServletRequest) servletRequest); filterChain.doFilter(xssRequest, servletResponse); } diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java index 79b5566..e604cfb 100644 --- a/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java @@ -9,18 +9,16 @@ import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.nio.charset.StandardCharsets; +import java.util.Map; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; -import java.nio.charset.StandardCharsets; -import java.util.Map; - /** - * 认证 拦截器 - * 为了注入其它的 Spring beans,需要通过 @Component 注解将该拦截器注册到 Spring 上下文 + * 认证 拦截器:为了注入其它的 Spring beans,需要通过 @Component 注解将该拦截器注册到 Spring 上下文 * * @author xiongxiaoyang * @date 2022/5/18 @@ -29,13 +27,14 @@ import java.util.Map; @RequiredArgsConstructor public class AuthInterceptor implements HandlerInterceptor { - private final Map authStrategy; + private final Map authStrategy; private final ObjectMapper objectMapper; @SuppressWarnings("NullableProblems") @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { // 获取登录 JWT String token = request.getHeader(SystemConfigConsts.HTTP_AUTH_HEADER_NAME); @@ -44,25 +43,27 @@ public class AuthInterceptor implements HandlerInterceptor { // 根据请求的 URI 得到认证策略 String subUri = requestUri.substring(ApiRouterConsts.API_URL_PREFIX.length() + 1); - String systemName = subUri.substring(0,subUri.indexOf("/")); - String authStrategyName = String.format("%sAuthStrategy",systemName); + String systemName = subUri.substring(0, subUri.indexOf("/")); + String authStrategyName = String.format("%sAuthStrategy", systemName); // 开始认证 try { - authStrategy.get(authStrategyName).auth(token,requestUri); + authStrategy.get(authStrategyName).auth(token, requestUri); return HandlerInterceptor.super.preHandle(request, response, handler); - }catch (BusinessException exception){ + } catch (BusinessException exception) { // 认证失败 response.setCharacterEncoding(StandardCharsets.UTF_8.name()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); - response.getWriter().write(objectMapper.writeValueAsString(RestResp.fail(exception.getErrorCodeEnum()))); + response.getWriter().write( + objectMapper.writeValueAsString(RestResp.fail(exception.getErrorCodeEnum()))); return false; } } @SuppressWarnings("NullableProblems") @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { // 清理当前线程保存的用户数据 UserHolder.clear(); HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/FileInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/FileInterceptor.java index 5121950..e7317bb 100644 --- a/src/main/java/io/github/xxyopen/novel/core/interceptor/FileInterceptor.java +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/FileInterceptor.java @@ -2,15 +2,14 @@ package io.github.xxyopen.novel.core.interceptor; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.OutputStream; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.OutputStream; - /** * 文件 拦截器 * @@ -26,12 +25,14 @@ public class FileInterceptor implements HandlerInterceptor { @SuppressWarnings("NullableProblems") @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { // 获取请求的 URI String requestUri = request.getRequestURI(); // 缓存10天 response.setDateHeader("expires", System.currentTimeMillis() + 60 * 60 * 24 * 10 * 1000); - try (OutputStream out = response.getOutputStream(); InputStream input = new FileInputStream(fileUploadPath + requestUri)) { + try (OutputStream out = response.getOutputStream(); InputStream input = new FileInputStream( + fileUploadPath + requestUri)) { byte[] b = new byte[4096]; for (int n; (n = input.read(b)) != -1; ) { out.write(b, 0, n); diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java index 0ca5ee2..7afe872 100644 --- a/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/FlowLimitInterceptor.java @@ -15,20 +15,18 @@ import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.common.util.IpUtils; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - /** - * 流量限制 拦截器 - * 实现接口防刷和限流 + * 流量限制 拦截器:实现接口防刷和限流 * * @author xiongxiaoyang * @date 2022/6/1 @@ -59,18 +57,19 @@ public class FlowLimitInterceptor implements HandlerInterceptor { // 接口防刷规则 1:所有的请求,限制每个 IP 每秒最多只能通过 50 个,超出限制直接拒绝 ParamFlowRule rule2 = new ParamFlowRule(NOVEL_RESOURCE) - .setParamIdx(0) - .setCount(50); + .setParamIdx(0) + .setCount(50); // 接口防刷规则 2:所有的请求,限制每个 IP 每分钟最多只能通过 1000 个,超出限制直接拒绝 ParamFlowRule rule3 = new ParamFlowRule(NOVEL_RESOURCE) - .setParamIdx(0) - .setCount(1000) - .setDurationInSec(60); + .setParamIdx(0) + .setCount(1000) + .setDurationInSec(60); ParamFlowRuleManager.loadRules(Arrays.asList(rule2, rule3)); } @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { String ip = IpUtils.getRealIp(request); Entry entry = null; try { @@ -85,7 +84,8 @@ public class FlowLimitInterceptor implements HandlerInterceptor { log.info("IP:{}被限流了!", ip); response.setCharacterEncoding(StandardCharsets.UTF_8.name()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); - response.getWriter().write(objectMapper.writeValueAsString(RestResp.fail(ErrorCodeEnum.USER_REQ_MANY))); + response.getWriter() + .write(objectMapper.writeValueAsString(RestResp.fail(ErrorCodeEnum.USER_REQ_MANY))); } finally { // 注意:exit 的时候也一定要带上对应的参数,否则可能会有统计错误。 if (entry != null) { diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java index 15514cf..6bf6851 100644 --- a/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java @@ -24,7 +24,8 @@ public class TokenParseInterceptor implements HandlerInterceptor { private final JwtUtils jwtUtils; @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { // 获取登录 JWT String token = request.getHeader(SystemConfigConsts.HTTP_AUTH_HEADER_NAME); if (StringUtils.hasText(token)) { @@ -35,7 +36,8 @@ public class TokenParseInterceptor implements HandlerInterceptor { } @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { // 清理当前线程保存的用户数据 UserHolder.clear(); HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); diff --git a/src/main/java/io/github/xxyopen/novel/core/json/deserializer/GlobalJsonDeserializer.java b/src/main/java/io/github/xxyopen/novel/core/json/deserializer/GlobalJsonDeserializer.java index b20d046..83476c8 100644 --- a/src/main/java/io/github/xxyopen/novel/core/json/deserializer/GlobalJsonDeserializer.java +++ b/src/main/java/io/github/xxyopen/novel/core/json/deserializer/GlobalJsonDeserializer.java @@ -3,9 +3,8 @@ package io.github.xxyopen.novel.core.json.deserializer; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; -import org.springframework.boot.jackson.JsonComponent; - import java.io.IOException; +import org.springframework.boot.jackson.JsonComponent; /** @@ -18,16 +17,16 @@ import java.io.IOException; public class GlobalJsonDeserializer { /** - * 字符串反序列化器 - * 过滤特殊字符,解决 XSS 攻击 + * 字符串反序列化器:过滤特殊字符,解决 XSS 攻击 */ public static class StringDeserializer extends JsonDeserializer { @Override - public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + public String deserialize(JsonParser jsonParser, + DeserializationContext deserializationContext) throws IOException { return jsonParser.getValueAsString() - .replace("<", "<") - .replace(">", ">"); + .replace("<", "<") + .replace(">", ">"); } } } diff --git a/src/main/java/io/github/xxyopen/novel/core/json/serializer/UsernameSerializer.java b/src/main/java/io/github/xxyopen/novel/core/json/serializer/UsernameSerializer.java index e2a1a9a..d14c25a 100644 --- a/src/main/java/io/github/xxyopen/novel/core/json/serializer/UsernameSerializer.java +++ b/src/main/java/io/github/xxyopen/novel/core/json/serializer/UsernameSerializer.java @@ -3,7 +3,6 @@ package io.github.xxyopen.novel.core.json.serializer; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; - import java.io.IOException; /** @@ -15,8 +14,9 @@ import java.io.IOException; public class UsernameSerializer extends JsonSerializer { @Override - public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { - jsonGenerator.writeString(s.substring(0,4) + "****" + s.substring(8)); + public void serialize(String s, JsonGenerator jsonGenerator, + SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeString(s.substring(0, 4) + "****" + s.substring(8)); } } diff --git a/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java b/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java index 1d0971f..49bb16c 100644 --- a/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java +++ b/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java @@ -21,7 +21,8 @@ import org.springframework.stereotype.Component; * @date 2022/5/25 */ @Component -@ConditionalOnProperty(prefix = "spring", name = {"elasticsearch.enable","amqp.enable"}, havingValue = "true") +@ConditionalOnProperty(prefix = "spring", name = {"elasticsearch.enable", + "amqp.enable"}, havingValue = "true") @RequiredArgsConstructor @Slf4j public class RabbitQueueListener { @@ -32,15 +33,15 @@ public class RabbitQueueListener { /** * 监听小说信息改变的 ES 更新队列,更新最新小说信息到 ES - * */ + */ @RabbitListener(queues = AmqpConsts.BookChangeMq.QUEUE_ES_UPDATE) @SneakyThrows public void updateEsBook(Long bookId) { BookInfo bookInfo = bookInfoMapper.selectById(bookId); IndexResponse response = esClient.index(i -> i - .index(EsConsts.BookIndex.INDEX_NAME) - .id(bookInfo.getId().toString()) - .document(EsBookDto.build(bookInfo)) + .index(EsConsts.BookIndex.INDEX_NAME) + .id(bookInfo.getId().toString()) + .document(EsBookDto.build(bookInfo)) ); log.info("Indexed with version " + response.version()); } diff --git a/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java b/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java index 69704c5..b597e21 100644 --- a/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java +++ b/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java @@ -13,14 +13,13 @@ import io.github.xxyopen.novel.core.constant.EsConsts; import io.github.xxyopen.novel.dao.entity.BookInfo; import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.es.EsBookDto; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; -import java.util.List; - /** * 小说数据同步到 elasticsearch 任务 * @@ -51,10 +50,10 @@ public class BookToEsTask { for (; ; ) { queryWrapper.clear(); queryWrapper - .orderByAsc(DatabaseConsts.CommonColumnEnum.ID.getName()) - .gt(DatabaseConsts.CommonColumnEnum.ID.getName(), maxId) - .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT, 0) - .last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); + .orderByAsc(DatabaseConsts.CommonColumnEnum.ID.getName()) + .gt(DatabaseConsts.CommonColumnEnum.ID.getName(), maxId) + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT, 0) + .last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); bookInfos = bookInfoMapper.selectList(queryWrapper); if (bookInfos.isEmpty()) { break; @@ -63,11 +62,11 @@ public class BookToEsTask { for (BookInfo book : bookInfos) { br.operations(op -> op - .index(idx -> idx - .index(EsConsts.BookIndex.INDEX_NAME) - .id(book.getId().toString()) - .document(EsBookDto.build(book)) - ) + .index(idx -> idx + .index(EsConsts.BookIndex.INDEX_NAME) + .id(book.getId().toString()) + .document(EsBookDto.build(book)) + ) ).timeout(Time.of(t -> t.time("10s"))); maxId = book.getId(); } diff --git a/src/main/java/io/github/xxyopen/novel/core/util/JwtUtils.java b/src/main/java/io/github/xxyopen/novel/core/util/JwtUtils.java index 723d889..470eef7 100644 --- a/src/main/java/io/github/xxyopen/novel/core/util/JwtUtils.java +++ b/src/main/java/io/github/xxyopen/novel/core/util/JwtUtils.java @@ -5,14 +5,13 @@ import io.jsonwebtoken.Jws; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; +import java.nio.charset.StandardCharsets; +import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; -import java.nio.charset.StandardCharsets; -import java.util.Objects; - /** * JWT 工具类 * @@ -37,21 +36,23 @@ public class JwtUtils { /** * 根据用户ID生成JWT - * @param uid 用户ID + * + * @param uid 用户ID * @param systemKey 系统标识 * @return JWT */ public String generateToken(Long uid, String systemKey) { return Jwts.builder() - .setHeaderParam(HEADER_SYSTEM_KEY, systemKey) - .setSubject(uid.toString()) - .signWith(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8))) - .compact(); + .setHeaderParam(HEADER_SYSTEM_KEY, systemKey) + .setSubject(uid.toString()) + .signWith(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8))) + .compact(); } /** * 解析JWT返回用户ID - * @param token JWT + * + * @param token JWT * @param systemKey 系统标识 * @return 用户ID */ @@ -59,9 +60,9 @@ public class JwtUtils { Jws claimsJws; try { claimsJws = Jwts.parserBuilder() - .setSigningKey(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8))) - .build() - .parseClaimsJws(token); + .setSigningKey(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8))) + .build() + .parseClaimsJws(token); // OK, we can trust this JWT // 判断该 JWT 是否属于指定系统 if (Objects.equals(claimsJws.getHeader().get(HEADER_SYSTEM_KEY), systemKey)) { diff --git a/src/main/java/io/github/xxyopen/novel/core/wrapper/XssHttpServletRequestWrapper.java b/src/main/java/io/github/xxyopen/novel/core/wrapper/XssHttpServletRequestWrapper.java index c96d94b..f743cb8 100644 --- a/src/main/java/io/github/xxyopen/novel/core/wrapper/XssHttpServletRequestWrapper.java +++ b/src/main/java/io/github/xxyopen/novel/core/wrapper/XssHttpServletRequestWrapper.java @@ -2,7 +2,6 @@ package io.github.xxyopen.novel.core.wrapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; - import java.util.HashMap; import java.util.Map; @@ -14,7 +13,7 @@ import java.util.Map; */ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { - private static final Map REPLACE_RULE = new HashMap<>(); + private static final Map REPLACE_RULE = new HashMap<>(); static { REPLACE_RULE.put("<", "<"); @@ -34,7 +33,8 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { for (int i = 0; i < length; i++) { escapeValues[i] = values[i]; int index = i; - REPLACE_RULE.forEach((k, v)-> escapeValues[index] = escapeValues[index].replaceAll(k, v)); + REPLACE_RULE.forEach( + (k, v) -> escapeValues[index] = escapeValues[index].replaceAll(k, v)); } return escapeValues; } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/AuthorInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/AuthorInfoCacheManager.java index 7aeb1cb..f9ed88f 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/AuthorInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/AuthorInfoCacheManager.java @@ -6,13 +6,12 @@ import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.dao.entity.AuthorInfo; import io.github.xxyopen.novel.dao.mapper.AuthorInfoMapper; import io.github.xxyopen.novel.dto.AuthorInfoDto; +import java.util.Objects; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; -import java.util.Objects; - /** * 作家信息 缓存管理类 * @@ -29,24 +28,24 @@ public class AuthorInfoCacheManager { * 查询作家信息,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, - value = CacheConsts.AUTHOR_INFO_CACHE_NAME, unless = "#result == null") + value = CacheConsts.AUTHOR_INFO_CACHE_NAME, unless = "#result == null") public AuthorInfoDto getAuthor(Long userId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper - .eq(DatabaseConsts.AuthorInfoTable.COLUMN_USER_ID, userId) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .eq(DatabaseConsts.AuthorInfoTable.COLUMN_USER_ID, userId) + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); AuthorInfo authorInfo = authorInfoMapper.selectOne(queryWrapper); if (Objects.isNull(authorInfo)) { return null; } return AuthorInfoDto.builder() - .id(authorInfo.getId()) - .penName(authorInfo.getPenName()) - .status(authorInfo.getStatus()).build(); + .id(authorInfo.getId()) + .penName(authorInfo.getPenName()) + .status(authorInfo.getStatus()).build(); } @CacheEvict(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, - value = CacheConsts.AUTHOR_INFO_CACHE_NAME) + value = CacheConsts.AUTHOR_INFO_CACHE_NAME) public void evictAuthorCache() { // 调用此方法自动清除作家信息的缓存 } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookCategoryCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookCategoryCacheManager.java index 817b8fe..077f216 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookCategoryCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookCategoryCacheManager.java @@ -6,12 +6,11 @@ import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.dao.entity.BookCategory; import io.github.xxyopen.novel.dao.mapper.BookCategoryMapper; import io.github.xxyopen.novel.dto.resp.BookCategoryRespDto; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; -import java.util.List; - /** * 小说分类 缓存管理类 * @@ -28,15 +27,15 @@ public class BookCategoryCacheManager { * 根据作品方向查询小说分类列表,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.BOOK_CATEGORY_LIST_CACHE_NAME) + value = CacheConsts.BOOK_CATEGORY_LIST_CACHE_NAME) public List listCategory(Integer workDirection) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookCategoryTable.COLUMN_WORK_DIRECTION, workDirection); return bookCategoryMapper.selectList(queryWrapper).stream().map(v -> - BookCategoryRespDto.builder() - .id(v.getId()) - .name(v.getName()) - .build()).toList(); + BookCategoryRespDto.builder() + .id(v.getId()) + .name(v.getName()) + .build()).toList(); } } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java index 83a0665..83aa618 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java @@ -24,17 +24,17 @@ public class BookChapterCacheManager { * 查询小说章节信息,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.BOOK_CHAPTER_CACHE_NAME) + value = CacheConsts.BOOK_CHAPTER_CACHE_NAME) public BookChapterRespDto getChapter(Long chapterId) { BookChapter bookChapter = bookChapterMapper.selectById(chapterId); return BookChapterRespDto.builder() - .id(chapterId) - .bookId(bookChapter.getBookId()) - .chapterNum(bookChapter.getChapterNum()) - .chapterName(bookChapter.getChapterName()) - .chapterWordCount(bookChapter.getWordCount()) - .chapterUpdateTime(bookChapter.getUpdateTime()) - .build(); + .id(chapterId) + .bookId(bookChapter.getBookId()) + .chapterNum(bookChapter.getChapterNum()) + .chapterName(bookChapter.getChapterName()) + .chapterWordCount(bookChapter.getWordCount()) + .chapterUpdateTime(bookChapter.getUpdateTime()) + .build(); } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java index 3f8fa50..c250ff3 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java @@ -25,11 +25,11 @@ public class BookContentCacheManager { * 查询小说内容,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, - value = CacheConsts.BOOK_CONTENT_CACHE_NAME) + value = CacheConsts.BOOK_CONTENT_CACHE_NAME) public String getBookContent(Long chapterId) { QueryWrapper contentQueryWrapper = new QueryWrapper<>(); contentQueryWrapper.eq(DatabaseConsts.BookContentTable.COLUMN_CHAPTER_ID, chapterId) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); BookContent bookContent = bookContentMapper.selectOne(contentQueryWrapper); return bookContent.getContent(); } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java index 18dfc9a..9aeb63a 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java @@ -8,14 +8,13 @@ import io.github.xxyopen.novel.dao.entity.BookInfo; import io.github.xxyopen.novel.dao.mapper.BookChapterMapper; import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; -import java.util.List; - /** * 小说信息 缓存管理类 * @@ -33,8 +32,9 @@ public class BookInfoCacheManager { /** * 从缓存中查询小说信息(先判断缓存中是否已存在,存在则直接从缓存中取,否则执行方法体中的逻辑后缓存结果) */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.BOOK_INFO_CACHE_NAME) + @Cacheable( + cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_INFO_CACHE_NAME) public BookInfoRespDto getBookInfo(Long id) { return cachePutBookInfo(id); } @@ -42,39 +42,41 @@ public class BookInfoCacheManager { /** * 缓存小说信息(不管缓存中是否存在都执行方法体中的逻辑,然后缓存起来) */ - @CachePut(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.BOOK_INFO_CACHE_NAME) + @CachePut( + cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_INFO_CACHE_NAME) public BookInfoRespDto cachePutBookInfo(Long id) { // 查询基础信息 BookInfo bookInfo = bookInfoMapper.selectById(id); // 查询首章ID QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper - .eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, id) - .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, id) + .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); BookChapter firstBookChapter = bookChapterMapper.selectOne(queryWrapper); // 组装响应对象 return BookInfoRespDto.builder() - .id(bookInfo.getId()) - .bookName(bookInfo.getBookName()) - .bookDesc(bookInfo.getBookDesc()) - .bookStatus(bookInfo.getBookStatus()) - .authorId(bookInfo.getAuthorId()) - .authorName(bookInfo.getAuthorName()) - .categoryId(bookInfo.getCategoryId()) - .categoryName(bookInfo.getCategoryName()) - .commentCount(bookInfo.getCommentCount()) - .firstChapterId(firstBookChapter.getId()) - .lastChapterId(bookInfo.getLastChapterId()) - .picUrl(bookInfo.getPicUrl()) - .visitCount(bookInfo.getVisitCount()) - .wordCount(bookInfo.getWordCount()) - .build(); + .id(bookInfo.getId()) + .bookName(bookInfo.getBookName()) + .bookDesc(bookInfo.getBookDesc()) + .bookStatus(bookInfo.getBookStatus()) + .authorId(bookInfo.getAuthorId()) + .authorName(bookInfo.getAuthorName()) + .categoryId(bookInfo.getCategoryId()) + .categoryName(bookInfo.getCategoryName()) + .commentCount(bookInfo.getCommentCount()) + .firstChapterId(firstBookChapter.getId()) + .lastChapterId(bookInfo.getLastChapterId()) + .picUrl(bookInfo.getPicUrl()) + .visitCount(bookInfo.getVisitCount()) + .wordCount(bookInfo.getWordCount()) + .build(); } - @CacheEvict(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.BOOK_INFO_CACHE_NAME) + @CacheEvict( + cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_INFO_CACHE_NAME) public void evictBookInfoCache(Long ignoredId) { // 调用此方法自动清除小说信息的缓存 } @@ -82,15 +84,16 @@ public class BookInfoCacheManager { /** * 查询每个类别下最新更新的 500 个小说ID列表,并放入缓存中 1 个小时 */ - @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.LAST_UPDATE_BOOK_ID_LIST_CACHE_NAME) + @Cacheable( + cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.LAST_UPDATE_BOOK_ID_LIST_CACHE_NAME) public List getLastUpdateIdList(Long categoryId) { QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq(DatabaseConsts.BookTable.COLUMN_CATEGORY_ID, categoryId) - .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT,0) - .orderByDesc(DatabaseConsts.BookTable.COLUMN_LAST_CHAPTER_UPDATE_TIME) - .last(DatabaseConsts.SqlEnum.LIMIT_500.getSql()); + queryWrapper + .eq(DatabaseConsts.BookTable.COLUMN_CATEGORY_ID, categoryId) + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT, 0) + .orderByDesc(DatabaseConsts.BookTable.COLUMN_LAST_CHAPTER_UPDATE_TIME) + .last(DatabaseConsts.SqlEnum.LIMIT_500.getSql()); return bookInfoMapper.selectList(queryWrapper).stream().map(BookInfo::getId).toList(); } - } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java index 6f28752..f019079 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookRankCacheManager.java @@ -6,12 +6,11 @@ import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.dao.entity.BookInfo; import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.resp.BookRankRespDto; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; -import java.util.List; - /** * 小说排行榜 缓存管理类 * @@ -28,7 +27,7 @@ public class BookRankCacheManager { * 查询小说点击榜列表,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, - value = CacheConsts.BOOK_VISIT_RANK_CACHE_NAME) + value = CacheConsts.BOOK_VISIT_RANK_CACHE_NAME) public List listVisitRankBooks() { QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); bookInfoQueryWrapper.orderByDesc(DatabaseConsts.BookTable.COLUMN_VISIT_COUNT); @@ -39,12 +38,12 @@ public class BookRankCacheManager { * 查询小说新书榜列表,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.BOOK_NEWEST_RANK_CACHE_NAME) + value = CacheConsts.BOOK_NEWEST_RANK_CACHE_NAME) public List listNewestRankBooks() { QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); bookInfoQueryWrapper - .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT,0) - .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()); + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT, 0) + .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()); return listRankBooks(bookInfoQueryWrapper); } @@ -52,19 +51,19 @@ public class BookRankCacheManager { * 查询小说更新榜列表,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.BOOK_UPDATE_RANK_CACHE_NAME) + value = CacheConsts.BOOK_UPDATE_RANK_CACHE_NAME) public List listUpdateRankBooks() { QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); bookInfoQueryWrapper - .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT,0) - .orderByDesc(DatabaseConsts.CommonColumnEnum.UPDATE_TIME.getName()); + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT, 0) + .orderByDesc(DatabaseConsts.CommonColumnEnum.UPDATE_TIME.getName()); return listRankBooks(bookInfoQueryWrapper); } private List listRankBooks(QueryWrapper bookInfoQueryWrapper) { bookInfoQueryWrapper - .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT,0) - .last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); + .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT, 0) + .last(DatabaseConsts.SqlEnum.LIMIT_30.getSql()); return bookInfoMapper.selectList(bookInfoQueryWrapper).stream().map(v -> { BookRankRespDto respDto = new BookRankRespDto(); respDto.setId(v.getId()); diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/FriendLinkCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/FriendLinkCacheManager.java index d0eba3c..23f4488 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/FriendLinkCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/FriendLinkCacheManager.java @@ -6,12 +6,11 @@ import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.dao.entity.HomeFriendLink; import io.github.xxyopen.novel.dao.mapper.HomeFriendLinkMapper; import io.github.xxyopen.novel.dto.resp.HomeFriendLinkRespDto; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; -import java.util.List; - /** * 友情链接 缓存管理类 * @@ -28,7 +27,7 @@ public class FriendLinkCacheManager { * 友情链接列表查询,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, - value = CacheConsts.HOME_FRIEND_LINK_CACHE_NAME) + value = CacheConsts.HOME_FRIEND_LINK_CACHE_NAME) public List listFriendLinks() { // 从友情链接表中查询出友情链接列表 QueryWrapper queryWrapper = new QueryWrapper<>(); diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/HomeBookCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/HomeBookCacheManager.java index 5e648f8..7344ec7 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/HomeBookCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/HomeBookCacheManager.java @@ -8,16 +8,15 @@ import io.github.xxyopen.novel.dao.entity.HomeBook; import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dao.mapper.HomeBookMapper; import io.github.xxyopen.novel.dto.resp.HomeBookRespDto; -import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; - import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; /** * 首页推荐小说 缓存管理类 @@ -37,7 +36,7 @@ public class HomeBookCacheManager { * 查询首页小说推荐,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.HOME_BOOK_CACHE_NAME) + value = CacheConsts.HOME_BOOK_CACHE_NAME) public List listHomeBooks() { // 从首页小说推荐表中查询出需要推荐的小说 QueryWrapper queryWrapper = new QueryWrapper<>(); @@ -47,8 +46,8 @@ public class HomeBookCacheManager { // 获取推荐小说ID列表 if (!CollectionUtils.isEmpty(homeBooks)) { List bookIds = homeBooks.stream() - .map(HomeBook::getBookId) - .toList(); + .map(HomeBook::getBookId) + .toList(); // 根据小说ID列表查询相关的小说信息列表 QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); @@ -56,9 +55,9 @@ public class HomeBookCacheManager { List bookInfos = bookInfoMapper.selectList(bookInfoQueryWrapper); // 组装 HomeBookRespDto 列表数据并返回 - if(!CollectionUtils.isEmpty(bookInfos)){ + if (!CollectionUtils.isEmpty(bookInfos)) { Map bookInfoMap = bookInfos.stream() - .collect(Collectors.toMap(BookInfo::getId, Function.identity())); + .collect(Collectors.toMap(BookInfo::getId, Function.identity())); return homeBooks.stream().map(v -> { BookInfo bookInfo = bookInfoMap.get(v.getBookId()); HomeBookRespDto bookRespDto = new HomeBookRespDto(); diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/NewsCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/NewsCacheManager.java index 65fd458..6150dab 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/NewsCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/NewsCacheManager.java @@ -6,12 +6,11 @@ import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.dao.entity.NewsInfo; import io.github.xxyopen.novel.dao.mapper.NewsInfoMapper; import io.github.xxyopen.novel.dto.resp.NewsInfoRespDto; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; -import java.util.List; - /** * 新闻 缓存管理类 * @@ -28,20 +27,20 @@ public class NewsCacheManager { * 最新新闻列表查询,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, - value = CacheConsts.LATEST_NEWS_CACHE_NAME) + value = CacheConsts.LATEST_NEWS_CACHE_NAME) public List listLatestNews() { // 从新闻信息表中查询出最新发布的两条新闻 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()) - .last(DatabaseConsts.SqlEnum.LIMIT_2.getSql()); + .last(DatabaseConsts.SqlEnum.LIMIT_2.getSql()); return newsInfoMapper.selectList(queryWrapper).stream().map(v -> NewsInfoRespDto.builder() - .id(v.getId()) - .categoryId(v.getCategoryId()) - .categoryName(v.getCategoryName()) - .title(v.getTitle()) - .sourceName(v.getSourceName()) - .updateTime(v.getUpdateTime()) - .build()).toList(); + .id(v.getId()) + .categoryId(v.getCategoryId()) + .categoryName(v.getCategoryName()) + .title(v.getTitle()) + .sourceName(v.getSourceName()) + .updateTime(v.getUpdateTime()) + .build()).toList(); } } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/UserInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/UserInfoCacheManager.java index 90ee1eb..7a92278 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/UserInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/UserInfoCacheManager.java @@ -4,12 +4,11 @@ import io.github.xxyopen.novel.core.constant.CacheConsts; import io.github.xxyopen.novel.dao.entity.UserInfo; import io.github.xxyopen.novel.dao.mapper.UserInfoMapper; import io.github.xxyopen.novel.dto.UserInfoDto; +import java.util.Objects; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; -import java.util.Objects; - /** * 用户信息 缓存管理类 * @@ -26,15 +25,15 @@ public class UserInfoCacheManager { * 查询用户信息,并放入缓存中 */ @Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, - value = CacheConsts.USER_INFO_CACHE_NAME) + value = CacheConsts.USER_INFO_CACHE_NAME) public UserInfoDto getUser(Long userId) { UserInfo userInfo = userInfoMapper.selectById(userId); if (Objects.isNull(userInfo)) { return null; } return UserInfoDto.builder() - .id(userInfo.getId()) - .status(userInfo.getStatus()).build(); + .id(userInfo.getId()) + .status(userInfo.getStatus()).build(); } diff --git a/src/main/java/io/github/xxyopen/novel/manager/dao/UserDaoManager.java b/src/main/java/io/github/xxyopen/novel/manager/dao/UserDaoManager.java index 7020f18..6ae41a8 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/dao/UserDaoManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/dao/UserDaoManager.java @@ -4,13 +4,13 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.dao.entity.UserInfo; import io.github.xxyopen.novel.dao.mapper.UserInfoMapper; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import java.util.List; - /** * 用户模块 DAO管理类 + * * @author xiongxiaoyang * @date 2022/5/20 */ @@ -22,12 +22,13 @@ public class UserDaoManager { /** * 根据用户ID集合批量查询用户信息列表 + * * @param userIds 需要查询的用户ID集合 * @return 满足条件的用户信息列表 - * */ - public List listUsers(List userIds){ + */ + public List listUsers(List userIds) { QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in(DatabaseConsts.CommonColumnEnum.ID.getName(),userIds); + queryWrapper.in(DatabaseConsts.CommonColumnEnum.ID.getName(), userIds); return userInfoMapper.selectList(queryWrapper); } diff --git a/src/main/java/io/github/xxyopen/novel/manager/mq/AmqpMsgManager.java b/src/main/java/io/github/xxyopen/novel/manager/mq/AmqpMsgManager.java index ecdcb5c..8a5b667 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/mq/AmqpMsgManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/mq/AmqpMsgManager.java @@ -2,6 +2,7 @@ package io.github.xxyopen.novel.manager.mq; import io.github.xxyopen.novel.core.common.constant.CommonConsts; import io.github.xxyopen.novel.core.constant.AmqpConsts; +import java.util.Objects; import lombok.RequiredArgsConstructor; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.beans.factory.annotation.Value; @@ -9,8 +10,6 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; -import java.util.Objects; - /** * AMQP 消息管理类 * @@ -35,15 +34,17 @@ public class AmqpMsgManager { } } - private void sendAmqpMessage(AmqpTemplate amqpTemplate, String exchange, String routingKey, Object message) { + private void sendAmqpMessage(AmqpTemplate amqpTemplate, String exchange, String routingKey, + Object message) { // 如果在事务中则在事务执行完成后再发送,否则可以直接发送 if (TransactionSynchronizationManager.isActualTransactionActive()) { - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCommit() { - amqpTemplate.convertAndSend(exchange, routingKey, message); - } - }); + TransactionSynchronizationManager.registerSynchronization( + new TransactionSynchronization() { + @Override + public void afterCommit() { + amqpTemplate.convertAndSend(exchange, routingKey, message); + } + }); return; } amqpTemplate.convertAndSend(exchange, routingKey, message); diff --git a/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java b/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java index e42adda..af873e6 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/redis/VerifyCodeManager.java @@ -2,15 +2,14 @@ package io.github.xxyopen.novel.manager.redis; import io.github.xxyopen.novel.core.common.util.ImgVerifyCodeUtils; import io.github.xxyopen.novel.core.constant.CacheConsts; +import java.io.IOException; +import java.time.Duration; +import java.util.Objects; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; -import java.io.IOException; -import java.time.Duration; -import java.util.Objects; - /** * 验证码 管理类 * @@ -31,7 +30,7 @@ public class VerifyCodeManager { String verifyCode = ImgVerifyCodeUtils.getRandomVerifyCode(4); String img = ImgVerifyCodeUtils.genVerifyCodeImg(verifyCode); stringRedisTemplate.opsForValue().set(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId, - verifyCode, Duration.ofMinutes(5)); + verifyCode, Duration.ofMinutes(5)); return img; } @@ -39,7 +38,8 @@ public class VerifyCodeManager { * 校验图形验证码 */ public boolean imgVerifyCodeOk(String sessionId, String verifyCode) { - return Objects.equals(stringRedisTemplate.opsForValue().get(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId), verifyCode); + return Objects.equals(stringRedisTemplate.opsForValue() + .get(CacheConsts.IMG_VERIFY_CODE_CACHE_KEY + sessionId), verifyCode); } /** diff --git a/src/main/java/io/github/xxyopen/novel/service/AuthorService.java b/src/main/java/io/github/xxyopen/novel/service/AuthorService.java index bf7c95a..0db8ff9 100644 --- a/src/main/java/io/github/xxyopen/novel/service/AuthorService.java +++ b/src/main/java/io/github/xxyopen/novel/service/AuthorService.java @@ -21,8 +21,9 @@ public interface AuthorService { /** * 查询作家状态 + * * @param userId 用户ID * @return 作家状态 - * */ + */ RestResp getStatus(Long userId); } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index dc0c996..b570c7e 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -11,7 +11,11 @@ import io.github.xxyopen.novel.core.common.req.PageReqDto; import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.DatabaseConsts; -import io.github.xxyopen.novel.dao.entity.*; +import io.github.xxyopen.novel.dao.entity.BookChapter; +import io.github.xxyopen.novel.dao.entity.BookComment; +import io.github.xxyopen.novel.dao.entity.BookContent; +import io.github.xxyopen.novel.dao.entity.BookInfo; +import io.github.xxyopen.novel.dao.entity.UserInfo; import io.github.xxyopen.novel.dao.mapper.BookChapterMapper; import io.github.xxyopen.novel.dao.mapper.BookCommentMapper; import io.github.xxyopen.novel.dao.mapper.BookContentMapper; @@ -20,22 +24,38 @@ import io.github.xxyopen.novel.dto.AuthorInfoDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; import io.github.xxyopen.novel.dto.req.UserCommentReqDto; -import io.github.xxyopen.novel.dto.resp.*; -import io.github.xxyopen.novel.manager.cache.*; +import io.github.xxyopen.novel.dto.resp.BookCategoryRespDto; +import io.github.xxyopen.novel.dto.resp.BookChapterAboutRespDto; +import io.github.xxyopen.novel.dto.resp.BookChapterRespDto; +import io.github.xxyopen.novel.dto.resp.BookCommentRespDto; +import io.github.xxyopen.novel.dto.resp.BookContentAboutRespDto; +import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; +import io.github.xxyopen.novel.dto.resp.BookRankRespDto; +import io.github.xxyopen.novel.manager.cache.AuthorInfoCacheManager; +import io.github.xxyopen.novel.manager.cache.BookCategoryCacheManager; +import io.github.xxyopen.novel.manager.cache.BookChapterCacheManager; +import io.github.xxyopen.novel.manager.cache.BookContentCacheManager; +import io.github.xxyopen.novel.manager.cache.BookInfoCacheManager; +import io.github.xxyopen.novel.manager.cache.BookRankCacheManager; import io.github.xxyopen.novel.manager.dao.UserDaoManager; import io.github.xxyopen.novel.manager.mq.AmqpMsgManager; import io.github.xxyopen.novel.service.BookService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Random; import java.util.function.Function; import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; /** * 小说模块 服务实现类 @@ -100,7 +120,8 @@ public class BookServiceImpl implements BookService { BookInfoRespDto bookInfo = bookInfoCacheManager.getBookInfo(bookId); // 查询最新章节信息 - BookChapterRespDto bookChapter = bookChapterCacheManager.getChapter(bookInfo.getLastChapterId()); + BookChapterRespDto bookChapter = bookChapterCacheManager.getChapter( + bookInfo.getLastChapterId()); // 查询章节内容 String content = bookContentCacheManager.getBookContent(bookInfo.getLastChapterId()); @@ -112,14 +133,15 @@ public class BookServiceImpl implements BookService { // 组装数据并返回 return RestResp.ok(BookChapterAboutRespDto.builder() - .chapterInfo(bookChapter) - .chapterTotal(chapterTotal) - .contentSummary(content.substring(0, 30)) - .build()); + .chapterInfo(bookChapter) + .chapterTotal(chapterTotal) + .contentSummary(content.substring(0, 30)) + .build()); } @Override - public RestResp> listRecBooks(Long bookId) throws NoSuchAlgorithmException { + public RestResp> listRecBooks(Long bookId) + throws NoSuchAlgorithmException { Long categoryId = bookInfoCacheManager.getBookInfo(bookId).getCategoryId(); List lastUpdateIdList = bookInfoCacheManager.getLastUpdateIdList(categoryId); List respDtoList = new ArrayList<>(); @@ -155,13 +177,13 @@ public class BookServiceImpl implements BookService { // 查询上一章信息并返回章节ID QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId) - .lt(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM, chapterNum) - .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .lt(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM, chapterNum) + .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); return RestResp.ok( - Optional.ofNullable(bookChapterMapper.selectOne(queryWrapper)) - .map(BookChapter::getId) - .orElse(null) + Optional.ofNullable(bookChapterMapper.selectOne(queryWrapper)) + .map(BookChapter::getId) + .orElse(null) ); } @@ -175,13 +197,13 @@ public class BookServiceImpl implements BookService { // 查询下一章信息并返回章节ID QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId) - .gt(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM, chapterNum) - .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .gt(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM, chapterNum) + .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); return RestResp.ok( - Optional.ofNullable(bookChapterMapper.selectOne(queryWrapper)) - .map(BookChapter::getId) - .orElse(null) + Optional.ofNullable(bookChapterMapper.selectOne(queryWrapper)) + .map(BookChapter::getId) + .orElse(null) ); } @@ -189,8 +211,9 @@ public class BookServiceImpl implements BookService { public RestResp> listChapters(Long bookId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId) - .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM); - return RestResp.ok(bookChapterMapper.selectList(queryWrapper).stream().map(v -> BookChapterRespDto.builder() + .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM); + return RestResp.ok(bookChapterMapper.selectList(queryWrapper).stream() + .map(v -> BookChapterRespDto.builder() .id(v.getId()) .chapterName(v.getChapterName()) .isVip(v.getIsVip()) @@ -204,11 +227,12 @@ public class BookServiceImpl implements BookService { @Lock(prefix = "userComment") @Override - public RestResp saveComment(@Key(expr = "#{userId + '::' + bookId}") UserCommentReqDto dto) { + public RestResp saveComment( + @Key(expr = "#{userId + '::' + bookId}") UserCommentReqDto dto) { // 校验用户是否已发表评论 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, dto.getUserId()) - .eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID, dto.getBookId()); + .eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID, dto.getBookId()); if (bookCommentMapper.selectCount(queryWrapper) > 0) { // 用户已发表评论 return RestResp.fail(ErrorCodeEnum.USER_COMMENTED); @@ -229,28 +253,30 @@ public class BookServiceImpl implements BookService { QueryWrapper commentCountQueryWrapper = new QueryWrapper<>(); commentCountQueryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID, bookId); Long commentTotal = bookCommentMapper.selectCount(commentCountQueryWrapper); - BookCommentRespDto bookCommentRespDto = BookCommentRespDto.builder().commentTotal(commentTotal).build(); + BookCommentRespDto bookCommentRespDto = BookCommentRespDto.builder() + .commentTotal(commentTotal).build(); if (commentTotal > 0) { // 查询最新的评论列表 QueryWrapper commentQueryWrapper = new QueryWrapper<>(); commentQueryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID, bookId) - .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()) - .last(DatabaseConsts.SqlEnum.LIMIT_5.getSql()); + .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()) + .last(DatabaseConsts.SqlEnum.LIMIT_5.getSql()); List bookComments = bookCommentMapper.selectList(commentQueryWrapper); // 查询评论用户信息,并设置需要返回的评论用户名 List userIds = bookComments.stream().map(BookComment::getUserId).toList(); List userInfos = userDaoManager.listUsers(userIds); - Map userInfoMap = userInfos.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity())); + Map userInfoMap = userInfos.stream() + .collect(Collectors.toMap(UserInfo::getId, Function.identity())); List commentInfos = bookComments.stream() - .map(v -> BookCommentRespDto.CommentInfo.builder() - .id(v.getId()) - .commentUserId(v.getUserId()) - .commentUser(userInfoMap.get(v.getUserId()).getUsername()) - .commentUserPhoto(userInfoMap.get(v.getUserId()).getUserPhoto()) - .commentContent(v.getCommentContent()) - .commentTime(v.getCreateTime()).build()).toList(); + .map(v -> BookCommentRespDto.CommentInfo.builder() + .id(v.getId()) + .commentUserId(v.getUserId()) + .commentUser(userInfoMap.get(v.getUserId()).getUsername()) + .commentUserPhoto(userInfoMap.get(v.getUserId()).getUserPhoto()) + .commentContent(v.getCommentContent()) + .commentTime(v.getCreateTime()).build()).toList(); bookCommentRespDto.setComments(commentInfos); } else { bookCommentRespDto.setComments(Collections.emptyList()); @@ -262,7 +288,7 @@ public class BookServiceImpl implements BookService { public RestResp deleteComment(Long userId, Long commentId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), commentId) - .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId); + .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId); bookCommentMapper.delete(queryWrapper); return RestResp.ok(); } @@ -271,7 +297,7 @@ public class BookServiceImpl implements BookService { public RestResp updateComment(Long userId, Long id, String content) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), id) - .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId); + .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId); BookComment bookComment = new BookComment(); bookComment.setCommentContent(content); bookCommentMapper.update(bookComment, queryWrapper); @@ -320,8 +346,8 @@ public class BookServiceImpl implements BookService { int chapterNum = 0; QueryWrapper chapterQueryWrapper = new QueryWrapper<>(); chapterQueryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, dto.getBookId()) - .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); BookChapter bookChapter = bookChapterMapper.selectOne(chapterQueryWrapper); if (Objects.nonNull(bookChapter)) { chapterNum = bookChapter.getChapterNum() + 1; @@ -369,18 +395,18 @@ public class BookServiceImpl implements BookService { page.setSize(dto.getPageSize()); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookTable.AUTHOR_ID, UserHolder.getAuthorId()) - .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()); + .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName()); IPage bookInfoPage = bookInfoMapper.selectPage(page, queryWrapper); return RestResp.ok(PageRespDto.of(dto.getPageNum(), dto.getPageSize(), page.getTotal(), - bookInfoPage.getRecords().stream().map(v -> BookInfoRespDto.builder() - .id(v.getId()) - .bookName(v.getBookName()) - .picUrl(v.getPicUrl()) - .categoryName(v.getCategoryName()) - .wordCount(v.getWordCount()) - .visitCount(v.getVisitCount()) - .updateTime(v.getUpdateTime()) - .build()).toList())); + bookInfoPage.getRecords().stream().map(v -> BookInfoRespDto.builder() + .id(v.getId()) + .bookName(v.getBookName()) + .picUrl(v.getPicUrl()) + .categoryName(v.getCategoryName()) + .wordCount(v.getWordCount()) + .visitCount(v.getVisitCount()) + .updateTime(v.getUpdateTime()) + .build()).toList())); } @Override @@ -390,15 +416,15 @@ public class BookServiceImpl implements BookService { page.setSize(dto.getPageSize()); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId) - .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM); + .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM); IPage bookChapterPage = bookChapterMapper.selectPage(page, queryWrapper); return RestResp.ok(PageRespDto.of(dto.getPageNum(), dto.getPageSize(), page.getTotal(), - bookChapterPage.getRecords().stream().map(v -> BookChapterRespDto.builder() - .id(v.getId()) - .chapterName(v.getChapterName()) - .chapterUpdateTime(v.getUpdateTime()) - .isVip(v.getIsVip()) - .build()).toList())); + bookChapterPage.getRecords().stream().map(v -> BookChapterRespDto.builder() + .id(v.getId()) + .chapterName(v.getChapterName()) + .chapterUpdateTime(v.getUpdateTime()) + .isVip(v.getIsVip()) + .build()).toList())); } @Override @@ -415,9 +441,9 @@ public class BookServiceImpl implements BookService { // 组装数据并返回 return RestResp.ok(BookContentAboutRespDto.builder() - .bookInfo(bookInfo) - .chapterInfo(bookChapter) - .bookContent(content) - .build()); + .bookInfo(bookInfo) + .chapterInfo(bookChapter) + .bookContent(content) + .build()); } } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java index 052886a..96d9423 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java @@ -8,13 +8,12 @@ import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.req.BookSearchReqDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.service.SearchService; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; -import java.util.List; - /** * 数据库搜索 服务实现类 * @@ -35,17 +34,18 @@ public class DbSearchServiceImpl implements SearchService { page.setCurrent(condition.getPageNum()); page.setSize(condition.getPageSize()); List bookInfos = bookInfoMapper.searchBooks(page, condition); - return RestResp.ok(PageRespDto.of(condition.getPageNum(), condition.getPageSize(), page.getTotal(), + return RestResp.ok( + PageRespDto.of(condition.getPageNum(), condition.getPageSize(), page.getTotal(), bookInfos.stream().map(v -> BookInfoRespDto.builder() - .id(v.getId()) - .bookName(v.getBookName()) - .categoryId(v.getCategoryId()) - .categoryName(v.getCategoryName()) - .authorId(v.getAuthorId()) - .authorName(v.getAuthorName()) - .wordCount(v.getWordCount()) - .lastChapterName(v.getLastChapterName()) - .build()).toList())); + .id(v.getId()) + .bookName(v.getBookName()) + .categoryId(v.getCategoryId()) + .categoryName(v.getCategoryName()) + .authorId(v.getAuthorId()) + .authorName(v.getAuthorName()) + .wordCount(v.getWordCount()) + .lastChapterName(v.getLastChapterName()) + .build()).toList())); } } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java index 271c94f..c004802 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java @@ -19,16 +19,15 @@ import io.github.xxyopen.novel.dto.es.EsBookDto; import io.github.xxyopen.novel.dto.req.BookSearchReqDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.service.SearchService; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - /** * Elasticsearch 搜索 服务实现类 * @@ -49,28 +48,28 @@ public class EsSearchServiceImpl implements SearchService { SearchResponse response = esClient.search(s -> { - SearchRequest.Builder searchBuilder = s.index(EsConsts.BookIndex.INDEX_NAME); - // 构建检索条件 - buildSearchCondition(condition, searchBuilder); - // 排序 - if (!StringUtils.isBlank(condition.getSort())) { - searchBuilder.sort(o -> o.field(f -> f - .field(StringUtils.underlineToCamel(condition.getSort().split(" ")[0])) - .order(SortOrder.Desc)) - ); - } - // 分页 - searchBuilder.from((condition.getPageNum() - 1) * condition.getPageSize()) - .size(condition.getPageSize()); - // 设置高亮显示 - searchBuilder.highlight(h -> h.fields(EsConsts.BookIndex.FIELD_BOOK_NAME, - t -> t.preTags("").postTags("")) - .fields(EsConsts.BookIndex.FIELD_AUTHOR_NAME, - t -> t.preTags("").postTags(""))); - - return searchBuilder; - }, - EsBookDto.class + SearchRequest.Builder searchBuilder = s.index(EsConsts.BookIndex.INDEX_NAME); + // 构建检索条件 + buildSearchCondition(condition, searchBuilder); + // 排序 + if (!StringUtils.isBlank(condition.getSort())) { + searchBuilder.sort(o -> o.field(f -> f + .field(StringUtils.underlineToCamel(condition.getSort().split(" ")[0])) + .order(SortOrder.Desc)) + ); + } + // 分页 + searchBuilder.from((condition.getPageNum() - 1) * condition.getPageSize()) + .size(condition.getPageSize()); + // 设置高亮显示 + searchBuilder.highlight(h -> h.fields(EsConsts.BookIndex.FIELD_BOOK_NAME, + t -> t.preTags("").postTags("")) + .fields(EsConsts.BookIndex.FIELD_AUTHOR_NAME, + t -> t.preTags("").postTags(""))); + + return searchBuilder; + }, + EsBookDto.class ); TotalHits total = response.hits().total(); @@ -84,45 +83,49 @@ public class EsSearchServiceImpl implements SearchService { if (!CollectionUtils.isEmpty(hit.highlight().get(EsConsts.BookIndex.FIELD_BOOK_NAME))) { book.setBookName(hit.highlight().get(EsConsts.BookIndex.FIELD_BOOK_NAME).get(0)); } - if (!CollectionUtils.isEmpty(hit.highlight().get(EsConsts.BookIndex.FIELD_AUTHOR_NAME))) { - book.setAuthorName(hit.highlight().get(EsConsts.BookIndex.FIELD_AUTHOR_NAME).get(0)); + if (!CollectionUtils.isEmpty( + hit.highlight().get(EsConsts.BookIndex.FIELD_AUTHOR_NAME))) { + book.setAuthorName( + hit.highlight().get(EsConsts.BookIndex.FIELD_AUTHOR_NAME).get(0)); } list.add(BookInfoRespDto.builder() - .id(book.getId()) - .bookName(book.getBookName()) - .categoryId(book.getCategoryId()) - .categoryName(book.getCategoryName()) - .authorId(book.getAuthorId()) - .authorName(book.getAuthorName()) - .wordCount(book.getWordCount()) - .lastChapterName(book.getLastChapterName()) - .build()); + .id(book.getId()) + .bookName(book.getBookName()) + .categoryId(book.getCategoryId()) + .categoryName(book.getCategoryName()) + .authorId(book.getAuthorId()) + .authorName(book.getAuthorName()) + .wordCount(book.getWordCount()) + .lastChapterName(book.getLastChapterName()) + .build()); } assert total != null; - return RestResp.ok(PageRespDto.of(condition.getPageNum(), condition.getPageSize(), total.value(), list)); + return RestResp.ok( + PageRespDto.of(condition.getPageNum(), condition.getPageSize(), total.value(), list)); } /** * 构建检索条件 */ - private void buildSearchCondition(BookSearchReqDto condition, SearchRequest.Builder searchBuilder) { + private void buildSearchCondition(BookSearchReqDto condition, + SearchRequest.Builder searchBuilder) { BoolQuery boolQuery = BoolQuery.of(b -> { // 只查有字数的小说 b.must(RangeQuery.of(m -> m - .field(EsConsts.BookIndex.FIELD_WORD_COUNT) - .gt(JsonData.of(0)) + .field(EsConsts.BookIndex.FIELD_WORD_COUNT) + .gt(JsonData.of(0)) )._toQuery()); if (!StringUtils.isBlank(condition.getKeyword())) { // 关键词匹配 b.must((q -> q.multiMatch(t -> t - .fields(EsConsts.BookIndex.FIELD_BOOK_NAME + "^2", - EsConsts.BookIndex.FIELD_AUTHOR_NAME + "^1.8", - EsConsts.BookIndex.FIELD_BOOK_DESC + "^0.1") - .query(condition.getKeyword()) + .fields(EsConsts.BookIndex.FIELD_BOOK_NAME + "^2", + EsConsts.BookIndex.FIELD_AUTHOR_NAME + "^1.8", + EsConsts.BookIndex.FIELD_BOOK_DESC + "^0.1") + .query(condition.getKeyword()) ) )); } @@ -130,37 +133,37 @@ public class EsSearchServiceImpl implements SearchService { // 精确查询 if (Objects.nonNull(condition.getWorkDirection())) { b.must(TermQuery.of(m -> m - .field(EsConsts.BookIndex.FIELD_WORK_DIRECTION) - .value(condition.getWorkDirection()) + .field(EsConsts.BookIndex.FIELD_WORK_DIRECTION) + .value(condition.getWorkDirection()) )._toQuery()); } if (Objects.nonNull(condition.getCategoryId())) { b.must(TermQuery.of(m -> m - .field(EsConsts.BookIndex.FIELD_CATEGORY_ID) - .value(condition.getCategoryId()) + .field(EsConsts.BookIndex.FIELD_CATEGORY_ID) + .value(condition.getCategoryId()) )._toQuery()); } // 范围查询 if (Objects.nonNull(condition.getWordCountMin())) { b.must(RangeQuery.of(m -> m - .field(EsConsts.BookIndex.FIELD_WORD_COUNT) - .gte(JsonData.of(condition.getWordCountMin())) + .field(EsConsts.BookIndex.FIELD_WORD_COUNT) + .gte(JsonData.of(condition.getWordCountMin())) )._toQuery()); } if (Objects.nonNull(condition.getWordCountMax())) { b.must(RangeQuery.of(m -> m - .field(EsConsts.BookIndex.FIELD_WORD_COUNT) - .lt(JsonData.of(condition.getWordCountMax())) + .field(EsConsts.BookIndex.FIELD_WORD_COUNT) + .lt(JsonData.of(condition.getWordCountMax())) )._toQuery()); } if (Objects.nonNull(condition.getUpdateTimeMin())) { b.must(RangeQuery.of(m -> m - .field(EsConsts.BookIndex.FIELD_LAST_CHAPTER_UPDATE_TIME) - .gte(JsonData.of(condition.getUpdateTimeMin().getTime())) + .field(EsConsts.BookIndex.FIELD_LAST_CHAPTER_UPDATE_TIME) + .gte(JsonData.of(condition.getUpdateTimeMin().getTime())) )._toQuery()); } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/NewsServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/NewsServiceImpl.java index c8d7431..ebe1b2c 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/NewsServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/NewsServiceImpl.java @@ -10,11 +10,10 @@ import io.github.xxyopen.novel.dao.mapper.NewsInfoMapper; import io.github.xxyopen.novel.dto.resp.NewsInfoRespDto; import io.github.xxyopen.novel.manager.cache.NewsCacheManager; import io.github.xxyopen.novel.service.NewsService; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.List; - /** * 新闻模块 服务实现类 * @@ -41,13 +40,13 @@ public class NewsServiceImpl implements NewsService { NewsInfo newsInfo = newsInfoMapper.selectById(id); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.NewsContentTable.COLUMN_NEWS_ID, id) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); NewsContent newsContent = newsContentMapper.selectOne(queryWrapper); return RestResp.ok(NewsInfoRespDto.builder() - .title(newsInfo.getTitle()) - .sourceName(newsInfo.getSourceName()) - .updateTime(newsInfo.getUpdateTime()) - .content(newsContent.getContent()) - .build()); + .title(newsInfo.getTitle()) + .sourceName(newsInfo.getSourceName()) + .updateTime(newsInfo.getUpdateTime()) + .content(newsContent.getContent()) + .build()); } } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/ResourceServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/ResourceServiceImpl.java index 4089d78..eae937d 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/ResourceServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/ResourceServiceImpl.java @@ -8,20 +8,19 @@ import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.dto.resp.ImgVerifyCodeRespDto; import io.github.xxyopen.novel.manager.redis.VerifyCodeManager; import io.github.xxyopen.novel.service.ResourceService; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import javax.imageio.ImageIO; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Objects; +import javax.imageio.ImageIO; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; /** * 资源(图片/视频/文档)相关服务实现类 @@ -43,9 +42,9 @@ public class ResourceServiceImpl implements ResourceService { public RestResp getImgVerifyCode() throws IOException { String sessionId = IdWorker.get32UUID(); return RestResp.ok(ImgVerifyCodeRespDto.builder() - .sessionId(sessionId) - .img(verifyCodeManager.genImgVerifyCode(sessionId)) - .build()); + .sessionId(sessionId) + .img(verifyCodeManager.genImgVerifyCode(sessionId)) + .build()); } @SneakyThrows @@ -53,10 +52,10 @@ public class ResourceServiceImpl implements ResourceService { public RestResp uploadImage(MultipartFile file) { LocalDateTime now = LocalDateTime.now(); String savePath = - SystemConfigConsts.IMAGE_UPLOAD_DIRECTORY - + now.format(DateTimeFormatter.ofPattern("yyyy")) + File.separator - + now.format(DateTimeFormatter.ofPattern("MM")) + File.separator - + now.format(DateTimeFormatter.ofPattern("dd")); + SystemConfigConsts.IMAGE_UPLOAD_DIRECTORY + + now.format(DateTimeFormatter.ofPattern("yyyy")) + File.separator + + now.format(DateTimeFormatter.ofPattern("MM")) + File.separator + + now.format(DateTimeFormatter.ofPattern("dd")); String oriName = file.getOriginalFilename(); assert oriName != null; String saveFileName = IdWorker.get32UUID() + oriName.substring(oriName.lastIndexOf(".")); diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/UserServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/UserServiceImpl.java index 480bd83..3d3ff96 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/UserServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/UserServiceImpl.java @@ -22,13 +22,12 @@ import io.github.xxyopen.novel.dto.resp.UserLoginRespDto; import io.github.xxyopen.novel.dto.resp.UserRegisterRespDto; import io.github.xxyopen.novel.manager.redis.VerifyCodeManager; import io.github.xxyopen.novel.service.UserService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.util.DigestUtils; - import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.Objects; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.util.DigestUtils; /** * 会员模块 服务实现类 @@ -61,7 +60,7 @@ public class UserServiceImpl implements UserService { // 校验手机号是否已注册 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.UserInfoTable.COLUMN_USERNAME, dto.getUsername()) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); if (userInfoMapper.selectCount(queryWrapper) > 0) { // 手机号已注册 throw new BusinessException(ErrorCodeEnum.USER_NAME_EXIST); @@ -69,7 +68,8 @@ public class UserServiceImpl implements UserService { // 注册成功,保存用户信息 UserInfo userInfo = new UserInfo(); - userInfo.setPassword(DigestUtils.md5DigestAsHex(dto.getPassword().getBytes(StandardCharsets.UTF_8))); + userInfo.setPassword( + DigestUtils.md5DigestAsHex(dto.getPassword().getBytes(StandardCharsets.UTF_8))); userInfo.setUsername(dto.getUsername()); userInfo.setNickName(dto.getUsername()); userInfo.setCreateTime(LocalDateTime.now()); @@ -82,10 +82,10 @@ public class UserServiceImpl implements UserService { // 生成JWT 并返回 return RestResp.ok( - UserRegisterRespDto.builder() - .token(jwtUtils.generateToken(userInfo.getId(), SystemConfigConsts.NOVEL_FRONT_KEY)) - .uid(userInfo.getId()) - .build() + UserRegisterRespDto.builder() + .token(jwtUtils.generateToken(userInfo.getId(), SystemConfigConsts.NOVEL_FRONT_KEY)) + .uid(userInfo.getId()) + .build() ); } @@ -95,7 +95,7 @@ public class UserServiceImpl implements UserService { // 查询用户信息 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.UserInfoTable.COLUMN_USERNAME, dto.getUsername()) - .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); UserInfo userInfo = userInfoMapper.selectOne(queryWrapper); if (Objects.isNull(userInfo)) { // 用户不存在 @@ -104,16 +104,16 @@ public class UserServiceImpl implements UserService { // 判断密码是否正确 if (!Objects.equals(userInfo.getPassword() - , DigestUtils.md5DigestAsHex(dto.getPassword().getBytes(StandardCharsets.UTF_8)))) { + , DigestUtils.md5DigestAsHex(dto.getPassword().getBytes(StandardCharsets.UTF_8)))) { // 密码错误 throw new BusinessException(ErrorCodeEnum.USER_PASSWORD_ERROR); } // 登录成功,生成JWT并返回 return RestResp.ok(UserLoginRespDto.builder() - .token(jwtUtils.generateToken(userInfo.getId(), SystemConfigConsts.NOVEL_FRONT_KEY)) - .uid(userInfo.getId()) - .nickName(userInfo.getNickName()).build()); + .token(jwtUtils.generateToken(userInfo.getId(), SystemConfigConsts.NOVEL_FRONT_KEY)) + .uid(userInfo.getId()) + .nickName(userInfo.getNickName()).build()); } @Override @@ -142,7 +142,7 @@ public class UserServiceImpl implements UserService { public RestResp deleteFeedback(Long userId, Long id) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), id) - .eq(DatabaseConsts.UserFeedBackTable.COLUMN_USER_ID, userId); + .eq(DatabaseConsts.UserFeedBackTable.COLUMN_USER_ID, userId); userFeedbackMapper.delete(queryWrapper); return RestResp.ok(); } @@ -151,11 +151,11 @@ public class UserServiceImpl implements UserService { public RestResp getBookshelfStatus(Long userId, String bookId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(DatabaseConsts.UserBookshelfTable.COLUMN_USER_ID, userId) - .eq(DatabaseConsts.UserBookshelfTable.COLUMN_BOOK_ID, bookId); + .eq(DatabaseConsts.UserBookshelfTable.COLUMN_BOOK_ID, bookId); return RestResp.ok( - userBookshelfMapper.selectCount(queryWrapper) > 0 - ? CommonConsts.YES - : CommonConsts.NO + userBookshelfMapper.selectCount(queryWrapper) > 0 + ? CommonConsts.YES + : CommonConsts.NO ); } @@ -163,9 +163,9 @@ public class UserServiceImpl implements UserService { public RestResp getUserInfo(Long userId) { UserInfo userInfo = userInfoMapper.selectById(userId); return RestResp.ok(UserInfoRespDto.builder() - .nickName(userInfo.getNickName()) - .userSex(userInfo.getUserSex()) - .userPhoto(userInfo.getUserPhoto()) - .build()); + .nickName(userInfo.getNickName()) + .userSex(userInfo.getUserSex()) + .userPhoto(userInfo.getUserPhoto()) + .build()); } } -- Gitee From 5852cc6d260b03a40374250d63b23b1fdb42b9db Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Fri, 1 Jul 2022 06:30:11 +0800 Subject: [PATCH 056/112] =?UTF-8?q?style:=20=E4=BB=A3=E7=A0=81=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../manager/cache/BookInfoCacheManager.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java index 9aeb63a..107453d 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java @@ -32,8 +32,7 @@ public class BookInfoCacheManager { /** * 从缓存中查询小说信息(先判断缓存中是否已存在,存在则直接从缓存中取,否则执行方法体中的逻辑后缓存结果) */ - @Cacheable( - cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, value = CacheConsts.BOOK_INFO_CACHE_NAME) public BookInfoRespDto getBookInfo(Long id) { return cachePutBookInfo(id); @@ -42,8 +41,7 @@ public class BookInfoCacheManager { /** * 缓存小说信息(不管缓存中是否存在都执行方法体中的逻辑,然后缓存起来) */ - @CachePut( - cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + @CachePut(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, value = CacheConsts.BOOK_INFO_CACHE_NAME) public BookInfoRespDto cachePutBookInfo(Long id) { // 查询基础信息 @@ -74,8 +72,7 @@ public class BookInfoCacheManager { .build(); } - @CacheEvict( - cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + @CacheEvict(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, value = CacheConsts.BOOK_INFO_CACHE_NAME) public void evictBookInfoCache(Long ignoredId) { // 调用此方法自动清除小说信息的缓存 @@ -84,16 +81,15 @@ public class BookInfoCacheManager { /** * 查询每个类别下最新更新的 500 个小说ID列表,并放入缓存中 1 个小时 */ - @Cacheable( - cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + @Cacheable(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, value = CacheConsts.LAST_UPDATE_BOOK_ID_LIST_CACHE_NAME) public List getLastUpdateIdList(Long categoryId) { QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper - .eq(DatabaseConsts.BookTable.COLUMN_CATEGORY_ID, categoryId) + queryWrapper.eq(DatabaseConsts.BookTable.COLUMN_CATEGORY_ID, categoryId) .gt(DatabaseConsts.BookTable.COLUMN_WORD_COUNT, 0) .orderByDesc(DatabaseConsts.BookTable.COLUMN_LAST_CHAPTER_UPDATE_TIME) .last(DatabaseConsts.SqlEnum.LIMIT_500.getSql()); return bookInfoMapper.selectList(queryWrapper).stream().map(BookInfo::getId).toList(); } + } -- Gitee From 97b0e4053403ebd41a4316e211cce619d8539689 Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Sat, 2 Jul 2022 08:59:57 +0800 Subject: [PATCH 057/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d01a8e0..11faa54 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,7 @@ git clone https://gitee.com/novel_dev_team/novel.git ``` mvn spring-boot:run ``` - 5. 接口文档访问地址:http://server:port/swagger-ui/index.html + 5. 接口文档访问地址:`http://server:port/swagger-ui/index.html` - 下载前端前台门户系统源码 -- Gitee From b0294a5b90ab4aa02745a7273b658d63679e90a6 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sat, 2 Jul 2022 09:55:47 +0800 Subject: [PATCH 058/112] =?UTF-8?q?chore:=20git=20=E5=BF=BD=E7=95=A5=20.sh?= =?UTF-8?q?ardingsphere=20=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4781089..ef9d58d 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ build/ .vscode/ /logs/ +/.shardingsphere/ -- Gitee From eea6682870465c3fe6ffb38dcf0e96d356ef055b Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Tue, 5 Jul 2022 23:58:09 +0800 Subject: [PATCH 059/112] =?UTF-8?q?docs:=20=E4=BC=98=E5=8C=96=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/github/xxyopen/novel/core/auth/AdminAuthStrategy.java | 3 ++- .../java/io/github/xxyopen/novel/core/auth/AuthStrategy.java | 5 +++-- .../github/xxyopen/novel/core/auth/AuthorAuthStrategy.java | 3 ++- .../io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/AdminAuthStrategy.java b/src/main/java/io/github/xxyopen/novel/core/auth/AdminAuthStrategy.java index 88759cb..a68dc70 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/AdminAuthStrategy.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/AdminAuthStrategy.java @@ -5,7 +5,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; /** - * 平台后台管理系统 认证策略 + * 平台后台管理系统 认证授权策略 * * @author xiongxiaoyang * @date 2022/5/18 @@ -18,4 +18,5 @@ public class AdminAuthStrategy implements AuthStrategy { public void auth(String token, String requestUri) throws BusinessException { // TODO 平台后台 token 校验 } + } \ No newline at end of file diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/AuthStrategy.java b/src/main/java/io/github/xxyopen/novel/core/auth/AuthStrategy.java index 99fbe12..758b1b0 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/AuthStrategy.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/AuthStrategy.java @@ -18,7 +18,7 @@ import org.springframework.util.StringUtils; public interface AuthStrategy { /** - * 请求用户认证 + * 用户认证授权 * * @param token 登录 token * @param requestUri 请求的 URI @@ -27,7 +27,7 @@ public interface AuthStrategy { void auth(String token, String requestUri) throws BusinessException; /** - * 前台多系统单点登录统一账号认证(门户系统、作家系统以及后面会扩展的漫画系统和视频系统等) + * 前台多系统单点登录统一账号认证授权(门户系统、作家系统以及后面会扩展的漫画系统和视频系统等) * * @param jwtUtils jwt 工具 * @param userInfoCacheManager 用户缓存管理对象 @@ -55,4 +55,5 @@ public interface AuthStrategy { // 返回 userId return userId; } + } diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java b/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java index 71e5ff1..f3e0827 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/AuthorAuthStrategy.java @@ -13,7 +13,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; /** - * 作家后台管理系统 认证策略 + * 作家后台管理系统 认证授权策略 * * @author xiongxiaoyang * @date 2022/5/18 @@ -54,4 +54,5 @@ public class AuthorAuthStrategy implements AuthStrategy { // 设置作家ID到当前线程 UserHolder.setAuthorId(authorInfo.getId()); } + } \ No newline at end of file diff --git a/src/main/java/io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java b/src/main/java/io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java index 4e1b807..214a747 100644 --- a/src/main/java/io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java +++ b/src/main/java/io/github/xxyopen/novel/core/auth/FrontAuthStrategy.java @@ -7,7 +7,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; /** - * 前台门户系统 认证策略 + * 前台门户系统 认证授权策略 * * @author xiongxiaoyang * @date 2022/5/18 @@ -25,4 +25,5 @@ public class FrontAuthStrategy implements AuthStrategy { // 统一账号认证 authSSO(jwtUtils, userInfoCacheManager, token); } + } \ No newline at end of file -- Gitee From 9600f9c7e658b209c71fd55d7b105f1a812cf373 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Wed, 6 Jul 2022 00:08:21 +0800 Subject: [PATCH 060/112] =?UTF-8?q?docs:=20=E4=BC=98=E5=8C=96=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/xxyopen/novel/core/interceptor/AuthInterceptor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java index e604cfb..3296a25 100644 --- a/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java @@ -18,7 +18,7 @@ import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** - * 认证 拦截器:为了注入其它的 Spring beans,需要通过 @Component 注解将该拦截器注册到 Spring 上下文 + * 认证授权 拦截器:为了注入其它的 Spring beans,需要通过 @Component 注解将该拦截器注册到 Spring 上下文 * * @author xiongxiaoyang * @date 2022/5/18 -- Gitee From ae7267b605a2fd1fff0da01b102a9a3465726e94 Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Wed, 6 Jul 2022 00:17:49 +0800 Subject: [PATCH 061/112] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 11faa54..f469b24 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,8 @@ io | | +- resp -- 接口响应工具及响应数据格式封装 | | +- util -- 通用工具 | | + | +- annotation -- 自定义注解类 + | +- aspect -- Spring AOP 切面 | +- auth -- 用户认证授权相关 | +- config -- 业务相关配置 | +- constant -- 业务相关常量 -- Gitee From fd9ce3cb496e0f7830b54339f4caffa62c7928d2 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 8 Jul 2022 07:59:24 +0800 Subject: [PATCH 062/112] =?UTF-8?q?docs:=20Java=20=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/style/intellij-java-google-style.xml | 627 ++--------------------- 1 file changed, 32 insertions(+), 595 deletions(-) diff --git a/doc/style/intellij-java-google-style.xml b/doc/style/intellij-java-google-style.xml index 67b3517..fb6821e 100644 --- a/doc/style/intellij-java-google-style.xml +++ b/doc/style/intellij-java-google-style.xml @@ -1,598 +1,35 @@ - - - -

- - - - xmlns:android - - ^$ - - - -
-
- - - - xmlns:.* - - ^$ - - - BY_NAME - -
-
- - - - .*:id - - http://schemas.android.com/apk/res/android - - - -
-
- - - - style - - ^$ - - - -
-
- - - - .* - - ^$ - - - BY_NAME - -
-
- - - - .*:.*Style - - http://schemas.android.com/apk/res/android - - - BY_NAME - -
-
- - - - .*:layout_width - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_height - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_weight - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_margin - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_marginTop - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_marginBottom - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_marginStart - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_marginEnd - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_marginLeft - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_marginRight - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:layout_.* - - http://schemas.android.com/apk/res/android - - - BY_NAME - -
-
- - - - .*:padding - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:paddingTop - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:paddingBottom - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:paddingStart - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:paddingEnd - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:paddingLeft - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:paddingRight - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .* - http://schemas.android.com/apk/res/android - - - BY_NAME - -
-
- - - - .* - http://schemas.android.com/apk/res-auto - - - BY_NAME - -
-
- - - - .* - http://schemas.android.com/tools - - - BY_NAME - -
-
- - - - .* - .* - - - BY_NAME - -
- - - - - - - - - + + + + -- Gitee From 4f7a4f964a226691cd2325750adccf12b127338a Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 8 Jul 2022 08:00:46 +0800 Subject: [PATCH 063/112] =?UTF-8?q?build:=20=E4=BE=9D=E8=B5=96=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 73fbb17..ba10b10 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - 4.0.0 @@ -23,6 +24,8 @@ 1.8.4 5.1.1 3.17.4 + 3.0.0-M1 + 2.0.0-M4-SNAPSHOT @@ -155,7 +158,7 @@ de.codecentric spring-boot-admin-starter-client - 3.0.0-M1 + ${spring-boot-admin.version} org.springframework.boot @@ -179,7 +182,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - 2.0.0-M4-SNAPSHOT + ${springdoc-openapi.version} -- Gitee From c3105c5b332327aca0bbb37205e3f32cb286e2c8 Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Fri, 8 Jul 2022 14:33:23 +0800 Subject: [PATCH 064/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f469b24..9cbb099 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![index]( https://s1.ax1x.com/2022/05/17/O5tgbR.png )]( https://curl.qcloud.com/kgMaOjoq )

- JDK 17 + Java 17 Spring Boot 3 Vue 3
Github stars -- Gitee From 6f6183af21ca2d9d084a76c434aec9823583f85d Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 9 Jul 2022 20:32:09 +0800 Subject: [PATCH 065/112] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E4=BA=91Maven=E4=B8=AD=E5=A4=AE=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pom.xml b/pom.xml index ba10b10..c8af1c4 100644 --- a/pom.xml +++ b/pom.xml @@ -224,6 +224,16 @@ + + ali + https://maven.aliyun.com/repository/public + + true + + + false + + spring-milestones Spring Milestones @@ -264,6 +274,16 @@ + + ali + https://maven.aliyun.com/repository/public + + true + + + false + + spring-milestones Spring Milestones -- Gitee From cf4c6b77dbbe04cfa9f86d7b6cf6d65218b3df70 Mon Sep 17 00:00:00 2001 From: 201206030 <1179705413@qq.com> Date: Tue, 12 Jul 2022 20:03:23 +0800 Subject: [PATCH 066/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9cbb099..ffeb29f 100644 --- a/README.md +++ b/README.md @@ -285,7 +285,7 @@ git clone https://gitee.com/novel_dev_team/novel-front-web.git - 回复「**笔记**」获取`Spring Boot 3 学习笔记` -![xxyopen](https://youdoc.gitee.io/img/qrcode_for_gh.jpg) +![xxyopen](https://youdoc.github.io/img/qrcode_for_gh.jpg) ## 赞赏支持 -- Gitee From 657c8a22863d867e72bb0ae7f4ce2ceb4837f1e1 Mon Sep 17 00:00:00 2001 From: xxy <1179705413@qq.com> Date: Fri, 15 Jul 2022 06:25:44 +0800 Subject: [PATCH 067/112] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ffeb29f..b73e131 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -[![index]( https://s1.ax1x.com/2022/05/17/O5tgbR.png )]( https://curl.qcloud.com/kgMaOjoq ) - +[![index]( https://youdoc.github.io/img/tencent.jpg )]( https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console )

Java 17 Spring Boot 3 -- Gitee From 8ba670cebb764f715de1d620b27f86625dc5693d Mon Sep 17 00:00:00 2001 From: xxy <1179705413@qq.com> Date: Thu, 21 Jul 2022 22:03:36 +0800 Subject: [PATCH 068/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b73e131..4fb1f76 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,7 @@ git clone https://gitee.com/novel_dev_team/novel-front-web.git ## 项目教程 -[手把手教你从零开始开发上线一个生产级别的小说系统](https://youdoc.github.io/course/novel/3.html) +[手把手教你从零开始开发上线一个生产级别的小说系统](https://docs.xxyopen.com/course/novel/3.html) ## 公众号 -- Gitee From 8b43851955ce0c179085a7906e980f3f7027e56b Mon Sep 17 00:00:00 2001 From: xxy <1179705413@qq.com> Date: Fri, 22 Jul 2022 21:16:54 +0800 Subject: [PATCH 069/112] Update README.md --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4fb1f76..c204c70 100644 --- a/README.md +++ b/README.md @@ -190,7 +190,7 @@ io - 下载后端源码 -``` +```bash git clone https://gitee.com/novel_dev_team/novel.git ``` @@ -208,7 +208,7 @@ git clone https://gitee.com/novel_dev_team/novel.git 1. 修改`src/resources/application.yml`配置文件中的数据源配置 - ``` + ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/novel_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai @@ -218,7 +218,7 @@ git clone https://gitee.com/novel_dev_team/novel.git 2. 修改`src/resources/application.yml` 和 `src/resources/redisson.yml` 配置文件中的`redis`连接配置 - ``` + ```yaml spring: redis: host: 127.0.0.1 @@ -226,7 +226,7 @@ git clone https://gitee.com/novel_dev_team/novel.git password: 123456 ``` - ``` + ```yaml singleServerConfig: address: "redis://127.0.0.1:6379" password: 123456 @@ -236,7 +236,7 @@ git clone https://gitee.com/novel_dev_team/novel.git 4. 项目根目录下运行如下命令来启动后端服务(有安装 IDE 的可以导入源码到 IDE 中运行) - ``` + ```bash mvn spring-boot:run ``` 5. 接口文档访问地址:`http://server:port/swagger-ui/index.html` @@ -244,7 +244,7 @@ git clone https://gitee.com/novel_dev_team/novel.git - 下载前端前台门户系统源码 -``` +```bash git clone https://gitee.com/novel_dev_team/novel-front-web.git ``` @@ -254,18 +254,18 @@ git clone https://gitee.com/novel_dev_team/novel-front-web.git 2. `yarn`安装 - ``` + ```bash npm install -g yarn ``` 3. 项目根目录下运行如下命令来安装项目依赖 - ``` + ```bash yarn install ``` 4. 项目根目录下运行如下命令启动 - ``` + ```bash yarn serve ``` 5. 浏览器通过`http://localhost:1024`来访问 -- Gitee From 1614e79106336407fe1c3d53854bf79a7215a2bb Mon Sep 17 00:00:00 2001 From: xxy <1179705413@qq.com> Date: Wed, 3 Aug 2022 19:11:04 +0800 Subject: [PATCH 070/112] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c204c70..9eae568 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,10 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 ## 项目地址 +- 网站:[项目官网](https://novel.xxyopen.com) | [演示站点](http://47.106.243.172:8888/) | [技术博客](https://www.xxyopen.com) | [在线文档](https://docs.xxyopen.com) - 后端项目(更新中):[GitHub](https://github.com/201206030/novel) | [码云](https://gitee.com/novel_dev_team/novel) - 前端项目(更新中):[GitHub](https://github.com/201206030/novel-front-web) | [码云](https://gitee.com/novel_dev_team/novel-front-web) -- 线上应用版:[GitHub](https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus) |[演示地址](http://47.106.243.172:8888/) +- 线上应用版:[GitHub](https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus) - 微服务版:[GitHub](https://github.com/201206030/novel-cloud) | [码云](https://gitee.com/novel_dev_team/novel-cloud) ## 开发环境 -- Gitee From ada179053c1e8932b26a75c21d99edf8c5fe07f0 Mon Sep 17 00:00:00 2001 From: xxy <1179705413@qq.com> Date: Thu, 4 Aug 2022 12:36:29 +0800 Subject: [PATCH 071/112] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 9eae568..9e95339 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,9 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 ## 项目地址 -- 网站:[项目官网](https://novel.xxyopen.com) | [演示站点](http://47.106.243.172:8888/) | [技术博客](https://www.xxyopen.com) | [在线文档](https://docs.xxyopen.com) - 后端项目(更新中):[GitHub](https://github.com/201206030/novel) | [码云](https://gitee.com/novel_dev_team/novel) - 前端项目(更新中):[GitHub](https://github.com/201206030/novel-front-web) | [码云](https://gitee.com/novel_dev_team/novel-front-web) -- 线上应用版:[GitHub](https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus) +- 线上应用版:[GitHub](https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus) | [演示站点](http://47.106.243.172:8888/) - 微服务版:[GitHub](https://github.com/201206030/novel-cloud) | [码云](https://gitee.com/novel_dev_team/novel-cloud) ## 开发环境 -- Gitee From 00acb47ec0ed410844777df523d959041d19f719 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 4 Aug 2022 23:57:51 +0800 Subject: [PATCH 072/112] =?UTF-8?q?build:=203.3.0=20=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c8af1c4..42428ef 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.github.xxyopen novel - 3.2.0 + 3.3.0 novel Spring Boot 3 + Vue 3 构建的前后端分离小说系统 -- Gitee From 7c0ff5e9ceb2f5ceb8aed8ed2e81050b3cf995c9 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 16 Aug 2022 21:37:02 +0800 Subject: [PATCH 073/112] Update README.md --- README.md | 111 ++++++++++-------------------------------------------- 1 file changed, 19 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index 9e95339..77e44d1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -[![index]( https://youdoc.github.io/img/tencent.jpg )]( https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console ) +

+ +

+ +------ +

Java 17 Spring Boot 3 @@ -12,13 +17,17 @@ ## 项目简介 -novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离的**学习型**小说项目,配备详细的项目教程手把手教你**从零开始**开发上线一个生产级别的 Java 系统,由小说门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成。包括小说推荐、作品检索、小说排行榜、小说阅读、小说评论、充值订阅、新闻发布等功能。 +novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离**学习型** +小说项目,配备[保姆级教程](https://docs.xxyopen.com/course/novel)手把手教你**从零开始**开发上线一套生产级别的 Java +系统,由小说门户系统、作家后台管理系统、平台后台管理系统等多个子系统构成。包括小说推荐、作品检索、小说排行榜、小说阅读、小说评论、会员中心、作家专区、充值订阅、新闻发布等功能。 ## 项目地址 - 后端项目(更新中):[GitHub](https://github.com/201206030/novel) | [码云](https://gitee.com/novel_dev_team/novel) -- 前端项目(更新中):[GitHub](https://github.com/201206030/novel-front-web) | [码云](https://gitee.com/novel_dev_team/novel-front-web) -- 线上应用版:[GitHub](https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus) | [演示站点](http://47.106.243.172:8888/) +- 前端项目(更新中):[GitHub](https://github.com/201206030/novel-front-web) + | [码云](https://gitee.com/novel_dev_team/novel-front-web) +- 线上应用版:[GitHub](https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus) + | [演示站点](http://47.106.243.172:8888/) - 微服务版:[GitHub](https://github.com/201206030/novel-cloud) | [码云](https://gitee.com/novel_dev_team/novel-cloud) ## 开发环境 @@ -61,6 +70,7 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | **注:更多热门新技术待集成。** + ## 前端技术选型 | 技术 | 版本 | 说明 | 官网 | 学习 | @@ -70,7 +80,7 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | axios | 0.27.2 | 基于 promise 的网络请求库 | https://axios-http.com | [进入](https://axios-http.com/zh/docs/intro) | | element-plus | 2.2.0 | 基于 Vue 3,面向设计师和开发者的组件库 | https://element-plus.org | [进入](https://element-plus.org/zh-CN/guide/design.html) | -## 编码规范 +## 编码规范 - 规范方式:严格遵守阿里编码规约。 - 命名统一:简介最大程度上达到了见名知意。 @@ -183,97 +193,14 @@ io ![img](https://youdoc.github.io/img/novel/SwaggerUI.png) - ## 安装步骤 -此安装步骤的前提是需要保证上一节的开发环境可用。 - -- 下载后端源码 - -```bash -git clone https://gitee.com/novel_dev_team/novel.git -``` - -- 数据库文件导入 - - 1. 新建数据库(建议 novel) - - 2. 解压后端源码`doc/sql/novel.sql.zip`压缩包,得到数据库结构文件`novel_struc.sql`和数据库小说数据文件`novel_data.sql` - - 3. 导入`novel_struct.sql`数据库结构文件 - - 4. 导入`novel_data.sql`数据库小说数据文件 - -- novel 后端服务安装 - - 1. 修改`src/resources/application.yml`配置文件中的数据源配置 - - ```yaml - spring: - datasource: - url: jdbc:mysql://localhost:3306/novel_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 - ``` - - 2. 修改`src/resources/application.yml` 和 `src/resources/redisson.yml` 配置文件中的`redis`连接配置 - - ```yaml - spring: - redis: - host: 127.0.0.1 - port: 6379 - password: 123456 - ``` - - ```yaml - singleServerConfig: - address: "redis://127.0.0.1:6379" - password: 123456 - ``` - - 3. 根据前后端的实际部署情况,修改`application.yml`中的跨域配置(默认情况可忽略此步骤) - - 4. 项目根目录下运行如下命令来启动后端服务(有安装 IDE 的可以导入源码到 IDE 中运行) - - ```bash - mvn spring-boot:run - ``` - 5. 接口文档访问地址:`http://server:port/swagger-ui/index.html` - - -- 下载前端前台门户系统源码 - -```bash -git clone https://gitee.com/novel_dev_team/novel-front-web.git -``` - -- novel-front-web 前端前台门户系统安装 - - 1. 根据前后端的实际部署情况,修改`.env.development`中的`VUE_APP_BASE_API_URL`属性(默认情况可忽略此步骤) - - 2. `yarn`安装 - - ```bash - npm install -g yarn - ``` - - 3. 项目根目录下运行如下命令来安装项目依赖 - - ```bash - yarn install - ``` - 4. 项目根目录下运行如下命令启动 +👉 [立即查看](https://docs.xxyopen.com/course/novel/#%E5%AE%89%E8%A3%85%E6%AD%A5%E9%AA%A4) - ```bash - yarn serve - ``` - 5. 浏览器通过`http://localhost:1024`来访问 +## 答疑 -## 项目教程 +为了方便管理和查阅,安装过程中遇到任何问题请统一在指定评论区 👉 [立即前往](https://www.xxyopen.com/2022/07/18/os/novel.html) 留言 ,谢谢大家的配合! -[手把手教你从零开始开发上线一个生产级别的小说系统](https://docs.xxyopen.com/course/novel/3.html) - ## 公众号 - 关注公众号接收`项目`和`文档`的更新动态 @@ -295,4 +222,4 @@ git clone https://gitee.com/novel_dev_team/novel-front-web.git - 为用户提供更好的开发环境 - 一杯咖啡 -![mini-code](https://s1.ax1x.com/2020/10/31/BUQJwq.png) +![](https://s1.ax1x.com/2020/10/31/BUQJwq.png) \ No newline at end of file -- Gitee From 3e89d2a363610360037fbdd59253695d5142df98 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 19 Aug 2022 19:36:08 +0800 Subject: [PATCH 074/112] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/core/aspect/LockAspect.java | 13 ++- .../xxyopen/novel/core/config/EsConfig.java | 2 +- .../novel/core/config/XxlJobConfig.java | 4 +- .../core/listener/RabbitQueueListener.java | 4 +- .../xxyopen/novel/core/task/BookToEsTask.java | 5 +- .../novel/manager/mq/AmqpMsgManager.java | 8 +- .../service/impl/DbSearchServiceImpl.java | 5 +- .../service/impl/EsSearchServiceImpl.java | 9 +- ...itional-spring-configuration-metadata.json | 65 +++++++++++++ src/main/resources/application.yml | 92 +++++++++++-------- 10 files changed, 147 insertions(+), 60 deletions(-) create mode 100644 src/main/resources/META-INF/additional-spring-configuration-metadata.json diff --git a/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java b/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java index 0b19ccf..fbdecc7 100644 --- a/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java +++ b/src/main/java/io/github/xxyopen/novel/core/aspect/LockAspect.java @@ -3,9 +3,7 @@ package io.github.xxyopen.novel.core.aspect; import io.github.xxyopen.novel.core.annotation.Key; import io.github.xxyopen.novel.core.annotation.Lock; import io.github.xxyopen.novel.core.common.exception.BusinessException; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -20,6 +18,10 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.concurrent.TimeUnit; + /** * 分布式锁 切面 * @@ -28,7 +30,10 @@ import org.springframework.util.StringUtils; */ @Aspect @Component -public record LockAspect(RedissonClient redissonClient) { +@RequiredArgsConstructor +public class LockAspect { + + private final RedissonClient redissonClient; private static final String KEY_PREFIX = "Lock"; diff --git a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java index df33e09..0bb2fb9 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java @@ -17,7 +17,7 @@ import org.springframework.context.annotation.Configuration; * @date 2022/5/23 */ @Configuration -@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "true") +@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enabled", havingValue = "true") @RequiredArgsConstructor public class EsConfig { diff --git a/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java index c722bed..5d87be1 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/XxlJobConfig.java @@ -2,8 +2,6 @@ package io.github.xxyopen.novel.core.config; import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; @@ -16,7 +14,7 @@ import org.springframework.context.annotation.Configuration; * @date 2022/5/31 */ @Configuration -@ConditionalOnProperty(prefix = "xxl.job", name = "enable", havingValue = "true") +@ConditionalOnProperty(prefix = "xxl.job", name = "enabled", havingValue = "true") @Slf4j public class XxlJobConfig { diff --git a/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java b/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java index 49bb16c..2189bef 100644 --- a/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java +++ b/src/main/java/io/github/xxyopen/novel/core/listener/RabbitQueueListener.java @@ -21,8 +21,8 @@ import org.springframework.stereotype.Component; * @date 2022/5/25 */ @Component -@ConditionalOnProperty(prefix = "spring", name = {"elasticsearch.enable", - "amqp.enable"}, havingValue = "true") +@ConditionalOnProperty(prefix = "spring", name = {"elasticsearch.enabled", + "amqp.enabled"}, havingValue = "true") @RequiredArgsConstructor @Slf4j public class RabbitQueueListener { diff --git a/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java b/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java index b597e21..e1008f5 100644 --- a/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java +++ b/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java @@ -13,20 +13,21 @@ import io.github.xxyopen.novel.core.constant.EsConsts; import io.github.xxyopen.novel.dao.entity.BookInfo; import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.es.EsBookDto; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; +import java.util.List; + /** * 小说数据同步到 elasticsearch 任务 * * @author xiongxiaoyang * @date 2022/5/23 */ -@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "true") +@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enabled", havingValue = "true") @Component @RequiredArgsConstructor @Slf4j diff --git a/src/main/java/io/github/xxyopen/novel/manager/mq/AmqpMsgManager.java b/src/main/java/io/github/xxyopen/novel/manager/mq/AmqpMsgManager.java index 8a5b667..dd0ad14 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/mq/AmqpMsgManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/mq/AmqpMsgManager.java @@ -1,8 +1,6 @@ package io.github.xxyopen.novel.manager.mq; -import io.github.xxyopen.novel.core.common.constant.CommonConsts; import io.github.xxyopen.novel.core.constant.AmqpConsts; -import java.util.Objects; import lombok.RequiredArgsConstructor; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.beans.factory.annotation.Value; @@ -22,14 +20,14 @@ public class AmqpMsgManager { private final AmqpTemplate amqpTemplate; - @Value("${spring.amqp.enable}") - private String enableAmqp; + @Value("${spring.amqp.enabled:false}") + private boolean amqpEnabled; /** * 发送小说信息改变消息 */ public void sendBookChangeMsg(Long bookId) { - if (Objects.equals(enableAmqp, CommonConsts.TRUE)) { + if (amqpEnabled) { sendAmqpMessage(amqpTemplate, AmqpConsts.BookChangeMq.EXCHANGE_NAME, null, bookId); } } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java index 96d9423..48477fe 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/DbSearchServiceImpl.java @@ -8,19 +8,20 @@ import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.req.BookSearchReqDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.service.SearchService; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import java.util.List; + /** * 数据库搜索 服务实现类 * * @author xiongxiaoyang * @date 2022/5/23 */ -@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "false") +@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enabled", havingValue = "false") @Service @RequiredArgsConstructor @Slf4j diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java index c004802..b2b7d75 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java @@ -19,22 +19,23 @@ import io.github.xxyopen.novel.dto.es.EsBookDto; import io.github.xxyopen.novel.dto.req.BookSearchReqDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; import io.github.xxyopen.novel.service.SearchService; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + /** * Elasticsearch 搜索 服务实现类 * * @author xiongxiaoyang * @date 2022/5/23 */ -@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "true") +@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enabled", havingValue = "true") @Service @RequiredArgsConstructor @Slf4j diff --git a/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 0000000..db7e44c --- /dev/null +++ b/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,65 @@ +{ + "properties": [ + { + "name": "spring.elasticsearch.enabled", + "description": "Whether enable elasticsearch or not.", + "type": "java.lang.Boolean" + }, + { + "defaultValue": false, + "name": "spring.amqp.enabled", + "description": "Whether enable amqp or not.", + "type": "java.lang.Boolean" + }, + { + "name": "xxl.job.enabled", + "description": "Whether enable xxl-job or not.", + "type": "java.lang.Boolean" + }, + { + "name": "novel.jwt.secret", + "type": "java.lang.String", + "description": "JWT 密钥." + }, + { + "name": "novel.xss.enabled", + "type": "java.lang.Boolean", + "description": "是否开启 XSS 过滤." + }, + { + "name": "novel.xss.excludes", + "type": "java.util.List", + "description": "XSS 过滤排除链接." + }, + { + "name": "novel.file.upload.path", + "type": "java.lang.String", + "description": "上传文件目录." + }, + { + "name": "novel.cors.allow-origins", + "type": "java.util.List", + "description": "允许跨域的域名." + }, + { + "name": "xxl.job.admin.addresses", + "type": "java.lang.String", + "description": "调度中心部署根地址." + }, + { + "name": "xxl.job.executor.appname", + "type": "java.lang.String", + "description": "执行器 AppName." + }, + { + "name": "xxl.job.executor.logpath", + "type": "java.lang.String", + "description": "执行器运行日志文件存储磁盘路径." + }, + { + "name": "xxl.job.accessToken", + "type": "java.lang.String", + "description": "xxl-job accessToken." + } + ] +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 53924df..6c8beae 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,20 +1,26 @@ +#---------------------通用配置------------------------- spring: + application: + # 应用名 + name: novel profiles: + # 激活特定配置 active: dev -# 将所有数字转为 String 类型返回,避免前端数据精度丢失的问题 jackson: generator: + # JSON 序列化时,将所有 Number 类型的属性都转为 String 类型返回,避免前端数据精度丢失的问题。 + # 由于 Javascript 标准规定所有数字处理都应使用 64 位 IEEE 754 浮点值完成, + # 结果是某些 64 位整数值无法准确表示(尾数只有 51 位宽) write-numbers-as-strings: true servlet: - # 上传文件最大大小 multipart: + # 上传文件最大大小 max-file-size: 5MB - application: - name: novel - server: + # 端口号 port: 8888 +#---------------------数据库配置------------------------- --- spring: datasource: @@ -75,31 +81,29 @@ spring: # 分片算法的行表达式 algorithm-expression: book_content$->{chapter_id % 10} - config: - activate: - on-profile: dev - +#---------------------中间件配置------------------------- --- spring: - # Redis 配置 - redis: - host: 127.0.0.1 - port: 6379 - password: 123456 - config: - activate: - on-profile: dev + data: + # Redis 配置 + redis: + host: 127.0.0.1 + port: 6379 + password: 123456 + # Elasticsearch 配置 elasticsearch: - # 是否开启 elasticsearch 搜索引擎功能:true-开启 false-不开启 - enable: false + # 是否开启 Elasticsearch 搜索引擎功能:true-开启 false-不开启 + enabled: false uris: - https://my-deployment-ce7ca3.es.us-central1.gcp.cloud.es.io:9243 username: elastic password: qTjgYVKSuExX6tWAsDuvuvwl + + # Spring AMQP 配置 amqp: # 是否开启 Spring AMQP:true-开启 false-不开启 - enable: false + enabled: false # RabbitMQ 配置 rabbitmq: addresses: "amqp://guest:guest@47.106.243.172" @@ -117,7 +121,7 @@ spring: xxl: job: # 是否开启 XXL-JOB:true-开启 false-不开启 - enable: false + enabled: false admin: ### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册; addresses: http://127.0.0.1:8080/xxl-job-admin @@ -129,13 +133,10 @@ xxl: ### xxl-job, access token accessToken: 123 - +#---------------------安全配置------------------------- --- spring: - config: - activate: - on-profile: dev -# Spring Boot 应用管理和监控 + # Spring Boot 应用管理和监控 boot: admin: client: @@ -167,7 +168,6 @@ management: exposure: # 公开所有的 Web 端点 include: "*" - # 端点启用配置 endpoint: logfile: @@ -175,7 +175,6 @@ management: enabled: true # 外部日志文件路径 external-file: logs/novel.log - info: env: # 公开所有以 info. 开头的环境属性 @@ -188,15 +187,7 @@ management: # 关闭 elasticsearch 的健康检查 enabled: false - - ---- -spring: - config: - activate: - on-profile: dev - -# 项目配置 +#---------------------自定义配置------------------------- novel: # 跨域配置 cors: @@ -221,4 +212,31 @@ novel: path: /Users/xiongxiaoyang/upload +#----------------------- dev 特定配置----------------------------- +--- +spring: + config: + activate: + on-profile: dev + +#----------------------- test 特定配置----------------------------- +--- +spring: + config: + activate: + on-profile: test + +#----------------------- prod 特定配置----------------------------- +--- +spring: + config: + activate: + on-profile: prod + data: + # Redis 配置 + redis: + host: 127.0.0.1 + port: 6379 + password: + -- Gitee From 570ef7e7cb421427556b374472604f40f7cc50a9 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 19 Aug 2022 20:33:00 +0800 Subject: [PATCH 075/112] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 6c8beae..f671caf 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,4 @@ -#---------------------通用配置------------------------- +#--------------------------通用配置------------------------- spring: application: # 应用名 @@ -20,8 +20,7 @@ server: # 端口号 port: 8888 -#---------------------数据库配置------------------------- ---- +--- #---------------------数据库配置--------------------------- spring: datasource: url: jdbc:mysql://localhost:3306/novel_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai @@ -81,8 +80,7 @@ spring: # 分片算法的行表达式 algorithm-expression: book_content$->{chapter_id % 10} -#---------------------中间件配置------------------------- ---- +--- #---------------------中间件配置--------------------------- spring: data: # Redis 配置 @@ -133,8 +131,7 @@ xxl: ### xxl-job, access token accessToken: 123 -#---------------------安全配置------------------------- ---- +--- #----------------------安全配置---------------------------- spring: # Spring Boot 应用管理和监控 boot: @@ -187,7 +184,7 @@ management: # 关闭 elasticsearch 的健康检查 enabled: false -#---------------------自定义配置------------------------- +--- #---------------------自定义配置---------------------------- novel: # 跨域配置 cors: @@ -212,22 +209,19 @@ novel: path: /Users/xiongxiaoyang/upload -#----------------------- dev 特定配置----------------------------- ---- +--- #------------------- dev 特定配置--------------------------- spring: config: activate: on-profile: dev -#----------------------- test 特定配置----------------------------- ---- +--- #------------------- test 特定配置-------------------------- spring: config: activate: on-profile: test -#----------------------- prod 特定配置----------------------------- ---- +--- #-------------------- prod 特定配置------------------------- spring: config: activate: -- Gitee From 3dc7ed59a15ff5fa13f3c24ad81acd6e4f6c7b78 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 20 Aug 2022 15:06:50 +0800 Subject: [PATCH 076/112] Update README.md --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 77e44d1..829769f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,4 @@ -

- -

- ------- +[![index]( https://youdoc.github.io/img/tencent.jpg )]( https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console )

Java 17 -- Gitee From 87fdd2e6fca4ba74e46f513473b9a496819876d2 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 1 Sep 2022 09:50:36 +0800 Subject: [PATCH 077/112] =?UTF-8?q?perf:=20=E4=BB=85=E5=9C=A8=20dev=20?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E7=94=9F=E6=88=90=E6=8E=A5=E5=8F=A3=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xxyopen/novel/NovelApplication.java | 12 ++------- .../novel/core/config/OpenApiConfig.java | 25 +++++++++++++++++++ src/main/resources/application.yml | 8 ++++++ 3 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 src/main/java/io/github/xxyopen/novel/core/config/OpenApiConfig.java diff --git a/src/main/java/io/github/xxyopen/novel/NovelApplication.java b/src/main/java/io/github/xxyopen/novel/NovelApplication.java index 7b6dae1..963962a 100644 --- a/src/main/java/io/github/xxyopen/novel/NovelApplication.java +++ b/src/main/java/io/github/xxyopen/novel/NovelApplication.java @@ -1,13 +1,5 @@ package io.github.xxyopen.novel; -import io.github.xxyopen.novel.core.constant.SystemConfigConsts; -import io.swagger.v3.oas.annotations.OpenAPIDefinition; -import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; -import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; -import io.swagger.v3.oas.annotations.info.Info; -import io.swagger.v3.oas.annotations.info.License; -import io.swagger.v3.oas.annotations.security.SecurityScheme; -import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.CommandLineRunner; @@ -22,8 +14,8 @@ import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; -@OpenAPIDefinition(info = @Info(title = "novel 项目接口文档", version = "v3.2.0", license = @License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0"))) -@SecurityScheme(type = SecuritySchemeType.APIKEY, in = SecuritySchemeIn.HEADER, name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME, description = "登录 token") +import java.util.Map; + @SpringBootApplication @MapperScan("io.github.xxyopen.novel.dao.mapper") @EnableCaching diff --git a/src/main/java/io/github/xxyopen/novel/core/config/OpenApiConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/OpenApiConfig.java new file mode 100644 index 0000000..c66b998 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/config/OpenApiConfig.java @@ -0,0 +1,25 @@ +package io.github.xxyopen.novel.core.config; + +import io.github.xxyopen.novel.core.constant.SystemConfigConsts; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.info.License; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +/** + * OpenApi 配置类 + * + * @author xiongxiaoyang + * @date 2022/9/1 + */ +@Configuration +@Profile("dev") +@OpenAPIDefinition(info = @Info(title = "novel 项目接口文档", version = "v3.2.0", license = @License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0"))) +@SecurityScheme(type = SecuritySchemeType.APIKEY, in = SecuritySchemeIn.HEADER, name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME, description = "登录 token") +public class OpenApiConfig { + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f671caf..69d9e2c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -184,6 +184,11 @@ management: # 关闭 elasticsearch 的健康检查 enabled: false +--- #--------------------接口文档配置--------------------------- +springdoc: + api-docs: + enabled: false + --- #---------------------自定义配置---------------------------- novel: # 跨域配置 @@ -214,6 +219,9 @@ spring: config: activate: on-profile: dev +springdoc: + api-docs: + enabled: true --- #------------------- test 特定配置-------------------------- spring: -- Gitee From 31bd2c0bf80151c794f73f27a772240acf67b580 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 21 Sep 2022 15:05:29 +0800 Subject: [PATCH 078/112] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=BF=9B?= =?UTF-8?q?=E5=85=A5=E4=BD=9C=E5=AE=B6=E4=B8=93=E5=8C=BA=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E8=AE=BF=E9=97=AE=E6=9C=AA=E6=8E=88=E6=9D=83=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原因:Spring Boot 3.0.0 在第 4 个 M(里程碑)版本中增加了 ElasticsearchClientConfigurations 配置类,该类改变了 Spring Boot Jackson 的默认配置,导致所有 null 属性都没有返回。 解决方案:将 Spring Boot 的版本修改为 M3 ,因为 SNAPSHOT(快照)版本一直在更新,后面可能会出现类似的问题,暂时不使用 Spring Boot 的 SNAPSHOT 版本,等 GA 版本发布后,再统一升级。 --- pom.xml | 35 +++++++++--------------------- src/main/resources/application.yml | 11 +++++----- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index 42428ef..6a006f9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,8 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 3.0.0-SNAPSHOT - + 3.0.0-M3 io.github.xxyopen novel @@ -17,7 +16,6 @@ 17 3.5.1 - 6.0.0-SNAPSHOT 0.11.5 8.2.0 2.3.1 @@ -235,20 +233,15 @@ - spring-milestones - Spring Milestones - https://repo.spring.io/milestone + spring-snapshots + https://repo.spring.io/snapshot - false + true - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - + spring-milestones + https://repo.spring.io/milestone sonatype-nexus-snapshots @@ -284,21 +277,13 @@ false - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - spring-snapshots - Spring Snapshots https://repo.spring.io/snapshot - - false - + + + spring-milestones + https://repo.spring.io/milestone diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 69d9e2c..2b600ed 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -82,12 +82,11 @@ spring: --- #---------------------中间件配置--------------------------- spring: - data: - # Redis 配置 - redis: - host: 127.0.0.1 - port: 6379 - password: 123456 + # Redis 配置 + redis: + host: 127.0.0.1 + port: 6379 + password: 123456 # Elasticsearch 配置 elasticsearch: -- Gitee From a3a2384c95a94b2cd3a9d4ca97b97d776fea179e Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 21 Sep 2022 16:57:14 +0800 Subject: [PATCH 079/112] =?UTF-8?q?build:=20=E5=8D=87=E7=BA=A7=20Spring=20?= =?UTF-8?q?Boot=20=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 35 +++++++++++++------ .../xxyopen/novel/core/config/EsConfig.java | 21 +++-------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/pom.xml b/pom.xml index 6a006f9..9d25a1b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,8 @@ org.springframework.boot spring-boot-starter-parent - 3.0.0-M3 + 3.0.0-M4 + io.github.xxyopen novel @@ -16,6 +17,7 @@ 17 3.5.1 + 6.0.0-SNAPSHOT 0.11.5 8.2.0 2.3.1 @@ -233,15 +235,20 @@ - spring-snapshots - https://repo.spring.io/snapshot + spring-milestones + Spring Milestones + https://repo.spring.io/milestone - true + false - spring-milestones - https://repo.spring.io/milestone + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + false + sonatype-nexus-snapshots @@ -277,13 +284,21 @@ false - - spring-snapshots - https://repo.spring.io/snapshot - spring-milestones + Spring Milestones https://repo.spring.io/milestone + + false + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + false + diff --git a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java index 0bb2fb9..58eafa9 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java @@ -1,12 +1,6 @@ package io.github.xxyopen.novel.core.config; -import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import lombok.RequiredArgsConstructor; -import org.elasticsearch.client.RestClient; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -17,19 +11,14 @@ import org.springframework.context.annotation.Configuration; * @date 2022/5/23 */ @Configuration -@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enabled", havingValue = "true") -@RequiredArgsConstructor public class EsConfig { + /** + * 解决 ElasticsearchClientConfigurations 修改默认 ObjectMapper 配置的问题 + */ @Bean - public ElasticsearchClient elasticsearchClient(RestClient restClient) { - - // Create the transport with a Jackson mapper - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper()); - - // And create the API client - return new ElasticsearchClient(transport); + JacksonJsonpMapper jacksonJsonpMapper() { + return new JacksonJsonpMapper(); } } -- Gitee From 4b3bcff05f4e6c59272c1dc393e34acde672bd88 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 29 Sep 2022 10:51:54 +0800 Subject: [PATCH 080/112] =?UTF-8?q?build(pom.xml):=20=E6=B8=85=E7=90=86=20?= =?UTF-8?q?SNAPSHOT=20=E4=BB=93=E5=BA=93=E5=92=8C=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 45 +++------------------------------------------ 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/pom.xml b/pom.xml index 9d25a1b..e9ae02d 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,6 @@ 17 3.5.1 - 6.0.0-SNAPSHOT 0.11.5 8.2.0 2.3.1 @@ -25,7 +24,7 @@ 5.1.1 3.17.4 3.0.0-M1 - 2.0.0-M4-SNAPSHOT + 2.0.0-M4 @@ -225,7 +224,7 @@ - ali + aliyun https://maven.aliyun.com/repository/public true @@ -242,40 +241,10 @@ false - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots/ - - true - - - false - - - - sonatype-nexus-snapshots-2 - Sonatype Nexus Snapshots 2 - https://s01.oss.sonatype.org/content/repositories/snapshots/ - - true - - - false - - - ali + aliyun https://maven.aliyun.com/repository/public true @@ -292,14 +261,6 @@ false - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - -- Gitee From 0ae939da16c6ba3eac74541c4cd9bf526d9888c7 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 6 Jan 2023 13:29:42 +0800 Subject: [PATCH 081/112] =?UTF-8?q?build:=20=E5=8D=87=E7=BA=A7=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 29 +++++-------------- .../xxyopen/novel/NovelApplication.java | 4 +-- .../core/NestedIOException.java | 15 ---------- src/main/resources/application.yml | 11 +++---- 4 files changed, 15 insertions(+), 44 deletions(-) delete mode 100644 src/main/java/org/springframework/core/NestedIOException.java diff --git a/pom.xml b/pom.xml index e9ae02d..483801a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 3.0.0-M4 + 3.0.0 io.github.xxyopen @@ -16,7 +16,8 @@ Spring Boot 3 + Vue 3 构建的前后端分离小说系统 17 - 3.5.1 + 3.5.3 + 3.5.1 0.11.5 8.2.0 2.3.1 @@ -24,7 +25,7 @@ 5.1.1 3.17.4 3.0.0-M1 - 2.0.0-M4 + 2.0.0 @@ -57,7 +58,7 @@ com.baomidou mybatis-plus-generator - ${mybatis-plus.version} + ${mybatis-plus-generator.version} test @@ -185,8 +186,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j runtime @@ -233,14 +234,6 @@ false - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - @@ -253,14 +246,6 @@ false - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - diff --git a/src/main/java/io/github/xxyopen/novel/NovelApplication.java b/src/main/java/io/github/xxyopen/novel/NovelApplication.java index 963962a..1f1c819 100644 --- a/src/main/java/io/github/xxyopen/novel/NovelApplication.java +++ b/src/main/java/io/github/xxyopen/novel/NovelApplication.java @@ -43,8 +43,8 @@ public class NovelApplication { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf().disable() - .requestMatcher(EndpointRequest.toAnyEndpoint()) - .authorizeRequests(requests -> requests.anyRequest().hasRole("ENDPOINT_ADMIN")); + .securityMatcher(EndpointRequest.toAnyEndpoint()) + .authorizeHttpRequests(requests -> requests.anyRequest().hasRole("ENDPOINT_ADMIN")); http.httpBasic(); return http.build(); } diff --git a/src/main/java/org/springframework/core/NestedIOException.java b/src/main/java/org/springframework/core/NestedIOException.java deleted file mode 100644 index 19d5f88..0000000 --- a/src/main/java/org/springframework/core/NestedIOException.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.springframework.core; - -import java.io.IOException; - -/** - * 兼容 mybatis-plus 3.5.1 - * mybatis-plus 的 MybatisSqlSessionFactoryBean 中使用到了这个异常 - * Spring 6 开始移除了该异常 - * - * @author xiongxiaoyang - * @date 2022/5/12 - */ -public class NestedIOException extends IOException { - -} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2b600ed..69d9e2c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -82,11 +82,12 @@ spring: --- #---------------------中间件配置--------------------------- spring: - # Redis 配置 - redis: - host: 127.0.0.1 - port: 6379 - password: 123456 + data: + # Redis 配置 + redis: + host: 127.0.0.1 + port: 6379 + password: 123456 # Elasticsearch 配置 elasticsearch: -- Gitee From fefa5d94caf66ba1dfa26a4f668bc36b6fcd50ac Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 6 Jan 2023 13:46:40 +0800 Subject: [PATCH 082/112] Update README.md --- README.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 829769f..6380ceb 100644 --- a/README.md +++ b/README.md @@ -42,28 +42,28 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 ## 后端技术选型 -| 技术 | 版本 | 说明 | 官网 | 学习 | -|---------------------|:--------------:|---------------------| --------------------------------------- |:---------------------------------------------------------------------------------------:| -| Spring Boot | 3.0.0-SNAPSHOT | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://youdoc.github.io/course/novel/11.html) | -| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | -| MyBatis-Plus | 3.5.1 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | -| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | -| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | -| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | -| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | -| Redisson | 3.17.4 | 分布式锁实现 | https://github.com/redisson/redisson | [进入](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | -| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | -| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | -| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | -| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | -| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | -| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | -| Springdoc-openapi | 2.0.0-M4-SNAPSHOT | Swagger 3 接口文档自动生成 | https://github.com/springdoc/springdoc-openapi | [进入](https://springdoc.org/) | -| Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | -| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | -| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | -| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | -| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | +| 技术 | 版本 | 说明 | 官网 | 学习 | +|---------------------|:--------------:|---------------------| --------------------------------------- |:-----------------------------------------------------------------------------------------------------------------------------:| +| Spring Boot | 3.0.0 | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://docs.spring.io/spring-boot/docs/3.0.0/reference/html) | +| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | +| MyBatis-Plus | 3.5.3 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | +| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | +| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | +| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | +| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | +| Redisson | 3.17.4 | 分布式锁实现 | https://github.com/redisson/redisson | [进入](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | +| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | +| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | +| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | +| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | +| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | +| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | +| Springdoc-openapi | 2.0.0 | Swagger 3 接口文档自动生成 | https://github.com/springdoc/springdoc-openapi | [进入](https://springdoc.org/) | +| Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | +| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | +| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | +| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | +| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | **注:更多热门新技术待集成。** -- Gitee From a318b05beeb5fe46605e3e40105b9564443a5ea8 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 11 Jan 2023 10:15:10 +0800 Subject: [PATCH 083/112] build: Use redisson-spring-boot-starter dependency instead of redisson dependency --- pom.xml | 4 +-- .../novel/core/config/RedissonConfig.java | 26 ------------------- src/main/resources/redisson.yml | 3 --- 3 files changed, 2 insertions(+), 31 deletions(-) delete mode 100644 src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java delete mode 100644 src/main/resources/redisson.yml diff --git a/pom.xml b/pom.xml index 483801a..691cfa1 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 2.3.1 1.8.4 5.1.1 - 3.17.4 + 3.19.1 3.0.0-M1 2.0.0 @@ -168,7 +168,7 @@ org.redisson - redisson + redisson-spring-boot-starter ${redisson.version} diff --git a/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java deleted file mode 100644 index ad85852..0000000 --- a/src/main/java/io/github/xxyopen/novel/core/config/RedissonConfig.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.xxyopen.novel.core.config; - -import lombok.SneakyThrows; -import org.redisson.Redisson; -import org.redisson.api.RedissonClient; -import org.redisson.config.Config; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Redisson 配置类 - * - * @author xiongxiaoyang - * @date 2022/6/20 - */ -@Configuration -public class RedissonConfig { - - @Bean - @SneakyThrows - public RedissonClient redissonClient() { - Config config = Config.fromYAML(getClass().getResource("/redisson.yml")); - return Redisson.create(config); - } - -} diff --git a/src/main/resources/redisson.yml b/src/main/resources/redisson.yml deleted file mode 100644 index bfe1a47..0000000 --- a/src/main/resources/redisson.yml +++ /dev/null @@ -1,3 +0,0 @@ -singleServerConfig: - address: "redis://127.0.0.1:6379" - password: 123456 -- Gitee From b5be90941523e8ddc90fb48b00008f63cbc84e01 Mon Sep 17 00:00:00 2001 From: xxy <1179705413@qq.com> Date: Wed, 11 Jan 2023 20:58:06 +0800 Subject: [PATCH 084/112] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 6380ceb..ac7f25a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 - 前端项目(更新中):[GitHub](https://github.com/201206030/novel-front-web) | [码云](https://gitee.com/novel_dev_team/novel-front-web) - 线上应用版:[GitHub](https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus) - | [演示站点](http://47.106.243.172:8888/) - 微服务版:[GitHub](https://github.com/201206030/novel-cloud) | [码云](https://gitee.com/novel_dev_team/novel-cloud) ## 开发环境 @@ -218,4 +217,4 @@ io - 为用户提供更好的开发环境 - 一杯咖啡 -![](https://s1.ax1x.com/2020/10/31/BUQJwq.png) \ No newline at end of file +![](https://s1.ax1x.com/2020/10/31/BUQJwq.png) -- Gitee From 3c93f90fad6482e6397b7fc30931a1b71dc95610 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 11 Mar 2023 22:38:08 +0800 Subject: [PATCH 085/112] =?UTF-8?q?fix(interceptor):=20handler=20=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=BC=82=E5=B8=B8=E6=97=B6=E6=B2=A1=E6=9C=89=E6=B8=85?= =?UTF-8?q?=E7=90=86=E6=8E=89=E5=BD=93=E5=89=8D=E7=BA=BF=E7=A8=8B=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E7=9A=84=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/interceptor/AuthInterceptor.java | 24 ++++++++++++++++--- .../interceptor/TokenParseInterceptor.java | 13 ++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java index 3296a25..2f16f58 100644 --- a/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/AuthInterceptor.java @@ -9,14 +9,15 @@ import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.nio.charset.StandardCharsets; -import java.util.Map; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; +import java.nio.charset.StandardCharsets; +import java.util.Map; + /** * 认证授权 拦截器:为了注入其它的 Spring beans,需要通过 @Component 注解将该拦截器注册到 Spring 上下文 * @@ -31,6 +32,9 @@ public class AuthInterceptor implements HandlerInterceptor { private final ObjectMapper objectMapper; + /** + * handle 执行前调用 + */ @SuppressWarnings("NullableProblems") @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, @@ -60,12 +64,26 @@ public class AuthInterceptor implements HandlerInterceptor { } } + /** + * handler 执行后调用,出现异常不调用 + */ @SuppressWarnings("NullableProblems") @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); + } + + /** + * DispatcherServlet 完全处理完请求后调用,出现异常照常调用 + */ + @SuppressWarnings("NullableProblems") + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { // 清理当前线程保存的用户数据 UserHolder.clear(); - HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); + HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } + } diff --git a/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java b/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java index 6bf6851..9642f84 100644 --- a/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java +++ b/src/main/java/io/github/xxyopen/novel/core/interceptor/TokenParseInterceptor.java @@ -9,7 +9,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.ModelAndView; /** * Token 解析拦截器 @@ -23,6 +22,7 @@ public class TokenParseInterceptor implements HandlerInterceptor { private final JwtUtils jwtUtils; + @SuppressWarnings("NullableProblems") @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { @@ -35,11 +35,16 @@ public class TokenParseInterceptor implements HandlerInterceptor { return HandlerInterceptor.super.preHandle(request, response, handler); } + /** + * DispatcherServlet 完全处理完请求后调用,出现异常照常调用 + */ + @SuppressWarnings("NullableProblems") @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, - ModelAndView modelAndView) throws Exception { + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { // 清理当前线程保存的用户数据 UserHolder.clear(); - HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); + HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } + } -- Gitee From 46d03883ed6c7fa266f60d550021e743f5366563 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 23 Mar 2023 01:59:07 +0800 Subject: [PATCH 086/112] =?UTF-8?q?fix(pom.xml):=20-source=20X=20=E4=B8=AD?= =?UTF-8?q?=E4=B8=8D=E6=94=AF=E6=8C=81=20XX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题描述:使用 maven 编译项目时,部分环境会编译失败,出现 -source X 中不支持 XX [ERROR] (请使用 -source Y 或更高版本以启用 XX) 解决方案:需要手动指定 Java 编译器的 -source 和 -target 参数 --- pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pom.xml b/pom.xml index 691cfa1..0226635 100644 --- a/pom.xml +++ b/pom.xml @@ -221,6 +221,15 @@ + + maven-compiler-plugin + + + ${java.version} + + ${java.version} + + -- Gitee From c866702e480165af290829b6f91ddb0ecaa34ee9 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 25 Mar 2023 12:54:15 +0800 Subject: [PATCH 087/112] =?UTF-8?q?feat:=20=E6=A8=A1=E7=89=88=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E6=A8=A1=E5=BC=8F=E5=AE=9E=E7=8E=B0=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E5=8F=91=E9=80=81=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 ++ .../novel/core/config/MailProperties.java | 14 +++ .../constant/MessageSenderTypeConsts.java | 25 +++++ .../manager/message/AbstractMailSender.java | 50 ++++++++++ .../message/AbstractMessageSender.java | 92 +++++++++++++++++++ .../message/AbstractSysNoticeSender.java | 26 ++++++ .../novel/manager/message/MessageSender.java | 21 +++++ .../manager/message/RegisterMailSender.java | 60 ++++++++++++ .../message/SeckillSystemNoticeSender.java | 25 +++++ src/main/resources/application.yml | 26 ++++++ 10 files changed, 345 insertions(+) create mode 100644 src/main/java/io/github/xxyopen/novel/core/config/MailProperties.java create mode 100644 src/main/java/io/github/xxyopen/novel/core/constant/MessageSenderTypeConsts.java create mode 100644 src/main/java/io/github/xxyopen/novel/manager/message/AbstractMailSender.java create mode 100644 src/main/java/io/github/xxyopen/novel/manager/message/AbstractMessageSender.java create mode 100644 src/main/java/io/github/xxyopen/novel/manager/message/AbstractSysNoticeSender.java create mode 100644 src/main/java/io/github/xxyopen/novel/manager/message/MessageSender.java create mode 100644 src/main/java/io/github/xxyopen/novel/manager/message/RegisterMailSender.java create mode 100644 src/main/java/io/github/xxyopen/novel/manager/message/SeckillSystemNoticeSender.java diff --git a/pom.xml b/pom.xml index 0226635..b56b669 100644 --- a/pom.xml +++ b/pom.xml @@ -185,6 +185,12 @@ ${springdoc-openapi.version} + + + org.springframework.boot + spring-boot-starter-mail + + com.mysql mysql-connector-j diff --git a/src/main/java/io/github/xxyopen/novel/core/config/MailProperties.java b/src/main/java/io/github/xxyopen/novel/core/config/MailProperties.java new file mode 100644 index 0000000..1849903 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/config/MailProperties.java @@ -0,0 +1,14 @@ +package io.github.xxyopen.novel.core.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * mail 配置属性 + * + * @author xiongxiaoyang + * @date 2023/3/25 + */ +@ConfigurationProperties(prefix = "spring.mail") +public record MailProperties(String nickname, String username) { + +} diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/MessageSenderTypeConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/MessageSenderTypeConsts.java new file mode 100644 index 0000000..8cbc25f --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/constant/MessageSenderTypeConsts.java @@ -0,0 +1,25 @@ +package io.github.xxyopen.novel.core.constant; + +/** + * 消息发送器的类型 + * + * @author xiongxiaoyang + * @date 2023/3/24 + */ +public class MessageSenderTypeConsts { + + private MessageSenderTypeConsts() { + throw new IllegalStateException("Constant class"); + } + + /** + * 注册成功的邮件发送器 + */ + public static final String REGISTER_MAIL_SENDER = "registerMailSender"; + + /** + * 秒杀活动的系统通知发送器 + */ + public static final String SECKILL_SYS_NOTICE_SENDER = "seckillSysNoticeSender"; + +} diff --git a/src/main/java/io/github/xxyopen/novel/manager/message/AbstractMailSender.java b/src/main/java/io/github/xxyopen/novel/manager/message/AbstractMailSender.java new file mode 100644 index 0000000..10d64e6 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/manager/message/AbstractMailSender.java @@ -0,0 +1,50 @@ +package io.github.xxyopen.novel.manager.message; + +import io.github.xxyopen.novel.core.config.MailProperties; +import jakarta.mail.internet.InternetAddress; +import jakarta.mail.internet.MimeMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; + +/** + * 抽象的邮件消息发送者 + * + * @author xiongxiaoyang + * @date 2023/3/24 + */ +@Slf4j +@RequiredArgsConstructor +public abstract class AbstractMailSender extends AbstractMessageSender { + + private final MailProperties mailProperties; + + private final JavaMailSender mailSender; + + @Override + protected void sendMessage(Long toUserId, String messageTitle, String messageContent) { + // TODO 根据消息接收方的用户ID查询出消息接收方的邮件地址 + String toEmail = "xxyopen@foxmail.com"; + // 开始发送邮件 + log.info("发送 HTML 邮件开始:{},{},{}", toEmail, messageTitle, messageContent); + // 使用 MimeMessage,MIME 协议 + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper; + // MimeMessageHelper 帮助我们设置更丰富的内容 + try { + helper = new MimeMessageHelper(message, true); + helper.setFrom(new InternetAddress(mailProperties.username(), mailProperties.nickname(), "UTF-8")); + helper.setTo(toEmail); + helper.setSubject(messageTitle); + // 第二个参数 true 代表支持 html + helper.setText(messageContent, true); + mailSender.send(message); + log.info("发送 HTML 邮件 to {} 成功", toEmail); + } catch (Exception e) { + // 邮件发送失败不会重试 + log.error("发送 HTML 邮件 to {} 失败", toEmail, e); + } + } + +} diff --git a/src/main/java/io/github/xxyopen/novel/manager/message/AbstractMessageSender.java b/src/main/java/io/github/xxyopen/novel/manager/message/AbstractMessageSender.java new file mode 100644 index 0000000..3559779 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/manager/message/AbstractMessageSender.java @@ -0,0 +1,92 @@ +package io.github.xxyopen.novel.manager.message; + +/** + * 抽象的消息发送器 + *

+ * 遵循松耦合的设计原则,所有的属性都使用构造函数注入,与 Spring 框架解藕 + *

+ * 所有的消息发送器既可以注册到 Spring 容器中,作为 Spring 的一个组件使用,也可以直接通过 new 对象的方式使用 + *

+ * 每种类型的消息发送时机可能都不一样,不同类型和发送时机的消息格式可能也不一样,所以由各个子类去拓展消息的格式 + * + * @author xiongxiaoyang + * @date 2023/3/24 + */ +public abstract class AbstractMessageSender implements MessageSender { + + private static final String PLACEHOLDER = "{}"; + + /** + * 定义消息发送的模版,子类不能修改此模版 + */ + @Override + public final void sendMessage(Long toUserId, Object... args) { + // 1.获取消息标题模版 + String titleTemplate = getTitleTemplate(); + // 2.获取消息内容模版 + String contentTemplate = getContentTemplate(); + // 3.解析消息模版,得到最终需要发送的消息标题 + String title = resolveTitle(titleTemplate, args); + // 4.解析消息内容,得到最终需要发送的消息内容 + String content = resolveContent(contentTemplate, args); + // 5.发送消息 + sendMessage(toUserId, title, content); + } + + /** + * 发送消息,具体发送到哪里由子类决定 + * + * @param toUserId 消息接收方的用户ID + * @param messageTitle 消息标题 + * @param messageContent 消息内容 + */ + protected abstract void sendMessage(Long toUserId, String messageTitle, String messageContent); + + /** + * 获取消息标题的模版,具体如何制定模版由子类决定 + * + * @return 消息标题 + */ + protected abstract String getTitleTemplate(); + + /** + * 获取消息内容的模版,具体如何制定模版由子类决定 + * + * @return 消息内容 + */ + protected abstract String getContentTemplate(); + + /** + * 通过给定的参数列表解析消息标题模版,默认固定标题,不需要解析,可以由子类来拓展它的功能 + * + * @param titleTemplate 消息标题模版 + * @param arguments 用来解析的参数列表 + * @return 解析后的消息标题 + */ + protected String resolveTitle(String titleTemplate, Object... arguments) { + return titleTemplate; + } + + /** + * 通过给定的参数列表解析消息内容模版,默认实现是使用参数列表来替换消息内容模版中的占位符,可以由子类来拓展它的功能 + *

+ * 子类可以根据第一个/前几个参数去数据库中查询动态内容,然后重组参数列表 + * + * @param contentTemplate 消息内容模版 + * @param args 用来解析的参数列表 + * @return 解析后的消息内容 + */ + protected String resolveContent(String contentTemplate, Object... args) { + if (args.length > 0) { + StringBuilder formattedContent = new StringBuilder(contentTemplate); + for (Object arg : args) { + int start = formattedContent.indexOf(PLACEHOLDER); + formattedContent.replace(start, start + PLACEHOLDER.length(), + String.valueOf(arg)); + } + return formattedContent.toString(); + } + return contentTemplate; + } + +} diff --git a/src/main/java/io/github/xxyopen/novel/manager/message/AbstractSysNoticeSender.java b/src/main/java/io/github/xxyopen/novel/manager/message/AbstractSysNoticeSender.java new file mode 100644 index 0000000..c457f25 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/manager/message/AbstractSysNoticeSender.java @@ -0,0 +1,26 @@ +package io.github.xxyopen.novel.manager.message; + +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * 抽象的系统通知发送者 + * + * @author xiongxiaoyang + * @date 2023/3/24 + */ +@Slf4j +public abstract class AbstractSysNoticeSender extends AbstractMessageSender { + + @Override + protected void sendMessage(Long toUserId, String messageTitle, String messageContent) { + // 生成消息的发送时间 + LocalDateTime messageDateTime = LocalDateTime.now(); + // TODO 在数据库系统通知表中插入一条记录 + log.info("系统通知发送成功,{},{},{},{}", toUserId, messageDateTime.format(DateTimeFormatter.ISO_DATE_TIME), + messageTitle, messageContent); + } + +} diff --git a/src/main/java/io/github/xxyopen/novel/manager/message/MessageSender.java b/src/main/java/io/github/xxyopen/novel/manager/message/MessageSender.java new file mode 100644 index 0000000..ca109fa --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/manager/message/MessageSender.java @@ -0,0 +1,21 @@ +package io.github.xxyopen.novel.manager.message; + +/** + * 消息发送器接口,用来发送各种消息 + *

+ * 消息按类型分系统通知、邮件、短信、小程序通知等,按发送时机分注册成功消息、充值成功消息、活动通知消息、账户封禁消息、小说下架消息等 + * + * @author xiongxiaoyang + * @date 2023/3/25 + */ +public interface MessageSender { + + /** + * 发送消息,支持动态消息标题和动态消息内容 + * + * @param toUserId 消息接收方的用户ID + * @param args 用来动态生成消息标题和消息内容的参数列表 + */ + void sendMessage(Long toUserId, Object... args); + +} diff --git a/src/main/java/io/github/xxyopen/novel/manager/message/RegisterMailSender.java b/src/main/java/io/github/xxyopen/novel/manager/message/RegisterMailSender.java new file mode 100644 index 0000000..712ff85 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/manager/message/RegisterMailSender.java @@ -0,0 +1,60 @@ +package io.github.xxyopen.novel.manager.message; + +import io.github.xxyopen.novel.core.config.MailProperties; +import io.github.xxyopen.novel.core.constant.MessageSenderTypeConsts; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.stream.Stream; + +/** + * 注册成功的邮件发送器 + * + * @author xiongxiaoyang + * @date 2023/3/24 + */ +@Component(value = MessageSenderTypeConsts.REGISTER_MAIL_SENDER) +@EnableConfigurationProperties(MailProperties.class) +public class RegisterMailSender extends AbstractMailSender { + + public RegisterMailSender(MailProperties mailProperties, JavaMailSender mailSender) { + super(mailProperties, mailSender); + } + + @Override + protected String getTitleTemplate() { + return "欢迎来到小说精品屋"; + } + + @Override + protected String getContentTemplate() { + return """ +

+ 感谢你注册小说精品屋!你的账户现在处于活动状态。 +
+
    +
  • 你的账户电子邮件:{} +
  • 你的账户用户名:{} +
+ + + 如果你有任何问题,请通过 {} 与我们联系。 + """; + } + + @Override + protected String resolveContent(String content, Object... args) { + // TODO 去数据库/配置文件中查询网站配置 + String websiteLink = "https://www.xxyopen.com"; + String websiteEmail = "xxyopen@foxmail.com"; + return super.resolveContent(content, + Stream.of(args, new Object[]{websiteLink, websiteEmail}).flatMap(Arrays::stream).toArray()); + } + +} diff --git a/src/main/java/io/github/xxyopen/novel/manager/message/SeckillSystemNoticeSender.java b/src/main/java/io/github/xxyopen/novel/manager/message/SeckillSystemNoticeSender.java new file mode 100644 index 0000000..5a7fb4a --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/manager/message/SeckillSystemNoticeSender.java @@ -0,0 +1,25 @@ +package io.github.xxyopen.novel.manager.message; + +import io.github.xxyopen.novel.core.constant.MessageSenderTypeConsts; +import org.springframework.stereotype.Component; + +/** + * 秒杀活动的系统通知发送器 + * + * @author xiongxiaoyang + * @date 2023/3/24 + */ +@Component(value = MessageSenderTypeConsts.SECKILL_SYS_NOTICE_SENDER) +public class SeckillSystemNoticeSender extends AbstractSysNoticeSender { + + @Override + protected String getTitleTemplate() { + return "秒杀即将开始"; + } + + @Override + protected String getContentTemplate() { + return "{}秒杀,{}即将开始,不要错过哦!点击 {} 前往。"; + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 69d9e2c..15788be 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -189,6 +189,32 @@ springdoc: api-docs: enabled: false +--- #----------------------邮箱配置----------------------------- +#邮箱服务器 +spring: + mail: + host: smtp.163.com + #发件人昵称 + nickname: xxyopen + #邮箱账户 + username: xxx@163.com + #邮箱第三方授权码 + password: xxx + #编码类型 + default-encoding: UTF-8 + port: 465 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + required: rue + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + fallback: false + --- #---------------------自定义配置---------------------------- novel: # 跨域配置 -- Gitee From 62d7169304c42ffda05c9f6e2537ffda06a86552 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 25 Mar 2023 14:57:32 +0800 Subject: [PATCH 088/112] =?UTF-8?q?chore:=20=E5=85=B3=E9=97=AD=20mail=20?= =?UTF-8?q?=E7=9A=84=E5=81=A5=E5=BA=B7=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 15788be..f0999bc 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -183,6 +183,9 @@ management: elasticsearch: # 关闭 elasticsearch 的健康检查 enabled: false + # 关闭 mail 的健康检查 + mail: + enabled: false --- #--------------------接口文档配置--------------------------- springdoc: -- Gitee From afeadde58152e4f7381e88a3fe8ada37f2261441 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 25 Mar 2023 14:59:40 +0800 Subject: [PATCH 089/112] =?UTF-8?q?docs:=20=E8=B0=83=E6=95=B4=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E7=9A=84=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f0999bc..9952814 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -183,8 +183,8 @@ management: elasticsearch: # 关闭 elasticsearch 的健康检查 enabled: false - # 关闭 mail 的健康检查 mail: + # 关闭 mail 的健康检查 enabled: false --- #--------------------接口文档配置--------------------------- -- Gitee From 46d62d6aa617e573c31d46961697885116aa6c57 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 28 Mar 2023 08:50:22 +0800 Subject: [PATCH 090/112] fix: fix sun.security.validator.ValidatorException for Elasticsearc PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target --- .../xxyopen/novel/core/config/EsConfig.java | 60 ++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java index 58eafa9..9578f31 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java @@ -1,16 +1,33 @@ package io.github.xxyopen.novel.core.config; import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.elasticsearch.RestClientBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; + /** - * elasticsearch 相关配置 + * Elasticsearch 相关配置 * * @author xiongxiaoyang * @date 2022/5/23 */ +@ConditionalOnProperty(value = "spring.elasticsearch.enabled", havingValue = "true") @Configuration +@Slf4j public class EsConfig { /** @@ -21,4 +38,45 @@ public class EsConfig { return new JacksonJsonpMapper(); } + /** + * fix `sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: + * unable to find valid certification path to requested target` + */ + @Bean + RestClient elasticsearchRestClient(RestClientBuilder restClientBuilder, + ObjectProvider builderCustomizers) { + restClientBuilder.setHttpClientConfigCallback((HttpAsyncClientBuilder clientBuilder) -> { + TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }}; + SSLContext sc = null; + try { + sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new SecureRandom()); + } catch (KeyManagementException | NoSuchAlgorithmException e) { + log.error("Elasticsearch RestClient 配置失败!", e); + } + assert sc != null; + clientBuilder.setSSLContext(sc); + clientBuilder.setSSLHostnameVerifier((hostname, session) -> true); + + builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(clientBuilder)); + return clientBuilder; + }); + return restClientBuilder.build(); + } + } -- Gitee From 65274eae80224d31b2b4211ea2c573a4590e9c3c Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 31 Mar 2023 09:37:43 +0800 Subject: [PATCH 091/112] Update README.md --- README.md | 48 +++++++++---------- .../novel/dto/resp/BookChapterRespDto.java | 4 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index ac7f25a..9e46e3b 100644 --- a/README.md +++ b/README.md @@ -43,26 +43,26 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | 技术 | 版本 | 说明 | 官网 | 学习 | |---------------------|:--------------:|---------------------| --------------------------------------- |:-----------------------------------------------------------------------------------------------------------------------------:| -| Spring Boot | 3.0.0 | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://docs.spring.io/spring-boot/docs/3.0.0/reference/html) | -| MyBatis | 3.5.9 | ORM 框架 | http://www.mybatis.org | [进入](https://mybatis.org/mybatis-3/zh/index.html) | -| MyBatis-Plus | 3.5.3 | MyBatis 增强工具 | https://baomidou.com/ | [进入](https://baomidou.com/pages/24112f/) | -| JJWT | 0.11.5 | JWT 登录支持 | https://github.com/jwtk/jjwt | - | -| Lombok | 1.18.24 | 简化对象封装工具 | https://github.com/projectlombok/lombok | [进入](https://projectlombok.org/features/all) | -| Caffeine | 3.1.0 | 本地缓存支持 | https://github.com/ben-manes/caffeine | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | -| Redis | 7.0 | 分布式缓存支持 | https://redis.io | [进入](https://redis.io/docs) | -| Redisson | 3.17.4 | 分布式锁实现 | https://github.com/redisson/redisson | [进入](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | -| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | -| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | -| Elasticsearch | 8.2.0 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | -| RabbitMQ | 3.10.2 | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | -| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) | -| Sentinel | 1.8.4 | 流量控制组件 | https://github.com/alibaba/Sentinel | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | -| Springdoc-openapi | 2.0.0 | Swagger 3 接口文档自动生成 | https://github.com/springdoc/springdoc-openapi | [进入](https://springdoc.org/) | -| Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | -| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) | -| Docker | - | 应用容器引擎 | https://www.docker.com/ | - | -| Jenkins | - | 自动化部署工具 | https://github.com/jenkinsci/jenkins | - | -| Sonarqube | - | 代码质量控制 | https://www.sonarqube.org/ | - | +| Spring Boot | 3.0.0 | 容器 + MVC 框架 | [进入](https://spring.io/projects/spring-boot) | [进入](https://docs.spring.io/spring-boot/docs/3.0.0/reference/html) | +| MyBatis | 3.5.9 | ORM 框架 | [进入](http://www.mybatis.org) | [进入](https://mybatis.org/mybatis-3/zh/index.html) | +| MyBatis-Plus | 3.5.3 | MyBatis 增强工具 | [进入](https://baomidou.com/) | [进入](https://baomidou.com/pages/24112f/) | +| JJWT | 0.11.5 | JWT 登录支持 | [进入](https://github.com/jwtk/jjwt) | - | +| Lombok | 1.18.24 | 简化对象封装工具 | [进入](https://github.com/projectlombok/lombok) | [进入](https://projectlombok.org/features/all) | +| Caffeine | 3.1.0 | 本地缓存支持 | [进入](https://github.com/ben-manes/caffeine) | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) | +| Redis | 7.0 | 分布式缓存支持 | [进入](https://redis.io) | [进入](https://redis.io/docs) | +| Redisson | 3.17.4 | 分布式锁实现 | [进入](https://github.com/redisson/redisson) | [进入](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | +| MySQL | 8.0 | 数据库服务 | [进入](https://www.mysql.com) | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) | +| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | [进入](https://shardingsphere.apache.org) | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) | +| Elasticsearch | 8.2.0 | 搜索引擎服务 | [进入](https://www.elastic.co) | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) | +| RabbitMQ | 3.10.2 | 开源消息中间件 | [进入](https://www.rabbitmq.com) | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) | +| XXL-JOB | 2.3.1 | 分布式任务调度平台 | [进入](https://www.xuxueli.com/xxl-job) | [进入](https://www.xuxueli.com/xxl-job) | +| Sentinel | 1.8.4 | 流量控制组件 | [进入](https://github.com/alibaba/Sentinel) | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) | +| Springdoc-openapi | 2.0.0 | Swagger 3 接口文档自动生成 | [进入](https://github.com/springdoc/springdoc-openapi) | [进入](https://springdoc.org/) | +| Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | [进入](https://github.com/codecentric/spring-boot-admin) | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) | +| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | [进入](https://undertow.io) | [进入](https://undertow.io/documentation.html) | +| Docker | - | 应用容器引擎 | [进入](https://www.docker.com/) | - | +| Jenkins | - | 自动化部署工具 | [进入](https://github.com/jenkinsci/jenkins) | - | +| Sonarqube | - | 代码质量控制 | [进入](https://www.sonarqube.org/) | - | **注:更多热门新技术待集成。** @@ -70,10 +70,10 @@ novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开 | 技术 | 版本 | 说明 | 官网 | 学习 | | :----------------- | :-----: | -------------------------- | --------------------------------------- | :-------------------------------------------------: | -| Vue.js | 3.2.13 | 渐进式 JavaScript 框架 | https://vuejs.org | [进入](https://staging-cn.vuejs.org/guide/introduction.html) | -| Vue Router | 4.0.15 | Vue.js 的官方路由 | https://router.vuejs.org | [进入](https://router.vuejs.org/zh/guide/) | -| axios | 0.27.2 | 基于 promise 的网络请求库 | https://axios-http.com | [进入](https://axios-http.com/zh/docs/intro) | -| element-plus | 2.2.0 | 基于 Vue 3,面向设计师和开发者的组件库 | https://element-plus.org | [进入](https://element-plus.org/zh-CN/guide/design.html) | +| Vue.js | 3.2.13 | 渐进式 JavaScript 框架 | [进入](https://vuejs.org) | [进入](https://staging-cn.vuejs.org/guide/introduction.html) | +| Vue Router | 4.0.15 | Vue.js 的官方路由 | [进入](https://router.vuejs.org) | [进入](https://router.vuejs.org/zh/guide/) | +| axios | 0.27.2 | 基于 promise 的网络请求库 | [进入](https://axios-http.com) | [进入](https://axios-http.com/zh/docs/intro) | +| element-plus | 2.2.0 | 基于 Vue 3,面向设计师和开发者的组件库 | [进入](https://element-plus.org) | [进入](https://element-plus.org/zh-CN/guide/design.html) | ## 编码规范 diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java index 665a129..c25786d 100644 --- a/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/BookChapterRespDto.java @@ -24,7 +24,7 @@ public class BookChapterRespDto implements Serializable { /** * 章节ID - * */ + */ @Schema(description = "章节ID") private Long id; @@ -56,7 +56,7 @@ public class BookChapterRespDto implements Serializable { * 章节更新时间 */ @Schema(description = "章节更新时间") - @JsonFormat(pattern = "yyyy/MM/dd HH:dd") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") private LocalDateTime chapterUpdateTime; /** -- Gitee From 7de1dc6370d9da01ce63cd6a080c317d12383bd7 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 16 Apr 2023 08:34:27 +0800 Subject: [PATCH 092/112] Update README.md --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 9e46e3b..7e733e4 100644 --- a/README.md +++ b/README.md @@ -198,14 +198,6 @@ io ## 公众号 -- 关注公众号接收`项目`和`文档`的更新动态 - -- 加微信群学习交流,公众号后台回复「**微信群**」即可 - -- 回复「**资料**」获取`Java 学习面试资料` - -- 回复「**笔记**」获取`Spring Boot 3 学习笔记` - ![xxyopen](https://youdoc.github.io/img/qrcode_for_gh.jpg) ## 赞赏支持 -- Gitee From df1719e14c47f2a5570c4e1ba2a289926a7cf48b Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 16 Apr 2023 08:44:16 +0800 Subject: [PATCH 093/112] Update README.md --- README.md | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 7e733e4..f2eea44 100644 --- a/README.md +++ b/README.md @@ -192,21 +192,7 @@ io 👉 [立即查看](https://docs.xxyopen.com/course/novel/#%E5%AE%89%E8%A3%85%E6%AD%A5%E9%AA%A4) -## 答疑 +## 联系我们 -为了方便管理和查阅,安装过程中遇到任何问题请统一在指定评论区 👉 [立即前往](https://www.xxyopen.com/2022/07/18/os/novel.html) 留言 ,谢谢大家的配合! +👉 [立即查看](https://novel.xxyopen.com/service.htm) -## 公众号 - -![xxyopen](https://youdoc.github.io/img/qrcode_for_gh.jpg) - -## 赞赏支持 - -开源项目不易,若此项目能得到你的青睐,那么你可以赞赏支持作者持续开发与维护。 - -- 更完善的文档教程 -- 服务器的费用也是一笔开销 -- 为用户提供更好的开发环境 -- 一杯咖啡 - -![](https://s1.ax1x.com/2020/10/31/BUQJwq.png) -- Gitee From 74f5b58252acc19a82e27e854a1d415c21e2fc2d Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 16 Apr 2023 10:57:14 +0800 Subject: [PATCH 094/112] Update README.md --- README.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/README.md b/README.md index f2eea44..3456f5c 100644 --- a/README.md +++ b/README.md @@ -196,3 +196,40 @@ io 👉 [立即查看](https://novel.xxyopen.com/service.htm) +## 问题 + +### 为什么有 novel/novel-cloud 学习版? + +最开始是没有学习版的,只有一个爬虫/原创小说项目(最终发展成为 [novel-plus](https://github.com/201206030/novel-plus) +项目),用户群体大部分是对小说有兴趣,想自建一个干净无广告的小说网站的个人和站长。 + +后面随着使用人数逐渐增加,想通过这个项目来学习 Java 技术的人数也多了起来,对这部分用户来说,之前的项目用来学习很困难,具体原因如下: + +1. novel-plus 功能模块比较多,重复性的增删改查占了大部分,而用户时间是有限的,很难在有限的时间内筛选出对自己有帮助的功能模块来学习。 +2. novel-plus 追求的是系统稳定,用户很难在其中学习到最新的技术。 +3. novel-plus 代码规范性不够,受限于开发时间限制,代码开发时没有选择一个标准化的规范去参考。 +4. novel-plus 文档缺失,由于功能比较多,整个系统的教程编写需要花费大量时间,即使教程最终上线成功,用户也不可能有那么多时间也没有意义去学习所有的功能。 + +最终,novel(单体架构) 和 novel-cloud(微服务架构)诞生了,这两个项目在保证核心流程完整的同时,从 novel-plus +中选用了一些有代表性的功能,使用最新技术栈(不间断地更新和集成新技术),在[保姆级教程](https://docs.xxyopen.com/course/novel)的帮助下,尽量保证每一个功能都能让你学到不重复的技术。 + +所以这两个项目我的重点是去堆技术而不是去堆功能,功能只是其中的辅助,堆太多的重复性增删改查功能没有意义,对学习的帮助也不大。 + +### 谁适合使用 novel/novel-cloud 学习版项目? + +如果对下面的所有问题你都能肯定地回答 "是": + +1. 你懂 Java 吗? +2. 你没有项目经验,想学习如何从零开始开发上线一个生产级别的 Java 项目? +3. 你有项目经验,但是公司技术栈太落后,想学习最新的主流开发技术? + +那么,本项目正是你需要的。 + +### 谁暂时还不适合使用 novel/novel-cloud 学习版项目? + +如果对下面任何一个问题你能回答 "是": + +1. 你不懂 Java ,只是想搭建一个小说网站使用? +2. 你想找一个完整的 Java 商用项目,有时间也有耐心去学习项目中的方方面面? + +那么,太遗憾了,本项目暂时不适合你,请使用 [novel-plus](https://github.com/201206030/novel-plus)。 -- Gitee From d5282a3974f0f804fb4f0e3e6b875cec0333de49 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 16 Apr 2023 11:06:50 +0800 Subject: [PATCH 095/112] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3456f5c..5d17c44 100644 --- a/README.md +++ b/README.md @@ -219,9 +219,8 @@ io 如果对下面的所有问题你都能肯定地回答 "是": -1. 你懂 Java 吗? -2. 你没有项目经验,想学习如何从零开始开发上线一个生产级别的 Java 项目? -3. 你有项目经验,但是公司技术栈太落后,想学习最新的主流开发技术? +1. 你没有项目经验,想学习如何从零开始开发上线一个生产级别的 Java 项目? +2. 你有项目经验,但是公司技术栈太落后,想学习最新的主流开发技术? 那么,本项目正是你需要的。 @@ -229,7 +228,8 @@ io 如果对下面任何一个问题你能回答 "是": -1. 你不懂 Java ,只是想搭建一个小说网站使用? -2. 你想找一个完整的 Java 商用项目,有时间也有耐心去学习项目中的方方面面? +1. 你不懂 Java ? +2. 你只是想搭建一个小说网站使用? +3. 你想找一个完整的 Java 商用项目,有时间也有耐心去学习项目中的方方面面? 那么,太遗憾了,本项目暂时不适合你,请使用 [novel-plus](https://github.com/201206030/novel-plus)。 -- Gitee From fc7983236bd786653b7b3c8d88d5d25eead3143b Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 16 Apr 2023 11:07:45 +0800 Subject: [PATCH 096/112] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d17c44..8caf41c 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,7 @@ io ### 谁适合使用 novel/novel-cloud 学习版项目? -如果对下面的所有问题你都能肯定地回答 "是": +如果对下面任何一个问题你能回答 "是": 1. 你没有项目经验,想学习如何从零开始开发上线一个生产级别的 Java 项目? 2. 你有项目经验,但是公司技术栈太落后,想学习最新的主流开发技术? -- Gitee From 90f5780796a1f3d7fad06619a18be7eb608e315a Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 21 Apr 2023 16:28:51 +0800 Subject: [PATCH 097/112] =?UTF-8?q?feat:=20=E8=AE=BE=E7=BD=AE=20Elasticsea?= =?UTF-8?q?rch=20=E7=9A=84=20ssl=20=E8=AE=A4=E8=AF=81=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/github/xxyopen/novel/core/config/EsConfig.java | 2 +- .../META-INF/additional-spring-configuration-metadata.json | 5 +++++ src/main/resources/application.yml | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java index 9578f31..a35fbb2 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java @@ -25,7 +25,6 @@ import java.security.cert.X509Certificate; * @author xiongxiaoyang * @date 2022/5/23 */ -@ConditionalOnProperty(value = "spring.elasticsearch.enabled", havingValue = "true") @Configuration @Slf4j public class EsConfig { @@ -42,6 +41,7 @@ public class EsConfig { * fix `sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: * unable to find valid certification path to requested target` */ + @ConditionalOnProperty(value = "spring.elasticsearch.ssl.verification-mode", havingValue = "none") @Bean RestClient elasticsearchRestClient(RestClientBuilder restClientBuilder, ObjectProvider builderCustomizers) { diff --git a/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/src/main/resources/META-INF/additional-spring-configuration-metadata.json index db7e44c..d74c6a7 100644 --- a/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -60,6 +60,11 @@ "name": "xxl.job.accessToken", "type": "java.lang.String", "description": "xxl-job accessToken." + }, + { + "name": "spring.elasticsearch.ssl.verification-mode", + "type": "java.lang.String", + "description": "设置 ssl 的认证模式,如果该配置项为 none ,说明不需要认证,信任所有的 ssl 证书." } ] } \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9952814..946e0d0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -97,6 +97,9 @@ spring: - https://my-deployment-ce7ca3.es.us-central1.gcp.cloud.es.io:9243 username: elastic password: qTjgYVKSuExX6tWAsDuvuvwl + # 设置 ssl 的认证模式,如果该配置项为 none ,说明不需要认证,信任所有的 ssl 证书。 + # ssl: + # verification-mode: none # Spring AMQP 配置 amqp: -- Gitee From 1f2d8dc49adb6fe3ed9ab9d83d4fdf0a6d1a897f Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 25 Apr 2023 13:10:08 +0800 Subject: [PATCH 098/112] =?UTF-8?q?feat:=20=E6=9F=A5=E8=AF=A2=E4=BC=9A?= =?UTF-8?q?=E5=91=98=E8=AF=84=E8=AE=BA=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/front/UserController.java | 21 +++--- .../novel/dto/resp/UserCommentRespDto.java | 33 +++++++++ .../xxyopen/novel/service/BookService.java | 10 +++ .../novel/service/impl/BookServiceImpl.java | 68 +++++++++++-------- 4 files changed, 95 insertions(+), 37 deletions(-) create mode 100644 src/main/java/io/github/xxyopen/novel/dto/resp/UserCommentRespDto.java diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java b/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java index c25c4ae..27bef85 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/UserController.java @@ -1,6 +1,8 @@ package io.github.xxyopen.novel.controller.front; import io.github.xxyopen.novel.core.auth.UserHolder; +import io.github.xxyopen.novel.core.common.req.PageReqDto; +import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.core.constant.SystemConfigConsts; @@ -8,6 +10,7 @@ import io.github.xxyopen.novel.dto.req.UserCommentReqDto; import io.github.xxyopen.novel.dto.req.UserInfoUptReqDto; import io.github.xxyopen.novel.dto.req.UserLoginReqDto; import io.github.xxyopen.novel.dto.req.UserRegisterReqDto; +import io.github.xxyopen.novel.dto.resp.UserCommentRespDto; import io.github.xxyopen.novel.dto.resp.UserInfoRespDto; import io.github.xxyopen.novel.dto.resp.UserLoginRespDto; import io.github.xxyopen.novel.dto.resp.UserRegisterRespDto; @@ -19,14 +22,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; /** * 前台门户-会员模块 API 控制器 @@ -138,4 +134,13 @@ public class UserController { return userService.getBookshelfStatus(UserHolder.getUserId(), bookId); } + /** + * 分页查询评论 + */ + @Operation(summary = "查询会员评论列表接口") + @GetMapping("comments") + public RestResp> listComments(PageReqDto pageReqDto) { + return bookService.listComments(UserHolder.getUserId(), pageReqDto); + } + } diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/UserCommentRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/UserCommentRespDto.java new file mode 100644 index 0000000..3e44524 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/UserCommentRespDto.java @@ -0,0 +1,33 @@ +package io.github.xxyopen.novel.dto.resp; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 用户评论响应 Dto + * + * @author xiongxiaoyang + * @date 2023/4/25 + */ +@Data +@Builder +public class UserCommentRespDto { + + @Schema(description = "评论内容") + private String commentContent; + + @Schema(description = "评论小说封面") + private String commentBookPic; + + @Schema(description = "评论小说") + private String commentBook; + + @Schema(description = "评论时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime commentTime; + +} diff --git a/src/main/java/io/github/xxyopen/novel/service/BookService.java b/src/main/java/io/github/xxyopen/novel/service/BookService.java index 4779dc1..efda4af 100644 --- a/src/main/java/io/github/xxyopen/novel/service/BookService.java +++ b/src/main/java/io/github/xxyopen/novel/service/BookService.java @@ -179,4 +179,14 @@ public interface BookService { * @return 章节分页列表数据 */ RestResp> listBookChapters(Long bookId, PageReqDto dto); + + /** + * 分页查询评论 + * + * @param userId 会员ID + * @param pageReqDto 分页参数 + * @return 评论分页列表数据 + */ + RestResp> listComments(Long userId, PageReqDto pageReqDto); + } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index b570c7e..7fdd0e8 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -11,11 +11,7 @@ import io.github.xxyopen.novel.core.common.req.PageReqDto; import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.core.constant.DatabaseConsts; -import io.github.xxyopen.novel.dao.entity.BookChapter; -import io.github.xxyopen.novel.dao.entity.BookComment; -import io.github.xxyopen.novel.dao.entity.BookContent; -import io.github.xxyopen.novel.dao.entity.BookInfo; -import io.github.xxyopen.novel.dao.entity.UserInfo; +import io.github.xxyopen.novel.dao.entity.*; import io.github.xxyopen.novel.dao.mapper.BookChapterMapper; import io.github.xxyopen.novel.dao.mapper.BookCommentMapper; import io.github.xxyopen.novel.dao.mapper.BookContentMapper; @@ -24,38 +20,23 @@ import io.github.xxyopen.novel.dto.AuthorInfoDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; import io.github.xxyopen.novel.dto.req.UserCommentReqDto; -import io.github.xxyopen.novel.dto.resp.BookCategoryRespDto; -import io.github.xxyopen.novel.dto.resp.BookChapterAboutRespDto; -import io.github.xxyopen.novel.dto.resp.BookChapterRespDto; -import io.github.xxyopen.novel.dto.resp.BookCommentRespDto; -import io.github.xxyopen.novel.dto.resp.BookContentAboutRespDto; -import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; -import io.github.xxyopen.novel.dto.resp.BookRankRespDto; -import io.github.xxyopen.novel.manager.cache.AuthorInfoCacheManager; -import io.github.xxyopen.novel.manager.cache.BookCategoryCacheManager; -import io.github.xxyopen.novel.manager.cache.BookChapterCacheManager; -import io.github.xxyopen.novel.manager.cache.BookContentCacheManager; -import io.github.xxyopen.novel.manager.cache.BookInfoCacheManager; -import io.github.xxyopen.novel.manager.cache.BookRankCacheManager; +import io.github.xxyopen.novel.dto.resp.*; +import io.github.xxyopen.novel.manager.cache.*; import io.github.xxyopen.novel.manager.dao.UserDaoManager; import io.github.xxyopen.novel.manager.mq.AmqpMsgManager; import io.github.xxyopen.novel.service.BookService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Random; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; /** * 小说模块 服务实现类 @@ -427,6 +408,35 @@ public class BookServiceImpl implements BookService { .build()).toList())); } + @Override + public RestResp> listComments(Long userId, PageReqDto pageReqDto) { + IPage page = new Page<>(); + page.setCurrent(pageReqDto.getPageNum()); + page.setSize(pageReqDto.getPageSize()); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId) + .orderByDesc(DatabaseConsts.CommonColumnEnum.UPDATE_TIME.getName()); + IPage bookCommentPage = bookCommentMapper.selectPage(page, queryWrapper); + List comments = bookCommentPage.getRecords(); + if (!CollectionUtils.isEmpty(comments)) { + List bookIds = comments.stream().map(BookComment::getBookId).toList(); + QueryWrapper bookInfoQueryWrapper = new QueryWrapper<>(); + bookInfoQueryWrapper.in(DatabaseConsts.CommonColumnEnum.ID.getName(), bookIds); + Map bookInfoMap = bookInfoMapper.selectList(bookInfoQueryWrapper).stream() + .collect(Collectors.toMap(BookInfo::getId, Function.identity())); + return RestResp.ok(PageRespDto.of(pageReqDto.getPageNum(), pageReqDto.getPageSize(), page.getTotal(), + comments.stream().map(v -> UserCommentRespDto.builder() + .commentContent(v.getCommentContent()) + .commentBook(bookInfoMap.get(v.getBookId()).getBookName()) + .commentBookPic(bookInfoMap.get(v.getBookId()).getPicUrl()) + .commentTime(v.getCreateTime()) + .build()).toList())); + + } + return RestResp.ok(PageRespDto.of(pageReqDto.getPageNum(), pageReqDto.getPageSize(), page.getTotal(), + Collections.emptyList())); + } + @Override public RestResp getBookContentAbout(Long chapterId) { log.debug("userId:{}", UserHolder.getUserId()); -- Gitee From d6df259e945d0215d910969608b9d5f8b2d80af8 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 25 Apr 2023 17:43:33 +0800 Subject: [PATCH 099/112] =?UTF-8?q?feat:=20=E5=B0=8F=E8=AF=B4=E7=AB=A0?= =?UTF-8?q?=E8=8A=82=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/author/AuthorController.java | 17 ++++--- .../cache/BookChapterCacheManager.java | 6 +++ .../cache/BookContentCacheManager.java | 7 +++ .../manager/cache/BookInfoCacheManager.java | 5 +- .../xxyopen/novel/service/BookService.java | 8 +++ .../novel/service/impl/BookServiceImpl.java | 49 +++++++++++++++++++ 6 files changed, 84 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index 4c8be34..167384f 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -20,12 +20,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; /** * 作家后台-作家模块 API 控制器 @@ -93,6 +88,16 @@ public class AuthorController { return bookService.saveBookChapter(dto); } + /** + * 小说章节删除接口 + */ + @Operation(summary = "小说章节删除接口") + @DeleteMapping("book/chapter/{chapterId}") + public RestResp deleteBookChapter( + @Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { + return bookService.deleteBookChapter(chapterId); + } + /** * 小说章节发布列表查询接口 */ diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java index 83aa618..9c21008 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java @@ -5,6 +5,7 @@ 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.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; @@ -37,5 +38,10 @@ public class BookChapterCacheManager { .build(); } + @CacheEvict(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, + value = CacheConsts.BOOK_CHAPTER_CACHE_NAME) + public void evictBookChapterCache(Long chapterId) { + // 调用此方法自动清除小说章节信息的缓存 + } } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java index c250ff3..de41fb3 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookContentCacheManager.java @@ -6,6 +6,7 @@ import io.github.xxyopen.novel.core.constant.DatabaseConsts; import io.github.xxyopen.novel.dao.entity.BookContent; import io.github.xxyopen.novel.dao.mapper.BookContentMapper; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; @@ -34,5 +35,11 @@ public class BookContentCacheManager { return bookContent.getContent(); } + @CacheEvict(cacheManager = CacheConsts.REDIS_CACHE_MANAGER, + value = CacheConsts.BOOK_CONTENT_CACHE_NAME) + public void evictBookContentCache(Long chapterId) { + // 调用此方法自动清除小说内容信息的缓存 + } + } diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java index 107453d..94a7db1 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookInfoCacheManager.java @@ -8,13 +8,14 @@ import io.github.xxyopen.novel.dao.entity.BookInfo; import io.github.xxyopen.novel.dao.mapper.BookChapterMapper; import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; +import java.util.List; + /** * 小说信息 缓存管理类 * @@ -74,7 +75,7 @@ public class BookInfoCacheManager { @CacheEvict(cacheManager = CacheConsts.CAFFEINE_CACHE_MANAGER, value = CacheConsts.BOOK_INFO_CACHE_NAME) - public void evictBookInfoCache(Long ignoredId) { + public void evictBookInfoCache(Long bookId) { // 调用此方法自动清除小说信息的缓存 } diff --git a/src/main/java/io/github/xxyopen/novel/service/BookService.java b/src/main/java/io/github/xxyopen/novel/service/BookService.java index efda4af..51f0c21 100644 --- a/src/main/java/io/github/xxyopen/novel/service/BookService.java +++ b/src/main/java/io/github/xxyopen/novel/service/BookService.java @@ -189,4 +189,12 @@ public interface BookService { */ RestResp> listComments(Long userId, PageReqDto pageReqDto); + /** + * 小说章节删除 + * + * @param chapterId 章节ID + * @return void + */ + RestResp deleteBookChapter(Long chapterId); + } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index 7fdd0e8..ca60c00 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -437,6 +437,55 @@ public class BookServiceImpl implements BookService { Collections.emptyList())); } + @Transactional(rollbackFor = Exception.class) + @Override + public RestResp deleteBookChapter(Long chapterId) { + // 1.查询章节信息 + BookChapterRespDto chapter = bookChapterCacheManager.getChapter(chapterId); + // 2.查询小说信息 + BookInfoRespDto bookInfo = bookInfoCacheManager.getBookInfo(chapter.getBookId()); + // 3.删除章节信息 + bookChapterMapper.deleteById(chapterId); + // 4.删除章节内容 + QueryWrapper bookContentQueryWrapper = new QueryWrapper<>(); + bookContentQueryWrapper.eq(DatabaseConsts.BookContentTable.COLUMN_CHAPTER_ID, chapterId); + bookContentMapper.delete(bookContentQueryWrapper); + // 5.更新小说信息 + BookInfo newBookInfo = new BookInfo(); + newBookInfo.setId(chapter.getBookId()); + newBookInfo.setUpdateTime(LocalDateTime.now()); + newBookInfo.setWordCount(bookInfo.getWordCount() - chapter.getChapterWordCount()); + if (Objects.equals(bookInfo.getLastChapterId(), chapterId)) { + // 设置最新章节信息 + QueryWrapper bookChapterQueryWrapper = new QueryWrapper<>(); + bookChapterQueryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, chapter.getBookId()) + .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM) + .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql()); + BookChapter bookChapter = bookChapterMapper.selectOne(bookChapterQueryWrapper); + Long lastChapterId = 0L; + String lastChapterName = ""; + LocalDateTime lastChapterUpdateTime = null; + if (Objects.nonNull(bookChapter)) { + lastChapterId = bookChapter.getId(); + lastChapterName = bookChapter.getChapterName(); + lastChapterUpdateTime = bookChapter.getUpdateTime(); + } + newBookInfo.setLastChapterId(lastChapterId); + newBookInfo.setLastChapterName(lastChapterName); + newBookInfo.setLastChapterUpdateTime(lastChapterUpdateTime); + } + bookInfoMapper.updateById(newBookInfo); + // 6.清理章节信息缓存 + bookChapterCacheManager.evictBookChapterCache(chapterId); + // 7.清理章节内容缓存 + bookContentCacheManager.evictBookContentCache(chapterId); + // 8.清理小说信息缓存 + bookInfoCacheManager.evictBookInfoCache(chapter.getBookId()); + // 9.发送小说信息更新的 MQ 消息 + amqpMsgManager.sendBookChangeMsg(chapter.getBookId()); + return RestResp.ok(); + } + @Override public RestResp getBookContentAbout(Long chapterId) { log.debug("userId:{}", UserHolder.getUserId()); -- Gitee From a31edb0c6944131b88491d6d85f84350b6c042ff Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 25 Apr 2023 19:19:44 +0800 Subject: [PATCH 100/112] =?UTF-8?q?feat:=20=E5=B0=8F=E8=AF=B4=E7=AB=A0?= =?UTF-8?q?=E8=8A=82=E6=9F=A5=E8=AF=A2&=E6=9B=B4=E6=96=B0=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/author/AuthorController.java | 23 ++++++++ .../novel/dto/req/ChapterUpdateReqDto.java | 40 +++++++++++++ .../novel/dto/resp/ChapterContentRespDto.java | 35 +++++++++++ .../cache/BookChapterCacheManager.java | 1 + .../xxyopen/novel/service/BookService.java | 17 ++++++ .../novel/service/impl/BookServiceImpl.java | 58 +++++++++++++++++++ 6 files changed, 174 insertions(+) create mode 100644 src/main/java/io/github/xxyopen/novel/dto/req/ChapterUpdateReqDto.java create mode 100644 src/main/java/io/github/xxyopen/novel/dto/resp/ChapterContentRespDto.java diff --git a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java index 167384f..bd56582 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/author/AuthorController.java @@ -9,8 +9,10 @@ import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.dto.req.AuthorRegisterReqDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; +import io.github.xxyopen.novel.dto.req.ChapterUpdateReqDto; import io.github.xxyopen.novel.dto.resp.BookChapterRespDto; import io.github.xxyopen.novel.dto.resp.BookInfoRespDto; +import io.github.xxyopen.novel.dto.resp.ChapterContentRespDto; import io.github.xxyopen.novel.service.AuthorService; import io.github.xxyopen.novel.service.BookService; import io.swagger.v3.oas.annotations.Operation; @@ -98,6 +100,27 @@ public class AuthorController { return bookService.deleteBookChapter(chapterId); } + /** + * 小说章节查询接口 + */ + @Operation(summary = "小说章节查询接口") + @GetMapping("book/chapter/{chapterId}") + public RestResp getBookChapter( + @Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId) { + return bookService.getBookChapter(chapterId); + } + + /** + * 小说章节更新接口 + */ + @Operation(summary = "小说章节更新接口") + @PutMapping("book/chapter/{chapterId}") + public RestResp updateBookChapter( + @Parameter(description = "章节ID") @PathVariable("chapterId") Long chapterId, + @Valid @RequestBody ChapterUpdateReqDto dto) { + return bookService.updateBookChapter(chapterId, dto); + } + /** * 小说章节发布列表查询接口 */ diff --git a/src/main/java/io/github/xxyopen/novel/dto/req/ChapterUpdateReqDto.java b/src/main/java/io/github/xxyopen/novel/dto/req/ChapterUpdateReqDto.java new file mode 100644 index 0000000..b131310 --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/dto/req/ChapterUpdateReqDto.java @@ -0,0 +1,40 @@ +package io.github.xxyopen.novel.dto.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 章节发布 请求DTO + * + * @author xiongxiaoyang + * @date 2022/5/23 + */ +@Data +public class ChapterUpdateReqDto { + + /** + * 章节名 + */ + @NotBlank + @Schema(description = "章节名", required = true) + private String chapterName; + + /** + * 章节内容 + */ + @Schema(description = "章节内容", required = true) + @NotBlank + @Length(min = 50) + private String chapterContent; + + /** + * 是否收费;1-收费 0-免费 + */ + @Schema(description = "是否收费;1-收费 0-免费", required = true) + @NotNull + private Integer isVip; + +} diff --git a/src/main/java/io/github/xxyopen/novel/dto/resp/ChapterContentRespDto.java b/src/main/java/io/github/xxyopen/novel/dto/resp/ChapterContentRespDto.java new file mode 100644 index 0000000..6caebea --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/dto/resp/ChapterContentRespDto.java @@ -0,0 +1,35 @@ +package io.github.xxyopen.novel.dto.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +/** + * 小说内容 响应DTO + * + * @author xiongxiaoyang + * @date 2022/5/15 + */ +@Data +@Builder +public class ChapterContentRespDto { + + /** + * 章节标题 + */ + @Schema(description = "章节名") + private String chapterName; + + /** + * 章节内容 + */ + @Schema(description = "章节内容") + private String chapterContent; + + /** + * 是否收费;1-收费 0-免费 + */ + @Schema(description = "是否收费;1-收费 0-免费") + private Integer isVip; + +} diff --git a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java index 9c21008..237137c 100644 --- a/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java +++ b/src/main/java/io/github/xxyopen/novel/manager/cache/BookChapterCacheManager.java @@ -35,6 +35,7 @@ public class BookChapterCacheManager { .chapterName(bookChapter.getChapterName()) .chapterWordCount(bookChapter.getWordCount()) .chapterUpdateTime(bookChapter.getUpdateTime()) + .isVip(bookChapter.getIsVip()) .build(); } diff --git a/src/main/java/io/github/xxyopen/novel/service/BookService.java b/src/main/java/io/github/xxyopen/novel/service/BookService.java index 51f0c21..1a725a8 100644 --- a/src/main/java/io/github/xxyopen/novel/service/BookService.java +++ b/src/main/java/io/github/xxyopen/novel/service/BookService.java @@ -5,6 +5,7 @@ import io.github.xxyopen.novel.core.common.resp.PageRespDto; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; +import io.github.xxyopen.novel.dto.req.ChapterUpdateReqDto; import io.github.xxyopen.novel.dto.req.UserCommentReqDto; import io.github.xxyopen.novel.dto.resp.*; @@ -197,4 +198,20 @@ public interface BookService { */ RestResp deleteBookChapter(Long chapterId); + /** + * 小说章节查询 + * + * @param chapterId 章节ID + * @return 章节内容 + */ + RestResp getBookChapter(Long chapterId); + + /** + * 小说章节更新 + * + * @param chapterId 章节ID + * @param dto 更新内容 + * @return void + */ + RestResp updateBookChapter(Long chapterId, ChapterUpdateReqDto dto); } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java index ca60c00..2054972 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/BookServiceImpl.java @@ -19,6 +19,7 @@ import io.github.xxyopen.novel.dao.mapper.BookInfoMapper; import io.github.xxyopen.novel.dto.AuthorInfoDto; import io.github.xxyopen.novel.dto.req.BookAddReqDto; import io.github.xxyopen.novel.dto.req.ChapterAddReqDto; +import io.github.xxyopen.novel.dto.req.ChapterUpdateReqDto; import io.github.xxyopen.novel.dto.req.UserCommentReqDto; import io.github.xxyopen.novel.dto.resp.*; import io.github.xxyopen.novel.manager.cache.*; @@ -486,6 +487,63 @@ public class BookServiceImpl implements BookService { return RestResp.ok(); } + @Override + public RestResp getBookChapter(Long chapterId) { + BookChapterRespDto chapter = bookChapterCacheManager.getChapter(chapterId); + String bookContent = bookContentCacheManager.getBookContent(chapterId); + return RestResp.ok( + ChapterContentRespDto.builder() + .chapterName(chapter.getChapterName()) + .chapterContent(bookContent) + .isVip(chapter.getIsVip()) + .build()); + } + + @Transactional + @Override + public RestResp updateBookChapter(Long chapterId, ChapterUpdateReqDto dto) { + // 1.查询章节信息 + BookChapterRespDto chapter = bookChapterCacheManager.getChapter(chapterId); + // 2.查询小说信息 + BookInfoRespDto bookInfo = bookInfoCacheManager.getBookInfo(chapter.getBookId()); + // 3.更新章节信息 + BookChapter newChapter = new BookChapter(); + newChapter.setId(chapterId); + newChapter.setChapterName(dto.getChapterName()); + newChapter.setWordCount(dto.getChapterContent().length()); + newChapter.setIsVip(dto.getIsVip()); + newChapter.setUpdateTime(LocalDateTime.now()); + bookChapterMapper.updateById(newChapter); + // 4.更新章节内容 + BookContent newContent = new BookContent(); + newContent.setContent(dto.getChapterContent()); + newContent.setUpdateTime(LocalDateTime.now()); + QueryWrapper bookContentQueryWrapper = new QueryWrapper<>(); + bookContentQueryWrapper.eq(DatabaseConsts.BookContentTable.COLUMN_CHAPTER_ID, chapterId); + bookContentMapper.update(newContent, bookContentQueryWrapper); + // 5.更新小说信息 + BookInfo newBookInfo = new BookInfo(); + newBookInfo.setId(chapter.getBookId()); + newBookInfo.setUpdateTime(LocalDateTime.now()); + newBookInfo.setWordCount( + bookInfo.getWordCount() - chapter.getChapterWordCount() + dto.getChapterContent().length()); + if (Objects.equals(bookInfo.getLastChapterId(), chapterId)) { + // 更新最新章节信息 + newBookInfo.setLastChapterName(dto.getChapterName()); + newBookInfo.setLastChapterUpdateTime(LocalDateTime.now()); + } + bookInfoMapper.updateById(newBookInfo); + // 6.清理章节信息缓存 + bookChapterCacheManager.evictBookChapterCache(chapterId); + // 7.清理章节内容缓存 + bookContentCacheManager.evictBookContentCache(chapterId); + // 8.清理小说信息缓存 + bookInfoCacheManager.evictBookInfoCache(chapter.getBookId()); + // 9.发送小说信息更新的 MQ 消息 + amqpMsgManager.sendBookChangeMsg(chapter.getBookId()); + return RestResp.ok(); + } + @Override public RestResp getBookContentAbout(Long chapterId) { log.debug("userId:{}", UserHolder.getUserId()); -- Gitee From 2270072d7ee1aa0fd193676e76bfcbfeeae2818f Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 25 Apr 2023 19:48:24 +0800 Subject: [PATCH 101/112] =?UTF-8?q?build:=203.4.0=20=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b56b669..d01f740 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@
io.github.xxyopen novel - 3.3.0 + 3.4.0 novel Spring Boot 3 + Vue 3 构建的前后端分离小说系统 -- Gitee From 7b4b97569b103ae849ae97335356ec3aea0ac6ae Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 21 Dec 2023 12:04:48 +0800 Subject: [PATCH 102/112] =?UTF-8?q?fix:=20=E5=88=86=E5=BA=93=E5=88=86?= =?UTF-8?q?=E8=A1=A8=E5=8A=9F=E8=83=BD=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit shardingsphere-jdbc-core-spring-boot-starter 依赖版本过低 --- pom.xml | 7 +++++- .../config/ShardingSphereConfiguration.java | 24 +++++++++++++++++++ ...itional-spring-configuration-metadata.json | 6 +++++ src/main/resources/application.yml | 15 ++++++------ 4 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 src/main/java/io/github/xxyopen/novel/core/config/ShardingSphereConfiguration.java diff --git a/pom.xml b/pom.xml index d01f740..99b1b9c 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ 8.2.0 2.3.1 1.8.4 - 5.1.1 + 5.2.1 3.19.1 3.0.0-M1 2.0.0 @@ -149,6 +149,11 @@ shardingsphere-jdbc-core-spring-boot-starter ${shardingsphere-jdbc.version}
+ + com.h2database + h2 + runtime + diff --git a/src/main/java/io/github/xxyopen/novel/core/config/ShardingSphereConfiguration.java b/src/main/java/io/github/xxyopen/novel/core/config/ShardingSphereConfiguration.java new file mode 100644 index 0000000..ec465ef --- /dev/null +++ b/src/main/java/io/github/xxyopen/novel/core/config/ShardingSphereConfiguration.java @@ -0,0 +1,24 @@ +package io.github.xxyopen.novel.core.config; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; + +/** + * ShardingSphere 配置类,控制是否开启 ShardingSphere + * + * @author xiongxiaoyang + * @date 2023/12/21 + */ +@Configuration +@EnableAutoConfiguration(exclude = { + org.apache.shardingsphere.spring.boot.ShardingSphereAutoConfiguration.class +}) +@ConditionalOnProperty( + prefix = "spring.shardingsphere", + name = {"enabled"}, + havingValue = "false" +) +public class ShardingSphereConfiguration { + +} diff --git a/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/src/main/resources/META-INF/additional-spring-configuration-metadata.json index d74c6a7..bdcd71d 100644 --- a/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -65,6 +65,12 @@ "name": "spring.elasticsearch.ssl.verification-mode", "type": "java.lang.String", "description": "设置 ssl 的认证模式,如果该配置项为 none ,说明不需要认证,信任所有的 ssl 证书." + }, + { + "defaultValue": true, + "name": "spring.shardingsphere.enabled", + "description": "Whether enable shardingsphere or not.", + "type": "java.lang.Boolean" } ] } \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 946e0d0..75f3bd0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -39,14 +39,15 @@ spring: mode: # 单机模式 type: Standalone + # 元数据持久化 repository: - # 文件持久化 - type: File + # 数据库持久化 + type: JDBC props: - # 元数据存储路径 - path: .shardingsphere - # 使用本地配置覆盖持久化配置 - overwrite: true + # 元数据存储类型 + provider: H2 + jdbc_url: jdbc:h2:./.h2/shardingsphere + # 数据源配置 datasource: names: ds_0 @@ -87,7 +88,7 @@ spring: redis: host: 127.0.0.1 port: 6379 - password: 123456 + password: test123456 # Elasticsearch 配置 elasticsearch: -- Gitee From e09aad2415841bb626db75406b7f9a8d7b6b79d7 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 1 Jun 2024 21:12:55 +0800 Subject: [PATCH 103/112] =?UTF-8?q?build:=20=E5=8D=87=E7=BA=A7spring-boot3?= =?UTF-8?q?=E8=87=B33.3.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 19 ++++++------------- .../xxyopen/novel/core/config/EsConfig.java | 9 --------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index 99b1b9c..e474fe5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 3.0.0 + 3.3.0 io.github.xxyopen @@ -16,16 +16,15 @@ Spring Boot 3 + Vue 3 构建的前后端分离小说系统 17 - 3.5.3 + 3.5.6 3.5.1 0.11.5 - 8.2.0 2.3.1 1.8.4 5.2.1 3.19.1 3.0.0-M1 - 2.0.0 + 2.5.0 @@ -50,7 +49,7 @@ com.baomidou - mybatis-plus-boot-starter + mybatis-plus-spring-boot3-starter ${mybatis-plus.version} @@ -107,15 +106,9 @@ hibernate-validator - - co.elastic.clients - elasticsearch-java - ${elasticsearch.version} - - - com.fasterxml.jackson.core - jackson-databind + org.springframework.boot + spring-boot-starter-data-elasticsearch diff --git a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java index a35fbb2..38620b2 100644 --- a/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java +++ b/src/main/java/io/github/xxyopen/novel/core/config/EsConfig.java @@ -1,6 +1,5 @@ package io.github.xxyopen.novel.core.config; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; import lombok.extern.slf4j.Slf4j; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; import org.elasticsearch.client.RestClient; @@ -29,14 +28,6 @@ import java.security.cert.X509Certificate; @Slf4j public class EsConfig { - /** - * 解决 ElasticsearchClientConfigurations 修改默认 ObjectMapper 配置的问题 - */ - @Bean - JacksonJsonpMapper jacksonJsonpMapper() { - return new JacksonJsonpMapper(); - } - /** * fix `sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: * unable to find valid certification path to requested target` -- Gitee From f547a8b7d87efb1cc07047ceadd979db2f754953 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 2 Jun 2024 08:04:25 +0800 Subject: [PATCH 104/112] =?UTF-8?q?build:=203.4.1=20=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 99b1b9c..82f496c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.github.xxyopen novel - 3.4.0 + 3.4.1 novel Spring Boot 3 + Vue 3 构建的前后端分离小说系统 -- Gitee From 03b3ca1d83fdea283463cb349d7c11ba42f745cd Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 2 Jun 2024 08:24:28 +0800 Subject: [PATCH 105/112] =?UTF-8?q?build:=20=E4=BF=AE=E6=94=B9=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fd4bb8d..bb95e45 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.github.xxyopen novel - 3.4.1 + 3.5.0-SNAPSHOT novel Spring Boot 3 + Vue 3 构建的前后端分离小说系统 -- Gitee From 9da5064a9e0e532e36875de1f64ab91cfebb6628 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 2 Jun 2024 08:47:57 +0800 Subject: [PATCH 106/112] =?UTF-8?q?perf:=20=E5=90=AF=E7=94=A8=E8=99=9A?= =?UTF-8?q?=E6=8B=9F=E7=BA=BF=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 需要在 Java 21 上运行 --- src/main/resources/application.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 75f3bd0..19bd297 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -16,6 +16,10 @@ spring: multipart: # 上传文件最大大小 max-file-size: 5MB + # 启用虚拟线程 + threads: + virtual: + enabled: true server: # 端口号 port: 8888 -- Gitee From 876d9b8cbe4ab0bbb72bbdc50d6ceb897d4f4f89 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 2 Jun 2024 12:15:05 +0800 Subject: [PATCH 107/112] =?UTF-8?q?build:=20=E4=BD=BF=E7=94=A8=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E7=9A=84=20Spring=20Boot=20=E5=86=85=E5=B5=8C=20Web?= =?UTF-8?q?=20=E5=AE=B9=E5=99=A8=EF=BC=8C=E5=AE=9E=E7=8E=B0=E8=99=9A?= =?UTF-8?q?=E6=8B=9F=E7=BA=BF=E7=A8=8B=E5=A4=84=E7=90=86=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spring Boot v3.3.0-M3 删除了对 Undertow 的虚拟线程支持,因为它会泄漏内存 --- pom.xml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pom.xml b/pom.xml index bb95e45..c4f4767 100644 --- a/pom.xml +++ b/pom.xml @@ -31,19 +31,6 @@ org.springframework.boot spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - - - org.springframework.boot - spring-boot-starter-undertow -- Gitee From e7005b90084e7fa300110e20ff72530df73db846 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 2 Jun 2024 14:02:48 +0800 Subject: [PATCH 108/112] =?UTF-8?q?build:=20=E6=9B=B4=E6=96=B0java?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=88=B021?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c4f4767..059366d 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ novel Spring Boot 3 + Vue 3 构建的前后端分离小说系统 - 17 + 21 3.5.6 3.5.1 0.11.5 -- Gitee From 63760c8e90942fba717cbc0dbc1c297e82366ce5 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 28 Jun 2024 01:46:16 +0800 Subject: [PATCH 109/112] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90=20Flyway?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 8 + .../resources/db/migration/R__xxl-job.sql | 190 ++++++ .../resources/db/migration/V3.4.0__novel.sql | 601 ++++++++++++++++++ 3 files changed, 799 insertions(+) create mode 100644 src/main/resources/db/migration/R__xxl-job.sql create mode 100644 src/main/resources/db/migration/V3.4.0__novel.sql diff --git a/pom.xml b/pom.xml index 059366d..75139fd 100644 --- a/pom.xml +++ b/pom.xml @@ -196,6 +196,14 @@ spring-boot-starter-test test
+ + org.flywaydb + flyway-core + + + org.flywaydb + flyway-mysql +
diff --git a/src/main/resources/db/migration/R__xxl-job.sql b/src/main/resources/db/migration/R__xxl-job.sql new file mode 100644 index 0000000..ceed371 --- /dev/null +++ b/src/main/resources/db/migration/R__xxl-job.sql @@ -0,0 +1,190 @@ +# +# XXL-JOB v2.4.0-SNAPSHOT +# Copyright (c) 2015-present, xuxueli. + +CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci; +use `xxl_job`; + +SET NAMES utf8mb4; + +CREATE TABLE `xxl_job_info` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `job_group` int(11) NOT NULL COMMENT '执行器主键ID', + `job_desc` varchar(255) NOT NULL, + `add_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + `author` varchar(64) DEFAULT NULL COMMENT '作者', + `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件', + `schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型', + `schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型', + `misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略', + `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略', + `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', + `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数', + `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略', + `executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒', + `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数', + `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型', + `glue_source` mediumtext COMMENT 'GLUE源代码', + `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注', + `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间', + `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔', + `trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行', + `trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间', + `trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_log` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `job_group` int(11) NOT NULL COMMENT '执行器主键ID', + `job_id` int(11) NOT NULL COMMENT '任务,主键ID', + `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址', + `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', + `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数', + `executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2', + `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数', + `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间', + `trigger_code` int(11) NOT NULL COMMENT '调度-结果', + `trigger_msg` text COMMENT '调度-日志', + `handle_time` datetime DEFAULT NULL COMMENT '执行-时间', + `handle_code` int(11) NOT NULL COMMENT '执行-状态', + `handle_msg` text COMMENT '执行-日志', + `alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败', + PRIMARY KEY (`id`), + KEY `I_trigger_time` (`trigger_time`), + KEY `I_handle_code` (`handle_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_log_report` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `trigger_day` datetime DEFAULT NULL COMMENT '调度-时间', + `running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量', + `suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量', + `fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量', + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_logglue` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `job_id` int(11) NOT NULL COMMENT '任务,主键ID', + `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型', + `glue_source` mediumtext COMMENT 'GLUE源代码', + `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注', + `add_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_registry` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `registry_group` varchar(50) NOT NULL, + `registry_key` varchar(255) NOT NULL, + `registry_value` varchar(255) NOT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_group` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `app_name` varchar(64) NOT NULL COMMENT '执行器AppName', + `title` varchar(12) NOT NULL COMMENT '执行器名称', + `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入', + `address_list` text COMMENT '执行器地址列表,多地址逗号分隔', + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL COMMENT '账号', + `password` varchar(50) NOT NULL COMMENT '密码', + `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员', + `permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割', + PRIMARY KEY (`id`), + UNIQUE KEY `i_username` (`username`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_lock` ( + `lock_name` varchar(50) NOT NULL COMMENT '锁名称', + PRIMARY KEY (`lock_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' ); +INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', ''); +INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL); +INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock'); + +commit; + + +-- 增加 novel 任务执行器和同步小说数据到 Elasticsearch 的任务 +-- 增加 novel 任务执行器和同步小说数据到 Elasticsearch 的任务 +INSERT INTO `xxl_job`.`xxl_job_group` ( `app_name`, `title`, `address_type`, `address_list`, `update_time` ) +VALUES + ( + 'xxl-job-executor-novel', + 'novel 任务执行器', + 0, + NULL, + now() + ); +INSERT INTO `xxl_job`.`xxl_job_info` ( + `job_group`, + `job_desc`, + `add_time`, + `update_time`, + `author`, + `alarm_email`, + `schedule_type`, + `schedule_conf`, + `misfire_strategy`, + `executor_route_strategy`, + `executor_handler`, + `executor_param`, + `executor_block_strategy`, + `executor_timeout`, + `executor_fail_retry_count`, + `glue_type`, + `glue_source`, + `glue_remark`, + `glue_updatetime`, + `child_jobid`, + `trigger_status`, + `trigger_last_time`, + `trigger_next_time` +) +VALUES + ( + (SELECT + id + FROM + xxl_job_group + WHERE + app_name = 'xxl-job-executor-novel'), + '同步小说数据到 Elasticsearch', + now(), + now(), + 'xxyopen', + '', + 'CRON', + '0 0 0 1 * ?', + 'DO_NOTHING', + 'FIRST', + 'saveToEsJobHandler', + '', + 'SERIAL_EXECUTION', + 0, + 0, + 'BEAN', + '', + 'GLUE代码初始化', + now(), + '', + 0, + 0, + 0 + ); \ No newline at end of file diff --git a/src/main/resources/db/migration/V3.4.0__novel.sql b/src/main/resources/db/migration/V3.4.0__novel.sql new file mode 100644 index 0000000..101961f --- /dev/null +++ b/src/main/resources/db/migration/V3.4.0__novel.sql @@ -0,0 +1,601 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 80012 + Source Host : localhost:3306 + Source Schema : novel + + Target Server Type : MySQL + Target Server Version : 80012 + File Encoding : 65001 + + Date: 16/05/2022 18:47:34 +*/ + +SET NAMES utf8mb4; +SET +FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for author_code +-- ---------------------------- +CREATE TABLE `author_code` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `invite_code` varchar(100) NOT NULL COMMENT '邀请码', + `validity_time` datetime NOT NULL COMMENT '有效时间', + `is_used` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否使用过;0-未使用 1-使用过', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_code` (`invite_code`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='作家邀请码'; + +-- ---------------------------- +-- Table structure for author_income +-- ---------------------------- +CREATE TABLE `author_income` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `author_id` bigint(20) unsigned NOT NULL COMMENT '作家ID', + `book_id` bigint(20) unsigned NOT NULL COMMENT '小说ID', + `income_month` date NOT NULL COMMENT '收入月份', + `pre_tax_income` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '税前收入;单位:分', + `after_tax_income` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '税后收入;单位:分', + `pay_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '支付状态;0-待支付 1-已支付', + `confirm_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '稿费确认状态;0-待确认 1-已确认', + `detail` varchar(255) DEFAULT NULL COMMENT '详情', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='稿费收入统计'; + +-- ---------------------------- +-- Table structure for author_income_detail +-- ---------------------------- +CREATE TABLE `author_income_detail` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `author_id` bigint(20) unsigned NOT NULL COMMENT '作家ID', + `book_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '小说ID;0表示全部作品', + `income_date` date NOT NULL COMMENT '收入日期', + `income_account` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订阅总额', + `income_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订阅次数', + `income_number` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订阅人数', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='稿费收入明细统计'; + +-- ---------------------------- +-- Table structure for author_info +-- ---------------------------- +CREATE TABLE `author_info` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', + `invite_code` varchar(20) NOT NULL COMMENT '邀请码', + `pen_name` varchar(20) NOT NULL COMMENT '笔名', + `tel_phone` varchar(20) DEFAULT NULL COMMENT '手机号码', + `chat_account` varchar(50) DEFAULT NULL COMMENT 'QQ或微信账号', + `email` varchar(50) DEFAULT NULL COMMENT '电子邮箱', + `work_direction` tinyint(3) unsigned DEFAULT NULL COMMENT '作品方向;0-男频 1-女频', + `status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '0:正常;1-封禁', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_userId` (`user_id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='作者信息'; + +-- ---------------------------- +-- Table structure for book_category +-- ---------------------------- +CREATE TABLE `book_category` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `work_direction` tinyint(3) unsigned NOT NULL COMMENT '作品方向;0-男频 1-女频', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '类别名', + `sort` tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '排序', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `pk_id` (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说类别'; + +-- ---------------------------- +-- Table structure for book_chapter +-- ---------------------------- +CREATE TABLE `book_chapter` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `book_id` bigint(20) unsigned NOT NULL COMMENT '小说ID', + `chapter_num` smallint(5) unsigned NOT NULL COMMENT '章节号', + `chapter_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '章节名', + `word_count` int(10) unsigned NOT NULL COMMENT '章节字数', + `is_vip` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否收费;1-收费 0-免费', + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_bookId_chapterNum` (`book_id`,`chapter_num`) USING BTREE, + UNIQUE KEY `pk_id` (`id`) USING BTREE, + KEY `idx_bookId` (`book_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1445988184596992001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说章节'; + +-- ---------------------------- +-- Table structure for book_comment +-- ---------------------------- +CREATE TABLE `book_comment` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `book_id` bigint(20) unsigned NOT NULL COMMENT '评论小说ID', + `user_id` bigint(20) unsigned NOT NULL COMMENT '评论用户ID', + `comment_content` varchar(512) NOT NULL COMMENT '评价内容', + `reply_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '回复数量', + `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_bookId_userId` (`book_id`,`user_id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说评论'; + +-- ---------------------------- +-- Table structure for book_comment_copy1 +-- ---------------------------- +CREATE TABLE `book_comment_copy1` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `book_id` bigint(20) unsigned NOT NULL COMMENT '评论小说ID', + `user_id` bigint(20) unsigned NOT NULL COMMENT '评论用户ID', + `comment_content` varchar(512) NOT NULL COMMENT '评价内容', + `reply_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '回复数量', + `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_bookId_userId` (`book_id`,`user_id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说评论'; + +-- ---------------------------- +-- Table structure for book_comment_reply +-- ---------------------------- +CREATE TABLE `book_comment_reply` +( + `id` bigint(20) unsigned NOT NULL COMMENT '主键', + `comment_id` bigint(20) unsigned NOT NULL COMMENT '评论ID', + `user_id` bigint(20) unsigned NOT NULL COMMENT '回复用户ID', + `reply_content` varchar(512) NOT NULL COMMENT '回复内容', + `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说评论回复'; + +-- ---------------------------- +-- Table structure for book_content +-- ---------------------------- +CREATE TABLE `book_content` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `chapter_id` bigint(20) unsigned NOT NULL COMMENT '章节ID', + `content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '小说章节内容', + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_chapterId` (`chapter_id`) USING BTREE, + UNIQUE KEY `pk_id` (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=4256332 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说内容'; + +-- ---------------------------- +-- Table structure for book_info +-- ---------------------------- +CREATE TABLE `book_info` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `work_direction` tinyint(3) unsigned DEFAULT NULL COMMENT '作品方向;0-男频 1-女频', + `category_id` bigint(20) unsigned DEFAULT NULL COMMENT '类别ID', + `category_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '类别名', + `pic_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '小说封面地址', + `book_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '小说名', + `author_id` bigint(20) unsigned NOT NULL COMMENT '作家id', + `author_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '作家名', + `book_desc` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '书籍描述', + `score` tinyint(3) unsigned NOT NULL COMMENT '评分;总分:10 ,真实评分 = score/10', + `book_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '书籍状态;0-连载中 1-已完结', + `visit_count` bigint(20) unsigned NOT NULL DEFAULT '103' COMMENT '点击量', + `word_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '总字数', + `comment_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '评论数', + `last_chapter_id` bigint(20) unsigned DEFAULT NULL COMMENT '最新章节ID', + `last_chapter_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '最新章节名', + `last_chapter_update_time` datetime DEFAULT NULL COMMENT '最新章节更新时间', + `is_vip` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否收费;1-收费 0-免费', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_bookName_authorName` (`book_name`,`author_name`) USING BTREE, + UNIQUE KEY `pk_id` (`id`) USING BTREE, + KEY `idx_createTime` (`create_time`) USING BTREE, + KEY `idx_lastChapterUpdateTime` (`last_chapter_update_time`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1431630596354977793 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说信息'; + +-- ---------------------------- +-- Table structure for home_book +-- ---------------------------- +CREATE TABLE `home_book` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `type` tinyint(3) unsigned NOT NULL COMMENT '推荐类型;0-轮播图 1-顶部栏 2-本周强推 3-热门推荐 4-精品推荐', + `sort` tinyint(3) unsigned NOT NULL COMMENT '推荐排序', + `book_id` bigint(20) unsigned NOT NULL COMMENT '推荐小说ID', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=96 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说推荐'; + +-- ---------------------------- +-- Table structure for home_friend_link +-- ---------------------------- +CREATE TABLE `home_friend_link` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `link_name` varchar(50) NOT NULL COMMENT '链接名', + `link_url` varchar(100) NOT NULL COMMENT '链接url', + `sort` tinyint(3) unsigned NOT NULL DEFAULT '11' COMMENT '排序号', + `is_open` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '是否开启;0-不开启 1-开启', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='友情链接'; + +-- ---------------------------- +-- Table structure for news_category +-- ---------------------------- +CREATE TABLE `news_category` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(20) NOT NULL COMMENT '类别名', + `sort` tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '排序', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='新闻类别'; + +-- ---------------------------- +-- Table structure for news_content +-- ---------------------------- +CREATE TABLE `news_content` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `news_id` bigint(20) unsigned NOT NULL COMMENT '新闻ID', + `content` mediumtext NOT NULL COMMENT '新闻内容', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_newsId` (`news_id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='新闻内容'; + +-- ---------------------------- +-- Table structure for news_info +-- ---------------------------- +CREATE TABLE `news_info` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `category_id` bigint(20) unsigned NOT NULL COMMENT '类别ID', + `category_name` varchar(50) NOT NULL COMMENT '类别名', + `source_name` varchar(50) NOT NULL COMMENT '新闻来源', + `title` varchar(100) NOT NULL COMMENT '新闻标题', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='新闻信息'; + +-- ---------------------------- +-- Table structure for pay_alipay +-- ---------------------------- +CREATE TABLE `pay_alipay` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `out_trade_no` varchar(64) NOT NULL COMMENT '商户订单号', + `trade_no` varchar(64) NOT NULL COMMENT '支付宝交易号', + `buyer_id` varchar(16) DEFAULT NULL COMMENT '买家支付宝账号 ID', + `trade_status` varchar(32) DEFAULT NULL COMMENT '交易状态;TRADE_SUCCESS-交易成功', + `total_amount` int(10) unsigned NOT NULL COMMENT '订单金额;单位:分', + `receipt_amount` int(10) unsigned DEFAULT NULL COMMENT '实收金额;单位:分', + `invoice_amount` int(10) unsigned DEFAULT NULL COMMENT '开票金额', + `gmt_create` datetime DEFAULT NULL COMMENT '交易创建时间', + `gmt_payment` datetime DEFAULT NULL COMMENT '交易付款时间', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`), + KEY `uk_outTradeNo` (`out_trade_no`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付宝支付'; + +-- ---------------------------- +-- Table structure for pay_wechat +-- ---------------------------- +CREATE TABLE `pay_wechat` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `out_trade_no` varchar(32) NOT NULL COMMENT '商户订单号', + `transaction_id` varchar(32) NOT NULL COMMENT '微信支付订单号', + `trade_type` varchar(16) DEFAULT NULL COMMENT '交易类型;JSAPI-公众号支付 NATIVE-扫码支付 APP-APP支付 MICROPAY-付款码支付 MWEB-H5支付 FACEPAY-刷脸支付', + `trade_state` varchar(32) DEFAULT NULL COMMENT '交易状态;SUCCESS-支付成功 REFUND-转入退款 NOTPAY-未支付 CLOSED-已关闭 REVOKED-已撤销(付款码支付) USERPAYING-用户支付中(付款码支付) PAYERROR-支付失败(其他原因,如银行返回失败)', + `trade_state_desc` varchar(255) DEFAULT NULL COMMENT '交易状态描述', + `amount` int(10) unsigned NOT NULL COMMENT '订单总金额;单位:分', + `payer_total` int(10) unsigned DEFAULT NULL COMMENT '用户支付金额;单位:分', + `success_time` datetime DEFAULT NULL COMMENT '支付完成时间', + `payer_openid` varchar(128) DEFAULT NULL COMMENT '支付者用户标识;用户在直连商户appid下的唯一标识', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`), + KEY `uk_outTradeNo` (`out_trade_no`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='微信支付'; + +-- ---------------------------- +-- Table structure for sys_log +-- ---------------------------- +CREATE TABLE `sys_log` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `user_id` bigint(20) unsigned DEFAULT NULL COMMENT '用户id', + `username` varchar(50) DEFAULT NULL COMMENT '用户名', + `operation` varchar(50) DEFAULT NULL COMMENT '用户操作', + `time` int(10) unsigned DEFAULT NULL COMMENT '响应时间', + `method` varchar(200) DEFAULT NULL COMMENT '请求方法', + `params` varchar(5000) DEFAULT NULL COMMENT '请求参数', + `ip` varchar(64) DEFAULT NULL COMMENT 'IP地址', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统日志'; + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +CREATE TABLE `sys_menu` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `parent_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '父菜单ID;一级菜单为0', + `name` varchar(50) NOT NULL COMMENT '菜单名称', + `url` varchar(200) DEFAULT NULL COMMENT '菜单URL', + `type` tinyint(3) unsigned NOT NULL COMMENT '类型;0-目录 1-菜单', + `icon` varchar(50) DEFAULT NULL COMMENT '菜单图标', + `sort` tinyint(3) unsigned DEFAULT NULL COMMENT '排序', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统菜单'; + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +CREATE TABLE `sys_role` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `role_name` varchar(100) NOT NULL COMMENT '角色名称', + `role_sign` varchar(100) DEFAULT NULL COMMENT '角色标识', + `remark` varchar(100) DEFAULT NULL COMMENT '备注', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色'; + +-- ---------------------------- +-- Table structure for sys_role_menu +-- ---------------------------- +CREATE TABLE `sys_role_menu` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `role_id` bigint(20) unsigned NOT NULL COMMENT '角色ID', + `menu_id` bigint(20) unsigned NOT NULL COMMENT '菜单ID', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色与菜单对应关系'; + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +CREATE TABLE `sys_user` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL COMMENT '用户名', + `password` varchar(50) NOT NULL COMMENT '密码', + `name` varchar(100) DEFAULT NULL COMMENT '真实姓名', + `sex` tinyint(3) unsigned DEFAULT NULL COMMENT '性别;0-男 1-女', + `birth` datetime DEFAULT NULL COMMENT '出身日期', + `email` varchar(100) DEFAULT NULL COMMENT '邮箱', + `mobile` varchar(100) DEFAULT NULL COMMENT '手机号', + `status` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '状态;0-禁用 1-正常', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户'; + +-- ---------------------------- +-- Table structure for sys_user_role +-- ---------------------------- +CREATE TABLE `sys_user_role` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', + `role_id` bigint(20) unsigned NOT NULL COMMENT '角色ID', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户与角色对应关系'; + +-- ---------------------------- +-- Table structure for test +-- ---------------------------- +CREATE TABLE `test` +( + `id` int(11) NOT NULL, + `test` tinyint(1) unsigned zerofill DEFAULT NULL, + `test2` tinyint(4) unsigned zerofill DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- ---------------------------- +-- Table structure for user_bookshelf +-- ---------------------------- +CREATE TABLE `user_bookshelf` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', + `book_id` bigint(20) unsigned NOT NULL COMMENT '小说ID', + `pre_content_id` bigint(20) unsigned DEFAULT NULL COMMENT '上一次阅读的章节内容表ID', + `create_time` datetime DEFAULT NULL COMMENT '创建时间;', + `update_time` datetime DEFAULT NULL COMMENT '更新时间;', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_userId_bookId` (`user_id`,`book_id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户书架'; + +-- ---------------------------- +-- Table structure for user_comment +-- ---------------------------- +CREATE TABLE `user_comment` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `user_id` bigint(20) unsigned NOT NULL COMMENT '评论用户ID', + `book_id` bigint(20) unsigned NOT NULL COMMENT '评论小说ID', + `comment_content` varchar(512) NOT NULL COMMENT '评价内容', + `reply_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '回复数量', + `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_bookId_userId` (`book_id`,`user_id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户评论'; + +-- ---------------------------- +-- Table structure for user_comment_reply +-- ---------------------------- +CREATE TABLE `user_comment_reply` +( + `id` bigint(20) unsigned NOT NULL COMMENT '主键', + `comment_id` bigint(20) unsigned NOT NULL COMMENT '评论ID', + `user_id` bigint(20) unsigned NOT NULL COMMENT '回复用户ID', + `reply_content` varchar(512) NOT NULL COMMENT '回复内容', + `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户评论回复'; + +-- ---------------------------- +-- Table structure for user_consume_log +-- ---------------------------- +CREATE TABLE `user_consume_log` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `user_id` bigint(20) unsigned NOT NULL COMMENT '消费用户ID', + `amount` int(10) unsigned NOT NULL COMMENT '消费使用的金额;单位:屋币', + `product_type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '消费商品类型;0-小说VIP章节', + `product_id` bigint(20) unsigned DEFAULT NULL COMMENT '消费的的商品ID;例如:章节ID', + `produc_name` varchar(50) DEFAULT NULL COMMENT '消费的的商品名;例如:章节名', + `produc_value` int(10) unsigned DEFAULT NULL COMMENT '消费的的商品值;例如:1', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户消费记录'; + +-- ---------------------------- +-- Table structure for user_feedback +-- ---------------------------- +CREATE TABLE `user_feedback` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `user_id` bigint(20) unsigned NOT NULL COMMENT '反馈用户id', + `content` varchar(512) NOT NULL COMMENT '反馈内容', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户反馈'; + +-- ---------------------------- +-- Table structure for user_info +-- ---------------------------- +CREATE TABLE `user_info` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL COMMENT '登录名', + `password` varchar(100) NOT NULL COMMENT '登录密码-加密', + `salt` varchar(8) NOT NULL COMMENT '加密盐值', + `nick_name` varchar(50) DEFAULT NULL COMMENT '昵称', + `user_photo` varchar(100) DEFAULT NULL COMMENT '用户头像', + `user_sex` tinyint(3) unsigned DEFAULT NULL COMMENT '用户性别;0-男 1-女', + `account_balance` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '账户余额', + `status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '用户状态;0-正常', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_username` (`username`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户信息'; + +-- ---------------------------- +-- Table structure for user_pay_log +-- ---------------------------- +CREATE TABLE `user_pay_log` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `user_id` bigint(20) unsigned NOT NULL COMMENT '充值用户ID', + `pay_channel` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '充值方式;0-支付宝 1-微信', + `out_trade_no` varchar(64) NOT NULL COMMENT '商户订单号', + `amount` int(10) unsigned NOT NULL COMMENT '充值金额;单位:分', + `product_type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '充值商品类型;0-屋币 1-包年VIP', + `product_id` bigint(20) unsigned DEFAULT NULL COMMENT '充值商品ID', + `product_name` varchar(255) NOT NULL COMMENT '充值商品名;示例值:屋币', + `product_value` int(10) unsigned DEFAULT NULL COMMENT '充值商品值;示例值:255', + `pay_time` datetime NOT NULL COMMENT '充值时间', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户充值记录'; + +-- ---------------------------- +-- Table structure for user_read_history +-- ---------------------------- +CREATE TABLE `user_read_history` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', + `book_id` bigint(20) unsigned NOT NULL COMMENT '小说ID', + `pre_content_id` bigint(20) unsigned NOT NULL COMMENT '上一次阅读的章节内容表ID', + `create_time` datetime DEFAULT NULL COMMENT '创建时间;', + `update_time` datetime DEFAULT NULL COMMENT '更新时间;', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_userId_bookId` (`user_id`,`book_id`), + UNIQUE KEY `pk_id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户阅读历史'; + +SET +FOREIGN_KEY_CHECKS = 1; + -- Gitee From b4ce4dd35dba1192c88250693c39fede6054a470 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 28 Jun 2024 07:03:14 +0800 Subject: [PATCH 110/112] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96SQL=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E6=96=87=E4=BB=B6=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/README.md | 6 +- .../resources/db/migration/R__xxl-job.sql | 190 ------ .../resources/db/migration/V3.4.0__novel.sql | 601 ------------------ 3 files changed, 2 insertions(+), 795 deletions(-) delete mode 100644 src/main/resources/db/migration/R__xxl-job.sql delete mode 100644 src/main/resources/db/migration/V3.4.0__novel.sql diff --git a/doc/sql/README.md b/doc/sql/README.md index add482c..7d28d83 100644 --- a/doc/sql/README.md +++ b/doc/sql/README.md @@ -1,6 +1,4 @@ 1. 初始状态下,MySQL 只需要执行 `novel.sql` 文件即可正常运行本系统 -2. 代码更新后再执行以日期命名的增量 SQL 文件 -3. 只有开启 XXL-JOB 的功能,才需要执行 `xxl-job.sql` 和以 xxl-job 开头日期结尾的增量 SQL 文件 -4. 只有开启 ShardingSphere-JDBC 的功能,才需要执行 `shardingsphere-jdbc.sql` 和以 shardingsphere-jdbc 开头日期结尾的增量 SQL - 文件 +2. 只有开启 XXL-JOB 的功能,才需要执行 `xxl-job.sql` 文件 +3. 只有开启 ShardingSphere-JDBC 的功能,才需要执行 `shardingsphere-jdbc.sql` 文件 diff --git a/src/main/resources/db/migration/R__xxl-job.sql b/src/main/resources/db/migration/R__xxl-job.sql deleted file mode 100644 index ceed371..0000000 --- a/src/main/resources/db/migration/R__xxl-job.sql +++ /dev/null @@ -1,190 +0,0 @@ -# -# XXL-JOB v2.4.0-SNAPSHOT -# Copyright (c) 2015-present, xuxueli. - -CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci; -use `xxl_job`; - -SET NAMES utf8mb4; - -CREATE TABLE `xxl_job_info` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `job_group` int(11) NOT NULL COMMENT '执行器主键ID', - `job_desc` varchar(255) NOT NULL, - `add_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - `author` varchar(64) DEFAULT NULL COMMENT '作者', - `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件', - `schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型', - `schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型', - `misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略', - `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略', - `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', - `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数', - `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略', - `executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒', - `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数', - `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型', - `glue_source` mediumtext COMMENT 'GLUE源代码', - `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注', - `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间', - `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔', - `trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行', - `trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间', - `trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE `xxl_job_log` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `job_group` int(11) NOT NULL COMMENT '执行器主键ID', - `job_id` int(11) NOT NULL COMMENT '任务,主键ID', - `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址', - `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', - `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数', - `executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2', - `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数', - `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间', - `trigger_code` int(11) NOT NULL COMMENT '调度-结果', - `trigger_msg` text COMMENT '调度-日志', - `handle_time` datetime DEFAULT NULL COMMENT '执行-时间', - `handle_code` int(11) NOT NULL COMMENT '执行-状态', - `handle_msg` text COMMENT '执行-日志', - `alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败', - PRIMARY KEY (`id`), - KEY `I_trigger_time` (`trigger_time`), - KEY `I_handle_code` (`handle_code`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE `xxl_job_log_report` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `trigger_day` datetime DEFAULT NULL COMMENT '调度-时间', - `running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量', - `suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量', - `fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量', - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE `xxl_job_logglue` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `job_id` int(11) NOT NULL COMMENT '任务,主键ID', - `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型', - `glue_source` mediumtext COMMENT 'GLUE源代码', - `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注', - `add_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE `xxl_job_registry` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `registry_group` varchar(50) NOT NULL, - `registry_key` varchar(255) NOT NULL, - `registry_value` varchar(255) NOT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE `xxl_job_group` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `app_name` varchar(64) NOT NULL COMMENT '执行器AppName', - `title` varchar(12) NOT NULL COMMENT '执行器名称', - `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入', - `address_list` text COMMENT '执行器地址列表,多地址逗号分隔', - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE `xxl_job_user` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `username` varchar(50) NOT NULL COMMENT '账号', - `password` varchar(50) NOT NULL COMMENT '密码', - `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员', - `permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割', - PRIMARY KEY (`id`), - UNIQUE KEY `i_username` (`username`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE `xxl_job_lock` ( - `lock_name` varchar(50) NOT NULL COMMENT '锁名称', - PRIMARY KEY (`lock_name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' ); -INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', ''); -INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL); -INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock'); - -commit; - - --- 增加 novel 任务执行器和同步小说数据到 Elasticsearch 的任务 --- 增加 novel 任务执行器和同步小说数据到 Elasticsearch 的任务 -INSERT INTO `xxl_job`.`xxl_job_group` ( `app_name`, `title`, `address_type`, `address_list`, `update_time` ) -VALUES - ( - 'xxl-job-executor-novel', - 'novel 任务执行器', - 0, - NULL, - now() - ); -INSERT INTO `xxl_job`.`xxl_job_info` ( - `job_group`, - `job_desc`, - `add_time`, - `update_time`, - `author`, - `alarm_email`, - `schedule_type`, - `schedule_conf`, - `misfire_strategy`, - `executor_route_strategy`, - `executor_handler`, - `executor_param`, - `executor_block_strategy`, - `executor_timeout`, - `executor_fail_retry_count`, - `glue_type`, - `glue_source`, - `glue_remark`, - `glue_updatetime`, - `child_jobid`, - `trigger_status`, - `trigger_last_time`, - `trigger_next_time` -) -VALUES - ( - (SELECT - id - FROM - xxl_job_group - WHERE - app_name = 'xxl-job-executor-novel'), - '同步小说数据到 Elasticsearch', - now(), - now(), - 'xxyopen', - '', - 'CRON', - '0 0 0 1 * ?', - 'DO_NOTHING', - 'FIRST', - 'saveToEsJobHandler', - '', - 'SERIAL_EXECUTION', - 0, - 0, - 'BEAN', - '', - 'GLUE代码初始化', - now(), - '', - 0, - 0, - 0 - ); \ No newline at end of file diff --git a/src/main/resources/db/migration/V3.4.0__novel.sql b/src/main/resources/db/migration/V3.4.0__novel.sql deleted file mode 100644 index 101961f..0000000 --- a/src/main/resources/db/migration/V3.4.0__novel.sql +++ /dev/null @@ -1,601 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : localhost - Source Server Type : MySQL - Source Server Version : 80012 - Source Host : localhost:3306 - Source Schema : novel - - Target Server Type : MySQL - Target Server Version : 80012 - File Encoding : 65001 - - Date: 16/05/2022 18:47:34 -*/ - -SET NAMES utf8mb4; -SET -FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for author_code --- ---------------------------- -CREATE TABLE `author_code` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `invite_code` varchar(100) NOT NULL COMMENT '邀请码', - `validity_time` datetime NOT NULL COMMENT '有效时间', - `is_used` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否使用过;0-未使用 1-使用过', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `idx_code` (`invite_code`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='作家邀请码'; - --- ---------------------------- --- Table structure for author_income --- ---------------------------- -CREATE TABLE `author_income` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `author_id` bigint(20) unsigned NOT NULL COMMENT '作家ID', - `book_id` bigint(20) unsigned NOT NULL COMMENT '小说ID', - `income_month` date NOT NULL COMMENT '收入月份', - `pre_tax_income` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '税前收入;单位:分', - `after_tax_income` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '税后收入;单位:分', - `pay_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '支付状态;0-待支付 1-已支付', - `confirm_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '稿费确认状态;0-待确认 1-已确认', - `detail` varchar(255) DEFAULT NULL COMMENT '详情', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='稿费收入统计'; - --- ---------------------------- --- Table structure for author_income_detail --- ---------------------------- -CREATE TABLE `author_income_detail` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `author_id` bigint(20) unsigned NOT NULL COMMENT '作家ID', - `book_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '小说ID;0表示全部作品', - `income_date` date NOT NULL COMMENT '收入日期', - `income_account` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订阅总额', - `income_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订阅次数', - `income_number` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订阅人数', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='稿费收入明细统计'; - --- ---------------------------- --- Table structure for author_info --- ---------------------------- -CREATE TABLE `author_info` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', - `invite_code` varchar(20) NOT NULL COMMENT '邀请码', - `pen_name` varchar(20) NOT NULL COMMENT '笔名', - `tel_phone` varchar(20) DEFAULT NULL COMMENT '手机号码', - `chat_account` varchar(50) DEFAULT NULL COMMENT 'QQ或微信账号', - `email` varchar(50) DEFAULT NULL COMMENT '电子邮箱', - `work_direction` tinyint(3) unsigned DEFAULT NULL COMMENT '作品方向;0-男频 1-女频', - `status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '0:正常;1-封禁', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_userId` (`user_id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='作者信息'; - --- ---------------------------- --- Table structure for book_category --- ---------------------------- -CREATE TABLE `book_category` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `work_direction` tinyint(3) unsigned NOT NULL COMMENT '作品方向;0-男频 1-女频', - `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '类别名', - `sort` tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '排序', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE KEY `pk_id` (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说类别'; - --- ---------------------------- --- Table structure for book_chapter --- ---------------------------- -CREATE TABLE `book_chapter` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `book_id` bigint(20) unsigned NOT NULL COMMENT '小说ID', - `chapter_num` smallint(5) unsigned NOT NULL COMMENT '章节号', - `chapter_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '章节名', - `word_count` int(10) unsigned NOT NULL COMMENT '章节字数', - `is_vip` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否收费;1-收费 0-免费', - `create_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) USING BTREE, - UNIQUE KEY `uk_bookId_chapterNum` (`book_id`,`chapter_num`) USING BTREE, - UNIQUE KEY `pk_id` (`id`) USING BTREE, - KEY `idx_bookId` (`book_id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=1445988184596992001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说章节'; - --- ---------------------------- --- Table structure for book_comment --- ---------------------------- -CREATE TABLE `book_comment` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `book_id` bigint(20) unsigned NOT NULL COMMENT '评论小说ID', - `user_id` bigint(20) unsigned NOT NULL COMMENT '评论用户ID', - `comment_content` varchar(512) NOT NULL COMMENT '评价内容', - `reply_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '回复数量', - `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_bookId_userId` (`book_id`,`user_id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说评论'; - --- ---------------------------- --- Table structure for book_comment_copy1 --- ---------------------------- -CREATE TABLE `book_comment_copy1` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `book_id` bigint(20) unsigned NOT NULL COMMENT '评论小说ID', - `user_id` bigint(20) unsigned NOT NULL COMMENT '评论用户ID', - `comment_content` varchar(512) NOT NULL COMMENT '评价内容', - `reply_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '回复数量', - `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_bookId_userId` (`book_id`,`user_id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说评论'; - --- ---------------------------- --- Table structure for book_comment_reply --- ---------------------------- -CREATE TABLE `book_comment_reply` -( - `id` bigint(20) unsigned NOT NULL COMMENT '主键', - `comment_id` bigint(20) unsigned NOT NULL COMMENT '评论ID', - `user_id` bigint(20) unsigned NOT NULL COMMENT '回复用户ID', - `reply_content` varchar(512) NOT NULL COMMENT '回复内容', - `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说评论回复'; - --- ---------------------------- --- Table structure for book_content --- ---------------------------- -CREATE TABLE `book_content` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `chapter_id` bigint(20) unsigned NOT NULL COMMENT '章节ID', - `content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '小说章节内容', - `create_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) USING BTREE, - UNIQUE KEY `uk_chapterId` (`chapter_id`) USING BTREE, - UNIQUE KEY `pk_id` (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=4256332 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说内容'; - --- ---------------------------- --- Table structure for book_info --- ---------------------------- -CREATE TABLE `book_info` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `work_direction` tinyint(3) unsigned DEFAULT NULL COMMENT '作品方向;0-男频 1-女频', - `category_id` bigint(20) unsigned DEFAULT NULL COMMENT '类别ID', - `category_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '类别名', - `pic_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '小说封面地址', - `book_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '小说名', - `author_id` bigint(20) unsigned NOT NULL COMMENT '作家id', - `author_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '作家名', - `book_desc` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '书籍描述', - `score` tinyint(3) unsigned NOT NULL COMMENT '评分;总分:10 ,真实评分 = score/10', - `book_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '书籍状态;0-连载中 1-已完结', - `visit_count` bigint(20) unsigned NOT NULL DEFAULT '103' COMMENT '点击量', - `word_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '总字数', - `comment_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '评论数', - `last_chapter_id` bigint(20) unsigned DEFAULT NULL COMMENT '最新章节ID', - `last_chapter_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '最新章节名', - `last_chapter_update_time` datetime DEFAULT NULL COMMENT '最新章节更新时间', - `is_vip` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否收费;1-收费 0-免费', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE KEY `uk_bookName_authorName` (`book_name`,`author_name`) USING BTREE, - UNIQUE KEY `pk_id` (`id`) USING BTREE, - KEY `idx_createTime` (`create_time`) USING BTREE, - KEY `idx_lastChapterUpdateTime` (`last_chapter_update_time`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=1431630596354977793 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说信息'; - --- ---------------------------- --- Table structure for home_book --- ---------------------------- -CREATE TABLE `home_book` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `type` tinyint(3) unsigned NOT NULL COMMENT '推荐类型;0-轮播图 1-顶部栏 2-本周强推 3-热门推荐 4-精品推荐', - `sort` tinyint(3) unsigned NOT NULL COMMENT '推荐排序', - `book_id` bigint(20) unsigned NOT NULL COMMENT '推荐小说ID', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=96 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='小说推荐'; - --- ---------------------------- --- Table structure for home_friend_link --- ---------------------------- -CREATE TABLE `home_friend_link` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `link_name` varchar(50) NOT NULL COMMENT '链接名', - `link_url` varchar(100) NOT NULL COMMENT '链接url', - `sort` tinyint(3) unsigned NOT NULL DEFAULT '11' COMMENT '排序号', - `is_open` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '是否开启;0-不开启 1-开启', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='友情链接'; - --- ---------------------------- --- Table structure for news_category --- ---------------------------- -CREATE TABLE `news_category` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(20) NOT NULL COMMENT '类别名', - `sort` tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '排序', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='新闻类别'; - --- ---------------------------- --- Table structure for news_content --- ---------------------------- -CREATE TABLE `news_content` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `news_id` bigint(20) unsigned NOT NULL COMMENT '新闻ID', - `content` mediumtext NOT NULL COMMENT '新闻内容', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_newsId` (`news_id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='新闻内容'; - --- ---------------------------- --- Table structure for news_info --- ---------------------------- -CREATE TABLE `news_info` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `category_id` bigint(20) unsigned NOT NULL COMMENT '类别ID', - `category_name` varchar(50) NOT NULL COMMENT '类别名', - `source_name` varchar(50) NOT NULL COMMENT '新闻来源', - `title` varchar(100) NOT NULL COMMENT '新闻标题', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='新闻信息'; - --- ---------------------------- --- Table structure for pay_alipay --- ---------------------------- -CREATE TABLE `pay_alipay` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `out_trade_no` varchar(64) NOT NULL COMMENT '商户订单号', - `trade_no` varchar(64) NOT NULL COMMENT '支付宝交易号', - `buyer_id` varchar(16) DEFAULT NULL COMMENT '买家支付宝账号 ID', - `trade_status` varchar(32) DEFAULT NULL COMMENT '交易状态;TRADE_SUCCESS-交易成功', - `total_amount` int(10) unsigned NOT NULL COMMENT '订单金额;单位:分', - `receipt_amount` int(10) unsigned DEFAULT NULL COMMENT '实收金额;单位:分', - `invoice_amount` int(10) unsigned DEFAULT NULL COMMENT '开票金额', - `gmt_create` datetime DEFAULT NULL COMMENT '交易创建时间', - `gmt_payment` datetime DEFAULT NULL COMMENT '交易付款时间', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`), - KEY `uk_outTradeNo` (`out_trade_no`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付宝支付'; - --- ---------------------------- --- Table structure for pay_wechat --- ---------------------------- -CREATE TABLE `pay_wechat` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `out_trade_no` varchar(32) NOT NULL COMMENT '商户订单号', - `transaction_id` varchar(32) NOT NULL COMMENT '微信支付订单号', - `trade_type` varchar(16) DEFAULT NULL COMMENT '交易类型;JSAPI-公众号支付 NATIVE-扫码支付 APP-APP支付 MICROPAY-付款码支付 MWEB-H5支付 FACEPAY-刷脸支付', - `trade_state` varchar(32) DEFAULT NULL COMMENT '交易状态;SUCCESS-支付成功 REFUND-转入退款 NOTPAY-未支付 CLOSED-已关闭 REVOKED-已撤销(付款码支付) USERPAYING-用户支付中(付款码支付) PAYERROR-支付失败(其他原因,如银行返回失败)', - `trade_state_desc` varchar(255) DEFAULT NULL COMMENT '交易状态描述', - `amount` int(10) unsigned NOT NULL COMMENT '订单总金额;单位:分', - `payer_total` int(10) unsigned DEFAULT NULL COMMENT '用户支付金额;单位:分', - `success_time` datetime DEFAULT NULL COMMENT '支付完成时间', - `payer_openid` varchar(128) DEFAULT NULL COMMENT '支付者用户标识;用户在直连商户appid下的唯一标识', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`), - KEY `uk_outTradeNo` (`out_trade_no`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='微信支付'; - --- ---------------------------- --- Table structure for sys_log --- ---------------------------- -CREATE TABLE `sys_log` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `user_id` bigint(20) unsigned DEFAULT NULL COMMENT '用户id', - `username` varchar(50) DEFAULT NULL COMMENT '用户名', - `operation` varchar(50) DEFAULT NULL COMMENT '用户操作', - `time` int(10) unsigned DEFAULT NULL COMMENT '响应时间', - `method` varchar(200) DEFAULT NULL COMMENT '请求方法', - `params` varchar(5000) DEFAULT NULL COMMENT '请求参数', - `ip` varchar(64) DEFAULT NULL COMMENT 'IP地址', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统日志'; - --- ---------------------------- --- Table structure for sys_menu --- ---------------------------- -CREATE TABLE `sys_menu` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `parent_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '父菜单ID;一级菜单为0', - `name` varchar(50) NOT NULL COMMENT '菜单名称', - `url` varchar(200) DEFAULT NULL COMMENT '菜单URL', - `type` tinyint(3) unsigned NOT NULL COMMENT '类型;0-目录 1-菜单', - `icon` varchar(50) DEFAULT NULL COMMENT '菜单图标', - `sort` tinyint(3) unsigned DEFAULT NULL COMMENT '排序', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统菜单'; - --- ---------------------------- --- Table structure for sys_role --- ---------------------------- -CREATE TABLE `sys_role` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `role_name` varchar(100) NOT NULL COMMENT '角色名称', - `role_sign` varchar(100) DEFAULT NULL COMMENT '角色标识', - `remark` varchar(100) DEFAULT NULL COMMENT '备注', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色'; - --- ---------------------------- --- Table structure for sys_role_menu --- ---------------------------- -CREATE TABLE `sys_role_menu` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `role_id` bigint(20) unsigned NOT NULL COMMENT '角色ID', - `menu_id` bigint(20) unsigned NOT NULL COMMENT '菜单ID', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色与菜单对应关系'; - --- ---------------------------- --- Table structure for sys_user --- ---------------------------- -CREATE TABLE `sys_user` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `username` varchar(50) NOT NULL COMMENT '用户名', - `password` varchar(50) NOT NULL COMMENT '密码', - `name` varchar(100) DEFAULT NULL COMMENT '真实姓名', - `sex` tinyint(3) unsigned DEFAULT NULL COMMENT '性别;0-男 1-女', - `birth` datetime DEFAULT NULL COMMENT '出身日期', - `email` varchar(100) DEFAULT NULL COMMENT '邮箱', - `mobile` varchar(100) DEFAULT NULL COMMENT '手机号', - `status` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '状态;0-禁用 1-正常', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户'; - --- ---------------------------- --- Table structure for sys_user_role --- ---------------------------- -CREATE TABLE `sys_user_role` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', - `role_id` bigint(20) unsigned NOT NULL COMMENT '角色ID', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户与角色对应关系'; - --- ---------------------------- --- Table structure for test --- ---------------------------- -CREATE TABLE `test` -( - `id` int(11) NOT NULL, - `test` tinyint(1) unsigned zerofill DEFAULT NULL, - `test2` tinyint(4) unsigned zerofill DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; - --- ---------------------------- --- Table structure for user_bookshelf --- ---------------------------- -CREATE TABLE `user_bookshelf` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', - `book_id` bigint(20) unsigned NOT NULL COMMENT '小说ID', - `pre_content_id` bigint(20) unsigned DEFAULT NULL COMMENT '上一次阅读的章节内容表ID', - `create_time` datetime DEFAULT NULL COMMENT '创建时间;', - `update_time` datetime DEFAULT NULL COMMENT '更新时间;', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_userId_bookId` (`user_id`,`book_id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户书架'; - --- ---------------------------- --- Table structure for user_comment --- ---------------------------- -CREATE TABLE `user_comment` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `user_id` bigint(20) unsigned NOT NULL COMMENT '评论用户ID', - `book_id` bigint(20) unsigned NOT NULL COMMENT '评论小说ID', - `comment_content` varchar(512) NOT NULL COMMENT '评价内容', - `reply_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '回复数量', - `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_bookId_userId` (`book_id`,`user_id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户评论'; - --- ---------------------------- --- Table structure for user_comment_reply --- ---------------------------- -CREATE TABLE `user_comment_reply` -( - `id` bigint(20) unsigned NOT NULL COMMENT '主键', - `comment_id` bigint(20) unsigned NOT NULL COMMENT '评论ID', - `user_id` bigint(20) unsigned NOT NULL COMMENT '回复用户ID', - `reply_content` varchar(512) NOT NULL COMMENT '回复内容', - `audit_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '审核状态;0-待审核 1-审核通过 2-审核不通过', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户评论回复'; - --- ---------------------------- --- Table structure for user_consume_log --- ---------------------------- -CREATE TABLE `user_consume_log` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `user_id` bigint(20) unsigned NOT NULL COMMENT '消费用户ID', - `amount` int(10) unsigned NOT NULL COMMENT '消费使用的金额;单位:屋币', - `product_type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '消费商品类型;0-小说VIP章节', - `product_id` bigint(20) unsigned DEFAULT NULL COMMENT '消费的的商品ID;例如:章节ID', - `produc_name` varchar(50) DEFAULT NULL COMMENT '消费的的商品名;例如:章节名', - `produc_value` int(10) unsigned DEFAULT NULL COMMENT '消费的的商品值;例如:1', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户消费记录'; - --- ---------------------------- --- Table structure for user_feedback --- ---------------------------- -CREATE TABLE `user_feedback` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `user_id` bigint(20) unsigned NOT NULL COMMENT '反馈用户id', - `content` varchar(512) NOT NULL COMMENT '反馈内容', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户反馈'; - --- ---------------------------- --- Table structure for user_info --- ---------------------------- -CREATE TABLE `user_info` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `username` varchar(50) NOT NULL COMMENT '登录名', - `password` varchar(100) NOT NULL COMMENT '登录密码-加密', - `salt` varchar(8) NOT NULL COMMENT '加密盐值', - `nick_name` varchar(50) DEFAULT NULL COMMENT '昵称', - `user_photo` varchar(100) DEFAULT NULL COMMENT '用户头像', - `user_sex` tinyint(3) unsigned DEFAULT NULL COMMENT '用户性别;0-男 1-女', - `account_balance` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '账户余额', - `status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '用户状态;0-正常', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_username` (`username`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户信息'; - --- ---------------------------- --- Table structure for user_pay_log --- ---------------------------- -CREATE TABLE `user_pay_log` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `user_id` bigint(20) unsigned NOT NULL COMMENT '充值用户ID', - `pay_channel` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '充值方式;0-支付宝 1-微信', - `out_trade_no` varchar(64) NOT NULL COMMENT '商户订单号', - `amount` int(10) unsigned NOT NULL COMMENT '充值金额;单位:分', - `product_type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '充值商品类型;0-屋币 1-包年VIP', - `product_id` bigint(20) unsigned DEFAULT NULL COMMENT '充值商品ID', - `product_name` varchar(255) NOT NULL COMMENT '充值商品名;示例值:屋币', - `product_value` int(10) unsigned DEFAULT NULL COMMENT '充值商品值;示例值:255', - `pay_time` datetime NOT NULL COMMENT '充值时间', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户充值记录'; - --- ---------------------------- --- Table structure for user_read_history --- ---------------------------- -CREATE TABLE `user_read_history` -( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', - `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', - `book_id` bigint(20) unsigned NOT NULL COMMENT '小说ID', - `pre_content_id` bigint(20) unsigned NOT NULL COMMENT '上一次阅读的章节内容表ID', - `create_time` datetime DEFAULT NULL COMMENT '创建时间;', - `update_time` datetime DEFAULT NULL COMMENT '更新时间;', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_userId_bookId` (`user_id`,`book_id`), - UNIQUE KEY `pk_id` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户阅读历史'; - -SET -FOREIGN_KEY_CHECKS = 1; - -- Gitee From 8da6f8263cc930392666051a78a453f3903cca9c Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Mon, 15 Jul 2024 18:07:29 +0800 Subject: [PATCH 111/112] =?UTF-8?q?fix:=20=E5=88=9D=E5=A7=8B=E5=8C=96=20Fl?= =?UTF-8?q?yway=20=E5=8E=86=E5=8F=B2=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit org.flywaydb.core.api.FlywayException: Found non-empty schema(s) `novel_test` but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table. --- src/main/resources/application.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 19bd297..4c0957d 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -20,6 +20,9 @@ spring: threads: virtual: enabled: true + # initialize the schema history table + flyway: + baseline-on-migrate: true server: # 端口号 port: 8888 -- Gitee From d63be23aca9f6841add3c58a4f6c5e09376bdbb7 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 17 Jul 2024 18:02:01 +0800 Subject: [PATCH 112/112] =?UTF-8?q?perf:=20/env=20=E7=AB=AF=E7=82=B9?= =?UTF-8?q?=E5=9C=A8=20dev=20=E7=8E=AF=E5=A2=83=E4=B8=8B=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 4c0957d..a91d118 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -259,9 +259,15 @@ spring: config: activate: on-profile: dev +# 开启 SpringDoc 接口文档 springdoc: api-docs: enabled: true +# /env 端点显示属性值 +management: + endpoint: + env: + show-values: when_authorized --- #------------------- test 特定配置-------------------------- spring: -- Gitee