Compare commits

...

3 Commits

Author SHA1 Message Date
8c7b891af2 build(AI): Spring AI 升级到 1.0.0 2025-07-18 21:24:24 +08:00
bb1a87e337 chore(sql): 内置海外专用源 2025-07-18 20:41:00 +08:00
1cd8a49fd4 perf: 优化排序参数校验 2025-07-18 16:21:35 +08:00
10 changed files with 71 additions and 29 deletions

View File

@ -3174,4 +3174,43 @@ CREATE TABLE `book_comment_reply`
`create_user_id` bigint(20) DEFAULT NULL COMMENT '回复时间', `create_user_id` bigint(20) DEFAULT NULL COMMENT '回复时间',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE = InnoDB ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='小说评论回复表'; DEFAULT CHARSET = utf8mb4 COMMENT ='小说评论回复表';
INSERT INTO crawl_source (source_name, crawl_rule, source_status, create_time
, update_time)
VALUES ('飘天文学网海外专用', '{
"bookListUrl": "https://www.piaotia.com/booksort{catId}/{page}.html",
"catIdRule": {
"catId1": "1/0",
"catId2": "2/0",
"catId3": "3/0",
"catId4": "4/0",
"catId5": "6/0",
"catId6": "5/0"
},
"bookIdPatten": "href=\\"https://www.piaotia.com/bookinfo/(\\\\d+/\\\\d+).html\\"",
"pagePatten": "<em\\\\s+id=\\"pagestats\\">(\\\\d+)/\\\\d+</em>",
"totalPagePatten": "<em\\\\s+id=\\"pagestats\\">\\\\d+/(\\\\d+)</em>",
"bookDetailUrl": "https://www.piaotia.com/bookinfo/{bookId}.html",
"bookNamePatten": "<h1>([^/]+)</h1>",
"authorNamePatten": "<td\\\\s+width=\\"\\\\d+%\\">作&nbsp;&nbsp;&nbsp; 者:([^/]+)<",
"picUrlPatten": "<img\\\\s+src=\\"(https://www.piaotia.com/files/article/image/[^\\"]+)\\"",
"statusPatten": "<td>文章状态:([^/]+)</td>",
"bookStatusRule": {
"连载中": 0,
"已完成": 1
},
"descStart": " <span class=\\"hottext\\">内容简介:</span><br />",
"descEnd": "</td>",
"filterDesc": "",
"bookIndexUrl": "https://www.piaotia.com/html/{bookId}/index.html",
"indexIdPatten": "<li><a href=\\"(\\\\d+).html\\">[^/]+</a></li>",
"indexNamePatten": "<li><a href=\\"\\\\d+.html\\">([^/]+)</a></li>",
"bookContentUrl": "https://www.piaotia.com/html/{bookId}/{indexId}.html",
"contentStart": "<br>",
"contentEnd": "</div>",
"filterContent": "",
"charset": "gbk"
}', 0, '2025-07-13 18:57:39'
, '2025-07-13 18:57:39');

View File

