From 89992dc781d8189f25ec58bca0558e22ae3dafff Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 1 Jun 2024 09:56:07 +0800 Subject: [PATCH 01/95] =?UTF-8?q?perf(novel-crawl):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=B0=8F=E8=AF=B4=E5=86=85=E5=AE=B9=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java2nb/novel/core/crawl/CrawlParser.java | 46 +++++++++++++------ .../java2nb/novel/core/crawl/RuleBean.java | 11 +++-- .../templates/crawl/crawlSource_add.html | 6 +++ .../templates/crawl/crawlSource_update.html | 8 ++++ 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java index 192c4e4..7a76987 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java @@ -89,14 +89,15 @@ public class CrawlParser { } } - String desc = bookDetailHtml.substring(bookDetailHtml.indexOf(ruleBean.getDescStart()) + ruleBean.getDescStart().length()); + String desc = bookDetailHtml.substring( + bookDetailHtml.indexOf(ruleBean.getDescStart()) + ruleBean.getDescStart().length()); desc = desc.substring(0, desc.indexOf(ruleBean.getDescEnd())); //过滤掉简介中的特殊标签 desc = desc.replaceAll("", "") - .replaceAll("", "") - .replaceAll("

\\s*

", "") - .replaceAll("

", "") - .replaceAll("

", "
"); + .replaceAll("", "") + .replaceAll("

\\s*

", "") + .replaceAll("

", "") + .replaceAll("