@ -25,10 +25,10 @@ import java.util.Map;
public class SortOrderValidationAspect { public class SortOrderValidationAspect {
/** /**
* 拦截所有的mapper方法 * 拦截mapper的所有list方法
*/ */
@SneakyThrows @SneakyThrows
@Around("execution(* com.java2nb.*.dao.*Dao.*(..))") @Around("execution(* com.java2nb.*.dao.*Dao.list*(..))")
public Object validateSortAndOrder(ProceedingJoinPoint joinPoint) { public Object validateSortAndOrder(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs(); Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();

View File

@ -14,8 +14,7 @@ import java.util.Set;
public class SortWhitelistUtil { public class SortWhitelistUtil {
private final Set<String> allowedColumns = new HashSet<>( private final Set<String> allowedColumns = new HashSet<>(
Arrays.asList("id", "name", "create_time", "update_time", "order_num", "last_index_update_time", "word_count", Arrays.asList("id", "name", "order_num"));
"visit_count"));
private final Set<String> allowedOrders = new HashSet<>(Arrays.asList("asc", "desc")); private final Set<String> allowedOrders = new HashSet<>(Arrays.asList("asc", "desc"));
public String sanitizeColumn(String input) { public String sanitizeColumn(String input) {

View File

@ -11,7 +11,6 @@ import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
/** /**
*
* @author xiongxy * @author xiongxy
* @email 1179705413@qq.com * @email 1179705413@qq.com
* @date 2019-10-03 09:45:11 * @date 2019-10-03 09:45:11
@ -19,23 +18,23 @@ import org.apache.ibatis.annotations.Param;
@Mapper @Mapper
public interface SysUserDao { public interface SysUserDao {
UserDO get(Long userId); UserDO get(Long userId);
List<UserDO> list(@ValidateSortOrder Map<String,Object> map);
int count(Map<String,Object> map);
int save(UserDO user);
int update(UserDO user);
int remove(Long userId);
int batchRemove(Long[] userIds);
Long[] listAllDept();
List<UserDO> listByPerm(Map<String, Object> map); List<UserDO> list(@ValidateSortOrder Map<String, Object> map);
int countByPerm(Map<String,Object> map); int count(Map<String, Object> map);
int save(UserDO user);
int update(UserDO user);
int remove(Long userId);
int batchRemove(Long[] userIds);
Long[] listAllDept();
List<UserDO> listByPerm(@ValidateSortOrder Map<String, Object> map);
int countByPerm(Map<String, Object> map);
} }

View File

@ -21,7 +21,7 @@ import java.util.*;
* @date 2025/7/17 * @date 2025/7/17
*/ */
@Aspect @Aspect
@Component //@Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class SortOrderValidationAspect { public class SortOrderValidationAspect {

View File

@ -59,7 +59,7 @@
<!-- AI --> <!-- AI -->
<dependency> <dependency>
<groupId>org.springframework.ai</groupId> <groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId> <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -15,6 +15,7 @@ import io.github.xxyopen.model.resp.RestResult;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.HashMap; import java.util.HashMap;
@ -82,7 +83,7 @@ public class BookController extends BaseController {
* 分页搜索 * 分页搜索
*/ */
@GetMapping("searchByPage") @GetMapping("searchByPage")
public RestResult<?> searchByPage(BookSpVO bookSP, @RequestParam(value = "curr", defaultValue = "1") int page, public RestResult<?> searchByPage(@Validated BookSpVO bookSP, @RequestParam(value = "curr", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "20") int pageSize) { @RequestParam(value = "limit", defaultValue = "20") int pageSize) {
return RestResult.ok(bookService.searchByPage(bookSP, page, pageSize)); return RestResult.ok(bookService.searchByPage(bookSP, page, pageSize));
} }

View File

@ -14,7 +14,7 @@ import java.util.List;
public interface FrontBookMapper extends BookMapper { public interface FrontBookMapper extends BookMapper {
List<BookVO> searchByPage(@ValidateSortOrder BookSpVO params); List<BookVO> searchByPage(BookSpVO params);
void addVisitCount(@Param("bookId") Long bookId, @Param("visitCount") Integer visitCount); void addVisitCount(@Param("bookId") Long bookId, @Param("visitCount") Integer visitCount);

View File

@ -1,6 +1,7 @@
package com.java2nb.novel.vo; package com.java2nb.novel.vo;
import com.java2nb.novel.core.vo.SortOrderVO; import com.java2nb.novel.core.vo.SortOrderVO;
import jakarta.validation.constraints.Pattern;
import lombok.Data; import lombok.Data;
import java.util.Date; import java.util.Date;
@ -10,7 +11,7 @@ import java.util.Date;
* @author 11797 * @author 11797
*/ */
@Data @Data
public class BookSpVO extends SortOrderVO { public class BookSpVO {
private String keyword; private String keyword;
@ -30,5 +31,8 @@ public class BookSpVO extends SortOrderVO {
private Long updatePeriod; private Long updatePeriod;
@Pattern(regexp = "^(last_index_update_time|word_count|visit_count)$")
private String sort;
} }

View File

@ -56,7 +56,7 @@
<dependency> <dependency>
<groupId>org.springframework.ai</groupId> <groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId> <artifactId>spring-ai-bom</artifactId>
<version>1.0.0-M6</version> <version>1.0.0</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>