", "
"); //设置书籍简介 book.setBookDesc(desc); if (StringUtils.isNotBlank(ruleBean.getStatusPatten())) { @@ -112,14 +113,16 @@ public class CrawlParser { } } - if (StringUtils.isNotBlank(ruleBean.getUpadateTimePatten()) && StringUtils.isNotBlank(ruleBean.getUpadateTimeFormatPatten())) { + if (StringUtils.isNotBlank(ruleBean.getUpadateTimePatten()) && StringUtils.isNotBlank( + ruleBean.getUpadateTimeFormatPatten())) { Pattern updateTimePatten = PatternFactory.getPattern(ruleBean.getUpadateTimePatten()); Matcher updateTimeMatch = updateTimePatten.matcher(bookDetailHtml); boolean isFindUpdateTime = updateTimeMatch.find(); if (isFindUpdateTime) { String updateTime = updateTimeMatch.group(1); //设置更新时间 - book.setLastIndexUpdateTime(new SimpleDateFormat(ruleBean.getUpadateTimeFormatPatten()).parse(updateTime)); + book.setLastIndexUpdateTime( + new SimpleDateFormat(ruleBean.getUpadateTimeFormatPatten()).parse(updateTime)); } } @@ -141,7 +144,8 @@ public class CrawlParser { handler.handle(book); } - public static boolean parseBookIndexAndContent(String sourceBookId, Book book, RuleBean ruleBean, Map existBookIndexMap, CrawlBookChapterHandler handler) { + public static boolean parseBookIndexAndContent(String sourceBookId, Book book, RuleBean ruleBean, + Map existBookIndexMap, CrawlBookChapterHandler handler) { Date currentDate = new Date(); @@ -153,7 +157,8 @@ public class CrawlParser { if (indexListHtml != null) { if (StringUtils.isNotBlank(ruleBean.getBookIndexStart())) { - indexListHtml = indexListHtml.substring(indexListHtml.indexOf(ruleBean.getBookIndexStart()) + ruleBean.getBookIndexStart().length()); + indexListHtml = indexListHtml.substring( + indexListHtml.indexOf(ruleBean.getBookIndexStart()) + ruleBean.getBookIndexStart().length()); } Pattern indexIdPatten = PatternFactory.getPattern(ruleBean.getIndexIdPatten()); @@ -174,14 +179,16 @@ public class CrawlParser { BookIndex hasIndex = existBookIndexMap.get(indexNum); String indexName = indexNameMatch.group(1); - if (hasIndex == null || !StringUtils.deleteWhitespace(hasIndex.getIndexName()).equals(StringUtils.deleteWhitespace(indexName))) { + if (hasIndex == null || !StringUtils.deleteWhitespace(hasIndex.getIndexName()) + .equals(StringUtils.deleteWhitespace(indexName))) { String sourceIndexId = indexIdMatch.group(1); String bookContentUrl = ruleBean.getBookContentUrl(); int calStart = bookContentUrl.indexOf("{cal_"); if (calStart != -1) { //内容页URL需要进行计算才能得到 - String calStr = bookContentUrl.substring(calStart, calStart + bookContentUrl.substring(calStart).indexOf("}")); + String calStr = bookContentUrl.substring(calStart, + calStart + bookContentUrl.substring(calStart).indexOf("}")); String[] calArr = calStr.split("_"); int calType = Integer.parseInt(calArr[1]); if (calType == 1) { @@ -206,13 +213,25 @@ public class CrawlParser { } - String contentUrl = bookContentUrl.replace("{bookId}", sourceBookId).replace("{indexId}", sourceIndexId); + String contentUrl = bookContentUrl.replace("{bookId}", sourceBookId) + .replace("{indexId}", sourceIndexId); //查询章节内容 String contentHtml = getByHttpClientWithChrome(contentUrl); if (contentHtml != null && !contentHtml.contains("正在手打中")) { - String content = contentHtml.substring(contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length()); + String content = contentHtml.substring( + contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length()); content = content.substring(0, content.indexOf(ruleBean.getContentEnd())); + // 小说内容过滤 + String filterContent = ruleBean.getFilterContent(); + if (StringUtils.isNotBlank(filterContent)) { + String[] filterRules = filterContent.replace("\r\n", "\n").split("\n"); + for (String filterRule : filterRules) { + if (StringUtils.isNotBlank(filterRule)) { + content = content.replaceAll(filterRule, ""); + } + } + } //插入章节目录和章节内容 BookIndex bookIndex = new BookIndex(); bookIndex.setIndexName(indexName); @@ -257,7 +276,6 @@ public class CrawlParser { isFindIndex = indexIdMatch.find() & indexNameMatch.find(); } - if (indexList.size() > 0) { //如果有爬到最新章节,则设置小说主表的最新章节信息 //获取爬取到的最新章节 diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/RuleBean.java b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/RuleBean.java index 6b42685..58a4efb 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/RuleBean.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/RuleBean.java @@ -6,6 +6,7 @@ import java.util.Map; /** * 爬虫解析规则bean + * * @author Administrator */ @Data @@ -13,17 +14,17 @@ public class RuleBean { /** * 小说更新列表url - * */ + */ private String updateBookListUrl; /** * 分类列表页URL规则 - * */ + */ private String bookListUrl; - private Map catIdRule; + private Map catIdRule; - private Map bookStatusRule; + private Map bookStatusRule; private String bookIdPatten; private String pagePatten; @@ -51,5 +52,7 @@ public class RuleBean { private String bookIndexStart; + private String filterContent; + } diff --git a/novel-crawl/src/main/resources/templates/crawl/crawlSource_add.html b/novel-crawl/src/main/resources/templates/crawl/crawlSource_add.html index 2d7dd83..5162663 100644 --- a/novel-crawl/src/main/resources/templates/crawl/crawlSource_add.html +++ b/novel-crawl/src/main/resources/templates/crawl/crawlSource_add.html @@ -144,6 +144,9 @@ 示例:<script>
  • + 示例:<div\s+id="content_tip">\s*<b>([^/]+)</b>\s*</div> +
  • @@ -405,6 +408,9 @@ crawlRule.contentEnd = contentEnd; + var filterContent = $("#filterContent").val(); + crawlRule.filterContent = filterContent; + $.ajax({ type: "POST", diff --git a/novel-crawl/src/main/resources/templates/crawl/crawlSource_update.html b/novel-crawl/src/main/resources/templates/crawl/crawlSource_update.html index edf0587..08dd048 100644 --- a/novel-crawl/src/main/resources/templates/crawl/crawlSource_update.html +++ b/novel-crawl/src/main/resources/templates/crawl/crawlSource_update.html @@ -145,6 +145,10 @@ 示例:<script>
  • + 示例:<div\s+id="content_tip">\s*<b>([^/]+)</b>\s*</div> +
  • +
  • @@ -269,6 +273,7 @@ $("#bookContentUrl").val(crawlRule.bookContentUrl); $("#contentStart").val(crawlRule.contentStart); $("#contentEnd").val(crawlRule.contentEnd); + $("#filterContent").val(crawlRule.filterContent); } } @@ -488,6 +493,9 @@ crawlRule.contentEnd = contentEnd; + var filterContent = $("#filterContent").val(); + crawlRule.filterContent = filterContent; + $.ajax({ type: "POST", From 3735023cef2545b50d9429e255a91e9a52e342dc Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 20 Jul 2024 21:48:29 +0800 Subject: [PATCH 02/95] =?UTF-8?q?perf(novel-front):=20UI=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-front/src/main/resources/templates/mobile/pay/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/novel-front/src/main/resources/templates/mobile/pay/index.html b/novel-front/src/main/resources/templates/mobile/pay/index.html index befa955..98a0a97 100644 --- a/novel-front/src/main/resources/templates/mobile/pay/index.html +++ b/novel-front/src/main/resources/templates/mobile/pay/index.html @@ -114,7 +114,7 @@ style="color: #3eaf7c" id="accountBalance">10 屋币 -
    +
    选择充值金额
  • From 21a6a49ce94ae0c1811b655e8be4f901f04f59f2 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 6 Aug 2024 21:14:22 +0800 Subject: [PATCH 03/95] =?UTF-8?q?fix:=20=E4=BD=9C=E5=AE=B6=E7=A8=BF?= =?UTF-8?q?=E8=B4=B9=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/schedule/MonthIncomeStaSchedule.java | 23 +-- .../java2nb/novel/service/AuthorService.java | 72 ++++---- .../novel/service/impl/AuthorServiceImpl.java | 156 +++++++++--------- 3 files changed, 133 insertions(+), 118 deletions(-) diff --git a/novel-front/src/main/java/com/java2nb/novel/core/schedule/MonthIncomeStaSchedule.java b/novel-front/src/main/java/com/java2nb/novel/core/schedule/MonthIncomeStaSchedule.java index 554d835..b0c4768 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/schedule/MonthIncomeStaSchedule.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/schedule/MonthIncomeStaSchedule.java @@ -3,7 +3,9 @@ package com.java2nb.novel.core.schedule; import com.java2nb.novel.core.config.AuthorIncomeProperties; import com.java2nb.novel.core.utils.DateUtil; -import com.java2nb.novel.entity.*; +import com.java2nb.novel.entity.Author; +import com.java2nb.novel.entity.AuthorIncome; +import com.java2nb.novel.entity.Book; import com.java2nb.novel.service.AuthorService; import com.java2nb.novel.service.BookService; import lombok.RequiredArgsConstructor; @@ -64,24 +66,23 @@ public class MonthIncomeStaSchedule { Long bookId = book.getId(); - //3.月收入数据未统计入库,分作品统计数据入库 Long monthIncome = authorService.queryTotalAccount(userId, bookId, startTime, endTime); BigDecimal monthIncomeShare = new BigDecimal(monthIncome) - .multiply(authorIncomeConfig.getShareProportion()); + .multiply(authorIncomeConfig.getShareProportion()); long preTaxIncome = monthIncomeShare - .multiply(authorIncomeConfig.getExchangeProportion()) - .multiply(new BigDecimal(100)) - .longValue(); + .multiply(authorIncomeConfig.getExchangeProportion()) + .multiply(new BigDecimal(100)) + .longValue(); totalPreTaxIncome += preTaxIncome; long afterTaxIncome = monthIncomeShare - .multiply(authorIncomeConfig.getTaxRate()) - .multiply(authorIncomeConfig.getExchangeProportion()) - .multiply(new BigDecimal(100)) - .longValue(); + .multiply(authorIncomeConfig.getTaxRate()) + .multiply(authorIncomeConfig.getExchangeProportion()) + .multiply(new BigDecimal(100)) + .longValue(); totalAfterTaxIncome += afterTaxIncome; @@ -102,7 +103,7 @@ public class MonthIncomeStaSchedule { } - if (totalPreTaxIncome > 0 && !authorService.queryIsStatisticsMonth(0L, endTime)) { + if (totalPreTaxIncome > 0 && !authorService.queryIsStatisticsMonth(authorId, 0L, endTime)) { AuthorIncome authorIncome = new AuthorIncome(); authorIncome.setAuthorId(authorId); diff --git a/novel-front/src/main/java/com/java2nb/novel/service/AuthorService.java b/novel-front/src/main/java/com/java2nb/novel/service/AuthorService.java index 3c42acd..2acb219 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/AuthorService.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/AuthorService.java @@ -1,10 +1,10 @@ package com.java2nb.novel.service; -import io.github.xxyopen.model.page.PageBean; import com.java2nb.novel.entity.Author; import com.java2nb.novel.entity.AuthorIncome; import com.java2nb.novel.entity.AuthorIncomeDetail; +import io.github.xxyopen.model.page.PageBean; import java.util.Date; import java.util.List; @@ -16,45 +16,51 @@ public interface AuthorService { /** * 校验笔名是否存在 + * * @param penName 校验的笔名 * @return true:存在该笔名,false: 不存在该笔名 - * */ + */ Boolean checkPenName(String penName); /** * 作家注册 + * * @param userId 注册用户ID - *@param author 注册信息 + * @param author 注册信息 * @return 返回错误信息 - * */ + */ String register(Long userId, Author author); /** * 判断是否是作家 + * * @param userId 用户ID * @return true:是作家,false: 不是作家 - * */ + */ Boolean isAuthor(Long userId); /** * 查询作家信息 + * * @param userId 用户ID * @return 作家对象 - * */ + */ Author queryAuthor(Long userId); /** * 查询作家列表 - * @return 作家列表 - * @param limit 查询条数 + * + * @param limit 查询条数 * @param maxAuthorCreateTime 最大申请时间 + * @return 作家列表 */ List queryAuthorList(int limit, Date maxAuthorCreateTime); /** * 查询收入日统计是否入库 + * * @param bookId 作品ID - * @param date 收入时间 + * @param date 收入时间 * @return true:已入库,false:未入库 */ boolean queryIsStatisticsDaily(Long bookId, Date date); @@ -62,67 +68,75 @@ public interface AuthorService { /** * 保存日收入统计(按作品) + * * @param authorIncomeDetail 收入详情 - * */ + */ void saveDailyIncomeSta(AuthorIncomeDetail authorIncomeDetail); - /** * 查询月收入统计是否入库 - * @param bookId 作品ID + * + * @param bookId 作品ID * @param incomeDate 收入时间 * @return true:已入库,false:未入库 - * */ + */ boolean queryIsStatisticsMonth(Long bookId, Date incomeDate); + boolean queryIsStatisticsMonth(Long authorId, Long bookId, Date incomeDate); + /** * 查询时间段内总订阅额 * * @param userId - * @param bookId 作品ID + * @param bookId 作品ID * @param startTime 开始时间 - * @param endTime 结束时间 + * @param endTime 结束时间 * @return 订阅额(屋币) - * */ + */ Long queryTotalAccount(Long userId, Long bookId, Date startTime, Date endTime); /** * 保存月收入统计 + * * @param authorIncome 收入详情 - * */ + */ void saveAuthorIncomeSta(AuthorIncome authorIncome); /** * 查询收入日统计是否入库 + * * @param authorId 作家ID - * @param bookId 作品ID - * @param date 收入时间 + * @param bookId 作品ID + * @param date 收入时间 * @return true:已入库,false:未入库 */ boolean queryIsStatisticsDaily(Long authorId, Long bookId, Date date); /** - *作家日收入统计数据分页列表查询 + * 作家日收入统计数据分页列表查询 + * * @param userId - * @param page 页码 - * @param pageSize 分页大小 - * @param bookId 小说ID + * @param page 页码 + * @param pageSize 分页大小 + * @param bookId 小说ID * @param startTime 开始时间 - * @param endTime 结束时间 + * @param endTime 结束时间 * @return 日收入统计数据分页数据 */ - PageBean listIncomeDailyByPage(int page, int pageSize, Long userId, Long bookId, Date startTime, Date endTime); + PageBean listIncomeDailyByPage(int page, int pageSize, Long userId, Long bookId, Date startTime, + Date endTime); /** * 作家月收入统计数据分页列表查询 - * @param page 页码 + * + * @param page 页码 * @param pageSize 分页大小 - * @param userId 用户ID - * @param bookId 小说ID + * @param userId 用户ID + * @param bookId 小说ID * @return 分页数据 - * */ + */ PageBean listIncomeMonthByPage(int page, int pageSize, Long userId, Long bookId); } diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/AuthorServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/AuthorServiceImpl.java index 499e257..2591bf8 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/AuthorServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/AuthorServiceImpl.java @@ -1,23 +1,15 @@ package com.java2nb.novel.service.impl; import com.github.pagehelper.PageHelper; -import io.github.xxyopen.model.page.PageBean; -import com.java2nb.novel.core.cache.CacheKey; -import com.java2nb.novel.core.cache.CacheService; -import com.java2nb.novel.core.enums.ResponseStatus; -import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder; -import io.github.xxyopen.web.exception.BusinessException; import com.java2nb.novel.entity.Author; import com.java2nb.novel.entity.AuthorIncome; import com.java2nb.novel.entity.AuthorIncomeDetail; -import com.java2nb.novel.entity.FriendLink; import com.java2nb.novel.mapper.*; import com.java2nb.novel.service.AuthorService; -import com.java2nb.novel.service.FriendLinkService; +import io.github.xxyopen.model.page.PageBean; +import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder; import lombok.RequiredArgsConstructor; import org.mybatis.dynamic.sql.render.RenderingStrategies; -import org.mybatis.dynamic.sql.select.CountDSLCompleter; -import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,10 +17,6 @@ import java.util.Date; import java.util.List; import static com.java2nb.novel.mapper.AuthorCodeDynamicSqlSupport.authorCode; -import static com.java2nb.novel.mapper.BookDynamicSqlSupport.book; -import static com.java2nb.novel.mapper.BookDynamicSqlSupport.id; -import static com.java2nb.novel.mapper.BookDynamicSqlSupport.updateTime; -import static com.java2nb.novel.mapper.FriendLinkDynamicSqlSupport.*; import static org.mybatis.dynamic.sql.SqlBuilder.*; import static org.mybatis.dynamic.sql.select.SelectDSL.select; @@ -52,7 +40,7 @@ public class AuthorServiceImpl implements AuthorService { @Override public Boolean checkPenName(String penName) { return authorMapper.count(c -> - c.where(AuthorDynamicSqlSupport.penName, isEqualTo(penName))) > 0; + c.where(AuthorDynamicSqlSupport.penName, isEqualTo(penName))) > 0; } @Transactional(rollbackFor = Exception.class) @@ -61,21 +49,21 @@ public class AuthorServiceImpl implements AuthorService { Date currentDate = new Date(); //判断邀请码是否有效 if (authorCodeMapper.count(c -> - c.where(AuthorCodeDynamicSqlSupport.inviteCode, isEqualTo(author.getInviteCode())) - .and(AuthorCodeDynamicSqlSupport.isUse, isEqualTo((byte) 0)) - .and(AuthorCodeDynamicSqlSupport.validityTime, isGreaterThan(currentDate))) > 0) { - //邀请码有效 + c.where(AuthorCodeDynamicSqlSupport.inviteCode, isEqualTo(author.getInviteCode())) + .and(AuthorCodeDynamicSqlSupport.isUse, isEqualTo((byte) 0)) + .and(AuthorCodeDynamicSqlSupport.validityTime, isGreaterThan(currentDate))) > 0) { + //邀请码有效 //保存作家信息 author.setUserId(userId); author.setCreateTime(currentDate); authorMapper.insertSelective(author); //设置邀请码状态为已使用 authorCodeMapper.update(update(authorCode) - .set(AuthorCodeDynamicSqlSupport.isUse) - .equalTo((byte) 1) - .where(AuthorCodeDynamicSqlSupport.inviteCode,isEqualTo(author.getInviteCode())) - .build() - .render(RenderingStrategies.MYBATIS3)); + .set(AuthorCodeDynamicSqlSupport.isUse) + .equalTo((byte) 1) + .where(AuthorCodeDynamicSqlSupport.inviteCode, isEqualTo(author.getInviteCode())) + .build() + .render(RenderingStrategies.MYBATIS3)); return ""; } else { //邀请码无效 @@ -87,15 +75,15 @@ public class AuthorServiceImpl implements AuthorService { @Override public Boolean isAuthor(Long userId) { return authorMapper.count(c -> - c.where(AuthorDynamicSqlSupport.userId, isEqualTo(userId))) > 0; + c.where(AuthorDynamicSqlSupport.userId, isEqualTo(userId))) > 0; } @Override public Author queryAuthor(Long userId) { return authorMapper.selectMany( - select(AuthorDynamicSqlSupport.id,AuthorDynamicSqlSupport.penName,AuthorDynamicSqlSupport.status) - .from(AuthorDynamicSqlSupport.author) - .where(AuthorDynamicSqlSupport.userId,isEqualTo(userId)) + select(AuthorDynamicSqlSupport.id, AuthorDynamicSqlSupport.penName, AuthorDynamicSqlSupport.status) + .from(AuthorDynamicSqlSupport.author) + .where(AuthorDynamicSqlSupport.userId, isEqualTo(userId)) .build() .render(RenderingStrategies.MYBATIS3)).get(0); } @@ -103,12 +91,12 @@ public class AuthorServiceImpl implements AuthorService { @Override public List queryAuthorList(int needAuthorNumber, Date maxAuthorCreateTime) { return authorMapper.selectMany(select(AuthorDynamicSqlSupport.id, AuthorDynamicSqlSupport.userId) - .from(AuthorDynamicSqlSupport.author) - .where(AuthorDynamicSqlSupport.createTime, isLessThan(maxAuthorCreateTime)) - .orderBy(AuthorDynamicSqlSupport.createTime.descending()) - .limit(needAuthorNumber) - .build() - .render(RenderingStrategies.MYBATIS3)); + .from(AuthorDynamicSqlSupport.author) + .where(AuthorDynamicSqlSupport.createTime, isLessThan(maxAuthorCreateTime)) + .orderBy(AuthorDynamicSqlSupport.createTime.descending()) + .limit(needAuthorNumber) + .build() + .render(RenderingStrategies.MYBATIS3)); } @@ -116,11 +104,11 @@ public class AuthorServiceImpl implements AuthorService { public boolean queryIsStatisticsDaily(Long bookId, Date date) { return authorIncomeDetailMapper.selectMany(select(AuthorIncomeDetailDynamicSqlSupport.id) - .from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail) - .where(AuthorIncomeDetailDynamicSqlSupport.bookId, isEqualTo(bookId)) - .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isEqualTo(date)) - .build() - .render(RenderingStrategies.MYBATIS3)).size() > 0; + .from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail) + .where(AuthorIncomeDetailDynamicSqlSupport.bookId, isEqualTo(bookId)) + .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isEqualTo(date)) + .build() + .render(RenderingStrategies.MYBATIS3)).size() > 0; } @@ -133,24 +121,35 @@ public class AuthorServiceImpl implements AuthorService { @Override public boolean queryIsStatisticsMonth(Long bookId, Date incomeDate) { return authorIncomeMapper.selectMany(select(AuthorIncomeDynamicSqlSupport.id) - .from(AuthorIncomeDynamicSqlSupport.authorIncome) - .where(AuthorIncomeDynamicSqlSupport.bookId, isEqualTo(bookId)) - .and(AuthorIncomeDynamicSqlSupport.incomeMonth, isEqualTo(incomeDate)) - .build() - .render(RenderingStrategies.MYBATIS3)).size() > 0; + .from(AuthorIncomeDynamicSqlSupport.authorIncome) + .where(AuthorIncomeDynamicSqlSupport.bookId, isEqualTo(bookId)) + .and(AuthorIncomeDynamicSqlSupport.incomeMonth, isEqualTo(incomeDate)) + .build() + .render(RenderingStrategies.MYBATIS3)).size() > 0; + } + + @Override + public boolean queryIsStatisticsMonth(Long authorId, Long bookId, Date incomeDate) { + return authorIncomeMapper.selectMany(select(AuthorIncomeDynamicSqlSupport.id) + .from(AuthorIncomeDynamicSqlSupport.authorIncome) + .where(AuthorIncomeDynamicSqlSupport.bookId, isEqualTo(bookId)) + .and(AuthorIncomeDynamicSqlSupport.authorId, isEqualTo(authorId)) + .and(AuthorIncomeDynamicSqlSupport.incomeMonth, isEqualTo(incomeDate)) + .build() + .render(RenderingStrategies.MYBATIS3)).size() > 0; } @Override public Long queryTotalAccount(Long userId, Long bookId, Date startTime, Date endTime) { return authorIncomeDetailMapper.selectStatistic(select(sum(AuthorIncomeDetailDynamicSqlSupport.incomeAccount)) - .from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail) - .where(AuthorIncomeDetailDynamicSqlSupport.userId, isEqualTo(userId)) - .and(AuthorIncomeDetailDynamicSqlSupport.bookId, isEqualTo(bookId)) - .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isGreaterThanOrEqualTo(startTime)) - .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isLessThanOrEqualTo(endTime)) - .build() - .render(RenderingStrategies.MYBATIS3)); + .from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail) + .where(AuthorIncomeDetailDynamicSqlSupport.userId, isEqualTo(userId)) + .and(AuthorIncomeDetailDynamicSqlSupport.bookId, isEqualTo(bookId)) + .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isGreaterThanOrEqualTo(startTime)) + .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isLessThanOrEqualTo(endTime)) + .build() + .render(RenderingStrategies.MYBATIS3)); } @@ -162,29 +161,30 @@ public class AuthorServiceImpl implements AuthorService { @Override public boolean queryIsStatisticsDaily(Long authorId, Long bookId, Date date) { return authorIncomeDetailMapper.selectMany(select(AuthorIncomeDetailDynamicSqlSupport.id) - .from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail) - .where(AuthorIncomeDetailDynamicSqlSupport.authorId, isEqualTo(authorId)) - .and(AuthorIncomeDetailDynamicSqlSupport.bookId, isEqualTo(bookId)) - .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isEqualTo(date)) - .build() - .render(RenderingStrategies.MYBATIS3)).size() > 0; + .from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail) + .where(AuthorIncomeDetailDynamicSqlSupport.authorId, isEqualTo(authorId)) + .and(AuthorIncomeDetailDynamicSqlSupport.bookId, isEqualTo(bookId)) + .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isEqualTo(date)) + .build() + .render(RenderingStrategies.MYBATIS3)).size() > 0; } @Override - public PageBean listIncomeDailyByPage(int page, int pageSize, Long userId, Long bookId, Date startTime, Date endTime) { + public PageBean listIncomeDailyByPage(int page, int pageSize, Long userId, Long bookId, + Date startTime, Date endTime) { PageHelper.startPage(page, pageSize); return PageBuilder.build(authorIncomeDetailMapper.selectMany( - select(AuthorIncomeDetailDynamicSqlSupport.incomeDate, AuthorIncomeDetailDynamicSqlSupport.incomeAccount - , AuthorIncomeDetailDynamicSqlSupport.incomeCount, AuthorIncomeDetailDynamicSqlSupport.incomeNumber) - .from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail) - .where(AuthorIncomeDetailDynamicSqlSupport.userId, isEqualTo(userId)) - .and(AuthorIncomeDetailDynamicSqlSupport.bookId, isEqualTo(bookId)) - .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isGreaterThanOrEqualTo(startTime)) - .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isLessThanOrEqualTo(endTime)) - .orderBy(AuthorIncomeDetailDynamicSqlSupport.incomeDate.descending()) - .build() - .render(RenderingStrategies.MYBATIS3))); + select(AuthorIncomeDetailDynamicSqlSupport.incomeDate, AuthorIncomeDetailDynamicSqlSupport.incomeAccount + , AuthorIncomeDetailDynamicSqlSupport.incomeCount, AuthorIncomeDetailDynamicSqlSupport.incomeNumber) + .from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail) + .where(AuthorIncomeDetailDynamicSqlSupport.userId, isEqualTo(userId)) + .and(AuthorIncomeDetailDynamicSqlSupport.bookId, isEqualTo(bookId)) + .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isGreaterThanOrEqualTo(startTime)) + .and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isLessThanOrEqualTo(endTime)) + .orderBy(AuthorIncomeDetailDynamicSqlSupport.incomeDate.descending()) + .build() + .render(RenderingStrategies.MYBATIS3))); } @@ -192,15 +192,15 @@ public class AuthorServiceImpl implements AuthorService { public PageBean listIncomeMonthByPage(int page, int pageSize, Long userId, Long bookId) { PageHelper.startPage(page, pageSize); return PageBuilder.build(authorIncomeMapper.selectMany(select(AuthorIncomeDynamicSqlSupport.incomeMonth - , AuthorIncomeDynamicSqlSupport.preTaxIncome - , AuthorIncomeDynamicSqlSupport.afterTaxIncome - , AuthorIncomeDynamicSqlSupport.payStatus - , AuthorIncomeDynamicSqlSupport.confirmStatus) - .from(AuthorIncomeDynamicSqlSupport.authorIncome) - .where(AuthorIncomeDynamicSqlSupport.userId, isEqualTo(userId)) - .and(AuthorIncomeDynamicSqlSupport.bookId, isEqualTo(bookId)) - .orderBy(AuthorIncomeDynamicSqlSupport.incomeMonth.descending()) - .build() - .render(RenderingStrategies.MYBATIS3))); + , AuthorIncomeDynamicSqlSupport.preTaxIncome + , AuthorIncomeDynamicSqlSupport.afterTaxIncome + , AuthorIncomeDynamicSqlSupport.payStatus + , AuthorIncomeDynamicSqlSupport.confirmStatus) + .from(AuthorIncomeDynamicSqlSupport.authorIncome) + .where(AuthorIncomeDynamicSqlSupport.userId, isEqualTo(userId)) + .and(AuthorIncomeDynamicSqlSupport.bookId, isEqualTo(bookId)) + .orderBy(AuthorIncomeDynamicSqlSupport.incomeMonth.descending()) + .build() + .render(RenderingStrategies.MYBATIS3))); } } From d55e1a3e2224cd093f715b5ffa13472e3b905b33 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 6 Aug 2024 22:42:43 +0800 Subject: [PATCH 04/95] =?UTF-8?q?revert:=20sql=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E8=BF=98=E5=8E=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/novel_plus.sql | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/sql/novel_plus.sql b/doc/sql/novel_plus.sql index dd7b73b..b4a8b12 100644 --- a/doc/sql/novel_plus.sql +++ b/doc/sql/novel_plus.sql @@ -1,7 +1,5 @@ -CREATE - database if NOT EXISTS `novel_plus` default character set utf8mb4 collate utf8mb4_unicode_ci; -use - `novel_plus`; +CREATE database if NOT EXISTS `novel_plus` default character set utf8mb4 collate utf8mb4_unicode_ci; +use `novel_plus`; SET NAMES utf8mb4; From 5c35f7af0ac1e4f22e33fcb87fee4ce4a56e207d Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Mon, 16 Sep 2024 21:08:32 +0800 Subject: [PATCH 05/95] =?UTF-8?q?=E6=9B=B4=E6=8D=A2=E9=BB=98=E8=AE=A4logo?= =?UTF-8?q?=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/green/static/images/logo.png | Bin 3226 -> 11792 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/templates/green/static/images/logo.png b/templates/green/static/images/logo.png index d29bb7d2ad66aa4797d5ce91cbce3b0c04c6df51..b407a0dedf660410ac490083b94220084e227e41 100644 GIT binary patch literal 11792 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 PArvZ#nhK>4Enoi+P@A?3 literal 3226 zcmeHK`#%%vAKzlqzR_qdCD-G)4Bgb0#M&Z8G`HB6YihZ6NOEmVj5#sNEpmz6W^ymr zFDjNhI}EYuxa4ls=uGk5`7_Sc(bxk3Qmw>3ipDhEz10RV^XF(xSc5SO(a*Z7=ynXWwj=IrsSPa=5 z57!|#X@Q01e^rjKN@Rh3z_SO34IKIsX6(x^7;?G$Jw7|5oQ)5kNV6X{7+HDyb5*61 zIzdjNG1z0GL6FNUj-*qZ=BI||budH3i;Gob9x33F%G&=#~kY%uPVkhAe}23*y7iPg0mr2k&`{rC-n7_9VgAXjtc1#}}MIi^GhL=;SOCY_^PVmZ&l$2O-Fp+3U)u*{cp*E&Uxr;XP15`L zYN_^9-dnee+;{Hak$3Z+jg#iH!-KkB`__PPld3blS-n~GHqD7Zp}Wiu@kId@0ldW4 zOzbX(Q8)u(19nN|5N~?F^Ts7S0dcyjPI+kKjthqWd0{+Sxo(Sae3t9T{M<)WMdFHOzF7M$KtZLd8(<$}@#ol9*>?dYUP(n^pKx5m$4DsAb-_ zw#W6)Rv1+VS0PwEpuMgi7RFF@7E9W!G$PRBsO?YZbU%9m5@CejwM+NyI|i1%-^?Co zOqDh~I_G&etDcyh=IPuqbo0J5*tV*~&9ZP(@TuZd1A!35wsuTyL9Q#w*np)SUi6-- z{mX=3s)a}X44=*bCs`$HG^gjulE~!u+|6#dE}KqK2`O5eRQ!Qht^Qo3QhmOu&p7MR zx5uOyK9UN3OulIqMaI&|p_?|JaeD}3p#@8W3uhasKn1GatKYtXs=-pV-rXDVyKM_m zIJM&i_Mp?q;~|aL?I46$==-kT$mis7Sdj|cWt|0me?t{iy&0HStkMA1j(?J|dk$3X zV2<)_nJUqaXQ06zv-8GQC|{X>kNP)P|L@Jv*(vVvF7V1oB4B~=U(rm*l+e2ZpbCTZ z5ZHbg`b9Mp=qctErUcV}RY$tx?YPFp-8+G&rOYNzw>d2nPPH>2Q{=IYc81zpQ~nlG zgkHlLyj6+AsL!>=NcuSICeEwMEjHq)B=m2RLu{EXN?Yun9s6mq9jb@F%vO1Ouw4V- z3aD!M5>mm7)nbB0j_`u_0a&wg{z8&Szs{F=skwo|`UfH+iAR9)BD_(+PNKIcXw#W! z1j@Z+hbcDx;k_GCA1AGJui2Iw*{_IUq)pt+3%P944V?O{aAn8;I;yEV_=85`vRz5H zWW*;m=EBj@JnBn+TFh(V{4hV4Oi?#~pxx^T(Q|(R2rtC7CMIHOCp(=thqbqFOLE9GG) zWkQd^YMVm5Wa$sKSGP6s%3)ihaRAWL%%;2nzS+RJz6$lK4wXLg1Tq20=dUbCb}b-b z7mkb~3bx|VoW-ZH86|&{Ad;r3Z7!D^og(=D8y@CI@qiBTokJ3Jt}YY6S-Pq(E;$=q zn3&#yae}}j^8=KX(ePc15Uk7&B|=B)gsa77Usm;8EbYF*%B-lc9!64(*DyTHsI;8B zJf~+mr;T9|i@PLqmOLc~?+D+JH38uCo^MNkJ>XbH_XPcFAhmk-M4c`WT%-Gv7u}1r z Date: Sat, 21 Sep 2024 10:15:45 +0800 Subject: [PATCH 06/95] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java2nb/novel/core/utils/FileUtil.java | 13 ++- .../java2nb/novel/core/utils/HttpUtil.java | 29 ++---- ...stTemplateUtil.java => RestTemplates.java} | 6 +- .../java2nb/novel/core/crawl/CrawlParser.java | 87 ++++------------- .../novel/core/listener/StarterListener.java | 28 ++++-- .../novel/service/impl/CrawlServiceImpl.java | 97 ++++++++++--------- .../com/java2nb/novel/utils/Constants.java | 4 +- .../java2nb/novel/utils/CrawlHttpClient.java | 57 +++++++++++ .../src/main/resources/application.yml | 12 ++- 9 files changed, 175 insertions(+), 158 deletions(-) rename novel-common/src/main/java/com/java2nb/novel/core/utils/{RestTemplateUtil.java => RestTemplates.java} (96%) create mode 100644 novel-crawl/src/main/java/com/java2nb/novel/utils/CrawlHttpClient.java diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java index f423fe0..cbe1b06 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java @@ -14,7 +14,10 @@ import org.springframework.http.ResponseEntity; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.util.Date; import java.util.Objects; @@ -37,10 +40,13 @@ public class FileUtil { //本地图片保存 HttpHeaders headers = new HttpHeaders(); HttpEntity requestEntity = new HttpEntity<>(null, headers); - ResponseEntity resEntity = RestTemplateUtil.getInstance(Charsets.ISO_8859_1.name()).exchange(picSrc, HttpMethod.GET, requestEntity, Resource.class); + ResponseEntity resEntity = RestTemplates.newInstance(Charsets.ISO_8859_1.name()) + .exchange(picSrc, HttpMethod.GET, requestEntity, Resource.class); input = Objects.requireNonNull(resEntity.getBody()).getInputStream(); Date currentDate = new Date(); - picSrc = visitPrefix + DateUtils.formatDate(currentDate, "yyyy") + "/" + DateUtils.formatDate(currentDate, "MM") + "/" + DateUtils.formatDate(currentDate, "dd") + "/" + picSrc = + visitPrefix + DateUtils.formatDate(currentDate, "yyyy") + "/" + DateUtils.formatDate(currentDate, "MM") + + "/" + DateUtils.formatDate(currentDate, "dd") + "/" + UUIDUtil.getUUID32() + picSrc.substring(picSrc.lastIndexOf(".")); File picFile = new File(picSavePath + picSrc); @@ -67,7 +73,6 @@ public class FileUtil { closeStream(input, out); } - return picSrc; } diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java index d1d65a1..d85f9c4 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java @@ -1,38 +1,24 @@ package com.java2nb.novel.core.utils; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.*; import org.springframework.web.client.RestTemplate; /** * @author Administrator */ +@Slf4j public class HttpUtil { - private static RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8"); - - - public static String getByHttpClient(String url) { - try { - - ResponseEntity forEntity = restTemplate.getForEntity(url, String.class); - if (forEntity.getStatusCode() == HttpStatus.OK) { - return forEntity.getBody(); - } else { - return null; - } - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } + private static final RestTemplate REST_TEMPLATE = RestTemplates.newInstance("utf-8"); public static String getByHttpClientWithChrome(String url) { try { - HttpHeaders headers = new HttpHeaders(); - headers.add("user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36"); + headers.add("user-agent", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36"); HttpEntity requestEntity = new HttpEntity<>(null, headers); - ResponseEntity forEntity = restTemplate.exchange(url.toString(), HttpMethod.GET, requestEntity, String.class); + ResponseEntity forEntity = REST_TEMPLATE.exchange(url, HttpMethod.GET, requestEntity, String.class); if (forEntity.getStatusCode() == HttpStatus.OK) { return forEntity.getBody(); @@ -40,8 +26,9 @@ public class HttpUtil { return null; } } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); return null; } } + } diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplateUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java similarity index 96% rename from novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplateUtil.java rename to novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java index d4d2684..80575ab 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplateUtil.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java @@ -26,16 +26,16 @@ import java.util.List; import java.util.Objects; @Component -public class RestTemplateUtil { +public class RestTemplates { private static HttpProxyProperties httpProxyProperties; - RestTemplateUtil(HttpProxyProperties properties) { + RestTemplates(HttpProxyProperties properties) { httpProxyProperties = properties; } @SneakyThrows - public static RestTemplate getInstance(String charset) { + public static RestTemplate newInstance(String charset) { TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java index 7a76987..3068ffe 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java @@ -1,23 +1,23 @@ package com.java2nb.novel.core.crawl; -import com.java2nb.novel.core.utils.HttpUtil; import com.java2nb.novel.core.utils.RandomBookInfoUtil; -import com.java2nb.novel.core.utils.RestTemplateUtil; import com.java2nb.novel.core.utils.StringUtil; import com.java2nb.novel.entity.Book; import com.java2nb.novel.entity.BookContent; import com.java2nb.novel.entity.BookIndex; import com.java2nb.novel.utils.Constants; +import com.java2nb.novel.utils.CrawlHttpClient; import io.github.xxyopen.util.IdWorker; +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; +import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -26,20 +26,19 @@ import java.util.regex.Pattern; * * @author Administrator */ -@Slf4j +@Component +@RequiredArgsConstructor public class CrawlParser { - private static final IdWorker idWorker = IdWorker.INSTANCE; + private final IdWorker ID_WORKER = IdWorker.INSTANCE; - private static final RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8"); - - private static final ThreadLocal retryCount = new ThreadLocal<>(); + private final CrawlHttpClient crawlHttpClient; @SneakyThrows - public static void parseBook(RuleBean ruleBean, String bookId, CrawlBookHandler handler) { + public void parseBook(RuleBean ruleBean, String bookId, CrawlBookHandler handler) { Book book = new Book(); String bookDetailUrl = ruleBean.getBookDetailUrl().replace("{bookId}", bookId); - String bookDetailHtml = getByHttpClientWithChrome(bookDetailUrl); + String bookDetailHtml = crawlHttpClient.get(bookDetailUrl); if (bookDetailHtml != null) { Pattern bookNamePatten = PatternFactory.getPattern(ruleBean.getBookNamePatten()); Matcher bookNameMatch = bookNamePatten.matcher(bookDetailHtml); @@ -144,7 +143,7 @@ public class CrawlParser { handler.handle(book); } - public static boolean parseBookIndexAndContent(String sourceBookId, Book book, RuleBean ruleBean, + public boolean parseBookIndexAndContent(String sourceBookId, Book book, RuleBean ruleBean, Map existBookIndexMap, CrawlBookChapterHandler handler) { Date currentDate = new Date(); @@ -153,7 +152,7 @@ public class CrawlParser { List contentList = new ArrayList<>(); //读取目录 String indexListUrl = ruleBean.getBookIndexUrl().replace("{bookId}", sourceBookId); - String indexListHtml = getByHttpClientWithChrome(indexListUrl); + String indexListHtml = crawlHttpClient.get(indexListUrl); if (indexListHtml != null) { if (StringUtils.isNotBlank(ruleBean.getBookIndexStart())) { @@ -217,7 +216,7 @@ public class CrawlParser { .replace("{indexId}", sourceIndexId); //查询章节内容 - String contentHtml = getByHttpClientWithChrome(contentUrl); + String contentHtml = crawlHttpClient.get(contentUrl); if (contentHtml != null && !contentHtml.contains("正在手打中")) { String content = contentHtml.substring( contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length()); @@ -254,7 +253,7 @@ public class CrawlParser { } else { //章节插入 //设置目录和章节内容 - Long indexId = idWorker.nextId(); + Long indexId = ID_WORKER.nextId(); bookIndex.setId(indexId); bookIndex.setBookId(book.getId()); @@ -308,56 +307,4 @@ public class CrawlParser { return false; } - - - private static String getByHttpClient(String url) { - try { - ResponseEntity forEntity = restTemplate.getForEntity(url, String.class); - if (forEntity.getStatusCode() == HttpStatus.OK) { - String body = forEntity.getBody(); - assert body != null; - if (body.length() < Constants.INVALID_HTML_LENGTH) { - return processErrorHttpResult(url); - } - //成功获得html内容 - return body; - } - } catch (Exception e) { - e.printStackTrace(); - } - return processErrorHttpResult(url); - - } - - private static String getByHttpClientWithChrome(String url) { - try { - - String body = HttpUtil.getByHttpClientWithChrome(url); - if (body != null && body.length() < Constants.INVALID_HTML_LENGTH) { - return processErrorHttpResult(url); - } - //成功获得html内容 - return body; - } catch (Exception e) { - e.printStackTrace(); - } - return processErrorHttpResult(url); - - } - - @SneakyThrows - private static String processErrorHttpResult(String url) { - Integer count = retryCount.get(); - if (count == null) { - count = 0; - } - if (count < Constants.HTTP_FAIL_RETRY_COUNT) { - Thread.sleep(new Random().nextInt(10 * 1000)); - retryCount.set(++count); - return getByHttpClient(url); - } - return null; - } - - } diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java b/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java index ad57357..1fd998c 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java @@ -1,10 +1,12 @@ package com.java2nb.novel.core.listener; import com.fasterxml.jackson.databind.ObjectMapper; -import com.java2nb.novel.core.crawl.ChapterBean; import com.java2nb.novel.core.crawl.CrawlParser; import com.java2nb.novel.core.crawl.RuleBean; -import com.java2nb.novel.entity.*; +import com.java2nb.novel.entity.Book; +import com.java2nb.novel.entity.BookIndex; +import com.java2nb.novel.entity.CrawlSingleTask; +import com.java2nb.novel.entity.CrawlSource; import com.java2nb.novel.service.BookService; import com.java2nb.novel.service.CrawlService; import com.java2nb.novel.utils.Constants; @@ -33,6 +35,8 @@ public class StarterListener implements ServletContextListener { private final CrawlService crawlService; + private final CrawlParser crawlParser; + @Value("${crawl.update.thread}") private int updateThreadCount; @@ -56,20 +60,24 @@ public class StarterListener implements ServletContextListener { CrawlSource source = crawlService.queryCrawlSource(needUpdateBook.getCrawlSourceId()); RuleBean ruleBean = new ObjectMapper().readValue(source.getCrawlRule(), RuleBean.class); //解析小说基本信息 - CrawlParser.parseBook(ruleBean, needUpdateBook.getCrawlBookId(),book -> { + crawlParser.parseBook(ruleBean, needUpdateBook.getCrawlBookId(), book -> { //这里只做老书更新 book.setId(needUpdateBook.getId()); book.setWordCount(needUpdateBook.getWordCount()); - if (needUpdateBook.getPicUrl() != null && needUpdateBook.getPicUrl().contains(Constants.LOCAL_PIC_PREFIX)) { + if (needUpdateBook.getPicUrl() != null && needUpdateBook.getPicUrl() + .contains(Constants.LOCAL_PIC_PREFIX)) { //本地图片则不更新 book.setPicUrl(null); } //查询已存在的章节 - Map existBookIndexMap = bookService.queryExistBookIndexMap(needUpdateBook.getId()); + Map existBookIndexMap = bookService.queryExistBookIndexMap( + needUpdateBook.getId()); //解析章节目录 - CrawlParser.parseBookIndexAndContent(needUpdateBook.getCrawlBookId(), book, ruleBean, existBookIndexMap,chapter -> { - bookService.updateBookAndIndexAndContent(book, chapter.getBookIndexList(), chapter.getBookContentList(), existBookIndexMap); - }); + crawlParser.parseBookIndexAndContent(needUpdateBook.getCrawlBookId(), book, + ruleBean, existBookIndexMap, chapter -> { + bookService.updateBookAndIndexAndContent(book, chapter.getBookIndexList(), + chapter.getBookContentList(), existBookIndexMap); + }); }); } catch (Exception e) { log.error(e.getMessage(), e); @@ -88,7 +96,6 @@ public class StarterListener implements ServletContextListener { } - new Thread(() -> { log.info("程序启动,开始执行单本采集任务线程。。。"); while (true) { @@ -103,7 +110,8 @@ public class StarterListener implements ServletContextListener { CrawlSource source = crawlService.queryCrawlSource(task.getSourceId()); RuleBean ruleBean = new ObjectMapper().readValue(source.getCrawlRule(), RuleBean.class); - if (crawlService.parseBookAndSave(task.getCatId(), ruleBean, task.getSourceId(), task.getSourceBookId())) { + if (crawlService.parseBookAndSave(task.getCatId(), ruleBean, task.getSourceId(), + task.getSourceBookId())) { //采集成功 crawlStatus = 1; } diff --git a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java index d8b02b8..9341b98 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java @@ -2,17 +2,11 @@ package com.java2nb.novel.service.impl; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; -import io.github.xxyopen.model.page.PageBean; import com.java2nb.novel.core.cache.CacheKey; import com.java2nb.novel.core.cache.CacheService; import com.java2nb.novel.core.crawl.CrawlParser; import com.java2nb.novel.core.crawl.RuleBean; import com.java2nb.novel.core.enums.ResponseStatus; -import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder; -import io.github.xxyopen.util.IdWorker; -import io.github.xxyopen.util.ThreadUtil; -import io.github.xxyopen.web.exception.BusinessException; -import io.github.xxyopen.web.util.BeanUtil; import com.java2nb.novel.entity.Book; import com.java2nb.novel.entity.CrawlSingleTask; import com.java2nb.novel.entity.CrawlSource; @@ -24,6 +18,12 @@ import com.java2nb.novel.service.BookService; import com.java2nb.novel.service.CrawlService; import com.java2nb.novel.vo.CrawlSingleTaskVO; import com.java2nb.novel.vo.CrawlSourceVO; +import io.github.xxyopen.model.page.PageBean; +import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder; +import io.github.xxyopen.util.IdWorker; +import io.github.xxyopen.util.ThreadUtil; +import io.github.xxyopen.web.exception.BusinessException; +import io.github.xxyopen.web.util.BeanUtil; import io.github.xxyopen.web.util.SpringUtil; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; @@ -51,6 +51,7 @@ import static org.mybatis.dynamic.sql.select.SelectDSL.select; @Slf4j public class CrawlServiceImpl implements CrawlService { + private final CrawlParser crawlParser; private final CrawlSourceMapper crawlSourceMapper; @@ -71,15 +72,16 @@ public class CrawlServiceImpl implements CrawlService { crawlSourceMapper.insertSelective(source); } + @Override public void updateCrawlSource(CrawlSource source) { - if(source.getId()!=null){ - Optional opt=crawlSourceMapper.selectByPrimaryKey(source.getId()); - if(opt.isPresent()) { - CrawlSource crawlSource =opt.get(); + if (source.getId() != null) { + Optional opt = crawlSourceMapper.selectByPrimaryKey(source.getId()); + if (opt.isPresent()) { + CrawlSource crawlSource = opt.get(); if (crawlSource.getSourceStatus() == (byte) 1) { //关闭 - openOrCloseCrawl(crawlSource.getId(),(byte)0); + openOrCloseCrawl(crawlSource.getId(), (byte) 0); } Date currentDate = new Date(); crawlSource.setUpdateTime(currentDate); @@ -89,14 +91,15 @@ public class CrawlServiceImpl implements CrawlService { } } } + @Override public PageBean listCrawlByPage(int page, int pageSize) { PageHelper.startPage(page, pageSize); SelectStatementProvider render = select(id, sourceName, sourceStatus, createTime, updateTime) - .from(crawlSource) - .orderBy(updateTime) - .build() - .render(RenderingStrategies.MYBATIS3); + .from(crawlSource) + .orderBy(updateTime) + .build() + .render(RenderingStrategies.MYBATIS3); List crawlSources = crawlSourceMapper.selectMany(render); PageBean pageBean = PageBuilder.build(crawlSources); pageBean.setList(BeanUtil.copyList(crawlSources, CrawlSourceVO.class)); @@ -113,7 +116,8 @@ public class CrawlServiceImpl implements CrawlService { if (sourceStatus == (byte) 0) { //关闭,直接修改数据库状态,并直接修改数据库状态后获取该爬虫正在运行的线程集合全部停止 SpringUtil.getBean(CrawlService.class).updateCrawlSourceStatus(sourceId, sourceStatus); - Set runningCrawlThreadId = (Set) cacheService.getObject(CacheKey.RUNNING_CRAWL_THREAD_KEY_PREFIX + sourceId); + Set runningCrawlThreadId = (Set) cacheService.getObject( + CacheKey.RUNNING_CRAWL_THREAD_KEY_PREFIX + sourceId); if (runningCrawlThreadId != null) { for (Long ThreadId : runningCrawlThreadId) { Thread thread = ThreadUtil.findThread(ThreadId); @@ -157,11 +161,12 @@ public class CrawlServiceImpl implements CrawlService { @Override public CrawlSource queryCrawlSource(Integer sourceId) { - SelectStatementProvider render = select(CrawlSourceDynamicSqlSupport.sourceStatus, CrawlSourceDynamicSqlSupport.crawlRule) - .from(crawlSource) - .where(id, isEqualTo(sourceId)) - .build() - .render(RenderingStrategies.MYBATIS3); + SelectStatementProvider render = select(CrawlSourceDynamicSqlSupport.sourceStatus, + CrawlSourceDynamicSqlSupport.crawlRule) + .from(crawlSource) + .where(id, isEqualTo(sourceId)) + .build() + .render(RenderingStrategies.MYBATIS3); return crawlSourceMapper.selectMany(render).get(0); } @@ -182,10 +187,10 @@ public class CrawlServiceImpl implements CrawlService { public PageBean listCrawlSingleTaskByPage(int page, int pageSize) { PageHelper.startPage(page, pageSize); SelectStatementProvider render = select(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask.allColumns()) - .from(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask) - .orderBy(CrawlSingleTaskDynamicSqlSupport.createTime.descending()) - .build() - .render(RenderingStrategies.MYBATIS3); + .from(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask) + .orderBy(CrawlSingleTaskDynamicSqlSupport.createTime.descending()) + .build() + .render(RenderingStrategies.MYBATIS3); List crawlSingleTasks = crawlSingleTaskMapper.selectMany(render); PageBean pageBean = PageBuilder.build(crawlSingleTasks); pageBean.setList(BeanUtil.copyList(crawlSingleTasks, CrawlSingleTaskVO.class)); @@ -200,7 +205,8 @@ public class CrawlServiceImpl implements CrawlService { @Override public CrawlSingleTask getCrawlSingleTask() { - List list = crawlSingleTaskMapper.selectMany(select(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask.allColumns()) + List list = crawlSingleTaskMapper.selectMany( + select(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask.allColumns()) .from(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask) .where(CrawlSingleTaskDynamicSqlSupport.taskStatus, isEqualTo((byte) 2)) .orderBy(CrawlSingleTaskDynamicSqlSupport.createTime) @@ -226,12 +232,12 @@ public class CrawlServiceImpl implements CrawlService { @Override public CrawlSource getCrawlSource(Integer id) { - Optional opt=crawlSourceMapper.selectByPrimaryKey(id); - if(opt.isPresent()) { - CrawlSource crawlSource =opt.get(); - return crawlSource; - } - return null; + Optional opt = crawlSourceMapper.selectByPrimaryKey(id); + if (opt.isPresent()) { + CrawlSource crawlSource = opt.get(); + return crawlSource; + } + return null; } /** @@ -251,8 +257,8 @@ public class CrawlServiceImpl implements CrawlService { if (StringUtils.isNotBlank(ruleBean.getCatIdRule().get("catId" + catId))) { //拼接分类URL String catBookListUrl = ruleBean.getBookListUrl() - .replace("{catId}", ruleBean.getCatIdRule().get("catId" + catId)) - .replace("{page}", page + ""); + .replace("{catId}", ruleBean.getCatIdRule().get("catId" + catId)) + .replace("{page}", page + ""); String bookListHtml = getByHttpClientWithChrome(catBookListUrl); if (bookListHtml != null) { @@ -268,14 +274,12 @@ public class CrawlServiceImpl implements CrawlService { return; } - String bookId = bookIdMatcher.group(1); parseBookAndSave(catId, ruleBean, sourceId, bookId); } catch (Exception e) { log.error(e.getMessage(), e); } - isFindBookId = bookIdMatcher.find(); } @@ -306,7 +310,7 @@ public class CrawlServiceImpl implements CrawlService { final AtomicBoolean parseResult = new AtomicBoolean(false); - CrawlParser.parseBook(ruleBean, bookId, book -> { + crawlParser.parseBook(ruleBean, bookId, book -> { if (book.getBookName() == null || book.getAuthorName() == null) { return; } @@ -330,9 +334,11 @@ public class CrawlServiceImpl implements CrawlService { book.setCrawlLastTime(new Date()); book.setId(idWorker.nextId()); //解析章节目录 - boolean parseIndexContentResult = CrawlParser.parseBookIndexAndContent(bookId, book, ruleBean, new HashMap<>(0), chapter -> { - bookService.saveBookAndIndexAndContent(book, chapter.getBookIndexList(), chapter.getBookContentList()); - }); + boolean parseIndexContentResult = crawlParser.parseBookIndexAndContent(bookId, book, ruleBean, + new HashMap<>(0), chapter -> { + bookService.saveBookAndIndexAndContent(book, chapter.getBookIndexList(), + chapter.getBookContentList()); + }); parseResult.set(parseIndexContentResult); } else { @@ -356,11 +362,12 @@ public class CrawlServiceImpl implements CrawlService { @Override public List queryCrawlSourceByStatus(Byte sourceStatus) { - SelectStatementProvider render = select(CrawlSourceDynamicSqlSupport.id, CrawlSourceDynamicSqlSupport.sourceStatus, CrawlSourceDynamicSqlSupport.crawlRule) - .from(crawlSource) - .where(CrawlSourceDynamicSqlSupport.sourceStatus, isEqualTo(sourceStatus)) - .build() - .render(RenderingStrategies.MYBATIS3); + SelectStatementProvider render = select(CrawlSourceDynamicSqlSupport.id, + CrawlSourceDynamicSqlSupport.sourceStatus, CrawlSourceDynamicSqlSupport.crawlRule) + .from(crawlSource) + .where(CrawlSourceDynamicSqlSupport.sourceStatus, isEqualTo(sourceStatus)) + .build() + .render(RenderingStrategies.MYBATIS3); return crawlSourceMapper.selectMany(render); } } diff --git a/novel-crawl/src/main/java/com/java2nb/novel/utils/Constants.java b/novel-crawl/src/main/java/com/java2nb/novel/utils/Constants.java index d278c19..5d3c59c 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/utils/Constants.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/utils/Constants.java @@ -7,7 +7,7 @@ public class Constants { /** * 本地图片保存前缀 - * */ + */ public static final String LOCAL_PIC_PREFIX = "/localPic/"; /** @@ -23,5 +23,5 @@ public class Constants { /** * 爬取小说http请求失败重试次数 */ - public static final Integer HTTP_FAIL_RETRY_COUNT = 5; + public static final Integer HTTP_FAIL_RETRY_COUNT = 3; } diff --git a/novel-crawl/src/main/java/com/java2nb/novel/utils/CrawlHttpClient.java b/novel-crawl/src/main/java/com/java2nb/novel/utils/CrawlHttpClient.java new file mode 100644 index 0000000..515f005 --- /dev/null +++ b/novel-crawl/src/main/java/com/java2nb/novel/utils/CrawlHttpClient.java @@ -0,0 +1,57 @@ +package com.java2nb.novel.utils; + +import com.java2nb.novel.core.utils.HttpUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Objects; +import java.util.Random; + +/** + * @author Administrator + */ +@Slf4j +@Component +public class CrawlHttpClient { + + @Value("${crawl.interval.min}") + private Integer intervalMin; + + @Value("${crawl.interval.max}") + private Integer intervalMax; + + private final Random random = new Random(); + + private static final ThreadLocal RETRY_COUNT = new ThreadLocal<>(); + + public String get(String url) { + if (Objects.nonNull(intervalMin) && Objects.nonNull(intervalMax) && intervalMax > intervalMin) { + try { + Thread.sleep(random.nextInt(intervalMax - intervalMin + 1) + intervalMin); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + } + String body = HttpUtil.getByHttpClientWithChrome(url); + if (Objects.isNull(body) || body.length() < Constants.INVALID_HTML_LENGTH) { + return processErrorHttpResult(url); + } + //成功获得html内容 + return body; + } + + private String processErrorHttpResult(String url) { + Integer count = RETRY_COUNT.get(); + if (count == null) { + count = 0; + } + if (count < Constants.HTTP_FAIL_RETRY_COUNT) { + RETRY_COUNT.set(++count); + return get(url); + } + RETRY_COUNT.remove(); + return null; + } + +} diff --git a/novel-crawl/src/main/resources/application.yml b/novel-crawl/src/main/resources/application.yml index 132a14e..b4908fe 100644 --- a/novel-crawl/src/main/resources/application.yml +++ b/novel-crawl/src/main/resources/application.yml @@ -14,12 +14,18 @@ admin: username: admin password: admin -#爬虫自动更新的线程数 -#建议小说数量不多或者正在运行新书入库爬虫的情况下设置为1即可 -#随着小说数量的增多可以逐渐增加,但建议不要超出CPU的线程数 + + crawl: update: + #爬虫自动更新的线程数 + #建议小说数量不多或者正在运行新书入库爬虫的情况下设置为1即可 + #随着小说数量的增多可以逐渐增加,但建议不要超出CPU的线程数 thread: 1 + # 采集间隔时间,单位:毫秒 + interval: + min: 300 + max: 500 From f78a2a36cfd5f2dc51bc365d1557811408dd1395 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 21 Sep 2024 11:10:44 +0800 Subject: [PATCH 07/95] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/java2nb/novel/service/impl/CrawlServiceImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java index 9341b98..690dfe5 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java @@ -16,6 +16,7 @@ import com.java2nb.novel.mapper.CrawlSourceDynamicSqlSupport; import com.java2nb.novel.mapper.CrawlSourceMapper; import com.java2nb.novel.service.BookService; import com.java2nb.novel.service.CrawlService; +import com.java2nb.novel.utils.CrawlHttpClient; import com.java2nb.novel.vo.CrawlSingleTaskVO; import com.java2nb.novel.vo.CrawlSourceVO; import io.github.xxyopen.model.page.PageBean; @@ -38,7 +39,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.java2nb.novel.core.utils.HttpUtil.getByHttpClientWithChrome; import static com.java2nb.novel.mapper.CrawlSourceDynamicSqlSupport.*; import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo; import static org.mybatis.dynamic.sql.select.SelectDSL.select; @@ -63,6 +63,8 @@ public class CrawlServiceImpl implements CrawlService { private final IdWorker idWorker = IdWorker.INSTANCE; + private CrawlHttpClient crawlHttpClient; + @Override public void addCrawlSource(CrawlSource source) { @@ -260,7 +262,7 @@ public class CrawlServiceImpl implements CrawlService { .replace("{catId}", ruleBean.getCatIdRule().get("catId" + catId)) .replace("{page}", page + ""); - String bookListHtml = getByHttpClientWithChrome(catBookListUrl); + String bookListHtml = crawlHttpClient.get(catBookListUrl); if (bookListHtml != null) { Pattern bookIdPatten = Pattern.compile(ruleBean.getBookIdPatten()); Matcher bookIdMatcher = bookIdPatten.matcher(bookListHtml); From 3586ffbc0ace93b8b052aacdfec0bf84c9851e66 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 21 Sep 2024 11:14:07 +0800 Subject: [PATCH 08/95] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/java2nb/novel/service/impl/CrawlServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java index 690dfe5..90f884f 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java @@ -63,7 +63,7 @@ public class CrawlServiceImpl implements CrawlService { private final IdWorker idWorker = IdWorker.INSTANCE; - private CrawlHttpClient crawlHttpClient; + private final CrawlHttpClient crawlHttpClient; @Override From 2136f7490f05c1dcc5fe40d96ae7b6d717ddb736 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 2 Nov 2024 13:24:28 +0800 Subject: [PATCH 09/95] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=88=AC=E8=99=AB?= =?UTF-8?q?=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/novel_plus.sql | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/doc/sql/novel_plus.sql b/doc/sql/novel_plus.sql index b4a8b12..1cbbf7e 100644 --- a/doc/sql/novel_plus.sql +++ b/doc/sql/novel_plus.sql @@ -3103,4 +3103,37 @@ where id = 16; update website_info set logo = '/images/logo.png', logo_dark='/images/logo.png' -where id = 1; \ No newline at end of file +where id = 1; + + +INSERT INTO crawl_source (source_name, crawl_rule, source_status, create_time, update_time) +VALUES ('香书小说网', '{ + "bookListUrl": "http://www.xbiqugu.net/fenlei/{catId}_{page}.html", + "catIdRule": { + "catId1": "1", + "catId2": "2", + "catId3": "3", + "catId4": "4", + "catId5": "6", + "catId6": "5" + }, + "bookIdPatten": "", + "pagePatten": "(\\\\d+)/\\\\d+", + "totalPagePatten": "\\\\d+/(\\\\d+)", + "bookDetailUrl": "http://www.xbiqugu.net/{bookId}/", + "bookNamePatten": "

    ([^/]+)

    ", + "authorNamePatten": "者:([^/]+)

    ", + "picUrlPatten": "src=\\"(http://www.xbiqugu.net/files/article/image/\\\\d+/\\\\d+/\\\\d+s\\\\.jpg)\\"", + "bookStatusRule": {}, + "descStart": "
    ", + "descEnd": "
    ", + "upadateTimePatten": "

    最后更新:(\\\\d+-\\\\d+-\\\\d+\\\\s\\\\d+:\\\\d+:\\\\d+)

    ", + "upadateTimeFormatPatten": "yyyy-MM-dd HH:mm:ss", + "bookIndexUrl": "http://www.xbiqugu.net/{bookId}/", + "indexIdPatten": "[^/]+", + "indexNamePatten": "([^/]+)", + "bookContentUrl": "http://www.xbiqugu.net/{bookId}/{indexId}.html", + "contentStart": "
    ", + "contentEnd": "

    ", + "filterContent":"\\\\s*([^/]+)\\\\s*

    " +}', 0, '2024-06-01 10:11:39', '2024-06-01 10:11:39'); \ No newline at end of file From 4b9dbe969cbf1f89ceafcc25ec296667c51f013f Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 2 Nov 2024 18:26:40 +0800 Subject: [PATCH 10/95] =?UTF-8?q?=E4=BF=AE=E5=A4=8Di=E7=AC=94=E8=B6=A3?= =?UTF-8?q?=E9=98=81=E7=88=AC=E8=99=AB=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/novel_plus.sql | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/sql/novel_plus.sql b/doc/sql/novel_plus.sql index 1cbbf7e..2ad0470 100644 --- a/doc/sql/novel_plus.sql +++ b/doc/sql/novel_plus.sql @@ -3136,4 +3136,9 @@ VALUES ('香书小说网', '{ "contentStart": "
    ", "contentEnd": "

    ", "filterContent":"\\\\s*([^/]+)\\\\s*

    " -}', 0, '2024-06-01 10:11:39', '2024-06-01 10:11:39'); \ No newline at end of file +}', 0, '2024-06-01 10:11:39', '2024-06-01 10:11:39'); + + +update crawl_source +set crawl_rule = replace(crawl_rule, 'ibiquzw.org', 'ibiqugu.net') +where id = 16; \ No newline at end of file From 71b9d1d9165f8f26593c45593494cb3dc15f4a42 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 2 Nov 2024 18:31:47 +0800 Subject: [PATCH 11/95] =?UTF-8?q?=E6=A8=A1=E7=89=88=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/green/html/mobile/pay/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/green/html/mobile/pay/index.html b/templates/green/html/mobile/pay/index.html index befa955..98a0a97 100644 --- a/templates/green/html/mobile/pay/index.html +++ b/templates/green/html/mobile/pay/index.html @@ -114,7 +114,7 @@ style="color: #3eaf7c" id="accountBalance">10 屋币
  • -
    +
    选择充值金额
  • From 3849a9b86f40a13566760306f9111f11e3fe3dae Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 2 Nov 2024 18:32:01 +0800 Subject: [PATCH 12/95] =?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 --- novel-admin/pom.xml | 2 +- novel-common/pom.xml | 2 +- novel-crawl/pom.xml | 2 +- novel-front/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index bbf634f..9343ab9 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel-admin - 4.3.0 + 4.4.0 jar novel-admin diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 0f7bde4..2f27a93 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 4.3.0 + 4.4.0 4.0.0 diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index a3958f9..176d6d4 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 4.3.0 + 4.4.0 4.0.0 diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 591c698..0319211 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 4.3.0 + 4.4.0 4.0.0 diff --git a/pom.xml b/pom.xml index 3aacc45..9305df8 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel - 4.3.0 + 4.4.0 novel-common novel-front From d8e559ab506754e5ddba4061dc7e233b25cac961 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 2 Nov 2024 21:19:27 +0800 Subject: [PATCH 13/95] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/novel_plus.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sql/novel_plus.sql b/doc/sql/novel_plus.sql index 2ad0470..7098f0d 100644 --- a/doc/sql/novel_plus.sql +++ b/doc/sql/novel_plus.sql @@ -3140,5 +3140,5 @@ VALUES ('香书小说网', '{ update crawl_source -set crawl_rule = replace(crawl_rule, 'ibiquzw.org', 'ibiqugu.net') +set crawl_rule = replace(crawl_rule, 'ibiquzw.org', 'biquxs.info') where id = 16; \ No newline at end of file From 2cb9f8508178cac6fa8e35da594fa040da7c4276 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 18 Jan 2025 00:46:39 +0800 Subject: [PATCH 14/95] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/static/js/appjs/novel/websiteInfo/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/novel-admin/src/main/resources/static/js/appjs/novel/websiteInfo/edit.js b/novel-admin/src/main/resources/static/js/appjs/novel/websiteInfo/edit.js index b3384bd..0a692f2 100644 --- a/novel-admin/src/main/resources/static/js/appjs/novel/websiteInfo/edit.js +++ b/novel-admin/src/main/resources/static/js/appjs/novel/websiteInfo/edit.js @@ -79,7 +79,7 @@ function update() { }, success: function (data) { if (data.code == 0) { - layer.msg("操作成功"); + layer.msg("操作成功,重启 novel-front 后生效"); } else { layer.alert(data.msg) } From 0ff87614ea2dc9caa40ec4af3bf83a805b9fbdcc Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 28 Feb 2025 22:02:11 +0800 Subject: [PATCH 15/95] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=A4=B1?= =?UTF-8?q?=E6=95=88=E7=9A=84=E7=88=AC=E8=99=AB=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/novel_plus.sql | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/sql/novel_plus.sql b/doc/sql/novel_plus.sql index 7098f0d..55bd4ad 100644 --- a/doc/sql/novel_plus.sql +++ b/doc/sql/novel_plus.sql @@ -3141,4 +3141,8 @@ VALUES ('香书小说网', '{ update crawl_source set crawl_rule = replace(crawl_rule, 'ibiquzw.org', 'biquxs.info') -where id = 16; \ No newline at end of file +where id = 16; + + +update crawl_source +set crawl_rule = replace(crawl_rule, 'xbiqugu.net', 'xbiqugu.la'); \ No newline at end of file From cdfe481d6030a9c2feb19282072b489a6aa16a8e Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 14 Mar 2025 17:48:35 +0800 Subject: [PATCH 16/95] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index baffe3c..2a699d5 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ -[![index]( https://youdoc.github.io/img/tencent.jpg )]( https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console ) - +

    + AD + AD +

    Github stars Github forks Gitee stars Gitee forks - visitors

    From 74d7ea7000cedbe88c57f703269ce6875732c8b5 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 14 Mar 2025 18:36:14 +0800 Subject: [PATCH 17/95] =?UTF-8?q?feat:=20=E4=BB=A3=E7=90=86IP=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=94=A8=E6=88=B7=E5=90=8D=E5=AF=86=E7=A0=81=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../novel/core/config/HttpProxyProperties.java | 4 ++++ .../java2nb/novel/core/utils/RestTemplates.java | 14 ++++++++++++++ .../src/main/resources/application-common-dev.yml | 8 ++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/novel-common/src/main/java/com/java2nb/novel/core/config/HttpProxyProperties.java b/novel-common/src/main/java/com/java2nb/novel/core/config/HttpProxyProperties.java index 140f298..d128c8e 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/config/HttpProxyProperties.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/config/HttpProxyProperties.java @@ -19,4 +19,8 @@ public class HttpProxyProperties { private Integer port; + private String username; + + private String password; + } diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java index 80575ab..58bf452 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java @@ -2,13 +2,18 @@ package com.java2nb.novel.core.utils; import com.java2nb.novel.core.config.HttpProxyProperties; import lombok.SneakyThrows; +import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; @@ -61,6 +66,15 @@ public class RestTemplates { if (Objects.nonNull(httpProxyProperties) && Boolean.TRUE.equals(httpProxyProperties.getEnabled())) { HttpHost proxy = new HttpHost(httpProxyProperties.getIp(), httpProxyProperties.getPort()); clientBuilder.setProxy(proxy); + if (StringUtils.isNotBlank(httpProxyProperties.getUsername()) && StringUtils.isNotBlank( + httpProxyProperties.getPassword())) { + // 创建CredentialsProvider实例并添加代理认证信息 + CredentialsProvider provider = new BasicCredentialsProvider(); + UsernamePasswordCredentials credentials = new UsernamePasswordCredentials( + httpProxyProperties.getUsername(), httpProxyProperties.getPassword()); + provider.setCredentials(AuthScope.ANY, credentials); + clientBuilder.setDefaultCredentialsProvider(provider); + } } CloseableHttpClient httpClient = clientBuilder.setConnectionManager(connectionManager) .build(); diff --git a/novel-common/src/main/resources/application-common-dev.yml b/novel-common/src/main/resources/application-common-dev.yml index a475996..4f21870 100644 --- a/novel-common/src/main/resources/application-common-dev.yml +++ b/novel-common/src/main/resources/application-common-dev.yml @@ -78,6 +78,10 @@ http: # 是否开启 HTTP 代理,true-开启,false-不开启 enabled: false # 代理 IP - ip: u493.kdltps.com + ip: us.swiftproxy.net # 代理端口号 - port: 15818 \ No newline at end of file + port: 7878 + # 代理用户名 + username: swiftproxy_u + # 代理密码 + password: swiftproxy_p \ No newline at end of file From 6d0ab337579c10e90f8b61f50c578a33dc349427 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 14 Mar 2025 19:03:30 +0800 Subject: [PATCH 18/95] =?UTF-8?q?perf:=20=E7=88=AC=E8=99=AB=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E8=A7=84=E5=88=99=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../novel/service/impl/CrawlServiceImpl.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java index 90f884f..c5b404d 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java @@ -255,12 +255,21 @@ public class CrawlServiceImpl implements CrawlService { while (page <= totalPage) { try { - - if (StringUtils.isNotBlank(ruleBean.getCatIdRule().get("catId" + catId))) { - //拼接分类URL - String catBookListUrl = ruleBean.getBookListUrl() - .replace("{catId}", ruleBean.getCatIdRule().get("catId" + catId)) - .replace("{page}", page + ""); + String catIdRule = ruleBean.getCatIdRule().get("catId" + catId); + if (StringUtils.isNotBlank(catIdRule)) { + String catBookListUrl = ""; + if (StringUtils.isNotBlank(ruleBean.getBookListUrl())) { + // 兼容老规则 + // 拼接分类URL + catBookListUrl = ruleBean.getBookListUrl() + .replace("{catId}", catIdRule) + .replace("{page}", page + ""); + } else { + // 新规则 + // 拼接分类URL + catBookListUrl = catIdRule.replace("{page}", page + ""); + } + log.info("catBookListUrl:{}", catBookListUrl); String bookListHtml = crawlHttpClient.get(catBookListUrl); if (bookListHtml != null) { From 85b64bbc10e3188d8fa0b28ea2ae9a7a49081fde Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 14 Mar 2025 19:27:46 +0800 Subject: [PATCH 19/95] =?UTF-8?q?perf:=20=E7=88=AC=E8=99=AB=E9=87=87?= =?UTF-8?q?=E9=9B=86=E6=B5=81=E7=A8=8B=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/java2nb/novel/core/utils/HttpUtil.java | 3 ++- .../java/com/java2nb/novel/service/impl/CrawlServiceImpl.java | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java index d85f9c4..47f900a 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java @@ -14,12 +14,13 @@ public class HttpUtil { public static String getByHttpClientWithChrome(String url) { try { + log.debug("Get url:{}", url); HttpHeaders headers = new HttpHeaders(); headers.add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36"); HttpEntity requestEntity = new HttpEntity<>(null, headers); ResponseEntity forEntity = REST_TEMPLATE.exchange(url, HttpMethod.GET, requestEntity, String.class); - + log.debug("Response code:{}", forEntity.getStatusCode()); if (forEntity.getStatusCode() == HttpStatus.OK) { return forEntity.getBody(); } else { diff --git a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java index c5b404d..0a30be5 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java @@ -309,6 +309,10 @@ public class CrawlServiceImpl implements CrawlService { } catch (Exception e) { log.error(e.getMessage(), e); } + if (page == totalPage) { + // 第一遍采集完成,翻到第一页,继续第二次采集,适用于分页数比较少的最近更新列表 + page = 0; + } page += 1; } From 73502a279bfae1e5db2f82a1d5c02d5fd5f93153 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 14 Mar 2025 20:39:57 +0800 Subject: [PATCH 20/95] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E9=9D=9Eutf-8?= =?UTF-8?q?=E7=BC=96=E7=A0=81=E7=9A=84=E7=BD=91=E7=AB=99=E9=87=87=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java2nb/novel/core/utils/HttpUtil.java | 25 ++++++++++++++++--- .../java2nb/novel/core/crawl/CrawlParser.java | 6 ++--- .../java2nb/novel/core/crawl/RuleBean.java | 7 ++++++ .../novel/service/impl/CrawlServiceImpl.java | 2 +- .../com/java2nb/novel/utils/Constants.java | 5 ++++ .../java2nb/novel/utils/CrawlHttpClient.java | 10 ++++---- .../templates/crawl/crawlSource_add.html | 7 ++++++ .../templates/crawl/crawlSource_update.html | 8 ++++++ 8 files changed, 57 insertions(+), 13 deletions(-) diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java index 47f900a..daabff1 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/HttpUtil.java @@ -4,22 +4,35 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.*; import org.springframework.web.client.RestTemplate; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + /** * @author Administrator */ @Slf4j public class HttpUtil { - private static final RestTemplate REST_TEMPLATE = RestTemplates.newInstance("utf-8"); + private static final String DEFAULT_CHARSET = "utf-8"; - public static String getByHttpClientWithChrome(String url) { + private static final Map REST_TEMPLATE_MAP = new HashMap<>(); + + public static String getByHttpClientWithChrome(String url, String charset) { + log.debug("Get url:{}", url); + if (!Charset.isSupported(charset)) { + log.error("字符编码{}无效!", charset); + return null; + } + RestTemplate restTemplate = REST_TEMPLATE_MAP.computeIfAbsent(charset, + k -> RestTemplates.newInstance(charset)); try { - log.debug("Get url:{}", url); HttpHeaders headers = new HttpHeaders(); headers.add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36"); HttpEntity requestEntity = new HttpEntity<>(null, headers); - ResponseEntity forEntity = REST_TEMPLATE.exchange(url, HttpMethod.GET, requestEntity, String.class); + ResponseEntity forEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, + String.class); log.debug("Response code:{}", forEntity.getStatusCode()); if (forEntity.getStatusCode() == HttpStatus.OK) { return forEntity.getBody(); @@ -32,4 +45,8 @@ public class HttpUtil { } } + public static String getByHttpClientWithChrome(String url) { + return getByHttpClientWithChrome(url, DEFAULT_CHARSET); + } + } diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java index 3068ffe..312ca43 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java @@ -38,7 +38,7 @@ public class CrawlParser { public void parseBook(RuleBean ruleBean, String bookId, CrawlBookHandler handler) { Book book = new Book(); String bookDetailUrl = ruleBean.getBookDetailUrl().replace("{bookId}", bookId); - String bookDetailHtml = crawlHttpClient.get(bookDetailUrl); + String bookDetailHtml = crawlHttpClient.get(bookDetailUrl, ruleBean.getCharset()); if (bookDetailHtml != null) { Pattern bookNamePatten = PatternFactory.getPattern(ruleBean.getBookNamePatten()); Matcher bookNameMatch = bookNamePatten.matcher(bookDetailHtml); @@ -152,7 +152,7 @@ public class CrawlParser { List contentList = new ArrayList<>(); //读取目录 String indexListUrl = ruleBean.getBookIndexUrl().replace("{bookId}", sourceBookId); - String indexListHtml = crawlHttpClient.get(indexListUrl); + String indexListHtml = crawlHttpClient.get(indexListUrl, ruleBean.getCharset()); if (indexListHtml != null) { if (StringUtils.isNotBlank(ruleBean.getBookIndexStart())) { @@ -216,7 +216,7 @@ public class CrawlParser { .replace("{indexId}", sourceIndexId); //查询章节内容 - String contentHtml = crawlHttpClient.get(contentUrl); + String contentHtml = crawlHttpClient.get(contentUrl, ruleBean.getCharset()); if (contentHtml != null && !contentHtml.contains("正在手打中")) { String content = contentHtml.substring( contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length()); diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/RuleBean.java b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/RuleBean.java index 58a4efb..e6f134d 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/RuleBean.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/RuleBean.java @@ -1,5 +1,6 @@ package com.java2nb.novel.core.crawl; +import com.java2nb.novel.utils.Constants; import lombok.Data; import java.util.Map; @@ -12,6 +13,12 @@ import java.util.Map; @Data public class RuleBean { + /** + * 网页字符编码 + */ + private String charset = Constants.CRAWL_DEFAULT_CHARSET; + + /** * 小说更新列表url */ diff --git a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java index 0a30be5..0e6f849 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java @@ -271,7 +271,7 @@ public class CrawlServiceImpl implements CrawlService { } log.info("catBookListUrl:{}", catBookListUrl); - String bookListHtml = crawlHttpClient.get(catBookListUrl); + String bookListHtml = crawlHttpClient.get(catBookListUrl, ruleBean.getCharset()); if (bookListHtml != null) { Pattern bookIdPatten = Pattern.compile(ruleBean.getBookIdPatten()); Matcher bookIdMatcher = bookIdPatten.matcher(bookListHtml); diff --git a/novel-crawl/src/main/java/com/java2nb/novel/utils/Constants.java b/novel-crawl/src/main/java/com/java2nb/novel/utils/Constants.java index 5d3c59c..b84f91a 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/utils/Constants.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/utils/Constants.java @@ -24,4 +24,9 @@ public class Constants { * 爬取小说http请求失败重试次数 */ public static final Integer HTTP_FAIL_RETRY_COUNT = 3; + + /** + * 爬虫默认编码 + */ + public static final String CRAWL_DEFAULT_CHARSET = "UTF-8"; } diff --git a/novel-crawl/src/main/java/com/java2nb/novel/utils/CrawlHttpClient.java b/novel-crawl/src/main/java/com/java2nb/novel/utils/CrawlHttpClient.java index 515f005..38e492b 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/utils/CrawlHttpClient.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/utils/CrawlHttpClient.java @@ -25,7 +25,7 @@ public class CrawlHttpClient { private static final ThreadLocal RETRY_COUNT = new ThreadLocal<>(); - public String get(String url) { + public String get(String url, String charset) { if (Objects.nonNull(intervalMin) && Objects.nonNull(intervalMax) && intervalMax > intervalMin) { try { Thread.sleep(random.nextInt(intervalMax - intervalMin + 1) + intervalMin); @@ -33,22 +33,22 @@ public class CrawlHttpClient { log.error(e.getMessage(), e); } } - String body = HttpUtil.getByHttpClientWithChrome(url); + String body = HttpUtil.getByHttpClientWithChrome(url, charset); if (Objects.isNull(body) || body.length() < Constants.INVALID_HTML_LENGTH) { - return processErrorHttpResult(url); + return processErrorHttpResult(url, charset); } //成功获得html内容 return body; } - private String processErrorHttpResult(String url) { + private String processErrorHttpResult(String url, String charset) { Integer count = RETRY_COUNT.get(); if (count == null) { count = 0; } if (count < Constants.HTTP_FAIL_RETRY_COUNT) { RETRY_COUNT.set(++count); - return get(url); + return get(url, charset); } RETRY_COUNT.remove(); return null; diff --git a/novel-crawl/src/main/resources/templates/crawl/crawlSource_add.html b/novel-crawl/src/main/resources/templates/crawl/crawlSource_add.html index 5162663..4b35329 100644 --- a/novel-crawl/src/main/resources/templates/crawl/crawlSource_add.html +++ b/novel-crawl/src/main/resources/templates/crawl/crawlSource_add.html @@ -54,6 +54,8 @@ + 示例:utf-8 +

  • 示例:http://m.xdingdiann.com/sort/{catId}/{page}.html ({catId}代表分类ID,{page}代表分页页码)
  • @@ -411,6 +413,11 @@ var filterContent = $("#filterContent").val(); crawlRule.filterContent = filterContent; + var charset = $('#charset').val(); + if (charset) { + crawlRule.charset = charset; + } + $.ajax({ type: "POST", diff --git a/novel-crawl/src/main/resources/templates/crawl/crawlSource_update.html b/novel-crawl/src/main/resources/templates/crawl/crawlSource_update.html index 08dd048..eec916b 100644 --- a/novel-crawl/src/main/resources/templates/crawl/crawlSource_update.html +++ b/novel-crawl/src/main/resources/templates/crawl/crawlSource_update.html @@ -55,6 +55,8 @@ + 示例:utf-8 +
  • 示例:http://m.xdingdiann.com/sort/{catId}/{page}.html ({catId}代表分类ID,{page}代表分页页码)
  • @@ -274,6 +276,7 @@ $("#contentStart").val(crawlRule.contentStart); $("#contentEnd").val(crawlRule.contentEnd); $("#filterContent").val(crawlRule.filterContent); + $("#charset").val(crawlRule.charset); } } @@ -496,6 +499,11 @@ var filterContent = $("#filterContent").val(); crawlRule.filterContent = filterContent; + var charset = $('#charset').val(); + if (charset) { + crawlRule.charset = charset; + } + $.ajax({ type: "POST", From fd200772c9a8cdd71cafc9183feffc31644327da Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 15 Mar 2025 09:15:26 +0800 Subject: [PATCH 21/95] =?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 --- novel-admin/pom.xml | 2 +- novel-common/pom.xml | 2 +- novel-crawl/pom.xml | 2 +- novel-front/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index 9343ab9..c590f48 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel-admin - 4.4.0 + 5.0.0-SNAPSHOT jar novel-admin diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 2f27a93..fecee4a 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 4.4.0 + 5.0.0-SNAPSHOT 4.0.0 diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index 176d6d4..64a5b68 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 4.4.0 + 5.0.0-SNAPSHOT 4.0.0 diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 0319211..5f0876f 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 4.4.0 + 5.0.0-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index 9305df8..80455b9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel - 4.4.0 + 5.0.0-SNAPSHOT novel-common novel-front From 9033ca63319186729880b8f0dd6ca2e094d8a803 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 15 Mar 2025 15:06:59 +0800 Subject: [PATCH 22/95] =?UTF-8?q?build:=20Java=E7=89=88=E6=9C=AC=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E5=88=B021=20&=20SpringBoot=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=88=B02.7.18?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/shardingsphere-jdbc.yml | 53 +++++++ doc/sql/novel_plus.sql | 10 +- novel-admin/pom.xml | 70 ++++----- .../java2nb/common/aspect/WebLogAspect.java | 10 +- .../java2nb/common/config/DruidDBConfig.java | 132 ---------------- .../java2nb/common/config/Swagger2Config.java | 48 ------ .../java2nb/common/dao/GeneratorMapper.java | 10 +- .../exception/MainsiteErrorController.java | 16 +- .../com/java2nb/common/utils/JSONUtils.java | 144 +++++++++--------- .../src/main/resources/application-dev.yml | 82 +--------- .../src/main/resources/application-prod.yml | 78 +--------- novel-common/pom.xml | 22 +-- .../main/resources/application-common-dev.yml | 45 +----- .../src/main/resources/application-common.yml | 2 + novel-crawl/pom.xml | 7 +- .../novel/core/listener/StarterListener.java | 12 +- .../src/main/resources/application.yml | 4 +- novel-front/pom.xml | 7 +- .../novel/core/listener/StarterListener.java | 32 ++-- .../src/main/resources/application.yml | 2 + pom.xml | 7 +- 21 files changed, 244 insertions(+), 549 deletions(-) create mode 100644 config/shardingsphere-jdbc.yml delete mode 100644 novel-admin/src/main/java/com/java2nb/common/config/DruidDBConfig.java delete mode 100644 novel-admin/src/main/java/com/java2nb/common/config/Swagger2Config.java diff --git a/config/shardingsphere-jdbc.yml b/config/shardingsphere-jdbc.yml new file mode 100644 index 0000000..5f12200 --- /dev/null +++ b/config/shardingsphere-jdbc.yml @@ -0,0 +1,53 @@ +mode: + # 单机模式 + type: Standalone + # 元数据持久化 + repository: + # 数据库持久化 + type: JDBC + +# 数据源配置 +dataSources: + ds_1: + dataSourceClassName: com.zaxxer.hikari.HikariDataSource + driverClassName: com.mysql.cj.jdbc.Driver + jdbcUrl: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: test123456 + ds_2: + dataSourceClassName: com.zaxxer.hikari.HikariDataSource + driverClassName: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/information_schema?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: test123456 +# 规则配置 +rules: + - !SINGLE + tables: + - "*.*" + - !SHARDING + tables: # 数据分片规则配置 + book_content: + # 分库策略,缺省表示使用默认分库策略 + actualDataNodes: ds_${1}.book_content${0..9} + # 分表策略 + tableStrategy: + standard: + # 分片列名称 + shardingColumn: chapter_id + # 分片算法名称 + shardingAlgorithmName: bookContentSharding + + shardingAlgorithms: + bookContentSharding: + # 行表达式分片算法,使用 Groovy 的表达式,提供对 SQL 语句中的 = 和 IN 的分片操作支持 + type: INLINE + props: + # 分片算法的行表达式 + algorithm-expression: book_content${chapter_id % 10} + + + +props: + # 是否在日志中打印 SQL + sql-show: true diff --git a/doc/sql/novel_plus.sql b/doc/sql/novel_plus.sql index 55bd4ad..57748f9 100644 --- a/doc/sql/novel_plus.sql +++ b/doc/sql/novel_plus.sql @@ -3145,4 +3145,12 @@ where id = 16; update crawl_source -set crawl_rule = replace(crawl_rule, 'xbiqugu.net', 'xbiqugu.la'); \ No newline at end of file +set crawl_rule = replace(crawl_rule, 'xbiqugu.net', 'xbiqugu.la'); + +delete +from sys_menu +where menu_id = 104; + +delete +from sys_menu +where menu_id = 57; \ No newline at end of file diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index c590f48..dbe7fd6 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -14,18 +14,14 @@ org.springframework.boot spring-boot-starter-parent - 2.1.18.RELEASE + 2.7.18 - UTF-8 - UTF-8 - 1.8 + 17 1.7 - 5.22.0 - 3.0.0 - 2.15.1 + 5.5.1 @@ -60,35 +56,24 @@ net.sourceforge.nekohtml nekohtml + + + org.hibernate.validator + hibernate-validator + mysql mysql-connector-java 8.0.29 - - org.mybatis - mybatis - 3.5.6 - org.mybatis.spring.boot mybatis-spring-boot-starter 1.1.1 - - - com.alibaba - druid - 1.2.9 - - - org.apache.commons - commons-lang3 - 3.6 - commons-configuration commons-configuration @@ -138,6 +123,12 @@ org.apache.velocity velocity 1.7 + + + commons-lang + commons-lang + + @@ -166,6 +157,12 @@ io.springfox springfox-swagger2 2.6.1 + + + guava + com.google.guava + + io.springfox @@ -195,24 +192,29 @@ org.apache.commons commons-text 1.4 + + + commons-lang3 + org.apache.commons + + + - io.shardingsphere - sharding-jdbc-spring-boot-starter - ${sharding.jdbc.version} + org.apache.shardingsphere + shardingsphere-jdbc + ${shardingsphere-jdbc.version} - - io.shardingsphere - sharding-jdbc-spring-namespace - ${sharding.jdbc.version} + org.yaml + snakeyaml + 2.2 - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} + com.h2database + h2 + runtime diff --git a/novel-admin/src/main/java/com/java2nb/common/aspect/WebLogAspect.java b/novel-admin/src/main/java/com/java2nb/common/aspect/WebLogAspect.java index 889fdb6..0d6dce5 100644 --- a/novel-admin/src/main/java/com/java2nb/common/aspect/WebLogAspect.java +++ b/novel-admin/src/main/java/com/java2nb/common/aspect/WebLogAspect.java @@ -1,19 +1,16 @@ package com.java2nb.common.aspect; -import com.java2nb.common.utils.HttpContextUtils; +import com.java2nb.common.utils.IPUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; -import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import sun.net.util.IPAddressUtil; import javax.servlet.http.HttpServletRequest; -import java.lang.reflect.Method; import java.util.Arrays; @Aspect @@ -37,11 +34,10 @@ public class WebLogAspect { logger.info("请求地址 : " + request.getRequestURL().toString()); logger.info("HTTP METHOD : " + request.getMethod()); // 获取真实的ip地址 - //logger.info("IP : " + IPAddressUtil.getClientIpAddress(request)); + logger.info("IP : " + IPUtils.getIpAddr(request)); logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." - + joinPoint.getSignature().getName()); + + joinPoint.getSignature().getName()); logger.info("参数 : " + Arrays.toString(joinPoint.getArgs())); -// loggger.info("参数 : " + joinPoint.getArgs()); } diff --git a/novel-admin/src/main/java/com/java2nb/common/config/DruidDBConfig.java b/novel-admin/src/main/java/com/java2nb/common/config/DruidDBConfig.java deleted file mode 100644 index 92a2383..0000000 --- a/novel-admin/src/main/java/com/java2nb/common/config/DruidDBConfig.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.java2nb.common.config; -import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.druid.support.http.StatViewServlet; -import com.alibaba.druid.support.http.WebStatFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - -import javax.sql.DataSource; -import java.sql.SQLException; - -/** - * Created by PrimaryKey on 17/2/4. - */ -@SuppressWarnings("AlibabaRemoveCommentedCode") -@Configuration -public class DruidDBConfig { - private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class); - @Value("${spring.datasource.url}") - private String dbUrl; - - @Value("${spring.datasource.username}") - private String username; - - @Value("${spring.datasource.password}") - private String password; - - @Value("${spring.datasource.driverClassName}") - private String driverClassName; - - @Value("${spring.datasource.initialSize}") - private int initialSize; - - @Value("${spring.datasource.minIdle}") - private int minIdle; - - @Value("${spring.datasource.maxActive}") - private int maxActive; - - @Value("${spring.datasource.maxWait}") - private int maxWait; - - @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") - private int timeBetweenEvictionRunsMillis; - - @Value("${spring.datasource.minEvictableIdleTimeMillis}") - private int minEvictableIdleTimeMillis; - - @Value("${spring.datasource.validationQuery}") - private String validationQuery; - - @Value("${spring.datasource.testWhileIdle}") - private boolean testWhileIdle; - - @Value("${spring.datasource.testOnBorrow}") - private boolean testOnBorrow; - - @Value("${spring.datasource.testOnReturn}") - private boolean testOnReturn; - - @Value("${spring.datasource.poolPreparedStatements}") - private boolean poolPreparedStatements; - - @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}") - private int maxPoolPreparedStatementPerConnectionSize; - - @Value("${spring.datasource.filters}") - private String filters; - - @Value("{spring.datasource.connectionProperties}") - private String connectionProperties; - - @Bean(initMethod = "init", destroyMethod = "close") //声明其为Bean实例 - @Primary //在同样的DataSource中,首先使用被标注的DataSource - public DataSource dataSource() { - DruidDataSource datasource = new DruidDataSource(); - - datasource.setUrl(this.dbUrl); - datasource.setUsername(username); - datasource.setPassword(password); - datasource.setDriverClassName(driverClassName); - - //configuration - datasource.setInitialSize(initialSize); - datasource.setMinIdle(minIdle); - datasource.setMaxActive(maxActive); - datasource.setMaxWait(maxWait); - datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); - datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); - datasource.setValidationQuery(validationQuery); - datasource.setTestWhileIdle(testWhileIdle); - datasource.setTestOnBorrow(testOnBorrow); - datasource.setTestOnReturn(testOnReturn); - datasource.setPoolPreparedStatements(poolPreparedStatements); - datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); - try { - datasource.setFilters(filters); - } catch (SQLException e) { - logger.error("druid configuration initialization filter", e); - } - datasource.setConnectionProperties(connectionProperties); - - return datasource; - } - - @Bean - public ServletRegistrationBean druidServlet() { - ServletRegistrationBean reg = new ServletRegistrationBean(); - reg.setServlet(new StatViewServlet()); - reg.addUrlMappings("/druid/*"); - reg.addInitParameter("allow", ""); //白名单 - return reg; - } - - @Bean public FilterRegistrationBean filterRegistrationBean() { - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); - filterRegistrationBean.setFilter(new WebStatFilter()); - filterRegistrationBean.addUrlPatterns("/*"); - filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); - filterRegistrationBean.addInitParameter("profileEnable", "true"); - filterRegistrationBean.addInitParameter("principalCookieName","USER_COOKIE"); - filterRegistrationBean.addInitParameter("principalSessionName","USER_SESSION"); - filterRegistrationBean.addInitParameter("DruidWebStatFilter","/*"); - return filterRegistrationBean; - } -} - diff --git a/novel-admin/src/main/java/com/java2nb/common/config/Swagger2Config.java b/novel-admin/src/main/java/com/java2nb/common/config/Swagger2Config.java deleted file mode 100644 index 90b912c..0000000 --- a/novel-admin/src/main/java/com/java2nb/common/config/Swagger2Config.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.java2nb.common.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.Contact; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -/** - * ${DESCRIPTION} - * - * @author xiongxy - * @create 2019-11-02 23:53 - */ -@EnableSwagger2 -@Configuration -public class Swagger2Config { - - @Bean - public Docket createRestApi() { - return new Docket(DocumentationType.SWAGGER_2) - .apiInfo(apiInfo()) - .select() - //为当前包路径 - .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.any()) - .build(); - } - - //构建 api文档的详细信息函数 - private ApiInfo apiInfo() { - return new ApiInfoBuilder() - //页面标题 - .title("功能测试") - //创建人 - .contact(new Contact("xiongxy", "1179705413@qq.com", "1179705413@qq.com")) - //版本号 - .version("1.0") - //描述 - .description("API 描述") - .build(); - } -} \ No newline at end of file diff --git a/novel-admin/src/main/java/com/java2nb/common/dao/GeneratorMapper.java b/novel-admin/src/main/java/com/java2nb/common/dao/GeneratorMapper.java index 38996bb..914affc 100644 --- a/novel-admin/src/main/java/com/java2nb/common/dao/GeneratorMapper.java +++ b/novel-admin/src/main/java/com/java2nb/common/dao/GeneratorMapper.java @@ -9,25 +9,25 @@ import java.util.Map; public interface GeneratorMapper { @Select( - "select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables" + "select table_name tableName, engine, table_comment tableComment, create_time createTime from tables" + " where table_schema = 'novel_plus' and table_name like concat('%',#{tableName},'%')") List> list(@Param("tableName") String tableName); - @Select("select count(*) from information_schema.tables where table_schema = 'novel_plus'") + @Select("select count(*) from tables where table_schema = 'novel_plus'") int count(Map map); @Select( - "select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables \r\n" + "select table_name tableName, engine, table_comment tableComment, create_time createTime from tables \r\n" + " where table_schema = 'novel_plus' and table_name = #{tableName}") Map get(String tableName); @Select( - "select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from information_schema.columns\r\n" + "select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from columns\r\n" + " where table_name = #{tableName} and table_schema = 'novel_plus' order by ordinal_position") List> listColumns(String tableName); @Select( - "select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from information_schema.columns\r\n" + "select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from columns\r\n" + " where table_name = #{tableName} and table_schema = 'novel_plus' and column_key = 'PRI' limit 1") Map getPriColumn(String tableName); } diff --git a/novel-admin/src/main/java/com/java2nb/common/exception/MainsiteErrorController.java b/novel-admin/src/main/java/com/java2nb/common/exception/MainsiteErrorController.java index 46da1fd..1a9fc10 100644 --- a/novel-admin/src/main/java/com/java2nb/common/exception/MainsiteErrorController.java +++ b/novel-admin/src/main/java/com/java2nb/common/exception/MainsiteErrorController.java @@ -2,32 +2,27 @@ package com.java2nb.common.exception; import com.java2nb.common.utils.R; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.error.ErrorAttributes; import org.springframework.boot.web.servlet.error.ErrorController; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.util.Map; @RestController public class MainsiteErrorController implements ErrorController { - private Logger logger = LoggerFactory.getLogger(getClass()); + private static final String ERROR_PATH = "/error"; @Autowired ErrorAttributes errorAttributes; @RequestMapping( - value = {ERROR_PATH}, - produces = {"text/html"} + value = {ERROR_PATH}, + produces = {"text/html"} ) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { int code = response.getStatus(); @@ -58,9 +53,4 @@ public class MainsiteErrorController implements ErrorController { } } - @Override - public String getErrorPath() { - // TODO Auto-generated method stub - return ERROR_PATH; - } } \ No newline at end of file diff --git a/novel-admin/src/main/java/com/java2nb/common/utils/JSONUtils.java b/novel-admin/src/main/java/com/java2nb/common/utils/JSONUtils.java index 4575bd4..7fc193f 100644 --- a/novel-admin/src/main/java/com/java2nb/common/utils/JSONUtils.java +++ b/novel-admin/src/main/java/com/java2nb/common/utils/JSONUtils.java @@ -1,6 +1,5 @@ package com.java2nb.common.utils; -import com.alibaba.druid.util.StringUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; @@ -8,79 +7,80 @@ import java.util.HashMap; import java.util.Map; public class JSONUtils { - /** - * Bean对象转JSON - * - * @param object - * @param dataFormatString - * @return - */ - public static String beanToJson(Object object, String dataFormatString) { - if (object != null) { - if (StringUtils.isEmpty(dataFormatString)) { - return JSONObject.toJSONString(object); - } - return JSON.toJSONStringWithDateFormat(object, dataFormatString); - } else { - return null; - } - } - /** - * Bean对象转JSON - * - * @param object - * @return - */ - public static String beanToJson(Object object) { - if (object != null) { - return JSON.toJSONString(object); - } else { - return null; - } - } + /** + * Bean对象转JSON + * + * @param object + * @param dataFormatString + * @return + */ + public static String beanToJson(Object object, String dataFormatString) { + if (object != null) { + if (StringUtils.isEmpty(dataFormatString)) { + return JSONObject.toJSONString(object); + } + return JSON.toJSONStringWithDateFormat(object, dataFormatString); + } else { + return null; + } + } - /** - * String转JSON字符串 - * - * @param key - * @param value - * @return - */ - public static String stringToJsonByFastjson(String key, String value) { - if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { - return null; - } - Map map = new HashMap(16); - map.put(key, value); - return beanToJson(map, null); - } + /** + * Bean对象转JSON + * + * @param object + * @return + */ + public static String beanToJson(Object object) { + if (object != null) { + return JSON.toJSONString(object); + } else { + return null; + } + } - /** - * 将json字符串转换成对象 - * - * @param json - * @param clazz - * @return - */ - public static Object jsonToBean(String json, Object clazz) { - if (StringUtils.isEmpty(json) || clazz == null) { - return null; - } - return JSON.parseObject(json, clazz.getClass()); - } + /** + * String转JSON字符串 + * + * @param key + * @param value + * @return + */ + public static String stringToJsonByFastjson(String key, String value) { + if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { + return null; + } + Map map = new HashMap(16); + map.put(key, value); + return beanToJson(map, null); + } - /** - * json字符串转map - * - * @param json - * @return - */ - @SuppressWarnings("unchecked") - public static Map jsonToMap(String json) { - if (StringUtils.isEmpty(json)) { - return null; - } - return JSON.parseObject(json, Map.class); - } + /** + * 将json字符串转换成对象 + * + * @param json + * @param clazz + * @return + */ + public static Object jsonToBean(String json, Object clazz) { + if (StringUtils.isEmpty(json) || clazz == null) { + return null; + } + return JSON.parseObject(json, clazz.getClass()); + } + + /** + * json字符串转map + * + * @param json + * @return + */ + @SuppressWarnings("unchecked") + public static Map jsonToMap(String json) { + if (StringUtils.isEmpty(json)) { + return null; + } + return JSON.parseObject(json, Map.class); + } } diff --git a/novel-admin/src/main/resources/application-dev.yml b/novel-admin/src/main/resources/application-dev.yml index 0ea1099..2ad7bd3 100644 --- a/novel-admin/src/main/resources/application-dev.yml +++ b/novel-admin/src/main/resources/application-dev.yml @@ -8,91 +8,13 @@ logging: com.java2nb: debug spring: datasource: - type: com.alibaba.druid.pool.DruidDataSource - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true - username: root - password: test123456 - #password: - initialSize: 1 - minIdle: 3 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 30000 - validationQuery: select 'x' - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - # 打开PSCache,并且指定每个连接上PSCache的大小 - poolPreparedStatements: true - maxPoolPreparedStatementPerConnectionSize: 20 - # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 - filters: stat,slf4j - # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 - connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 - # 合并多个DruidDataSource的监控数据 - #useGlobalDataSourceStat: true + driverClassName: org.apache.shardingsphere.driver.ShardingSphereDriver + url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml redis: host: 127.0.0.1 port: 6379 password: test123456 # 连接超时时间(毫秒) timeout: 10000 - jedis: - pool: - # 连接池中的最大空闲连接 - max-idle: 8 - # 连接池中的最小空闲连接 - min-idle: 10 - # 连接池最大连接数(使用负值表示没有限制) - max-active: 100 - # 连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: -1 - -####使用shardingJdbc时, -####所有的jdbcType都不能是LONGVARCHAR,否则会导致java.io.NotSerializableException: java.io.StringReader错误 -##### 应该替换所有的 LONGVARCHAR 类型为VARCHAR - -sharding: - jdbc: - datasource: - names: ds0,ds1 - ds0: - type: com.zaxxer.hikari.HikariDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 - ds1: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.jdbc.Driver - url: jdbc:mysql://localhost:3306/information_schema?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 - config: - sharding: - props: - sql.show: true - tables: - book_content: #book_content表 - key-generator-column-name: id #主键 - actual-data-nodes: ds${0}.book_content${0..9} #数据节点 - # database-strategy: #分库策略 - # inline: - # sharding-column: book_id - # algorithm-expression: ds${book_id % 10} - table-strategy: #分表策略 - inline: - shardingColumn: index_id - algorithm-expression: book_content${index_id % 10} - tables: - actual-data-nodes: ds${1}.tables - columns: - actual-data-nodes: ds${1}.columns - default-data-source-name: ds0 \ No newline at end of file diff --git a/novel-admin/src/main/resources/application-prod.yml b/novel-admin/src/main/resources/application-prod.yml index bb63df2..aba7d84 100644 --- a/novel-admin/src/main/resources/application-prod.yml +++ b/novel-admin/src/main/resources/application-prod.yml @@ -8,85 +8,13 @@ logging: com.java2nb: error spring: datasource: - type: com.alibaba.druid.pool.DruidDataSource - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true - username: root - password: test123456 - #password: - initialSize: 1 - minIdle: 3 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 30000 - validationQuery: select 'x' - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - # 打开PSCache,并且指定每个连接上PSCache的大小 - poolPreparedStatements: true - maxPoolPreparedStatementPerConnectionSize: 20 - # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 - filters: stat,slf4j - # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 - connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 - # 合并多个DruidDataSource的监控数据 - #useGlobalDataSourceStat: true + driverClassName: org.apache.shardingsphere.driver.ShardingSphereDriver + url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml redis: host: 127.0.0.1 port: 6379 - password: test + password: test123456 # 连接超时时间(毫秒) timeout: 10000 - jedis: - pool: - # 连接池中的最大空闲连接 - max-idle: 8 - # 连接池中的最小空闲连接 - min-idle: 10 - # 连接池最大连接数(使用负值表示没有限制) - max-active: 100 - # 连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: -1 -####使用shardingJdbc时, -####所有的jdbcType都不能是LONGVARCHAR,否则会导致java.io.NotSerializableException: java.io.StringReader错误 -##### 应该替换所有的 LONGVARCHAR 类型为VARCHAR - -sharding: - jdbc: - datasource: - names: ds0 #,ds1 - ds0: - type: com.zaxxer.hikari.HikariDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 - # ds1: - # type: com.alibaba.druid.pool.DruidDataSource - # driver-class-name: com.mysql.jdbc.Driver - # url: jdbc:mysql://localhost:3306/novel_plus2 - # username: root - # password: test123456 - config: - sharding: - props: - sql.show: true - tables: - book_content: #book_content表 - key-generator-column-name: id #主键 - actual-data-nodes: ds${0}.book_content${0..9} #数据节点 - # database-strategy: #分库策略 - # inline: - # sharding-column: book_id - # algorithm-expression: ds${book_id % 10} - table-strategy: #分表策略 - inline: - shardingColumn: index_id - algorithm-expression: book_content${index_id % 10} diff --git a/novel-common/pom.xml b/novel-common/pom.xml index fecee4a..5b968e2 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -52,18 +52,16 @@ - - + - io.shardingsphere - sharding-jdbc-spring-boot-starter - ${sharding.jdbc.version} + org.apache.shardingsphere + shardingsphere-jdbc + ${shardingsphere-jdbc.version} - - io.shardingsphere - sharding-jdbc-spring-namespace - ${sharding.jdbc.version} + com.h2database + h2 + runtime @@ -117,6 +115,12 @@ true + + + org.hibernate.validator + hibernate-validator + + io.github.xxyopen xxy-model diff --git a/novel-common/src/main/resources/application-common-dev.yml b/novel-common/src/main/resources/application-common-dev.yml index 4f21870..cd4dc74 100644 --- a/novel-common/src/main/resources/application-common-dev.yml +++ b/novel-common/src/main/resources/application-common-dev.yml @@ -23,49 +23,8 @@ spring: #连接超时时间(毫秒) timeout: 30000 datasource: - url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 - driver-class-name: com.mysql.cj.jdbc.Driver - - -####使用shardingJdbc时, -####所有的jdbcType都不能是LONGVARCHAR,否则会导致java.io.NotSerializableException: java.io.StringReader错误 -##### 应该替换所有的 LONGVARCHAR 类型为VARCHAR - -sharding: - jdbc: - datasource: - names: ds0 #,ds1 - ds0: - type: com.zaxxer.hikari.HikariDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 - # ds1: - # type: com.alibaba.druid.pool.DruidDataSource - # driver-class-name: com.mysql.jdbc.Driver - # url: jdbc:mysql://localhost:3306/novel_plus2 - # username: root - # password: test123456 - config: - sharding: - props: - sql.show: true - tables: - book_content: #book_content表 - key-generator-column-name: id #主键 - actual-data-nodes: ds${0}.book_content${0..9} #数据节点 - # database-strategy: #分库策略 - # inline: - # sharding-column: book_id - # algorithm-expression: ds${book_id % 10} - table-strategy: #分表策略 - inline: - shardingColumn: index_id - algorithm-expression: book_content${index_id % 10} - + url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml + driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver content: save: diff --git a/novel-common/src/main/resources/application-common.yml b/novel-common/src/main/resources/application-common.yml index 08d4b46..b23e73b 100644 --- a/novel-common/src/main/resources/application-common.yml +++ b/novel-common/src/main/resources/application-common.yml @@ -27,6 +27,8 @@ mybatis: logging: config: classpath:logback-boot.xml +pagehelper: + helper-dialect: mysql diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index 64a5b68..6f8c74c 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -21,6 +21,12 @@ novel-common + + org.yaml + snakeyaml + 2.2 + + org.springframework.boot spring-boot-starter-security @@ -29,7 +35,6 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java b/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java index 1fd998c..c15cdae 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java @@ -14,10 +14,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.time.DateUtils; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.stereotype.Component; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; +import javax.servlet.ServletContext; import java.util.Date; import java.util.List; import java.util.Map; @@ -26,10 +26,10 @@ import java.util.concurrent.TimeUnit; /** * @author Administrator */ -@WebListener +@Component @Slf4j @RequiredArgsConstructor -public class StarterListener implements ServletContextListener { +public class StarterListener implements ServletContextInitializer { private final BookService bookService; @@ -41,7 +41,7 @@ public class StarterListener implements ServletContextListener { private int updateThreadCount; @Override - public void contextInitialized(ServletContextEvent sce) { + public void onStartup(ServletContext servletContext) { for (int i = 0; i < updateThreadCount; i++) { new Thread(() -> { log.info("程序启动,开始执行自动更新线程。。。"); diff --git a/novel-crawl/src/main/resources/application.yml b/novel-crawl/src/main/resources/application.yml index b4908fe..0979161 100644 --- a/novel-crawl/src/main/resources/application.yml +++ b/novel-crawl/src/main/resources/application.yml @@ -8,7 +8,9 @@ server: spring: profiles: active: dev - + config: + use-legacy-processing: true + #登录用户名密码 admin: username: admin diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 5f0876f..1c8c2c2 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -20,6 +20,12 @@ novel-common + + org.yaml + snakeyaml + 2.2 + + io.jsonwebtoken @@ -48,7 +54,6 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} diff --git a/novel-front/src/main/java/com/java2nb/novel/core/listener/StarterListener.java b/novel-front/src/main/java/com/java2nb/novel/core/listener/StarterListener.java index 41d5a5f..96a6b48 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/listener/StarterListener.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/listener/StarterListener.java @@ -5,36 +5,34 @@ import com.java2nb.novel.entity.WebsiteInfo; import com.java2nb.novel.mapper.WebsiteInfoMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.stereotype.Component; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; +import javax.servlet.ServletContext; /** * 启动监听器 * * @author xiongxiaoyang */ -@WebListener +@Component @Slf4j @RequiredArgsConstructor -public class StarterListener implements ServletContextListener { +public class StarterListener implements ServletContextInitializer { private final WebsiteProperties websiteProperties; - private final WebsiteInfoMapper websiteInfoMapper; @Override - public void contextInitialized(ServletContextEvent sce) { - sce.getServletContext() - .setAttribute("website", websiteInfoMapper.selectByPrimaryKey(1L).orElse(new WebsiteInfo() {{ - setName(websiteProperties.getName()); - setDomain(websiteProperties.getDomain()); - setKeyword(websiteProperties.getKeyword()); - setDescription(websiteProperties.getDescription()); - setQq(websiteProperties.getQq()); - setLogo("/images/logo.png"); - setLogoDark("/images/logo_white.png"); - }})); + public void onStartup(ServletContext servletContext) { + servletContext.setAttribute("website", websiteInfoMapper.selectByPrimaryKey(1L).orElse(new WebsiteInfo() {{ + setName(websiteProperties.getName()); + setDomain(websiteProperties.getDomain()); + setKeyword(websiteProperties.getKeyword()); + setDescription(websiteProperties.getDescription()); + setQq(websiteProperties.getQq()); + setLogo("/images/logo.png"); + setLogoDark("/images/logo_white.png"); + }})); } } diff --git a/novel-front/src/main/resources/application.yml b/novel-front/src/main/resources/application.yml index 5261537..26cb4c3 100644 --- a/novel-front/src/main/resources/application.yml +++ b/novel-front/src/main/resources/application.yml @@ -5,6 +5,8 @@ spring: profiles: active: dev include: website,alipay,oss + config: + use-legacy-processing: true jwt: secret: novel!#20191230 diff --git a/pom.xml b/pom.xml index 80455b9..d91feb3 100644 --- a/pom.xml +++ b/pom.xml @@ -20,14 +20,14 @@ org.springframework.boot spring-boot-starter-parent - 2.1.18.RELEASE + 2.7.18 UTF-8 UTF-8 - 1.8 + 17 true 8.0.29 2.1.4 @@ -40,12 +40,11 @@ 6.3.1 1.4.1.RELEASE 3.12.5 - 3.0.0 + 5.5.1 3.16.3 1.5 4.35.139.ALL 1.0.0 - 2.15.1 From af1237e2d7428c77f8da5ef9a2396258e0f26741 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 15 Mar 2025 15:13:36 +0800 Subject: [PATCH 23/95] =?UTF-8?q?build:=20Java=E7=89=88=E6=9C=AC=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E5=88=B021?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-admin/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index dbe7fd6..36fb42b 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -19,7 +19,7 @@ - 17 + 21 1.7 5.5.1 diff --git a/pom.xml b/pom.xml index d91feb3..5030b48 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ UTF-8 UTF-8 - 17 + 21 true 8.0.29 2.1.4 From 81c1514a21a86a38f498e4a4db2995211f4e9f52 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 15 Mar 2025 17:25:10 +0800 Subject: [PATCH 24/95] =?UTF-8?q?build:=20=E6=9E=84=E5=BB=BA=E7=94=9F?= =?UTF-8?q?=E4=BA=A7=E7=8E=AF=E5=A2=83=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/shardingsphere-jdbc.yml | 4 +- novel-admin/pom.xml | 5 ++ .../main/build/config/application-prod.yml | 11 ---- .../src/main/resources/application-dev.yml | 3 - .../src/main/resources/application-prod.yml | 3 - .../src/main/resources/application.yml | 5 +- .../main/resources/application-common-dev.yml | 15 +---- .../resources/application-common-prod.yml | 57 +------------------ .../src/main/resources/application-common.yml | 3 + novel-crawl/pom.xml | 5 ++ .../build/config/application-common-prod.yml | 15 ----- novel-front/pom.xml | 5 ++ .../build/config/application-common-prod.yml | 14 ----- 13 files changed, 26 insertions(+), 119 deletions(-) diff --git a/config/shardingsphere-jdbc.yml b/config/shardingsphere-jdbc.yml index 5f12200..d7cd327 100644 --- a/config/shardingsphere-jdbc.yml +++ b/config/shardingsphere-jdbc.yml @@ -34,7 +34,7 @@ rules: tableStrategy: standard: # 分片列名称 - shardingColumn: chapter_id + shardingColumn: index_id # 分片算法名称 shardingAlgorithmName: bookContentSharding @@ -44,7 +44,7 @@ rules: type: INLINE props: # 分片算法的行表达式 - algorithm-expression: book_content${chapter_id % 10} + algorithm-expression: book_content${index_id % 10} diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index 36fb42b..5033d3e 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -284,6 +284,11 @@ + + + + + diff --git a/novel-admin/src/main/build/config/application-prod.yml b/novel-admin/src/main/build/config/application-prod.yml index 73d0c2f..5f7b883 100644 --- a/novel-admin/src/main/build/config/application-prod.yml +++ b/novel-admin/src/main/build/config/application-prod.yml @@ -2,19 +2,8 @@ server: port: 8088 spring: - datasource: - url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 redis: host: 127.0.0.1 port: 6379 password: test123456 -sharding: - jdbc: - datasource: - ds0: - jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 diff --git a/novel-admin/src/main/resources/application-dev.yml b/novel-admin/src/main/resources/application-dev.yml index 2ad7bd3..0efd72e 100644 --- a/novel-admin/src/main/resources/application-dev.yml +++ b/novel-admin/src/main/resources/application-dev.yml @@ -7,9 +7,6 @@ logging: root: info com.java2nb: debug spring: - datasource: - driverClassName: org.apache.shardingsphere.driver.ShardingSphereDriver - url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml redis: host: 127.0.0.1 port: 6379 diff --git a/novel-admin/src/main/resources/application-prod.yml b/novel-admin/src/main/resources/application-prod.yml index aba7d84..0fab20d 100644 --- a/novel-admin/src/main/resources/application-prod.yml +++ b/novel-admin/src/main/resources/application-prod.yml @@ -7,9 +7,6 @@ logging: root: error com.java2nb: error spring: - datasource: - driverClassName: org.apache.shardingsphere.driver.ShardingSphereDriver - url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml redis: host: 127.0.0.1 port: 6379 diff --git a/novel-admin/src/main/resources/application.yml b/novel-admin/src/main/resources/application.yml index 7c2fd02..5cc1028 100644 --- a/novel-admin/src/main/resources/application.yml +++ b/novel-admin/src/main/resources/application.yml @@ -9,6 +9,9 @@ server: # basic: # enabled: false spring: + datasource: + driverClassName: org.apache.shardingsphere.driver.ShardingSphereDriver + url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml thymeleaf: mode: LEGACYHTML5 cache: false @@ -23,7 +26,7 @@ spring: multipart: max-file-size: 100MB max-request-size: 100MB - + devtools: restart: enabled: true diff --git a/novel-common/src/main/resources/application-common-dev.yml b/novel-common/src/main/resources/application-common-dev.yml index cd4dc74..e44d19a 100644 --- a/novel-common/src/main/resources/application-common-dev.yml +++ b/novel-common/src/main/resources/application-common-dev.yml @@ -10,21 +10,8 @@ spring: port: 6379 #Redis服务器连接密码 password: test123456 - jedis: - pool: - #连接池最大连接数(使用负值表示没有限制) - max-active: 8 - #连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: 1 - #连接池最大阻塞等待时间(使用负值表示没有限制) - max-idle: 8 - #连接池中的最小空闲连接 - min-idle: 0 #连接超时时间(毫秒) - timeout: 30000 - datasource: - url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml - driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver + timeout: 10000 content: save: diff --git a/novel-common/src/main/resources/application-common-prod.yml b/novel-common/src/main/resources/application-common-prod.yml index df2b262..7a8d8b3 100644 --- a/novel-common/src/main/resources/application-common-prod.yml +++ b/novel-common/src/main/resources/application-common-prod.yml @@ -9,63 +9,8 @@ spring: #Redis服务器连接端口 port: 6379 #Redis服务器连接密码 - password: test - jedis: - pool: - #连接池最大连接数(使用负值表示没有限制) - max-active: 8 - #连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: 1 - #连接池最大阻塞等待时间(使用负值表示没有限制) - max-idle: 8 - #连接池中的最小空闲连接 - min-idle: 0 - #连接超时时间(毫秒) - timeout: 30000 - datasource: - url: jdbc:mysql://127.0.0.1:3306/novel_biz?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root password: test123456 - driver-class-name: com.mysql.cj.jdbc.Driver - - -####使用shardingJdbc时, -####所有的jdbcType都不能是LONGVARCHAR,否则会导致java.io.NotSerializableException: java.io.StringReader错误 -##### 应该替换所有的 LONGVARCHAR 类型为VARCHAR - -sharding: - jdbc: - datasource: - names: ds0 #,ds1 - ds0: - type: com.zaxxer.hikari.HikariDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 - # ds1: - # type: com.alibaba.druid.pool.DruidDataSource - # driver-class-name: com.mysql.jdbc.Driver - # url: jdbc:mysql://localhost:3306/novel_plus2 - # username: root - # password: test123456 - config: - sharding: - props: - sql.show: true - tables: - book_content: #book_content表 - key-generator-column-name: id #主键 - actual-data-nodes: ds${0}.book_content${0..9} #数据节点 - # database-strategy: #分库策略 - # inline: - # sharding-column: book_id - # algorithm-expression: ds${book_id % 10} - table-strategy: #分表策略 - inline: - shardingColumn: index_id - algorithm-expression: book_content${index_id % 10} - + timeout: 10000 logging: level: diff --git a/novel-common/src/main/resources/application-common.yml b/novel-common/src/main/resources/application-common.yml index b23e73b..be2c512 100644 --- a/novel-common/src/main/resources/application-common.yml +++ b/novel-common/src/main/resources/application-common.yml @@ -1,4 +1,7 @@ spring: + datasource: + url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml + driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver cache: ehcache: config: classpath:ehcache.xml diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index 6f8c74c..e47cd31 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -63,6 +63,11 @@ + + + + + diff --git a/novel-crawl/src/main/build/config/application-common-prod.yml b/novel-crawl/src/main/build/config/application-common-prod.yml index 86a6abd..b318604 100644 --- a/novel-crawl/src/main/build/config/application-common-prod.yml +++ b/novel-crawl/src/main/build/config/application-common-prod.yml @@ -4,26 +4,11 @@ server: #不分表的数据库配置 spring: - datasource: - url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: root redis: host: 127.0.0.1 port: 6379 password: test123456 -####使用shardingJdbc时, -####所有的jdbcType都不能是LONGVARCHAR,否则会导致java.io.NotSerializableException: java.io.StringReader错误 -##### 应该替换所有的 LONGVARCHAR 类型为VARCHAR -sharding: - jdbc: - datasource: - ds0: - jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 - #登录用户名密码 admin: username: admin diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 1c8c2c2..b0e92b1 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -84,6 +84,11 @@ + + + + + diff --git a/novel-front/src/main/build/config/application-common-prod.yml b/novel-front/src/main/build/config/application-common-prod.yml index f21795f..15d9be5 100644 --- a/novel-front/src/main/build/config/application-common-prod.yml +++ b/novel-front/src/main/build/config/application-common-prod.yml @@ -4,25 +4,11 @@ server: #不分表的数据库配置 spring: - datasource: - url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: root redis: host: 127.0.0.1 port: 6379 password: test123456 -####使用shardingJdbc时, -####所有的jdbcType都不能是LONGVARCHAR,否则会导致java.io.NotSerializableException: java.io.StringReader错误 -##### 应该替换所有的 LONGVARCHAR 类型为VARCHAR -sharding: - jdbc: - datasource: - ds0: - jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: test123456 pic: save: From 11978c2c9e03d9f5aa1d742f52ae48052eb66851 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 15 Mar 2025 19:29:37 +0800 Subject: [PATCH 25/95] =?UTF-8?q?build:=20v5.0.0=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-admin/pom.xml | 2 +- novel-common/pom.xml | 2 +- novel-crawl/pom.xml | 2 +- novel-front/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index 5033d3e..83a6042 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel-admin - 5.0.0-SNAPSHOT + 5.0.0 jar novel-admin diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 5b968e2..32bb22d 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.0-SNAPSHOT + 5.0.0 4.0.0 diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index e47cd31..68b2de6 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.0-SNAPSHOT + 5.0.0 4.0.0 diff --git a/novel-front/pom.xml b/novel-front/pom.xml index b0e92b1..21cc448 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.0-SNAPSHOT + 5.0.0 4.0.0 diff --git a/pom.xml b/pom.xml index 5030b48..907434a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel - 5.0.0-SNAPSHOT + 5.0.0 novel-common novel-front From 8d35aa80ab8551c19b111df25f7e0914c6be5d03 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 15 Mar 2025 19:51:43 +0800 Subject: [PATCH 26/95] =?UTF-8?q?build:=20=E4=BF=AE=E6=94=B9=E6=89=93?= =?UTF-8?q?=E5=8C=85=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/build/config/application-common-prod.yml | 8 ++++++-- .../src/main/build/config/application-common-prod.yml | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/novel-crawl/src/main/build/config/application-common-prod.yml b/novel-crawl/src/main/build/config/application-common-prod.yml index b318604..fd708fd 100644 --- a/novel-crawl/src/main/build/config/application-common-prod.yml +++ b/novel-crawl/src/main/build/config/application-common-prod.yml @@ -33,6 +33,10 @@ http: # 是否开启 HTTP 代理,true-开启,false-不开启 enabled: false # 代理 IP - ip: u493.kdltps.com + ip: us.swiftproxy.net # 代理端口号 - port: 15818 \ No newline at end of file + port: 7878 + # 代理用户名 + username: swiftproxy_u + # 代理密码 + password: swiftproxy_p \ No newline at end of file diff --git a/novel-front/src/main/build/config/application-common-prod.yml b/novel-front/src/main/build/config/application-common-prod.yml index 15d9be5..bcb1ab3 100644 --- a/novel-front/src/main/build/config/application-common-prod.yml +++ b/novel-front/src/main/build/config/application-common-prod.yml @@ -36,7 +36,11 @@ http: # 是否开启 HTTP 代理,true-开启,false-不开启 enabled: false # 代理 IP - ip: u493.kdltps.com + ip: us.swiftproxy.net # 代理端口号 - port: 15818 + port: 7878 + # 代理用户名 + username: swiftproxy_u + # 代理密码 + password: swiftproxy_p From d77ce5b4468616e2476a9e5cea5fea3ad86b6226 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 15 Mar 2025 23:35:47 +0800 Subject: [PATCH 27/95] =?UTF-8?q?build:=20Spring=20Boot=20=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E5=88=B0=203.4.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-common/pom.xml | 16 +---- .../java2nb/novel/core/utils/FileUtil.java | 2 +- .../com/java2nb/novel/core/utils/IpUtil.java | 2 +- .../novel/core/utils/RestTemplates.java | 38 +++++------ .../java2nb/novel/core/utils/SpringUtil.java | 37 +++++++++++ .../java/com/java2nb/novel/entity/User.java | 2 +- .../main/resources/application-common-dev.yml | 21 +++--- .../resources/application-common-prod.yml | 4 +- .../core/config/SecurityConfiguration.java | 64 ++++++++++--------- .../novel/core/listener/StarterListener.java | 2 +- .../novel/service/impl/CrawlServiceImpl.java | 2 +- .../src/main/resources/application-dev.yml | 4 +- .../src/main/resources/application-prod.yml | 4 +- .../src/main/resources/application.yml | 4 +- .../src/main/resources/logback-boot.xml | 37 +++++------ .../novel/controller/AuthorController.java | 4 +- .../novel/controller/BaseController.java | 3 +- .../novel/controller/BookController.java | 2 +- .../novel/controller/FileController.java | 4 +- .../novel/controller/PayController.java | 4 +- .../novel/controller/UserController.java | 2 +- .../novel/controller/page/PageController.java | 2 +- .../novel/core/config/FilterConfig.java | 2 +- .../novel/core/config/WebMvcConfig.java | 4 +- .../novel/core/filter/NovelFilter.java | 13 ++-- .../java2nb/novel/core/filter/XssFilter.java | 4 +- .../novel/core/listener/StarterListener.java | 2 +- .../java2nb/novel/core/utils/BrowserUtil.java | 3 +- .../java2nb/novel/core/utils/CookieUtil.java | 8 +-- .../novel/core/utils/ThreadLocalUtil.java | 1 - .../wrapper/XssHttpServletRequestWrapper.java | 8 +-- .../novel/service/impl/BookServiceImpl.java | 28 +++----- .../com/java2nb/novel/vo/BookCommentVO.java | 1 - .../src/main/resources/application-dev.yml | 4 +- .../src/main/resources/application-prod.yml | 4 +- .../src/main/resources/logback-boot.xml | 39 ++++++----- .../mybatis/mapping/BookCommentMapper.xml | 2 +- .../resources/mybatis/mapping/BookMapper.xml | 3 + pom.xml | 7 +- 39 files changed, 201 insertions(+), 192 deletions(-) create mode 100644 novel-common/src/main/java/com/java2nb/novel/core/utils/SpringUtil.java diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 32bb22d..462c5e9 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -71,11 +71,6 @@ pagehelper-spring-boot-starter ${pagehelper.version} - - com.cuisongliu - orderbyhelper-spring-boot-starter - ${orderbyhelper.version} - org.apache.commons @@ -84,15 +79,8 @@ - org.apache.httpcomponents - httpclient - 4.5.14 - - - commons-logging - commons-logging - - + org.apache.httpcomponents.client5 + httpclient5 diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java index cbe1b06..f64e4eb 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java @@ -5,7 +5,7 @@ import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.Charsets; -import org.apache.http.client.utils.DateUtils; +import org.apache.hc.client5.http.utils.DateUtils; import org.springframework.core.io.Resource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/IpUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/IpUtil.java index c7f92d2..754e93d 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/IpUtil.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/IpUtil.java @@ -1,6 +1,6 @@ package com.java2nb.novel.core.utils; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public class IpUtil { diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java index 58bf452..b7de405 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java @@ -3,21 +3,21 @@ package com.java2nb.novel.core.utils; import com.java2nb.novel.core.config.HttpProxyProperties; import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.TrustStrategy; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.socket.ConnectionSocketFactory; +import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.config.Registry; +import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.hc.core5.ssl.SSLContexts; +import org.apache.hc.core5.ssl.TrustStrategy; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; @@ -45,7 +45,7 @@ public class RestTemplates { TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; //忽略证书 - SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom() + SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial(null, acceptingTrustStrategy) .build(); @@ -69,10 +69,10 @@ public class RestTemplates { if (StringUtils.isNotBlank(httpProxyProperties.getUsername()) && StringUtils.isNotBlank( httpProxyProperties.getPassword())) { // 创建CredentialsProvider实例并添加代理认证信息 - CredentialsProvider provider = new BasicCredentialsProvider(); + BasicCredentialsProvider provider = new BasicCredentialsProvider(); UsernamePasswordCredentials credentials = new UsernamePasswordCredentials( - httpProxyProperties.getUsername(), httpProxyProperties.getPassword()); - provider.setCredentials(AuthScope.ANY, credentials); + httpProxyProperties.getUsername(), httpProxyProperties.getPassword().toCharArray()); + provider.setCredentials(new AuthScope(null, -1), credentials); clientBuilder.setDefaultCredentialsProvider(provider); } } diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/SpringUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/SpringUtil.java new file mode 100644 index 0000000..5c7ea6d --- /dev/null +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/SpringUtil.java @@ -0,0 +1,37 @@ +package com.java2nb.novel.core.utils; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class SpringUtil implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + public SpringUtil() { + } + + public void setApplicationContext(ApplicationContext applicationContext) { + if (SpringUtil.applicationContext == null) { + SpringUtil.applicationContext = applicationContext; + } + + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static Object getBean(String name) { + return getApplicationContext().getBean(name); + } + + public static T getBean(Class clazz) { + return (T)getApplicationContext().getBean(clazz); + } + + public static T getBean(String name, Class clazz) { + return (T)getApplicationContext().getBean(name, clazz); + } +} + diff --git a/novel-common/src/main/java/com/java2nb/novel/entity/User.java b/novel-common/src/main/java/com/java2nb/novel/entity/User.java index a3a1d5a..7da42eb 100644 --- a/novel-common/src/main/java/com/java2nb/novel/entity/User.java +++ b/novel-common/src/main/java/com/java2nb/novel/entity/User.java @@ -2,9 +2,9 @@ package com.java2nb.novel.entity; import io.github.xxyopen.web.valid.AddGroup; import io.github.xxyopen.web.valid.UpdateGroup; +import jakarta.validation.constraints.*; import javax.annotation.Generated; -import javax.validation.constraints.*; import java.util.Date; public class User { diff --git a/novel-common/src/main/resources/application-common-dev.yml b/novel-common/src/main/resources/application-common-dev.yml index e44d19a..003144c 100644 --- a/novel-common/src/main/resources/application-common-dev.yml +++ b/novel-common/src/main/resources/application-common-dev.yml @@ -1,17 +1,18 @@ spring: - profiles: - include: [ common ] + config: + import: classpath:application-common.yml main: allow-bean-definition-overriding: true #Redis服务器IP - redis: - host: 127.0.0.1 - #Redis服务器连接端口 - port: 6379 - #Redis服务器连接密码 - password: test123456 - #连接超时时间(毫秒) - timeout: 10000 + data: + redis: + host: 127.0.0.1 + #Redis服务器连接端口 + port: 6379 + #Redis服务器连接密码 + password: test123456 + #连接超时时间(毫秒) + timeout: 10000 content: save: diff --git a/novel-common/src/main/resources/application-common-prod.yml b/novel-common/src/main/resources/application-common-prod.yml index 7a8d8b3..7c99121 100644 --- a/novel-common/src/main/resources/application-common-prod.yml +++ b/novel-common/src/main/resources/application-common-prod.yml @@ -1,6 +1,6 @@ spring: - profiles: - include: [ common ] + config: + import: classpath:application-common.yml main: allow-bean-definition-overriding: true #Redis服务器IP diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/config/SecurityConfiguration.java b/novel-crawl/src/main/java/com/java2nb/novel/core/config/SecurityConfiguration.java index ff35ebc..f684fe4 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/config/SecurityConfiguration.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/config/SecurityConfiguration.java @@ -4,14 +4,15 @@ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; /** * SpringSecurity配置 @@ -21,7 +22,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @RequiredArgsConstructor -public class SecurityConfiguration extends WebSecurityConfigurerAdapter { +public class SecurityConfiguration { @Value("${admin.username}") private String username; @@ -29,39 +30,40 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Value("${admin.password}") private String password; - @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } - - @Override - public void configure(WebSecurity web) throws Exception { - super.configure(web); + @Bean + public InMemoryUserDetailsManager userDetailsService() { + UserDetails admin = User.builder() + .username(username) + .password(passwordEncoder().encode(password)) + .roles("ADMIN") + .build(); + return new InMemoryUserDetailsManager(admin); } - @Override - public void configure(AuthenticationManagerBuilder auth) throws Exception { + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) // 禁用 CSRF + .authorizeHttpRequests(auth -> auth + .requestMatchers("/css/**", "/favicon.ico").permitAll() // 允许访问静态资源 + .anyRequest().hasRole("ADMIN") // 其他请求需要 ADMIN 角色 + ) + .formLogin(form -> form + .loginPage("/login.html") // 自定义登录页面 + .loginProcessingUrl("/login") // 登录处理 URL + .permitAll() + ) + .logout(logout -> logout + .logoutUrl("/logout") // 登出 URL + .logoutSuccessUrl("/") // 登出成功后跳转的页面 + ) + .httpBasic(Customizer.withDefaults()); // 启用 HTTP Basic 认证 - User.UserBuilder builder = User.builder().passwordEncoder(passwordEncoder()::encode); - auth.inMemoryAuthentication().withUser(builder.username(username).password(password).roles("ADMIN").build()); + return http.build(); } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable() - .authorizeRequests() - .antMatchers("/css/**").permitAll() - .antMatchers("/favicon.ico").permitAll() - .antMatchers("/**").hasRole("ADMIN") - .and().formLogin().loginPage("/login.html").loginProcessingUrl("/login").permitAll() - .and().logout() - .logoutUrl("/logout") - .logoutSuccessUrl("/") - .and().httpBasic(); - - } - - -} +} \ No newline at end of file diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java b/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java index c15cdae..6d7f9cf 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/listener/StarterListener.java @@ -10,6 +10,7 @@ import com.java2nb.novel.entity.CrawlSource; import com.java2nb.novel.service.BookService; import com.java2nb.novel.service.CrawlService; import com.java2nb.novel.utils.Constants; +import jakarta.servlet.ServletContext; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.time.DateUtils; @@ -17,7 +18,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.stereotype.Component; -import javax.servlet.ServletContext; import java.util.Date; import java.util.List; import java.util.Map; diff --git a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java index 0e6f849..b3bc75b 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/service/impl/CrawlServiceImpl.java @@ -7,6 +7,7 @@ import com.java2nb.novel.core.cache.CacheService; import com.java2nb.novel.core.crawl.CrawlParser; import com.java2nb.novel.core.crawl.RuleBean; import com.java2nb.novel.core.enums.ResponseStatus; +import com.java2nb.novel.core.utils.SpringUtil; import com.java2nb.novel.entity.Book; import com.java2nb.novel.entity.CrawlSingleTask; import com.java2nb.novel.entity.CrawlSource; @@ -25,7 +26,6 @@ import io.github.xxyopen.util.IdWorker; import io.github.xxyopen.util.ThreadUtil; import io.github.xxyopen.web.exception.BusinessException; import io.github.xxyopen.web.util.BeanUtil; -import io.github.xxyopen.web.util.SpringUtil; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; diff --git a/novel-crawl/src/main/resources/application-dev.yml b/novel-crawl/src/main/resources/application-dev.yml index 4ea9fe8..f53bb81 100644 --- a/novel-crawl/src/main/resources/application-dev.yml +++ b/novel-crawl/src/main/resources/application-dev.yml @@ -1,3 +1,3 @@ spring: - profiles: - include: [common-dev] \ No newline at end of file + config: + import: classpath:application-common-dev.yml \ No newline at end of file diff --git a/novel-crawl/src/main/resources/application-prod.yml b/novel-crawl/src/main/resources/application-prod.yml index 54ce802..14d0afa 100644 --- a/novel-crawl/src/main/resources/application-prod.yml +++ b/novel-crawl/src/main/resources/application-prod.yml @@ -1,3 +1,3 @@ spring: - profiles: - include: [common-prod] \ No newline at end of file + config: + import: classpath:application-common-prod.yml \ No newline at end of file diff --git a/novel-crawl/src/main/resources/application.yml b/novel-crawl/src/main/resources/application.yml index 0979161..b4908fe 100644 --- a/novel-crawl/src/main/resources/application.yml +++ b/novel-crawl/src/main/resources/application.yml @@ -8,9 +8,7 @@ server: spring: profiles: active: dev - config: - use-legacy-processing: true - + #登录用户名密码 admin: username: admin diff --git a/novel-crawl/src/main/resources/logback-boot.xml b/novel-crawl/src/main/resources/logback-boot.xml index 05c7c83..2691bfd 100644 --- a/novel-crawl/src/main/resources/logback-boot.xml +++ b/novel-crawl/src/main/resources/logback-boot.xml @@ -12,9 +12,6 @@ - ${CONSOLE_LOG_PATTERN} UTF-8 @@ -22,43 +19,43 @@ - - + + - - logs/novel-crawl.log + + logs/novel-crawl.log - - + + - - logs/debug.%d.%i.log + + logs/debug.%d{yyyy-MM-dd}.%i.log 30 - - - 10MB - + + 10MB + + 1GB - - %d %p (%file:%line\)- %m%n - + %d %p (%file:%line\)- %m%n UTF-8 + + - + - + \ No newline at end of file diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java b/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java index c89d02f..2b4912e 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java @@ -12,11 +12,11 @@ import com.java2nb.novel.entity.AuthorIncomeDetail; import com.java2nb.novel.entity.Book; import com.java2nb.novel.service.AuthorService; import com.java2nb.novel.service.BookService; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; import java.util.Date; /** @@ -54,7 +54,7 @@ public class AuthorController extends BaseController{ * 发布小说 * */ @PostMapping("addBook") - public RestResult addBook(@RequestParam("bookDesc") String bookDesc,Book book,HttpServletRequest request){ + public RestResult addBook(@RequestParam("bookDesc") String bookDesc, Book book, HttpServletRequest request){ Author author = checkAuthor(request); diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/BaseController.java b/novel-front/src/main/java/com/java2nb/novel/controller/BaseController.java index 0df2607..3439135 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/BaseController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/BaseController.java @@ -3,11 +3,10 @@ package com.java2nb.novel.controller; import com.java2nb.novel.core.bean.UserDetails; import com.java2nb.novel.core.utils.CookieUtil; import com.java2nb.novel.core.utils.JwtTokenUtil; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; /** * @author 11797 diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java index 5581bb1..b5d1faf 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java @@ -15,11 +15,11 @@ import com.java2nb.novel.vo.BookVO; import io.github.xxyopen.model.page.PageBean; import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder; import io.github.xxyopen.model.resp.RestResult; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/FileController.java b/novel-front/src/main/java/com/java2nb/novel/controller/FileController.java index e696599..7f6f39c 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/FileController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/FileController.java @@ -10,6 +10,8 @@ import com.java2nb.novel.core.utils.RandomValidateCodeUtil; import io.github.xxyopen.model.resp.RestResult; import io.github.xxyopen.util.UUIDUtil; import io.github.xxyopen.web.exception.BusinessException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -19,8 +21,6 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.File; import java.util.Date; diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/PayController.java b/novel-front/src/main/java/com/java2nb/novel/controller/PayController.java index f5bb878..96d2e0f 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/PayController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/PayController.java @@ -12,6 +12,8 @@ import com.java2nb.novel.core.bean.UserDetails; import com.java2nb.novel.core.config.AlipayProperties; import com.java2nb.novel.core.utils.ThreadLocalUtil; import com.java2nb.novel.service.OrderService; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -19,8 +21,6 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.HashMap; diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/UserController.java b/novel-front/src/main/java/com/java2nb/novel/controller/UserController.java index 5357d9f..958db22 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/UserController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/UserController.java @@ -13,13 +13,13 @@ import com.java2nb.novel.service.UserService; import io.github.xxyopen.model.resp.RestResult; import io.github.xxyopen.web.valid.AddGroup; import io.github.xxyopen.web.valid.UpdateGroup; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java b/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java index bf4c69f..765b07e 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java @@ -8,6 +8,7 @@ import com.java2nb.novel.service.*; import com.java2nb.novel.vo.BookCommentVO; import com.java2nb.novel.vo.BookSettingVO; import io.github.xxyopen.model.page.PageBean; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -17,7 +18,6 @@ import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; -import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; diff --git a/novel-front/src/main/java/com/java2nb/novel/core/config/FilterConfig.java b/novel-front/src/main/java/com/java2nb/novel/core/config/FilterConfig.java index 7229594..9d73865 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/config/FilterConfig.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/config/FilterConfig.java @@ -2,13 +2,13 @@ package com.java2nb.novel.core.config; import com.java2nb.novel.core.filter.NovelFilter; import com.java2nb.novel.core.filter.XssFilter; +import jakarta.servlet.DispatcherType; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import javax.servlet.DispatcherType; import java.util.HashMap; import java.util.Map; diff --git a/novel-front/src/main/java/com/java2nb/novel/core/config/WebMvcConfig.java b/novel-front/src/main/java/com/java2nb/novel/core/config/WebMvcConfig.java index c535b6d..2d36783 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/config/WebMvcConfig.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/config/WebMvcConfig.java @@ -3,13 +3,13 @@ package com.java2nb.novel.core.config; import com.java2nb.novel.core.converter.DateConverter; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author xiongxiaoyang */ @Configuration -public class WebMvcConfig extends WebMvcConfigurerAdapter { +public class WebMvcConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new DateConverter()); diff --git a/novel-front/src/main/java/com/java2nb/novel/core/filter/NovelFilter.java b/novel-front/src/main/java/com/java2nb/novel/core/filter/NovelFilter.java index 88e3e6d..7de65dd 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/filter/NovelFilter.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/filter/NovelFilter.java @@ -4,13 +4,14 @@ import com.java2nb.novel.core.cache.CacheKey; import com.java2nb.novel.core.cache.CacheService; import com.java2nb.novel.core.utils.*; import io.github.xxyopen.util.UUIDUtil; -import io.github.xxyopen.web.util.SpringUtil; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; -import javax.servlet.*; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.*; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; /** * 项目核心过滤器 diff --git a/novel-front/src/main/java/com/java2nb/novel/core/filter/XssFilter.java b/novel-front/src/main/java/com/java2nb/novel/core/filter/XssFilter.java index 898ccb9..f285a48 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/filter/XssFilter.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/filter/XssFilter.java @@ -1,11 +1,11 @@ package com.java2nb.novel.core.filter; import com.java2nb.novel.core.wrapper.XssHttpServletRequestWrapper; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/novel-front/src/main/java/com/java2nb/novel/core/listener/StarterListener.java b/novel-front/src/main/java/com/java2nb/novel/core/listener/StarterListener.java index 96a6b48..2af02bd 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/listener/StarterListener.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/listener/StarterListener.java @@ -3,12 +3,12 @@ package com.java2nb.novel.core.listener; import com.java2nb.novel.core.config.WebsiteProperties; import com.java2nb.novel.entity.WebsiteInfo; import com.java2nb.novel.mapper.WebsiteInfoMapper; +import jakarta.servlet.ServletContext; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.stereotype.Component; -import javax.servlet.ServletContext; /** * 启动监听器 diff --git a/novel-front/src/main/java/com/java2nb/novel/core/utils/BrowserUtil.java b/novel-front/src/main/java/com/java2nb/novel/core/utils/BrowserUtil.java index 29915f4..be2bddb 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/utils/BrowserUtil.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/utils/BrowserUtil.java @@ -1,6 +1,7 @@ package com.java2nb.novel.core.utils; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; + import java.util.regex.Pattern; public class BrowserUtil { diff --git a/novel-front/src/main/java/com/java2nb/novel/core/utils/CookieUtil.java b/novel-front/src/main/java/com/java2nb/novel/core/utils/CookieUtil.java index 7fd4f0d..06b0954 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/utils/CookieUtil.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/utils/CookieUtil.java @@ -1,15 +1,15 @@ package com.java2nb.novel.core.utils; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * @author Administrator */ public class CookieUtil { - public static String getCookie(HttpServletRequest request,String key){ + public static String getCookie(HttpServletRequest request, String key){ Cookie[] cookies = request.getCookies(); if(cookies != null) { for (Cookie cookie : cookies) { diff --git a/novel-front/src/main/java/com/java2nb/novel/core/utils/ThreadLocalUtil.java b/novel-front/src/main/java/com/java2nb/novel/core/utils/ThreadLocalUtil.java index 0cc9da8..b830c6f 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/utils/ThreadLocalUtil.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/utils/ThreadLocalUtil.java @@ -2,7 +2,6 @@ package com.java2nb.novel.core.utils; import com.java2nb.novel.core.cache.CacheKey; import com.java2nb.novel.core.cache.CacheService; -import io.github.xxyopen.web.util.SpringUtil; /** * 模板操作工具类 diff --git a/novel-front/src/main/java/com/java2nb/novel/core/wrapper/XssHttpServletRequestWrapper.java b/novel-front/src/main/java/com/java2nb/novel/core/wrapper/XssHttpServletRequestWrapper.java index c99e459..6c7b102 100644 --- a/novel-front/src/main/java/com/java2nb/novel/core/wrapper/XssHttpServletRequestWrapper.java +++ b/novel-front/src/main/java/com/java2nb/novel/core/wrapper/XssHttpServletRequestWrapper.java @@ -1,11 +1,7 @@ package com.java2nb.novel.core.wrapper; -import org.apache.commons.lang3.StringUtils; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import java.util.Arrays; -import java.util.List; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; /** * XSS过滤处理 diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java index b625a2d..194908d 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java @@ -29,19 +29,16 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import tk.mybatis.orderbyhelper.OrderByHelper; import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import static com.java2nb.novel.mapper.BookCategoryDynamicSqlSupport.bookCategory; @@ -201,9 +198,6 @@ public class BookServiceImpl implements BookService { PageHelper.startPage(page, pageSize); - if (StringUtils.isNotBlank(params.getSort())) { - OrderByHelper.orderBy(params.getSort() + " desc"); - } return PageBuilder.build(bookMapper.searchByPage(params)); } @@ -231,23 +225,22 @@ public class BookServiceImpl implements BookService { @Override public List queryIndexList(Long bookId, String orderBy, Integer page, Integer pageSize) { - if (StringUtils.isNotBlank(orderBy)) { - OrderByHelper.orderBy(orderBy); - } if (page != null && pageSize != null) { PageHelper.startPage(page, pageSize); } - - SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, + QueryExpressionDSL.QueryExpressionWhereBuilder where = select( + BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.updateTime, BookIndexDynamicSqlSupport.isVip) .from(bookIndex) - .where(BookIndexDynamicSqlSupport.bookId, isEqualTo(bookId)) + .where(BookIndexDynamicSqlSupport.bookId, isEqualTo(bookId)); + if("index_num desc".equals(orderBy)){ + where.orderBy(BookIndexDynamicSqlSupport.indexNum.descending()); + } + return bookIndexMapper.selectMany(where .build() - .render(RenderingStrategies.MYBATIS3); - - return bookIndexMapper.selectMany(selectStatement); + .render(RenderingStrategies.MYBATIS3)); } @@ -384,7 +377,6 @@ public class BookServiceImpl implements BookService { @Override public PageBean listCommentByPage(Long userId, Long bookId, int page, int pageSize) { PageHelper.startPage(page, pageSize); - OrderByHelper.orderBy("t1.create_time desc"); return PageBuilder.build(bookCommentMapper.listCommentByPage(userId, bookId)); } diff --git a/novel-front/src/main/java/com/java2nb/novel/vo/BookCommentVO.java b/novel-front/src/main/java/com/java2nb/novel/vo/BookCommentVO.java index 5b1e3c4..1d553cf 100644 --- a/novel-front/src/main/java/com/java2nb/novel/vo/BookCommentVO.java +++ b/novel-front/src/main/java/com/java2nb/novel/vo/BookCommentVO.java @@ -6,7 +6,6 @@ import com.java2nb.novel.core.serialize.CommentUserNameSerialize; import com.java2nb.novel.entity.BookComment; import lombok.Data; -import javax.annotation.Generated; import java.util.Date; /** diff --git a/novel-front/src/main/resources/application-dev.yml b/novel-front/src/main/resources/application-dev.yml index f0dbf87..5eda262 100644 --- a/novel-front/src/main/resources/application-dev.yml +++ b/novel-front/src/main/resources/application-dev.yml @@ -1,6 +1,6 @@ spring: - profiles: - include: [ common-dev ] + config: + import: classpath:application-common-dev.yml pic: diff --git a/novel-front/src/main/resources/application-prod.yml b/novel-front/src/main/resources/application-prod.yml index f55090d..5378c0f 100644 --- a/novel-front/src/main/resources/application-prod.yml +++ b/novel-front/src/main/resources/application-prod.yml @@ -1,6 +1,6 @@ spring: - profiles: - include: [ common-prod ] + config: + import: classpath:application-common-prod.yml #静态文件路径配置 resources: diff --git a/novel-front/src/main/resources/logback-boot.xml b/novel-front/src/main/resources/logback-boot.xml index ccc3d13..35f35cb 100644 --- a/novel-front/src/main/resources/logback-boot.xml +++ b/novel-front/src/main/resources/logback-boot.xml @@ -12,9 +12,6 @@ - ${CONSOLE_LOG_PATTERN} UTF-8 @@ -22,43 +19,43 @@ - - + + - - logs/novel-front.log + + logs/novel-front.log - - + + - - logs/debug.%d.%i.log + + logs/debug.%d{yyyy-MM-dd}.%i.log 30 - - - 10MB - + + 10MB + + 1GB - - %d %p (%file:%line\)- %m%n - + %d %p (%file:%line\)- %m%n UTF-8 + + - + - + - + \ No newline at end of file diff --git a/novel-front/src/main/resources/mybatis/mapping/BookCommentMapper.xml b/novel-front/src/main/resources/mybatis/mapping/BookCommentMapper.xml index 654b5a9..ea38ff2 100644 --- a/novel-front/src/main/resources/mybatis/mapping/BookCommentMapper.xml +++ b/novel-front/src/main/resources/mybatis/mapping/BookCommentMapper.xml @@ -14,7 +14,7 @@ and t1.create_user_id = #{userId} - + order by t1.create_time desc diff --git a/novel-front/src/main/resources/mybatis/mapping/BookMapper.xml b/novel-front/src/main/resources/mybatis/mapping/BookMapper.xml index b020f40..b986293 100644 --- a/novel-front/src/main/resources/mybatis/mapping/BookMapper.xml +++ b/novel-front/src/main/resources/mybatis/mapping/BookMapper.xml @@ -31,6 +31,9 @@ and last_index_update_time >= #{updateTimeMin} + + order by ${sort} desc + diff --git a/pom.xml b/pom.xml index 907434a..9152b2b 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.18 + 3.4.0 @@ -30,11 +30,10 @@ 21 true 8.0.29 - 2.1.4 + 3.0.4 1.4.0 - 1.1.4 + 1.5.0 1.4.6 - 1.0.2 3.4 0.9.1 6.3.1 From 467290b9089b4ce6daa970946d363c72a6215540 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 16 Mar 2025 13:03:37 +0800 Subject: [PATCH 28/95] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90=20Spring=20AI?= =?UTF-8?q?=20=E5=AE=9E=E7=8E=B0=E5=9F=BA=E7=A1=80=E7=9A=84=20AI=20?= =?UTF-8?q?=E5=86=99=E4=BD=9C=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-front/pom.xml | 6 + .../novel/controller/AuthorController.java | 52 +++++ .../java2nb/novel/core/config/AiConfig.java | 47 ++++ .../src/main/resources/application.yml | 10 +- .../templates/author/content_add.html | 220 ++++++++++++++++-- pom.xml | 7 + 6 files changed, 325 insertions(+), 17 deletions(-) create mode 100644 novel-front/src/main/java/com/java2nb/novel/core/config/AiConfig.java diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 21cc448..76d7ef1 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -55,6 +55,12 @@ com.fasterxml.jackson.core jackson-databind + + + + org.springframework.ai + spring-ai-openai-spring-boot-starter + diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java b/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java index 2b4912e..41ba628 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java @@ -12,9 +12,11 @@ import com.java2nb.novel.entity.AuthorIncomeDetail; import com.java2nb.novel.entity.Book; import com.java2nb.novel.service.AuthorService; import com.java2nb.novel.service.BookService; +import io.swagger.v3.oas.annotations.Operation; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.client.ChatClient; import org.springframework.web.bind.annotation.*; import java.util.Date; @@ -32,6 +34,8 @@ public class AuthorController extends BaseController{ private final BookService bookService; + private final ChatClient chatClient; + /** * 校验笔名是否存在 * */ @@ -220,6 +224,54 @@ public class AuthorController extends BaseController{ } + /** + * AI扩写 + */ + @PostMapping("ai/expand") + public RestResult expandText(@RequestParam("text") String text, @RequestParam("ratio") Double ratio) { + String prompt = "请将以下文本扩写为原长度的" + ratio/100 + "倍:" + text; + return RestResult.ok(chatClient.prompt() + .user(prompt) + .call() + .content()); + } + + /** + * AI缩写 + */ + @PostMapping("ai/condense") + public RestResult condenseText(@RequestParam("text") String text, @RequestParam("ratio") Integer ratio) { + String prompt = "请将以下文本缩写为原长度的" + 100/ratio + "分之一:" + text; + return RestResult.ok(chatClient.prompt() + .user(prompt) + .call() + .content()); + } + + /** + * AI续写 + */ + @PostMapping("ai/continue") + public RestResult continueText(@RequestParam("text") String text, @RequestParam("length") Integer length) { + String prompt = "请续写以下文本,续写长度约为" + length + "字:" + text; + return RestResult.ok(chatClient.prompt() + .user(prompt) + .call() + .content()); + } + + /** + * AI润色 + */ + @PostMapping("ai/polish") + public RestResult polishText(@RequestParam("text") String text) { + String prompt = "请润色优化以下文本,保持原意:" + text; + return RestResult.ok(chatClient.prompt() + .user(prompt) + .call() + .content()); + } + diff --git a/novel-front/src/main/java/com/java2nb/novel/core/config/AiConfig.java b/novel-front/src/main/java/com/java2nb/novel/core/config/AiConfig.java new file mode 100644 index 0000000..6cd0740 --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/core/config/AiConfig.java @@ -0,0 +1,47 @@ +package com.java2nb.novel.core.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestClient; + +/** + * Ai 相关配置 + * + * @author xiongxiaoyang + * @date 2025/2/19 + */ +@Configuration +@Slf4j +public class AiConfig { + + /** + * 目的:配置自定义的 RestClientBuilder 对象 + *

    + * 原因:Spring AI 框架的 ChatClient 内部通过 RestClient(Spring Framework 6 和 Spring Boot 3 中引入) 发起 HTTP REST 请求与远程的大模型服务进行通信, + * 如果项目中没有配置自定义的 RestClientBuilder 对象, 那么在 RestClient 的自动配置类 org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration + * 中配置的 RestClientBuilder 对象会使用 Spring 容器中提供的 HttpMessageConverters, 由于本项目中配置了 spring.jackson.generator.write-numbers-as-strings + * = true, 所以 Spring 容器中的 HttpMessageConverters 在 RestClient 发起 HTTP REST 请求转换 Java 对象为 JSON 字符串时会自动将 Number 类型的 + * Java 对象属性转换为字符串而导致请求参数错误 + *

    + * 示例:"temperature": 0.7 =》"temperature": "0.7" + * {"code":20015,"message":"The parameter is invalid. Please check again.","data":null} + */ + @Bean + public RestClient.Builder restClientBuilder() { + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + // 连接超时时间 + factory.setConnectTimeout(5000); + // 读取超时时间 + factory.setReadTimeout(60000); + return RestClient.builder().requestFactory(factory); + } + + @Bean + public ChatClient chatClient(ChatClient.Builder chatClientBuilder) { + return chatClientBuilder.build(); + } + +} diff --git a/novel-front/src/main/resources/application.yml b/novel-front/src/main/resources/application.yml index 26cb4c3..13c725d 100644 --- a/novel-front/src/main/resources/application.yml +++ b/novel-front/src/main/resources/application.yml @@ -46,7 +46,15 @@ book: value: 5 - +--- #--------------------- Spring AI 配置---------------------- +spring: + ai: + openai: + api-key: sk-nnhjmxuljagcuubbovjztbhkiawqaabzziazeurppinxtgva + base-url: https://api.siliconflow.cn + chat: + options: + model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B diff --git a/novel-front/src/main/resources/templates/author/content_add.html b/novel-front/src/main/resources/templates/author/content_add.html index 183bee0..771f2fd 100644 --- a/novel-front/src/main/resources/templates/author/content_add.html +++ b/novel-front/src/main/resources/templates/author/content_add.html @@ -8,6 +8,79 @@ 作家管理系统-小说精品屋 + @@ -46,18 +119,29 @@

    • 章节名: -
    • - 章节内容:
    • -

    • +
    • + 章节内容: +
    • + - 是否收费: -
    • 免费 - 收费
    • + 是否收费: +
    • 免费 + 收费 +
    • -
    • +
    • @@ -113,9 +197,10 @@ var lock = false; + function addBookContent() { - if(lock){ + if (lock) { return; } lock = true; @@ -125,14 +210,14 @@ var indexName = $("#bookIndex").val(); - if(!indexName){ + if (!indexName) { $("#LabErr").html("章节名不能为空!"); lock = false; return; } var content = $("#bookContent").val(); - if(!content){ + if (!content) { $("#LabErr").html("章节内容不能为空!"); lock = false; return; @@ -142,17 +227,15 @@ var isVip = $("input:checked[name=isVip]").val(); - - $.ajax({ type: "POST", url: "/author/addBookContent", - data: {'bookId':bookId,'indexName':indexName,'content':content,'isVip':isVip}, + data: {'bookId': bookId, 'indexName': indexName, 'content': content, 'isVip': isVip}, dataType: "json", success: function (data) { if (data.code == 200) { - window.location.href = '/author/index_list.html?bookId='+bookId; + window.location.href = '/author/index_list.html?bookId=' + bookId; } else { @@ -169,5 +252,110 @@ } + + // 打字机效果函数 + function typeWriter(textarea, text, speed = 50) { + let i = 0; + const timer = setInterval(() => { + if (i < text.length) { + textarea.val(textarea.val() + text.charAt(i)); + i++; + // 滚动到底部 + textarea.scrollTop(textarea[0].scrollHeight); + } else { + clearInterval(timer); + } + }, speed); + } + + $('.ai-toolbar .ai-link').click(function(e){ + e.preventDefault(); // 阻止默认链接行为 + const type = $(this).data('type'); + const textarea = $('#bookContent'); + const selectedText = textarea.val().substring(textarea[0].selectionStart, textarea[0].selectionEnd); + + // 检查是否选中文本 + if (!selectedText) { + layer.msg('请先选中要处理的文本'); + return; + } + + const loading = layer.load(1, {shade: 0.3}); + + // 参数配置 + let params = {text: selectedText}; + if(type === 'expand' || type === 'condense'){ + layer.prompt({ + title: '请输入比例', + value: 2, + btn: ['确定', '取消'], + btn2: function(){ + layer.close(loading); + }, + cancel: function(){ + layer.close(loading); + } + }, function(value, index){ + if(isNaN(Number(value)) || isNaN(parseFloat(value))){ + layer.msg('请输入正确的比例'); + return; + } + if(type === 'expand' && value <= 1){ + layer.msg('请输入正确的比例'); + return; + } + if(type === 'condense' && (value <=0 || value >= 1)){ + layer.msg('请输入正确的比例'); + return; + } + params.ratio = parseFloat(value) * 100; + layer.close(index); + sendRequest(type, params, loading, textarea); + }); + return; + }else if(type === 'continue'){ + layer.prompt({ + title: '请输入续写长度(字数)', + value: 200, + btn: ['确定', '取消'], + btn2: function(){ + layer.close(loading); + }, + cancel: function(){ + layer.close(loading); + } + }, function(value, index){ + if(!Number.isInteger(Number(value)) || value <= 0){ + layer.msg('请输入正确的长度'); + return; + } + params.length = parseInt(value); + layer.close(index); + sendRequest(type, params, loading, textarea); + }); + return; + } + + sendRequest(type, params, loading, textarea); + }); + + function sendRequest(type, params, loading, textarea){ + $.ajax({ + url: '/author/ai/' + type, + type: 'POST', + data: params, + success: function(res){ + layer.close(loading); + // 将生成的内容追加到文本末尾 + const newText = "\n\n" + res.data; // 添加换行符分隔 + typeWriter(textarea, newText); // 使用打字机效果 + }, + error: function(){ + layer.msg('请求失败,请稍后重试'); + layer.close(loading); + } + }); + } + diff --git a/pom.xml b/pom.xml index 9152b2b..b22d4af 100644 --- a/pom.xml +++ b/pom.xml @@ -53,6 +53,13 @@ novel-common ${project.version} + + org.springframework.ai + spring-ai-bom + 1.0.0-M6 + pom + import + From 14a1ff69bf748884fcf513987754b8c49c736801 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 16 Mar 2025 14:27:47 +0800 Subject: [PATCH 29/95] =?UTF-8?q?build:=20=E5=8D=87=E7=BA=A7=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{application-prod.yml => application.yml} | 18 ++-- .../resources/application-common-prod.yml | 18 ++-- ...cation-common-prod.yml => application.yml} | 87 +++++++++-------- ...cation-common-prod.yml => application.yml} | 97 ++++++++++--------- .../src/main/resources/application.yml | 2 - 5 files changed, 116 insertions(+), 106 deletions(-) rename novel-admin/src/main/build/config/{application-prod.yml => application.yml} (92%) rename novel-crawl/src/main/build/config/{application-common-prod.yml => application.yml} (77%) rename novel-front/src/main/build/config/{application-common-prod.yml => application.yml} (74%) diff --git a/novel-admin/src/main/build/config/application-prod.yml b/novel-admin/src/main/build/config/application.yml similarity index 92% rename from novel-admin/src/main/build/config/application-prod.yml rename to novel-admin/src/main/build/config/application.yml index 5f7b883..597dfad 100644 --- a/novel-admin/src/main/build/config/application-prod.yml +++ b/novel-admin/src/main/build/config/application.yml @@ -1,9 +1,9 @@ -#端口号 -server: - port: 8088 -spring: - redis: - host: 127.0.0.1 - port: 6379 - password: test123456 - +#端口号 +server: + port: 8088 +spring: + redis: + host: 127.0.0.1 + port: 6379 + password: test123456 + diff --git a/novel-common/src/main/resources/application-common-prod.yml b/novel-common/src/main/resources/application-common-prod.yml index 7c99121..3afeae2 100644 --- a/novel-common/src/main/resources/application-common-prod.yml +++ b/novel-common/src/main/resources/application-common-prod.yml @@ -3,14 +3,16 @@ spring: import: classpath:application-common.yml main: allow-bean-definition-overriding: true - #Redis服务器IP - redis: - host: 127.0.0.1 - #Redis服务器连接端口 - port: 6379 - #Redis服务器连接密码 - password: test123456 - timeout: 10000 + data: + redis: + #Redis服务器IP + host: 127.0.0.1 + #Redis服务器连接端口 + port: 6379 + #Redis服务器连接密码 + password: test123456 + #连接超时时间(毫秒) + timeout: 10000 logging: level: diff --git a/novel-crawl/src/main/build/config/application-common-prod.yml b/novel-crawl/src/main/build/config/application.yml similarity index 77% rename from novel-crawl/src/main/build/config/application-common-prod.yml rename to novel-crawl/src/main/build/config/application.yml index fd708fd..370d2b4 100644 --- a/novel-crawl/src/main/build/config/application-common-prod.yml +++ b/novel-crawl/src/main/build/config/application.yml @@ -1,42 +1,47 @@ -#端口号 -server: - port: 8083 - -#不分表的数据库配置 -spring: - redis: - host: 127.0.0.1 - port: 6379 - password: test123456 - -#登录用户名密码 -admin: - username: admin - password: admin -# -##爬虫自动更新的线程数 -##建议小说数量不多或者正在运行新书入库爬虫的情况下设置为1即可 -##随着小说数量的增多可以逐渐增加,但建议不要超出CPU的线程数 -crawl: - update: - thread: 1 - -#小说内容保存配置 -content: - save: - storage: db # 小说内容存储方式:db-数据库,txt-TXT文本 - path: /Users/xiongxiaoyang/books # 小说TXT文本保存路径 - -# HTTP 代理配置 -http: - proxy: - # 是否开启 HTTP 代理,true-开启,false-不开启 - enabled: false - # 代理 IP - ip: us.swiftproxy.net - # 代理端口号 - port: 7878 - # 代理用户名 - username: swiftproxy_u - # 代理密码 +#端口号 +server: + port: 8083 + +spring: + data: + redis: + #Redis服务器IP + host: 127.0.0.1 + #Redis服务器连接端口 + port: 6379 + #Redis服务器连接密码 + password: test123456 + #连接超时时间(毫秒) + timeout: 10000 + +#登录用户名密码 +admin: + username: admin + password: admin +# +##爬虫自动更新的线程数 +##建议小说数量不多或者正在运行新书入库爬虫的情况下设置为1即可 +##随着小说数量的增多可以逐渐增加,但建议不要超出CPU的线程数 +crawl: + update: + thread: 1 + +#小说内容保存配置 +content: + save: + storage: db # 小说内容存储方式:db-数据库,txt-TXT文本 + path: /Users/xiongxiaoyang/books # 小说TXT文本保存路径 + +# HTTP 代理配置 +http: + proxy: + # 是否开启 HTTP 代理,true-开启,false-不开启 + enabled: false + # 代理 IP + ip: us.swiftproxy.net + # 代理端口号 + port: 7878 + # 代理用户名 + username: swiftproxy_u + # 代理密码 password: swiftproxy_p \ No newline at end of file diff --git a/novel-front/src/main/build/config/application-common-prod.yml b/novel-front/src/main/build/config/application.yml similarity index 74% rename from novel-front/src/main/build/config/application-common-prod.yml rename to novel-front/src/main/build/config/application.yml index bcb1ab3..d99280f 100644 --- a/novel-front/src/main/build/config/application-common-prod.yml +++ b/novel-front/src/main/build/config/application.yml @@ -1,46 +1,51 @@ -#端口号 -server: - port: 8085 - -#不分表的数据库配置 -spring: - redis: - host: 127.0.0.1 - port: 6379 - password: test123456 - - -pic: - save: - #图片保存方式, 1不保存,使用网络图片 ,2本地保存 - type: 2 - #图片保存路径 - path: /var/pic - - -#模版配置 -templates: - name: green - -#小说内容保存配置 -content: - save: - storage: db # 小说内容存储方式:db-数据库,txt-TXT文本 - path: /Users/xiongxiaoyang/books # 小说TXT文本保存路径 - - - -# HTTP 代理配置 -http: - proxy: - # 是否开启 HTTP 代理,true-开启,false-不开启 - enabled: false - # 代理 IP - ip: us.swiftproxy.net - # 代理端口号 - port: 7878 - # 代理用户名 - username: swiftproxy_u - # 代理密码 - password: swiftproxy_p - +#端口号 +server: + port: 8085 + +spring: + data: + redis: + #Redis服务器IP + host: 127.0.0.1 + #Redis服务器连接端口 + port: 6379 + #Redis服务器连接密码 + password: test123456 + #连接超时时间(毫秒) + timeout: 10000 + + +pic: + save: + #图片保存方式, 1不保存,使用网络图片 ,2本地保存 + type: 2 + #图片保存路径 + path: /var/pic + + +#模版配置 +templates: + name: green + +#小说内容保存配置 +content: + save: + storage: db # 小说内容存储方式:db-数据库,txt-TXT文本 + path: /Users/xiongxiaoyang/books # 小说TXT文本保存路径 + + + +# HTTP 代理配置 +http: + proxy: + # 是否开启 HTTP 代理,true-开启,false-不开启 + enabled: false + # 代理 IP + ip: us.swiftproxy.net + # 代理端口号 + port: 7878 + # 代理用户名 + username: swiftproxy_u + # 代理密码 + password: swiftproxy_p + diff --git a/novel-front/src/main/resources/application.yml b/novel-front/src/main/resources/application.yml index 13c725d..1a64054 100644 --- a/novel-front/src/main/resources/application.yml +++ b/novel-front/src/main/resources/application.yml @@ -5,8 +5,6 @@ spring: profiles: active: dev include: website,alipay,oss - config: - use-legacy-processing: true jwt: secret: novel!#20191230 From a046899dd6154090d25307e8ad9c85c206317c85 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Mon, 17 Mar 2025 10:12:53 +0800 Subject: [PATCH 30/95] =?UTF-8?q?fix=EF=BC=9A=E9=80=9A=E7=94=A8=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/advice/CommonExceptionHandler.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java diff --git a/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java b/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java new file mode 100644 index 0000000..c564246 --- /dev/null +++ b/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java @@ -0,0 +1,36 @@ +package com.java2nb.novel.core.advice; + +import io.github.xxyopen.model.resp.RestResult; +import io.github.xxyopen.model.resp.SysResultCode; +import io.github.xxyopen.web.exception.BusinessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.validation.BindException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class CommonExceptionHandler { + private static final Logger log = LoggerFactory.getLogger(io.github.xxyopen.web.exception.CommonExceptionHandler.class); + + public CommonExceptionHandler() { + } + + @ExceptionHandler({BindException.class}) + public RestResult handlerBindException(BindException e) { + log.error(e.getMessage(), e); + return RestResult.fail(SysResultCode.PARAM_ERROR); + } + + @ExceptionHandler({BusinessException.class}) + public RestResult handlerBusinessException(BusinessException e) { + log.error(e.getMessage(), e); + return RestResult.fail(e.getResultCode()); + } + + @ExceptionHandler({Exception.class}) + public RestResult handlerException(Exception e) { + log.error(e.getMessage(), e); + return RestResult.error(); + } +} \ No newline at end of file From 84a06a703722ea2ac418119b806789b0994d185d Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Mon, 17 Mar 2025 10:18:18 +0800 Subject: [PATCH 31/95] =?UTF-8?q?fix:=20=E9=80=9A=E7=94=A8=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java2nb/novel/core/advice/CommonExceptionHandler.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java b/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java index c564246..16509b1 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java @@ -3,15 +3,14 @@ package com.java2nb.novel.core.advice; import io.github.xxyopen.model.resp.RestResult; import io.github.xxyopen.model.resp.SysResultCode; import io.github.xxyopen.web.exception.BusinessException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +@Slf4j @RestControllerAdvice public class CommonExceptionHandler { - private static final Logger log = LoggerFactory.getLogger(io.github.xxyopen.web.exception.CommonExceptionHandler.class); public CommonExceptionHandler() { } From 8781cc54d4957d4f59c68b3e9418371484401e28 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Mon, 17 Mar 2025 18:47:05 +0800 Subject: [PATCH 32/95] =?UTF-8?q?chore:=20=E6=A8=A1=E7=89=88/=E9=85=8D?= =?UTF-8?q?=E7=BD=AE/SQL/=E6=96=87=E6=A1=A3=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + doc/sql/20250317.sql | 44 ++++ .../src/main/build/config/application.yml | 10 + templates/green/html/author/content_add.html | 220 ++++++++++++++++-- 4 files changed, 259 insertions(+), 16 deletions(-) create mode 100644 doc/sql/20250317.sql diff --git a/README.md b/README.md index 2a699d5..707aa1d 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ novel-plus -- 父工程 | 技术 | 说明 |---------------------| --------------------------- | Spring Boot | Spring 应用快速开发脚手架 +| Spring AI | Spring 官方 AI 框架 | MyBatis | 持久层 ORM 框架 | MyBatis Dynamic SQL | Mybatis 动态 sql | PageHelper | MyBatis 分页插件 diff --git a/doc/sql/20250317.sql b/doc/sql/20250317.sql new file mode 100644 index 0000000..56f1808 --- /dev/null +++ b/doc/sql/20250317.sql @@ -0,0 +1,44 @@ +INSERT INTO crawl_source (source_name, crawl_rule, source_status, create_time, update_time) +VALUES ('香书小说网', '{ + "bookListUrl": "http://www.xbiqugu.la/fenlei/{catId}_{page}.html", + "catIdRule": { + "catId1": "1", + "catId2": "2", + "catId3": "3", + "catId4": "4", + "catId5": "6", + "catId6": "5" + }, + "bookIdPatten": "", + "pagePatten": "(\\\\d+)/\\\\d+", + "totalPagePatten": "\\\\d+/(\\\\d+)", + "bookDetailUrl": "http://www.xbiqugu.la/{bookId}/", + "bookNamePatten": "

      ([^/]+)

      ", + "authorNamePatten": "者:([^/]+)

      ", + "picUrlPatten": "src=\\"(http://www.xbiqugu.la/files/article/image/\\\\d+/\\\\d+/\\\\d+s\\\\.jpg)\\"", + "bookStatusRule": {}, + "descStart": "
      ", + "descEnd": "
      ", + "upadateTimePatten": "

      最后更新:(\\\\d+-\\\\d+-\\\\d+\\\\s\\\\d+:\\\\d+:\\\\d+)

      ", + "upadateTimeFormatPatten": "yyyy-MM-dd HH:mm:ss", + "bookIndexUrl": "http://www.xbiqugu.la/{bookId}/", + "indexIdPatten": "[^/]+", + "indexNamePatten": "([^/]+)", + "bookContentUrl": "http://www.xbiqugu.la/{bookId}/{indexId}.html", + "contentStart": "
      ", + "contentEnd": "

      ", + "filterContent":"\\\\s*([^/]+)\\\\s*

      " +}', 0, '2024-06-01 10:11:39', '2024-06-01 10:11:39'); + + +update crawl_source +set crawl_rule = replace(crawl_rule, 'ibiquzw.org', 'biquxs.info') +where id = 16; + +delete +from sys_menu +where menu_id = 104; + +delete +from sys_menu +where menu_id = 57; \ No newline at end of file diff --git a/novel-front/src/main/build/config/application.yml b/novel-front/src/main/build/config/application.yml index d99280f..187f827 100644 --- a/novel-front/src/main/build/config/application.yml +++ b/novel-front/src/main/build/config/application.yml @@ -49,3 +49,13 @@ http: # 代理密码 password: swiftproxy_p + +--- #--------------------- Spring AI 配置---------------------- +spring: + ai: + openai: + api-key: sk-nnhjmxuljagcuubbovjztbhkiawqaabzziazeurppinxtgva + base-url: https://api.siliconflow.cn + chat: + options: + model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B \ No newline at end of file diff --git a/templates/green/html/author/content_add.html b/templates/green/html/author/content_add.html index 183bee0..771f2fd 100644 --- a/templates/green/html/author/content_add.html +++ b/templates/green/html/author/content_add.html @@ -8,6 +8,79 @@ 作家管理系统-小说精品屋 + @@ -46,18 +119,29 @@
      • 章节名: -
      • - 章节内容:
      • -

      • +
      • + 章节内容: +
      • + - 是否收费: -
      • 免费 - 收费
      • + 是否收费: +
      • 免费 + 收费 +
      • -
      • +
      • @@ -113,9 +197,10 @@ var lock = false; + function addBookContent() { - if(lock){ + if (lock) { return; } lock = true; @@ -125,14 +210,14 @@ var indexName = $("#bookIndex").val(); - if(!indexName){ + if (!indexName) { $("#LabErr").html("章节名不能为空!"); lock = false; return; } var content = $("#bookContent").val(); - if(!content){ + if (!content) { $("#LabErr").html("章节内容不能为空!"); lock = false; return; @@ -142,17 +227,15 @@ var isVip = $("input:checked[name=isVip]").val(); - - $.ajax({ type: "POST", url: "/author/addBookContent", - data: {'bookId':bookId,'indexName':indexName,'content':content,'isVip':isVip}, + data: {'bookId': bookId, 'indexName': indexName, 'content': content, 'isVip': isVip}, dataType: "json", success: function (data) { if (data.code == 200) { - window.location.href = '/author/index_list.html?bookId='+bookId; + window.location.href = '/author/index_list.html?bookId=' + bookId; } else { @@ -169,5 +252,110 @@ } + + // 打字机效果函数 + function typeWriter(textarea, text, speed = 50) { + let i = 0; + const timer = setInterval(() => { + if (i < text.length) { + textarea.val(textarea.val() + text.charAt(i)); + i++; + // 滚动到底部 + textarea.scrollTop(textarea[0].scrollHeight); + } else { + clearInterval(timer); + } + }, speed); + } + + $('.ai-toolbar .ai-link').click(function(e){ + e.preventDefault(); // 阻止默认链接行为 + const type = $(this).data('type'); + const textarea = $('#bookContent'); + const selectedText = textarea.val().substring(textarea[0].selectionStart, textarea[0].selectionEnd); + + // 检查是否选中文本 + if (!selectedText) { + layer.msg('请先选中要处理的文本'); + return; + } + + const loading = layer.load(1, {shade: 0.3}); + + // 参数配置 + let params = {text: selectedText}; + if(type === 'expand' || type === 'condense'){ + layer.prompt({ + title: '请输入比例', + value: 2, + btn: ['确定', '取消'], + btn2: function(){ + layer.close(loading); + }, + cancel: function(){ + layer.close(loading); + } + }, function(value, index){ + if(isNaN(Number(value)) || isNaN(parseFloat(value))){ + layer.msg('请输入正确的比例'); + return; + } + if(type === 'expand' && value <= 1){ + layer.msg('请输入正确的比例'); + return; + } + if(type === 'condense' && (value <=0 || value >= 1)){ + layer.msg('请输入正确的比例'); + return; + } + params.ratio = parseFloat(value) * 100; + layer.close(index); + sendRequest(type, params, loading, textarea); + }); + return; + }else if(type === 'continue'){ + layer.prompt({ + title: '请输入续写长度(字数)', + value: 200, + btn: ['确定', '取消'], + btn2: function(){ + layer.close(loading); + }, + cancel: function(){ + layer.close(loading); + } + }, function(value, index){ + if(!Number.isInteger(Number(value)) || value <= 0){ + layer.msg('请输入正确的长度'); + return; + } + params.length = parseInt(value); + layer.close(index); + sendRequest(type, params, loading, textarea); + }); + return; + } + + sendRequest(type, params, loading, textarea); + }); + + function sendRequest(type, params, loading, textarea){ + $.ajax({ + url: '/author/ai/' + type, + type: 'POST', + data: params, + success: function(res){ + layer.close(loading); + // 将生成的内容追加到文本末尾 + const newText = "\n\n" + res.data; // 添加换行符分隔 + typeWriter(textarea, newText); // 使用打字机效果 + }, + error: function(){ + layer.msg('请求失败,请稍后重试'); + layer.close(loading); + } + }); + } + From c4a6acf2b30f93a2d48f44f864763a39df93b748 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 18 Mar 2025 14:24:19 +0800 Subject: [PATCH 33/95] =?UTF-8?q?fix:=20=E7=BD=91=E7=AB=99ico=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/{ => static}/favicon.ico | Bin .../main/resources/{ => static}/favicon.ico | Bin .../main/resources/{ => static}/favicon.ico | Bin templates/green/static/favicon.ico | Bin 0 -> 166172 bytes 4 files changed, 0 insertions(+), 0 deletions(-) rename novel-admin/src/main/resources/{ => static}/favicon.ico (100%) rename novel-crawl/src/main/resources/{ => static}/favicon.ico (100%) rename novel-front/src/main/resources/{ => static}/favicon.ico (100%) create mode 100644 templates/green/static/favicon.ico diff --git a/novel-admin/src/main/resources/favicon.ico b/novel-admin/src/main/resources/static/favicon.ico similarity index 100% rename from novel-admin/src/main/resources/favicon.ico rename to novel-admin/src/main/resources/static/favicon.ico diff --git a/novel-crawl/src/main/resources/favicon.ico b/novel-crawl/src/main/resources/static/favicon.ico similarity index 100% rename from novel-crawl/src/main/resources/favicon.ico rename to novel-crawl/src/main/resources/static/favicon.ico diff --git a/novel-front/src/main/resources/favicon.ico b/novel-front/src/main/resources/static/favicon.ico similarity index 100% rename from novel-front/src/main/resources/favicon.ico rename to novel-front/src/main/resources/static/favicon.ico diff --git a/templates/green/static/favicon.ico b/templates/green/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..67a7463dfc09cba6e302cfc07aebdab0d1c22f3b GIT binary patch literal 166172 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 literal 0 HcmV?d00001 From 3858cd4e496c75a582a5ea838a10a8dfff912723 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 18 Mar 2025 19:10:10 +0800 Subject: [PATCH 34/95] =?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 --- novel-admin/pom.xml | 2 +- novel-common/pom.xml | 2 +- novel-crawl/pom.xml | 2 +- novel-front/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index 83a6042..e483397 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel-admin - 5.0.0 + 5.0.1-SNAPSHOT jar novel-admin diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 462c5e9..1b9292b 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.0 + 5.0.1-SNAPSHOT 4.0.0 diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index 68b2de6..bbbd895 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.0 + 5.0.1-SNAPSHOT 4.0.0 diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 76d7ef1..8640766 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.0 + 5.0.1-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index b22d4af..4ac1f58 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel - 5.0.0 + 5.0.1-SNAPSHOT novel-common novel-front From f5a9a7423f903a9b0e06094ef54eaa890ccc696a Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 18 Mar 2025 20:22:54 +0800 Subject: [PATCH 35/95] =?UTF-8?q?fix:=20=E7=94=9F=E4=BA=A7=E7=8E=AF?= =?UTF-8?q?=E5=A2=83web=E9=9D=99=E6=80=81=E8=B5=84=E6=BA=90=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-admin/src/main/resources/application.yml | 6 ------ novel-common/src/main/resources/application-common.yml | 3 --- novel-front/src/main/resources/application-prod.yml | 5 +++-- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/novel-admin/src/main/resources/application.yml b/novel-admin/src/main/resources/application.yml index 5cc1028..16fae56 100644 --- a/novel-admin/src/main/resources/application.yml +++ b/novel-admin/src/main/resources/application.yml @@ -27,9 +27,6 @@ spring: max-file-size: 100MB max-request-size: 100MB - devtools: - restart: - enabled: true main: allow-bean-definition-overriding: true @@ -39,9 +36,6 @@ mybatis: map-underscore-to-camel-case: true mapper-locations: mybatis/**/*Mapper.xml typeAliasesPackage: com.java2nb.**.domain -#[弃用]配置缓存和session存储方式,默认ehcache,可选redis,[弃用]调整至 spring cache type【shiro.用户,权限,session,spring.cache通用】 -#[弃用]cacheType: ehcache - logging: config: classpath:logback-boot.xml diff --git a/novel-common/src/main/resources/application-common.yml b/novel-common/src/main/resources/application-common.yml index be2c512..419b9ec 100644 --- a/novel-common/src/main/resources/application-common.yml +++ b/novel-common/src/main/resources/application-common.yml @@ -2,9 +2,6 @@ spring: datasource: url: jdbc:shardingsphere:absolutepath:${user.dir}/config/shardingsphere-jdbc.yml driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver - cache: - ehcache: - config: classpath:ehcache.xml thymeleaf: mode: LEGACYHTML5 #去除thymeleaf的html严格校验thymeleaf.mode=LEGACYHTML5 cache: false # 是否开启模板缓存,默认true,建议在开发时关闭缓存,不然没法看到实时 diff --git a/novel-front/src/main/resources/application-prod.yml b/novel-front/src/main/resources/application-prod.yml index 5378c0f..de13d4c 100644 --- a/novel-front/src/main/resources/application-prod.yml +++ b/novel-front/src/main/resources/application-prod.yml @@ -3,12 +3,13 @@ spring: import: classpath:application-common-prod.yml #静态文件路径配置 - resources: - static-locations: file:${user.dir}/templates/${templates.name}/static/ #thymeleaf模版路径配置 thymeleaf: prefix: file:${user.dir}/templates/${templates.name}/html/ suffix: .html + web: + resources: + static-locations: file:${user.dir}/templates/${templates.name}/static/ #模版配置 templates: From 0afc7b1bbf31ef21866ecc2cc02218dfaf284364 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 18 Mar 2025 21:03:21 +0800 Subject: [PATCH 36/95] =?UTF-8?q?fix:=20=E9=80=9A=E7=94=A8=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/advice/CommonExceptionHandler.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java b/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java index 16509b1..cae9f25 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/advice/CommonExceptionHandler.java @@ -3,11 +3,19 @@ package com.java2nb.novel.core.advice; import io.github.xxyopen.model.resp.RestResult; import io.github.xxyopen.model.resp.SysResultCode; import io.github.xxyopen.web.exception.BusinessException; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; import org.springframework.validation.BindException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.ModelAndView; +/** + * 统一异常处理器 + * + * @author xiongxiaoyang + */ @Slf4j @RestControllerAdvice public class CommonExceptionHandler { @@ -27,9 +35,21 @@ public class CommonExceptionHandler { return RestResult.fail(e.getResultCode()); } - @ExceptionHandler({Exception.class}) - public RestResult handlerException(Exception e) { + @ExceptionHandler(Exception.class) + public Object handleException(HttpServletRequest request, Exception e) { log.error(e.getMessage(), e); - return RestResult.error(); + if (isJsonRequest(request)) { + // 如果是REST请求,返回JSON格式的错误响应 + return RestResult.error(); + } else { + //跳转页面过程中出现异常时统一跳转到404页面 + return new ModelAndView("404"); + } } + + private boolean isJsonRequest(HttpServletRequest request) { + String acceptHeader = request.getHeader("Accept"); + return acceptHeader != null && acceptHeader.contains(MediaType.APPLICATION_JSON_VALUE); + } + } \ No newline at end of file From eecbb2dd9c4a6ca5931c51ea1971294ab0b8d2b1 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 18 Mar 2025 21:18:51 +0800 Subject: [PATCH 37/95] =?UTF-8?q?fix:=20=E9=80=9A=E7=94=A8=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/advice/PageExceptionHandler.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 novel-common/src/main/java/com/java2nb/novel/core/advice/PageExceptionHandler.java diff --git a/novel-common/src/main/java/com/java2nb/novel/core/advice/PageExceptionHandler.java b/novel-common/src/main/java/com/java2nb/novel/core/advice/PageExceptionHandler.java deleted file mode 100644 index 85041fd..0000000 --- a/novel-common/src/main/java/com/java2nb/novel/core/advice/PageExceptionHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.java2nb.novel.core.advice; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -/** - * 页面异常处理器 - * - * @author 11797 - */ -@Slf4j -@ControllerAdvice(basePackages = "com.java2nb.novel.controller.page") -public class PageExceptionHandler { - - - /** - * 处理所有异常 - */ - @ExceptionHandler(Exception.class) - public String handlerException(Exception e) { - log.error(e.getMessage(), e); - //跳转页面过程中出现异常时统一跳转到404页面 - return "404"; - } -} From c1583f83bb80f5d7575a439d2c4e7c4e449912aa Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 18 Mar 2025 21:19:18 +0800 Subject: [PATCH 38/95] =?UTF-8?q?fix:=20=E7=BD=91=E7=AB=99icon=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/templates/common/file/file.html | 2 +- novel-admin/src/main/resources/templates/error/403.html | 2 +- novel-admin/src/main/resources/templates/error/404.html | 2 +- novel-admin/src/main/resources/templates/error/500.html | 2 +- novel-admin/src/main/resources/templates/error/error.html | 2 +- novel-admin/src/main/resources/templates/include.html | 2 +- novel-admin/src/main/resources/templates/index.html | 2 +- .../src/main/resources/templates/system/menu/edit.html | 2 +- .../src/main/resources/templates/system/user/include.html | 2 +- novel-front/src/main/resources/templates/book/bookclass.html | 4 ++-- novel-front/src/main/resources/templates/index.html | 4 ++-- templates/green/html/book/bookclass.html | 4 ++-- templates/green/html/index.html | 4 ++-- templates/orange/html/book/bookclass.html | 4 ++-- templates/orange/html/index.html | 4 ++-- 15 files changed, 21 insertions(+), 21 deletions(-) diff --git a/novel-admin/src/main/resources/templates/common/file/file.html b/novel-admin/src/main/resources/templates/common/file/file.html index fa0de95..9efd53f 100644 --- a/novel-admin/src/main/resources/templates/common/file/file.html +++ b/novel-admin/src/main/resources/templates/common/file/file.html @@ -6,7 +6,7 @@ 小说精品屋 - 文件管理器 - + diff --git a/novel-admin/src/main/resources/templates/error/403.html b/novel-admin/src/main/resources/templates/error/403.html index 7738e91..2e98ace 100644 --- a/novel-admin/src/main/resources/templates/error/403.html +++ b/novel-admin/src/main/resources/templates/error/403.html @@ -6,7 +6,7 @@ 403 页面 - + diff --git a/novel-admin/src/main/resources/templates/error/404.html b/novel-admin/src/main/resources/templates/error/404.html index 55cd586..babef5d 100644 --- a/novel-admin/src/main/resources/templates/error/404.html +++ b/novel-admin/src/main/resources/templates/error/404.html @@ -10,7 +10,7 @@ - + diff --git a/novel-admin/src/main/resources/templates/error/500.html b/novel-admin/src/main/resources/templates/error/500.html index 194f536..61981d8 100644 --- a/novel-admin/src/main/resources/templates/error/500.html +++ b/novel-admin/src/main/resources/templates/error/500.html @@ -11,7 +11,7 @@ - + diff --git a/novel-admin/src/main/resources/templates/error/error.html b/novel-admin/src/main/resources/templates/error/error.html index 802339f..9db6e11 100644 --- a/novel-admin/src/main/resources/templates/error/error.html +++ b/novel-admin/src/main/resources/templates/error/error.html @@ -6,7 +6,7 @@ 500错误 - + diff --git a/novel-admin/src/main/resources/templates/include.html b/novel-admin/src/main/resources/templates/include.html index 9bd4ce7..90be390 100644 --- a/novel-admin/src/main/resources/templates/include.html +++ b/novel-admin/src/main/resources/templates/include.html @@ -4,7 +4,7 @@ - + - + diff --git a/novel-admin/src/main/resources/templates/system/menu/edit.html b/novel-admin/src/main/resources/templates/system/menu/edit.html index a7bcfba..6c42c89 100644 --- a/novel-admin/src/main/resources/templates/system/menu/edit.html +++ b/novel-admin/src/main/resources/templates/system/menu/edit.html @@ -11,7 +11,7 @@ - + diff --git a/novel-admin/src/main/resources/templates/system/user/include.html b/novel-admin/src/main/resources/templates/system/user/include.html index 6498fec..7dec980 100644 --- a/novel-admin/src/main/resources/templates/system/user/include.html +++ b/novel-admin/src/main/resources/templates/system/user/include.html @@ -4,7 +4,7 @@ - + diff --git a/novel-front/src/main/resources/templates/book/bookclass.html b/novel-front/src/main/resources/templates/book/bookclass.html index a44cea9..afa7291 100644 --- a/novel-front/src/main/resources/templates/book/bookclass.html +++ b/novel-front/src/main/resources/templates/book/bookclass.html @@ -6,8 +6,8 @@ - - + + diff --git a/novel-front/src/main/resources/templates/index.html b/novel-front/src/main/resources/templates/index.html index 53f6627..1e48ad7 100644 --- a/novel-front/src/main/resources/templates/index.html +++ b/novel-front/src/main/resources/templates/index.html @@ -7,8 +7,8 @@ - - + + diff --git a/templates/green/html/book/bookclass.html b/templates/green/html/book/bookclass.html index a44cea9..afa7291 100644 --- a/templates/green/html/book/bookclass.html +++ b/templates/green/html/book/bookclass.html @@ -6,8 +6,8 @@ - - + + diff --git a/templates/green/html/index.html b/templates/green/html/index.html index 53f6627..1e48ad7 100644 --- a/templates/green/html/index.html +++ b/templates/green/html/index.html @@ -7,8 +7,8 @@ - - + + diff --git a/templates/orange/html/book/bookclass.html b/templates/orange/html/book/bookclass.html index a44cea9..afa7291 100644 --- a/templates/orange/html/book/bookclass.html +++ b/templates/orange/html/book/bookclass.html @@ -6,8 +6,8 @@ - - + + diff --git a/templates/orange/html/index.html b/templates/orange/html/index.html index 53f6627..1e48ad7 100644 --- a/templates/orange/html/index.html +++ b/templates/orange/html/index.html @@ -7,8 +7,8 @@ - - + + From d9f9fd8bd23847ae14a4d5827f57f7ae335f7bae Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Tue, 18 Mar 2025 21:39:01 +0800 Subject: [PATCH 39/95] =?UTF-8?q?build:=20=E4=BC=98=E5=8C=96=E6=89=93?= =?UTF-8?q?=E5=8C=85=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-admin/pom.xml | 5 -- .../main/build/config/shardingsphere-jdbc.yml | 47 +++++++++++++++++++ novel-crawl/pom.xml | 5 -- .../main/build/config/shardingsphere-jdbc.yml | 47 +++++++++++++++++++ novel-front/pom.xml | 5 -- .../main/build/config/shardingsphere-jdbc.yml | 47 +++++++++++++++++++ 6 files changed, 141 insertions(+), 15 deletions(-) create mode 100644 novel-admin/src/main/build/config/shardingsphere-jdbc.yml create mode 100644 novel-crawl/src/main/build/config/shardingsphere-jdbc.yml create mode 100644 novel-front/src/main/build/config/shardingsphere-jdbc.yml diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index e483397..b1d9fad 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -284,11 +284,6 @@ - - - - - diff --git a/novel-admin/src/main/build/config/shardingsphere-jdbc.yml b/novel-admin/src/main/build/config/shardingsphere-jdbc.yml new file mode 100644 index 0000000..8659c28 --- /dev/null +++ b/novel-admin/src/main/build/config/shardingsphere-jdbc.yml @@ -0,0 +1,47 @@ +mode: + # 单机模式 + type: Standalone + # 元数据持久化 + repository: + # 数据库持久化 + type: JDBC + +# 数据源配置 +dataSources: + ds_1: + dataSourceClassName: com.zaxxer.hikari.HikariDataSource + driverClassName: com.mysql.cj.jdbc.Driver + jdbcUrl: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: test123456 +# 规则配置 +rules: + - !SINGLE + tables: + - "*.*" + - !SHARDING + tables: # 数据分片规则配置 + book_content: + # 分库策略,缺省表示使用默认分库策略 + actualDataNodes: ds_${1}.book_content${0..9} + # 分表策略 + tableStrategy: + standard: + # 分片列名称 + shardingColumn: index_id + # 分片算法名称 + shardingAlgorithmName: bookContentSharding + + shardingAlgorithms: + bookContentSharding: + # 行表达式分片算法,使用 Groovy 的表达式,提供对 SQL 语句中的 = 和 IN 的分片操作支持 + type: INLINE + props: + # 分片算法的行表达式 + algorithm-expression: book_content${index_id % 10} + + + +props: + # 是否在日志中打印 SQL + sql-show: true diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index bbbd895..f0e6a6a 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -63,11 +63,6 @@ - - - - - diff --git a/novel-crawl/src/main/build/config/shardingsphere-jdbc.yml b/novel-crawl/src/main/build/config/shardingsphere-jdbc.yml new file mode 100644 index 0000000..8659c28 --- /dev/null +++ b/novel-crawl/src/main/build/config/shardingsphere-jdbc.yml @@ -0,0 +1,47 @@ +mode: + # 单机模式 + type: Standalone + # 元数据持久化 + repository: + # 数据库持久化 + type: JDBC + +# 数据源配置 +dataSources: + ds_1: + dataSourceClassName: com.zaxxer.hikari.HikariDataSource + driverClassName: com.mysql.cj.jdbc.Driver + jdbcUrl: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: test123456 +# 规则配置 +rules: + - !SINGLE + tables: + - "*.*" + - !SHARDING + tables: # 数据分片规则配置 + book_content: + # 分库策略,缺省表示使用默认分库策略 + actualDataNodes: ds_${1}.book_content${0..9} + # 分表策略 + tableStrategy: + standard: + # 分片列名称 + shardingColumn: index_id + # 分片算法名称 + shardingAlgorithmName: bookContentSharding + + shardingAlgorithms: + bookContentSharding: + # 行表达式分片算法,使用 Groovy 的表达式,提供对 SQL 语句中的 = 和 IN 的分片操作支持 + type: INLINE + props: + # 分片算法的行表达式 + algorithm-expression: book_content${index_id % 10} + + + +props: + # 是否在日志中打印 SQL + sql-show: true diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 8640766..c5e315a 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -90,11 +90,6 @@ - - - - - diff --git a/novel-front/src/main/build/config/shardingsphere-jdbc.yml b/novel-front/src/main/build/config/shardingsphere-jdbc.yml new file mode 100644 index 0000000..8659c28 --- /dev/null +++ b/novel-front/src/main/build/config/shardingsphere-jdbc.yml @@ -0,0 +1,47 @@ +mode: + # 单机模式 + type: Standalone + # 元数据持久化 + repository: + # 数据库持久化 + type: JDBC + +# 数据源配置 +dataSources: + ds_1: + dataSourceClassName: com.zaxxer.hikari.HikariDataSource + driverClassName: com.mysql.cj.jdbc.Driver + jdbcUrl: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: test123456 +# 规则配置 +rules: + - !SINGLE + tables: + - "*.*" + - !SHARDING + tables: # 数据分片规则配置 + book_content: + # 分库策略,缺省表示使用默认分库策略 + actualDataNodes: ds_${1}.book_content${0..9} + # 分表策略 + tableStrategy: + standard: + # 分片列名称 + shardingColumn: index_id + # 分片算法名称 + shardingAlgorithmName: bookContentSharding + + shardingAlgorithms: + bookContentSharding: + # 行表达式分片算法,使用 Groovy 的表达式,提供对 SQL 语句中的 = 和 IN 的分片操作支持 + type: INLINE + props: + # 分片算法的行表达式 + algorithm-expression: book_content${index_id % 10} + + + +props: + # 是否在日志中打印 SQL + sql-show: true From 4b00ea68a9127086d9b57a5ed92316db7abb0e11 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 19 Mar 2025 00:09:10 +0800 Subject: [PATCH 40/95] =?UTF-8?q?perf:=20=E6=8F=90=E9=AB=98=E7=AC=AC?= =?UTF-8?q?=E4=B8=80=E6=AC=A1=E7=99=BB=E5=BD=95=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/java2nb/AdminApplication.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/novel-admin/src/main/java/com/java2nb/AdminApplication.java b/novel-admin/src/main/java/com/java2nb/AdminApplication.java index cb20c22..4c75cc6 100644 --- a/novel-admin/src/main/java/com/java2nb/AdminApplication.java +++ b/novel-admin/src/main/java/com/java2nb/AdminApplication.java @@ -11,6 +11,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.transaction.annotation.EnableTransactionManagement; +import javax.sql.DataSource; import java.net.InetAddress; @@ -18,19 +19,25 @@ import java.net.InetAddress; @ServletComponentScan @MapperScan("com.java2nb.*.dao") @SpringBootApplication(exclude = { - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class + org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class }) @EnableCaching @Slf4j public class AdminApplication { + public static void main(String[] args) { SpringApplication.run(AdminApplication.class, args); } @Bean - public CommandLineRunner commandLineRunner(ApplicationContext ctx) { + public CommandLineRunner commandLineRunner(ApplicationContext ctx, DataSource dataSource) { return args -> { - log.info("项目启动啦,访问路径:{}", "http://" + InetAddress.getLocalHost().getHostAddress() + ":" + ctx.getEnvironment().getProperty("server.port")); + // 提前创建连接池,而不是在第一次访问数据库时才创建,提高第一次登录速度 + log.info("创建连接池..."); + dataSource.getConnection(); + log.info("项目启动啦,访问路径:{}", + "http://" + InetAddress.getLocalHost().getHostAddress() + ":" + ctx.getEnvironment() + .getProperty("server.port")); }; } From acf9c76757c194b37498f5b3442985e41fc35cc3 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 19 Mar 2025 07:50:50 +0800 Subject: [PATCH 41/95] =?UTF-8?q?perf:=20=E6=8F=90=E5=89=8D=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E6=95=B0=E6=8D=AE=E5=BA=93=E8=BF=9E=E6=8E=A5=E6=B1=A0?= =?UTF-8?q?=20Spring=20Boot=20=E6=96=B0=E7=89=88=E6=9C=AC=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E4=BC=9A=E5=9C=A8=E7=AC=AC=E4=B8=80=E6=AC=A1=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E6=95=B0=E6=8D=AE=E5=BA=93=E6=97=B6=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/java2nb/AdminApplication.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/novel-admin/src/main/java/com/java2nb/AdminApplication.java b/novel-admin/src/main/java/com/java2nb/AdminApplication.java index 4c75cc6..ccf4958 100644 --- a/novel-admin/src/main/java/com/java2nb/AdminApplication.java +++ b/novel-admin/src/main/java/com/java2nb/AdminApplication.java @@ -1,5 +1,6 @@ package com.java2nb; +import com.zaxxer.hikari.HikariDataSource; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.CommandLineRunner; @@ -13,6 +14,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; import java.net.InetAddress; +import java.sql.Connection; @EnableTransactionManagement @@ -34,7 +36,14 @@ public class AdminApplication { return args -> { // 提前创建连接池,而不是在第一次访问数据库时才创建,提高第一次登录速度 log.info("创建连接池..."); - dataSource.getConnection(); + try (Connection connection = dataSource.getConnection()) { + HikariDataSource hikariDataSource = (HikariDataSource) dataSource; + log.info("最小空闲连接数:{}", hikariDataSource.getMinimumIdle()); + log.info("最大连接数:{}", hikariDataSource.getMaximumPoolSize()); + log.info("创建连接池完成."); + log.info("数据库:{}", connection.getMetaData().getDatabaseProductName()); + log.info("数据库版本:{}", connection.getMetaData().getDatabaseProductVersion()); + } log.info("项目启动啦,访问路径:{}", "http://" + InetAddress.getLocalHost().getHostAddress() + ":" + ctx.getEnvironment() .getProperty("server.port")); From 82658f3b5f5ddac4a4fa4e5180823f4a34af38af Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 19 Mar 2025 08:03:45 +0800 Subject: [PATCH 42/95] =?UTF-8?q?perf:=20=E5=85=BC=E5=AE=B9=E5=85=B6?= =?UTF-8?q?=E5=AE=83=E6=95=B0=E6=8D=AE=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/java2nb/AdminApplication.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/novel-admin/src/main/java/com/java2nb/AdminApplication.java b/novel-admin/src/main/java/com/java2nb/AdminApplication.java index ccf4958..5ba01df 100644 --- a/novel-admin/src/main/java/com/java2nb/AdminApplication.java +++ b/novel-admin/src/main/java/com/java2nb/AdminApplication.java @@ -34,15 +34,17 @@ public class AdminApplication { @Bean public CommandLineRunner commandLineRunner(ApplicationContext ctx, DataSource dataSource) { return args -> { - // 提前创建连接池,而不是在第一次访问数据库时才创建,提高第一次登录速度 - log.info("创建连接池..."); - try (Connection connection = dataSource.getConnection()) { - HikariDataSource hikariDataSource = (HikariDataSource) dataSource; - log.info("最小空闲连接数:{}", hikariDataSource.getMinimumIdle()); - log.info("最大连接数:{}", hikariDataSource.getMaximumPoolSize()); - log.info("创建连接池完成."); - log.info("数据库:{}", connection.getMetaData().getDatabaseProductName()); - log.info("数据库版本:{}", connection.getMetaData().getDatabaseProductVersion()); + if (dataSource instanceof HikariDataSource) { + // 如果使用的是HikariDataSource,需要提前创建连接池,而不是在第一次访问数据库时才创建,提高第一次登录的速度 + log.info("创建连接池..."); + try (Connection connection = dataSource.getConnection()) { + HikariDataSource hikariDataSource = (HikariDataSource) dataSource; + log.info("最小空闲连接数:{}", hikariDataSource.getMinimumIdle()); + log.info("最大连接数:{}", hikariDataSource.getMaximumPoolSize()); + log.info("创建连接池完成."); + log.info("数据库:{}", connection.getMetaData().getDatabaseProductName()); + log.info("数据库版本:{}", connection.getMetaData().getDatabaseProductVersion()); + } } log.info("项目启动啦,访问路径:{}", "http://" + InetAddress.getLocalHost().getHostAddress() + ":" + ctx.getEnvironment() From 4b1507b2d1b17b1d40b60e9190a2a796dc0c2b34 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 19 Mar 2025 10:04:54 +0800 Subject: [PATCH 43/95] =?UTF-8?q?perf:=20=E8=BF=9E=E6=8E=A5=E6=B1=A0?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/java2nb/AdminApplication.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/novel-admin/src/main/java/com/java2nb/AdminApplication.java b/novel-admin/src/main/java/com/java2nb/AdminApplication.java index 5ba01df..92135e9 100644 --- a/novel-admin/src/main/java/com/java2nb/AdminApplication.java +++ b/novel-admin/src/main/java/com/java2nb/AdminApplication.java @@ -1,6 +1,5 @@ package com.java2nb; -import com.zaxxer.hikari.HikariDataSource; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.CommandLineRunner; @@ -34,22 +33,15 @@ public class AdminApplication { @Bean public CommandLineRunner commandLineRunner(ApplicationContext ctx, DataSource dataSource) { return args -> { - if (dataSource instanceof HikariDataSource) { - // 如果使用的是HikariDataSource,需要提前创建连接池,而不是在第一次访问数据库时才创建,提高第一次登录的速度 - log.info("创建连接池..."); - try (Connection connection = dataSource.getConnection()) { - HikariDataSource hikariDataSource = (HikariDataSource) dataSource; - log.info("最小空闲连接数:{}", hikariDataSource.getMinimumIdle()); - log.info("最大连接数:{}", hikariDataSource.getMaximumPoolSize()); - log.info("创建连接池完成."); - log.info("数据库:{}", connection.getMetaData().getDatabaseProductName()); - log.info("数据库版本:{}", connection.getMetaData().getDatabaseProductVersion()); - } + log.info("创建连接池..."); + try (Connection connection = dataSource.getConnection()) { + log.info("创建连接池完成."); + log.info("数据库:{}", connection.getMetaData().getDatabaseProductName()); + log.info("数据库版本:{}", connection.getMetaData().getDatabaseProductVersion()); } log.info("项目启动啦,访问路径:{}", "http://" + InetAddress.getLocalHost().getHostAddress() + ":" + ctx.getEnvironment() .getProperty("server.port")); }; } - } From 1081b8e10a201c09eb094250d10dbabdfcce75b3 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Wed, 19 Mar 2025 10:12:22 +0800 Subject: [PATCH 44/95] =?UTF-8?q?chore:=20=E4=BF=AE=E6=94=B9=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-admin/src/main/java/com/java2nb/AdminApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/novel-admin/src/main/java/com/java2nb/AdminApplication.java b/novel-admin/src/main/java/com/java2nb/AdminApplication.java index 92135e9..29b7a12 100644 --- a/novel-admin/src/main/java/com/java2nb/AdminApplication.java +++ b/novel-admin/src/main/java/com/java2nb/AdminApplication.java @@ -35,7 +35,7 @@ public class AdminApplication { return args -> { log.info("创建连接池..."); try (Connection connection = dataSource.getConnection()) { - log.info("创建连接池完成."); + log.info("连接池已创建."); log.info("数据库:{}", connection.getMetaData().getDatabaseProductName()); log.info("数据库版本:{}", connection.getMetaData().getDatabaseProductVersion()); } From 99f2a159909659b5571b68bcc2678965f2375e48 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 12:21:45 +0800 Subject: [PATCH 45/95] =?UTF-8?q?build:=20=E5=88=9B=E5=BB=BA=20GitHub=20Ac?= =?UTF-8?q?tions=20=E5=B7=A5=E4=BD=9C=E6=B5=81=E8=87=AA=E5=8A=A8=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 54 +++++++++++++++++++++++++++++++++++ novel-common/pom.xml | 24 ++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..7a0dbeb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,54 @@ +name: Create novel-plus Maven Release with ZIPs + +on: + push: + # 匹配所有以'v'开头的标签 + tags: + - 'v*' + +jobs: + build-and-release: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: '21' + # 可选,默认是 temurin,也可以选择其他发行版 + distribution: 'temurin' + + - name: Build project with Maven + run: mvn clean install -DskipTests=true + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # 使用 tag_name 而不是 github.ref + tag_name: ${{ github.ref_name }} + release_name: novel-plus ${{ github.ref_name }} + draft: false + prerelease: false + + - name: Upload all *.zip artifacts from submodules + run: | + for module in novel-common novel-crawl novel-front novel-admin + do + for file in $(find ./$module/target/build -type f -name "*.zip") + do + asset_path="$file" + asset_name=$(basename "$file") + echo "Uploading $asset_name..." + curl -X POST \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/zip" \ + --data-binary @"$file" \ + "${{ steps.create_release.outputs.upload_url }}?name=$asset_name" + done + done \ No newline at end of file diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 1b9292b..6b4a68b 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -130,5 +130,29 @@ + + + + maven-antrun-plugin + 1.8 + + + package + + run + + + + + + + + + + + + + + \ No newline at end of file From d955b1116564d08b01657c18bd4cbed990639529 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 12:21:45 +0800 Subject: [PATCH 46/95] =?UTF-8?q?ci:=20=E5=88=9B=E5=BB=BA=20GitHub=20Actio?= =?UTF-8?q?ns=20=E5=B7=A5=E4=BD=9C=E6=B5=81=E8=87=AA=E5=8A=A8=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 54 +++++++++++++++++++++++++++++++++++ novel-common/pom.xml | 24 ++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..7a0dbeb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,54 @@ +name: Create novel-plus Maven Release with ZIPs + +on: + push: + # 匹配所有以'v'开头的标签 + tags: + - 'v*' + +jobs: + build-and-release: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: '21' + # 可选,默认是 temurin,也可以选择其他发行版 + distribution: 'temurin' + + - name: Build project with Maven + run: mvn clean install -DskipTests=true + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # 使用 tag_name 而不是 github.ref + tag_name: ${{ github.ref_name }} + release_name: novel-plus ${{ github.ref_name }} + draft: false + prerelease: false + + - name: Upload all *.zip artifacts from submodules + run: | + for module in novel-common novel-crawl novel-front novel-admin + do + for file in $(find ./$module/target/build -type f -name "*.zip") + do + asset_path="$file" + asset_name=$(basename "$file") + echo "Uploading $asset_name..." + curl -X POST \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/zip" \ + --data-binary @"$file" \ + "${{ steps.create_release.outputs.upload_url }}?name=$asset_name" + done + done \ No newline at end of file diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 1b9292b..6b4a68b 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -130,5 +130,29 @@ + + + + maven-antrun-plugin + 1.8 + + + package + + run + + + + + + + + + + + + + + \ No newline at end of file From 6cdb68899bc7c5708ed2ee4b21b83e643e260675 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 13:26:10 +0800 Subject: [PATCH 47/95] =?UTF-8?q?ci:=20GitHub=20Actions=20=E6=8C=87?= =?UTF-8?q?=E5=AE=9A=E4=B8=AD=E5=A4=AE=E4=BB=93=E5=BA=93=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=20maven=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 2 +- novel-admin/pom.xml | 31 +++++++++++++++++++++++++++++++ pom.xml | 31 +++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7a0dbeb..6ac888f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,7 @@ jobs: distribution: 'temurin' - name: Build project with Maven - run: mvn clean install -DskipTests=true + run: mvn clean install -DskipTests=true -Pcentral-repo - name: Create Release id: create_release diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index b1d9fad..1140350 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -332,4 +332,35 @@ + + + + + central-repo + + + central + https://repo.maven.apache.org/maven2/ + + true + + + false + + + + + + central-plugin + https://repo.maven.apache.org/maven2/ + + true + + + false + + + + + diff --git a/pom.xml b/pom.xml index 4ac1f58..661c29d 100644 --- a/pom.xml +++ b/pom.xml @@ -113,4 +113,35 @@ + + + + + central-repo + + + central + https://repo.maven.apache.org/maven2/ + + true + + + false + + + + + + central-plugin + https://repo.maven.apache.org/maven2/ + + true + + + false + + + + + From 5dcc2b0b46f9614b30e53081e7c4d7ae3d9c13a2 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 13:27:46 +0800 Subject: [PATCH 48/95] =?UTF-8?q?v5.0.1=20=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-admin/pom.xml | 2 +- novel-common/pom.xml | 2 +- novel-crawl/pom.xml | 2 +- novel-front/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index 1140350..e32cea5 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel-admin - 5.0.1-SNAPSHOT + 5.0.1 jar novel-admin diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 6b4a68b..ed24e2f 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.1-SNAPSHOT + 5.0.1 4.0.0 diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index f0e6a6a..8f63044 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.1-SNAPSHOT + 5.0.1 4.0.0 diff --git a/novel-front/pom.xml b/novel-front/pom.xml index c5e315a..57c8f18 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.0.1-SNAPSHOT + 5.0.1 4.0.0 diff --git a/pom.xml b/pom.xml index 661c29d..d03c874 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel - 5.0.1-SNAPSHOT + 5.0.1 novel-common novel-front From c0634a335ed8d0ebe79f90b03b2e7d12bbd0ac67 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 14:48:42 +0800 Subject: [PATCH 49/95] =?UTF-8?q?ci:=20GitHub=20Actions=20=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0ZIP=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 49 +++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6ac888f..79e8a3a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,19 +36,36 @@ jobs: draft: false prerelease: false - - name: Upload all *.zip artifacts from submodules - run: | - for module in novel-common novel-crawl novel-front novel-admin - do - for file in $(find ./$module/target/build -type f -name "*.zip") - do - asset_path="$file" - asset_name=$(basename "$file") - echo "Uploading $asset_name..." - curl -X POST \ - -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - -H "Content-Type: application/zip" \ - --data-binary @"$file" \ - "${{ steps.create_release.outputs.upload_url }}?name=$asset_name" - done - done \ No newline at end of file + + # 使用 action 来替代直接 curl 进行上传 + - name: Upload sql.zip + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ github.workspace }}/novel-common/target/build/sql.zip + asset_name: sql.zip + asset_content_type: application/zip + + - name: Upload novel-crawl.zip + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ github.workspace }}/novel-crawl/target/build/novel-crawl.zip + asset_name: novel-crawl.zip + asset_content_type: application/zip + + - name: Upload novel-front.zip + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ github.workspace }}/novel-front/target/build/novel-front.zip + asset_name: novel-front.zip + asset_content_type: application/zip + + - name: Upload novel-admin.zip + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ github.workspace }}/novel-admin/target/build/novel-admin.zip + asset_name: novel-admin.zip + asset_content_type: application/zip \ No newline at end of file From 73654dda2b62016dfcdddb1be108a67bc8af38c4 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 14:58:26 +0800 Subject: [PATCH 50/95] =?UTF-8?q?ci:=20GitHub=20Actions=20=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E4=B8=8A=E4=BC=A0=20token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 79e8a3a..229bd24 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,6 +40,8 @@ jobs: # 使用 action 来替代直接 curl 进行上传 - name: Upload sql.zip uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ${{ github.workspace }}/novel-common/target/build/sql.zip @@ -48,6 +50,8 @@ jobs: - name: Upload novel-crawl.zip uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ${{ github.workspace }}/novel-crawl/target/build/novel-crawl.zip @@ -56,6 +60,8 @@ jobs: - name: Upload novel-front.zip uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ${{ github.workspace }}/novel-front/target/build/novel-front.zip @@ -64,6 +70,8 @@ jobs: - name: Upload novel-admin.zip uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ${{ github.workspace }}/novel-admin/target/build/novel-admin.zip From 06074faf9af103fcccb2437baa073c1f60ba9add Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 17:30:18 +0800 Subject: [PATCH 51/95] =?UTF-8?q?feat(pc):=20=E7=A7=BB=E9=99=A4=E4=B9=A6?= =?UTF-8?q?=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/templates/user/favorites.html | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/novel-front/src/main/resources/templates/user/favorites.html b/novel-front/src/main/resources/templates/user/favorites.html index 985bec0..92facf3 100644 --- a/novel-front/src/main/resources/templates/user/favorites.html +++ b/novel-front/src/main/resources/templates/user/favorites.html @@ -53,7 +53,7 @@ 更新时间 - 书签 + 操作 @@ -94,7 +94,7 @@ var bookShelfListHtml = ""; for (var i = 0; i < bookShelfList.length; i++) { var book = bookShelfList[i]; - bookShelfListHtml += (" \n" + + bookShelfListHtml += (" \n" + " \n" + " [" + book.catName + "]\n" + " \n" + @@ -109,7 +109,8 @@ " " + book.lastIndexUpdateTime + "\n" + " \n" + " \n" + - "继续阅读" + + "" + + "" + " \n" + " "); } @@ -160,5 +161,21 @@ }) } + + function removeFromBookShelf(bookId) { + + $.ajax({ + type: "delete", + url: "/user/removeFromBookShelf/" + bookId, + data: {}, + dataType: "json", + success: function (data) { + if (data.code == 200) { + $("#shelf" + bookId).remove(); + } + } + }); + + } From ec9674f2aaac006b8d56d3bc12fa1d9e8e2a5d1d Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 21:51:51 +0800 Subject: [PATCH 52/95] =?UTF-8?q?feat:=20=E7=A7=BB=E5=87=BA=E4=B9=A6?= =?UTF-8?q?=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/mobile/user/favorites.html | 138 +++++++++++++++--- .../resources/templates/user/favorites.html | 2 +- 2 files changed, 121 insertions(+), 19 deletions(-) diff --git a/novel-front/src/main/resources/templates/mobile/user/favorites.html b/novel-front/src/main/resources/templates/mobile/user/favorites.html index 44d3d44..793c76f 100644 --- a/novel-front/src/main/resources/templates/mobile/user/favorites.html +++ b/novel-front/src/main/resources/templates/mobile/user/favorites.html @@ -20,6 +20,28 @@ - @@ -95,6 +127,10 @@
    +
    @@ -105,11 +141,12 @@ -
    diff --git a/novel-front/src/main/resources/templates/user/favorites.html b/novel-front/src/main/resources/templates/user/favorites.html index 92facf3..08ebb60 100644 --- a/novel-front/src/main/resources/templates/user/favorites.html +++ b/novel-front/src/main/resources/templates/user/favorites.html @@ -110,7 +110,7 @@ " \n" + " \n" + "" + - "" + + "" + " \n" + " "); } From e4e511aed867b88187db7b364670c04c640a6238 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Thu, 20 Mar 2025 22:03:10 +0800 Subject: [PATCH 53/95] =?UTF-8?q?feat:=20=E7=A7=BB=E5=87=BA=E4=B9=A6?= =?UTF-8?q?=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../green/html/mobile/user/favorites.html | 138 +++++++++++++++--- templates/green/html/user/favorites.html | 23 ++- 2 files changed, 140 insertions(+), 21 deletions(-) diff --git a/templates/green/html/mobile/user/favorites.html b/templates/green/html/mobile/user/favorites.html index 44d3d44..793c76f 100644 --- a/templates/green/html/mobile/user/favorites.html +++ b/templates/green/html/mobile/user/favorites.html @@ -20,6 +20,28 @@ - @@ -95,6 +127,10 @@
    +
    @@ -105,11 +141,12 @@ -
    diff --git a/templates/green/html/user/favorites.html b/templates/green/html/user/favorites.html index 985bec0..08ebb60 100644 --- a/templates/green/html/user/favorites.html +++ b/templates/green/html/user/favorites.html @@ -53,7 +53,7 @@ 更新时间 - 书签 + 操作 @@ -94,7 +94,7 @@ var bookShelfListHtml = ""; for (var i = 0; i < bookShelfList.length; i++) { var book = bookShelfList[i]; - bookShelfListHtml += (" \n" + + bookShelfListHtml += (" \n" + " \n" + " [" + book.catName + "]\n" + " \n" + @@ -109,7 +109,8 @@ " " + book.lastIndexUpdateTime + "\n" + " \n" + " \n" + - "继续阅读" + + "" + + "" + " \n" + " "); } @@ -160,5 +161,21 @@ }) } + + function removeFromBookShelf(bookId) { + + $.ajax({ + type: "delete", + url: "/user/removeFromBookShelf/" + bookId, + data: {}, + dataType: "json", + success: function (data) { + if (data.code == 200) { + $("#shelf" + bookId).remove(); + } + } + }); + + } From f8079f443aea6e116d91cba99a634f927d3e7499 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 21 Mar 2025 13:14:01 +0800 Subject: [PATCH 54/95] Update README.md --- README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 707aa1d..0efc1a6 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ novel-plus 是一个多端(PC、WAP)阅读,功能完善的原创文学 CMS 系统。由前台门户系统、作家后台管理系统、平台后台管理系统和爬虫管理系统等多个子系统构成,包括小说推荐、作品检索、小说排行、小说阅读、小说评论、会员中心、作家专区等功能,支持自定义多模版、可拓展的多种小说内容存储方式(内置数据库分表存储和 -TXT 文本存储)、阅读主题切换、多爬虫源自动采集和更新数据、会员充值、订阅模式、新闻发布和实时统计报表。 +TXT 文本存储)、阅读主题切换、多爬虫源自动采集和更新数据、AI写作、会员充值、订阅模式、新闻发布和实时统计报表。 ## 项目地址 @@ -67,6 +67,28 @@ novel-plus -- 父工程 [![点击查看大图](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png)](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png) [![点击查看大图](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png)](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png) +## AI写作 + +novel-plus 5.x 版本已集成 Spring 官方最新发布的 Spring AI 框架,在小说章节发布页面的文本编辑器中推出了多项智能编辑功能,包括 AI 扩写、缩写、续写及文本润色等。这些功能的设计灵感来源于百家号文章编辑器中的 AI 助手。 + +目前,AI 编辑功能仍处于实验阶段,仅实现了基础的核心功能。我们非常重视用户的实际使用体验和反馈,未来将根据用户需求和使用情况,持续优化和调整该功能。如果用户反馈积极,我们计划进一步开发更高级的 AI 功能,例如自动生成有声小说、智能情节推荐等,以全面提升 novel-plus 的创作能力和用户体验。 + +我们将持续关注 AI 技术的发展,并致力于将其与小说创作场景深度融合,为用户带来更智能、更便捷的创作工具。 + +由于 DeepSeek 官方 API 目前不可用,novel-plus 项目默认使用的是第三方[硅基流动](https://cloud.siliconflow.cn/i/DOgMRH9S)提供的 API,采用的 AI 模型为:`deepseek-ai/DeepSeek-R1-Distill-Llama-8B`(DeepSeek-R1 的蒸馏版本,免费使用)。只需注册一个硅基流动账号,创建一个 API 密钥,并将其添加到 novel-plus 项目 novel-front 模块的 yaml 配置文件中,即可体验 novel-plus 项目的 AI 写作功能。 + +```yaml +spring: + ai: + openai: + api-key: sk-rrrupturhdofbiqzjutduuiceecpvfqlnvmgcyiaipbdikoi + base-url: https://api.siliconflow.cn + chat: + options: + model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B +``` + +![](https://www.xxyopen.com/images/ai_editor.png) ## 演示视频 https://www.bilibili.com/video/BV18e41197xs From 970ad407f1e57ae72300679c933a2aaa17ff5fd2 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 23 Mar 2025 06:44:31 +0800 Subject: [PATCH 55/95] =?UTF-8?q?perf:=20AI=E5=86=85=E5=AE=B9=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=A4=B1=E8=B4=A5=E6=8F=90=E9=86=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/templates/author/content_add.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/novel-front/src/main/resources/templates/author/content_add.html b/novel-front/src/main/resources/templates/author/content_add.html index 771f2fd..7e4c0c8 100644 --- a/novel-front/src/main/resources/templates/author/content_add.html +++ b/novel-front/src/main/resources/templates/author/content_add.html @@ -347,8 +347,12 @@ success: function(res){ layer.close(loading); // 将生成的内容追加到文本末尾 - const newText = "\n\n" + res.data; // 添加换行符分隔 - typeWriter(textarea, newText); // 使用打字机效果 + if(res.code == '200'){ + const newText = "\n\n【AI生成内容】" + res.data; // 添加换行符分隔 + typeWriter(textarea, newText); // 使用打字机效果 + }else{ + layer.msg('AI内容生成失败,请稍后重试'); + } }, error: function(){ layer.msg('请求失败,请稍后重试'); From 04fc8e878add7f603a0232472a4435cda88bf250 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 23 Mar 2025 09:28:01 +0800 Subject: [PATCH 56/95] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=8D=87?= =?UTF-8?q?=E7=BA=A7v5.0.0=E5=AF=BC=E8=87=B4=E5=9B=BE=E7=89=87=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 当使用 `$.ajax`发起异步请求时 ,设置`dataType: "json"`会在请求头中自动添加`Accept: application/json`,表示客户端期望服务器返回`JSON`格式的数据。 - 当使用 `$.ajaxFileUpload` 上传文件时,它的行为与`$.ajax`不同,不会自动修改`Accept`请求头,即使设置了`dataType: "json"` `$.ajaxFileUpload`也不会在请求头中添加`Accept: application/json`。 Spring Boot 默认返回`JSON`格式的响应,但它支持内容协商,它会根据客户端请求的`Accept`头来决定返回的响应格式。如果浏览器发送的请求中 `Accept`头包含`application/xml`,并且 Spring Boot 支持`XML`格式响应的话,Spring Boot 会返`XML`格式的响应。但 Spring Boot 默认不支持`XML`格式的响应,当升级`Sharding-JDBC `版本后,自动引入了`jackson-dataformat-xml`依赖,才开始支持`XML`格式的响应,由于`$.ajaxFileUpload`上传文件的默认`Accept`头包含`application/xml`,所以需要在后端上传文件接口处明确指定返回的数据类型为`application/json`。 --- .../java2nb/novel/controller/FileController.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/FileController.java b/novel-front/src/main/java/com/java2nb/novel/controller/FileController.java index 7f6f39c..46f5524 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/FileController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/FileController.java @@ -17,6 +17,7 @@ import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.http.client.utils.DateUtils; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -61,11 +62,20 @@ public class FileController { /** * 图片上传 * - * @return + * - 当使用 `$.ajax`发起异步请求时 ,设置`dataType: "json"`会在请求头中自动添加`Accept: application/json`,表示客户端期望服务器返回 + * `JSON`格式的数据。 + * - 当使用 `$.ajaxFileUpload` 上传文件时,它的行为与`$.ajax`不同,不会自动修改`Accept`请求头,即使设置了`dataType: "json"`, + * `$.ajaxFileUpload`也不会在请求头中添加`Accept: application/json`。 + * + * Spring Boot 默认返回`JSON`格式的响应,但它支持内容协商,它会根据客户端请求的`Accept`头来决定返回的响应格式。 + * 如果浏览器发送的请求中`Accept`头包含`application/xml`,并且 Spring Boot 支持`XML`格式响应的话,Spring Boot 会返回`XML`格式的响应。 + * 但 Spring Boot 默认不支持`XML`格式的响应,当升级`Sharding-JDBC `版本后,自动引入了`jackson-dataformat-xml`依赖,才开始支持`XML`格式的响应, + * 由于`$.ajaxFileUpload`上传文件的默认`Accept`头包含`application/xml`,所以需要在后端上传文件接口处明确指定返回的数据类型为`application/json`。 + * */ @SneakyThrows @ResponseBody - @PostMapping("/picUpload") + @PostMapping(value = "/picUpload", produces = MediaType.APPLICATION_JSON_VALUE) RestResult upload(@RequestParam("file") MultipartFile file) { Date currentDate = new Date(); String savePath = From 328bd5558781ed4909c3646146ad26d3097e5eb5 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sun, 23 Mar 2025 11:46:12 +0800 Subject: [PATCH 57/95] =?UTF-8?q?feat:=20AI=E8=87=AA=E5=8A=A8=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=B0=8F=E8=AF=B4=E5=B0=81=E9=9D=A2=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 63 +++++++++++-------- .../java2nb/novel/core/utils/FileUtil.java | 23 +++++++ .../novel/service/impl/BookServiceImpl.java | 48 +++++++++++++- .../src/main/resources/application.yml | 12 ++-- .../resources/templates/author/index.html | 15 ++++- 5 files changed, 126 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 0efc1a6..3a1c24d 100644 --- a/README.md +++ b/README.md @@ -39,25 +39,25 @@ novel-plus -- 父工程 ## 技术选型 -| 技术 | 说明 -|---------------------| --------------------------- -| Spring Boot | Spring 应用快速开发脚手架 -| Spring AI | Spring 官方 AI 框架 -| MyBatis | 持久层 ORM 框架 -| MyBatis Dynamic SQL | Mybatis 动态 sql -| PageHelper | MyBatis 分页插件 -| MyBatis Generator | 持久层代码生成插件 -| Sharding-JDBC | 代码层分库分表中间件 -| JJWT | JWT 登录支持 -| Spring Security | 安全框架 -| Apache Shiro | 安全框架 -| Redis | 缓存方案 -| Aliyun OSS | 阿里云对象存储服务(图片存储备选方案) -| Lombok | 简化对象封装工具 -| Docker | 应用容器引擎 -| MySQL | 数据库服务 -| Thymeleaf | 模板引擎 -| Layui | 前端 UI 框架 +| 技术 | 说明 +|---------------------|--------------------- +| Spring Boot | Spring 应用快速开发脚手架 +| Spring AI | Spring 官方 AI 框架 +| MyBatis | 持久层 ORM 框架 +| MyBatis Dynamic SQL | Mybatis 动态 sql +| PageHelper | MyBatis 分页插件 +| MyBatis Generator | 持久层代码生成插件 +| Sharding-JDBC | 代码层分库分表中间件 +| JJWT | JWT 登录支持 +| Spring Security | 安全框架 +| Apache Shiro | 安全框架 +| Redis | 缓存方案 +| Aliyun OSS | 阿里云对象存储服务(图片存储备选方案) +| Lombok | 简化对象封装工具 +| Docker | 应用容器引擎 +| MySQL | 数据库服务 +| Thymeleaf | 模板引擎 +| Layui | 前端 UI 框架 ## 项目截图 @@ -67,15 +67,25 @@ novel-plus -- 父工程 [![点击查看大图](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png)](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png) [![点击查看大图](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png)](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png) -## AI写作 +## 演示视频 -novel-plus 5.x 版本已集成 Spring 官方最新发布的 Spring AI 框架,在小说章节发布页面的文本编辑器中推出了多项智能编辑功能,包括 AI 扩写、缩写、续写及文本润色等。这些功能的设计灵感来源于百家号文章编辑器中的 AI 助手。 +https://www.bilibili.com/video/BV18e41197xs -目前,AI 编辑功能仍处于实验阶段,仅实现了基础的核心功能。我们非常重视用户的实际使用体验和反馈,未来将根据用户需求和使用情况,持续优化和调整该功能。如果用户反馈积极,我们计划进一步开发更高级的 AI 功能,例如自动生成有声小说、智能情节推荐等,以全面提升 novel-plus 的创作能力和用户体验。 +## AI 功能 + +novel-plus 5.x 已集成 Spring 官方最新发布的 Spring AI 框架,并推出多项 AI 功能: + +1. v5.0.0 版本在小说章节发布页面的文本编辑器中集成了多项智能编辑功能,包括 AI 扩写、缩写、续写及文本润色等。这些功能的设计灵感来源于百家号文章编辑器中的 AI 助手。 +2. v5.1.0 版本在小说发布页面,新增 AI 生成封面图功能。若作家未上传自定义封面图,系统将根据小说信息自动生成封面图。 + +目前,AI 功能仍处于实验阶段,仅实现了基础的核心功能。我们非常重视用户的实际使用体验和反馈,未来将根据用户需求和使用情况,持续优化和调整该功能。如果用户反馈积极,我们计划进一步开发更高级的 +AI 功能,例如自动生成有声小说、智能情节推荐等,以全面提升 novel-plus 的创作能力和用户体验。 我们将持续关注 AI 技术的发展,并致力于将其与小说创作场景深度融合,为用户带来更智能、更便捷的创作工具。 -由于 DeepSeek 官方 API 目前不可用,novel-plus 项目默认使用的是第三方[硅基流动](https://cloud.siliconflow.cn/i/DOgMRH9S)提供的 API,采用的 AI 模型为:`deepseek-ai/DeepSeek-R1-Distill-Llama-8B`(DeepSeek-R1 的蒸馏版本,免费使用)。只需注册一个硅基流动账号,创建一个 API 密钥,并将其添加到 novel-plus 项目 novel-front 模块的 yaml 配置文件中,即可体验 novel-plus 项目的 AI 写作功能。 +由于 DeepSeek 官方 API 目前不可用,novel-plus 项目默认使用的是第三方[硅基流动](https://cloud.siliconflow.cn/i/DOgMRH9S) +提供的 API,采用的 AI 模型有对话模型`deepseek-ai/DeepSeek-R1-Distill-Llama-8B`(DeepSeek-R1 的蒸馏版本,免费使用)和生图模型`Kwai-Kolors/Kolors`(快手 Kolors 团队开发的文本到图像生成模型,免费使用)。只需注册一个硅基流动账号,创建一个 +API 密钥,并将其添加到 novel-plus 项目 novel-front 模块的 yaml 配置文件中,即可体验 novel-plus 项目的 AI 写作功能。 ```yaml spring: @@ -88,10 +98,7 @@ spring: model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B ``` -![](https://www.xxyopen.com/images/ai_editor.png) -## 演示视频 - -https://www.bilibili.com/video/BV18e41197xs +> ⚠️ novel-plus 项目默认使用的都是免费 AI 模型,生成效果有限。如果对生成内容有更高的要求,建议选用付费的 AI 模型。 ## 增值服务 @@ -117,3 +124,5 @@ https://www.bilibili.com/video/BV18e41197xs ## 免责声明 本项目提供的爬虫工具仅用于采集项目初期的测试数据,请勿用于商业盈利。 用户使用本系统从事任何违法违规的事情,一切后果由用户自行承担,作者不承担任何责任。 + + diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java index f64e4eb..656fe8f 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/FileUtil.java @@ -18,6 +18,11 @@ import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.util.Date; import java.util.Objects; @@ -125,5 +130,23 @@ public class FileUtil { } + /** + * 下载文件 + * + * @param downloadUrl 下载的URL + * @param savePath 保存的路径 + */ + @SneakyThrows + public void downloadFile(String downloadUrl, String savePath) { + Path path = Paths.get(savePath); + Path parentPath = path.getParent(); + if (Files.notExists(parentPath)) { + Files.createDirectories(parentPath); + } + URL url = new URL(downloadUrl); + try (InputStream in = url.openStream()) { + Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING); + } + } } diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java index 194908d..ccb878f 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java @@ -7,6 +7,7 @@ import com.java2nb.novel.core.cache.CacheService; import com.java2nb.novel.core.config.BookPriceProperties; import com.java2nb.novel.core.enums.ResponseStatus; import com.java2nb.novel.core.utils.Constants; +import com.java2nb.novel.core.utils.FileUtil; import com.java2nb.novel.core.utils.StringUtil; import com.java2nb.novel.entity.Book; import com.java2nb.novel.entity.*; @@ -27,10 +28,16 @@ import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.utils.DateUtils; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.render.RenderingStrategies; import org.mybatis.dynamic.sql.select.QueryExpressionDSL; import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.springframework.ai.image.Image; +import org.springframework.ai.image.ImagePrompt; +import org.springframework.ai.image.ImageResponse; +import org.springframework.ai.openai.OpenAiImageModel; +import org.springframework.ai.openai.OpenAiImageOptions; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -39,13 +46,16 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; +import java.util.concurrent.ThreadPoolExecutor; import java.util.stream.Collectors; import static com.java2nb.novel.mapper.BookCategoryDynamicSqlSupport.bookCategory; +import static com.java2nb.novel.mapper.BookCategoryDynamicSqlSupport.sort; import static com.java2nb.novel.mapper.BookCommentDynamicSqlSupport.bookComment; import static com.java2nb.novel.mapper.BookContentDynamicSqlSupport.bookContent; import static com.java2nb.novel.mapper.BookContentDynamicSqlSupport.content; import static com.java2nb.novel.mapper.BookDynamicSqlSupport.*; +import static com.java2nb.novel.mapper.BookDynamicSqlSupport.book; import static com.java2nb.novel.mapper.BookIndexDynamicSqlSupport.bookIndex; import static com.java2nb.novel.mapper.BookSettingDynamicSqlSupport.bookSetting; import static org.mybatis.dynamic.sql.SqlBuilder.*; @@ -87,6 +97,10 @@ public class BookServiceImpl implements BookService { private final BookPriceProperties bookPriceConfig; + private final OpenAiImageModel openAiImageModel; + + private final ThreadPoolExecutor threadPoolExecutor; + private final IdWorker idWorker = IdWorker.INSTANCE; @@ -235,7 +249,7 @@ public class BookServiceImpl implements BookService { BookIndexDynamicSqlSupport.isVip) .from(bookIndex) .where(BookIndexDynamicSqlSupport.bookId, isEqualTo(bookId)); - if("index_num desc".equals(orderBy)){ + if ("index_num desc".equals(orderBy)) { where.orderBy(BookIndexDynamicSqlSupport.indexNum.descending()); } return bookIndexMapper.selectMany(where @@ -502,6 +516,7 @@ public class BookServiceImpl implements BookService { @Override public void addBook(Book book, Long authorId, String penName) { + book.setId(IdWorker.INSTANCE.nextId()); //判断小说名是否存在 if (queryIdByNameAndAuthor(book.getBookName(), penName) != null) { //该作者发布过此书名的小说 @@ -516,7 +531,36 @@ public class BookServiceImpl implements BookService { book.setCreateTime(new Date()); book.setUpdateTime(book.getCreateTime()); bookMapper.insertSelective(book); - + if (Objects.isNull(book.getPicUrl()) || !book.getPicUrl().startsWith(Constants.LOCAL_PIC_PREFIX)) { + // 用户没有上传封面图片,AI自动生成封面图片 + threadPoolExecutor.execute(() -> { + String prompt = String.format("生成一本小说的封面图片,图片中间显示书名《%s》,书名下方显示作者“%s 著”。", + book.getBookName(), book.getAuthorName()); + log.debug("prompt:{}", prompt); + ImageResponse response = openAiImageModel.call( + new ImagePrompt(prompt, + OpenAiImageOptions.builder() + .quality("hd") + .height(800) + .width(600).build()) + ); + Image output = response.getResult().getOutput(); + Date currentDate = new Date(); + String picUrl = Constants.LOCAL_PIC_PREFIX + + "aiGen/" + DateUtils.formatDate(currentDate, "yyyy") + "/" + + DateUtils.formatDate(currentDate, "MM") + "/" + + DateUtils.formatDate(currentDate, "dd") + "/" + book.getId() + ".png"; + FileUtil.downloadFile(output.getUrl(), picSavePath + picUrl); + bookMapper.update(update(BookDynamicSqlSupport.book) + .set(BookDynamicSqlSupport.picUrl) + .equalTo(picUrl) + .set(updateTime) + .equalTo(currentDate) + .where(id, isEqualTo(book.getId())) + .build() + .render(RenderingStrategies.MYBATIS3)); + }); + } } @Override diff --git a/novel-front/src/main/resources/application.yml b/novel-front/src/main/resources/application.yml index 1a64054..b4eda39 100644 --- a/novel-front/src/main/resources/application.yml +++ b/novel-front/src/main/resources/application.yml @@ -48,13 +48,17 @@ book: spring: ai: openai: - api-key: sk-nnhjmxuljagcuubbovjztbhkiawqaabzziazeurppinxtgva + image: + enabled: true + base-url: https://api.siliconflow.cn + api-key: sk-jjtixmivxaccndqgkqfkbgkzvmbctdxogcrfbjzfttbouitt + options: + model: Kwai-Kolors/Kolors + response_format: URL + api-key: sk-jjtixmivxaccndqgkqfkbgkzvmbctdxogcrfbjzfttbouitt base-url: https://api.siliconflow.cn chat: options: model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B - - - diff --git a/novel-front/src/main/resources/templates/author/index.html b/novel-front/src/main/resources/templates/author/index.html index b843bab..1a3c3da 100644 --- a/novel-front/src/main/resources/templates/author/index.html +++ b/novel-front/src/main/resources/templates/author/index.html @@ -51,7 +51,8 @@