refactor: 重构排序参数处理代码

This commit is contained in:
xiongxiaoyang 2025-07-19 17:27:21 +08:00
parent 8c7b891af2
commit 11d9d6f6e8
38 changed files with 116 additions and 247 deletions

View File

@ -0,0 +1,14 @@
package com.java2nb.common.annotation;
import java.lang.annotation.*;
/**
* 标记某个方法参数需要进行 Map 字段的清理和标准化处理
*
* <p>通常用于 DAO 接口中 list 方法的 Map 参数用于防止非法排序字段或排序顺序</p>
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SanitizeMap {
}

View File

@ -1,13 +0,0 @@
package com.java2nb.common.annotation;
import java.lang.annotation.*;
/**
* @author xiongxiaoyang
* @date 2025/7/17
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidateSortOrder {
}

View File

@ -1,6 +1,6 @@
package com.java2nb.common.aspect;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.common.utils.SortWhitelistUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
@ -16,20 +16,33 @@ import java.util.Arrays;
import java.util.Map;
/**
* @author xiongxiaoyang
* @date 2025/7/17
* 拦截所有 Mapper 接口的 list* 方法对带有 @SanitizeMap 注解的 Map 参数进行排序字段和顺序的规范化处理
*
* <p>主要防止 SQL 注入或非法排序字段非法排序顺序的问题
* 例如对 sort order 字段进行白名单过滤和标准化处理</p>
*/
@Aspect
@Component
@RequiredArgsConstructor
public class SortOrderValidationAspect {
public class MapSortValidationAspect {
/**
* 拦截mapper的所有list方法
* 拦截所有 Mapper 接口的 list* 方法 list(), listByPage
* 对带有 @SanitizeMap 注解的 Map 参数进行处理
*
* <p>执行逻辑</p>
* <ol>
* <li>获取方法参数及注解信息</li>
* <li>遍历所有参数检查是否带有 @SanitizeMap 注解</li>
* <li>如果参数是 Map 类型且有注解则进行字段清理</li>
* </ol>
*
* @param joinPoint 切点信息
* @return 方法执行结果
*/
@SneakyThrows
@Around("execution(* com.java2nb.*.dao.*Dao.list*(..))")
public Object validateSortAndOrder(ProceedingJoinPoint joinPoint) {
public Object sanitizeMapParameters(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
@ -38,7 +51,7 @@ public class SortOrderValidationAspect {
for (int i = 0; i < parameterAnnotations.length; i++) {
boolean hasAnnotation = Arrays.stream(parameterAnnotations[i])
.anyMatch(a -> a.annotationType().equals(ValidateSortOrder.class));
.anyMatch(a -> a.annotationType().equals(SanitizeMap.class));
if (hasAnnotation && args[i] instanceof Map map) {
if (map.get("sort") instanceof String sortStr) {

View File

@ -1,6 +1,6 @@
package com.java2nb.common.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.common.domain.DictDO;
import java.util.List;
@ -20,7 +20,7 @@ public interface DictDao {
DictDO get(Long id);
List<DictDO> list(@ValidateSortOrder Map<String, Object> map);
List<DictDO> list(@SanitizeMap Map<String, Object> map);
int count(Map<String, Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.common.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.common.domain.FileDO;
import java.util.List;
@ -19,7 +19,7 @@ public interface FileDao {
FileDO get(Long id);
List<FileDO> list(@ValidateSortOrder Map<String,Object> map);
List<FileDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -3,7 +3,7 @@ package com.java2nb.common.dao;
import java.util.List;
import java.util.Map;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.common.domain.GenColumnsDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -20,7 +20,7 @@ public interface GenColumnsDao {
GenColumnsDO get(Long id);
List<GenColumnsDO> list(@ValidateSortOrder Map<String,Object> map);
List<GenColumnsDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.common.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.common.domain.LogDO;
import java.util.List;
@ -19,7 +19,7 @@ public interface LogDao {
LogDO get(Long id);
List<LogDO> list(@ValidateSortOrder Map<String,Object> map);
List<LogDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -2,26 +2,42 @@ package com.java2nb.common.utils;
import lombok.experimental.UtilityClass;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* @author xiongxiaoyang
* @date 2025/7/17
* 排序字段和排序顺序的白名单工具类
*/
@UtilityClass
public class SortWhitelistUtil {
private final Set<String> allowedColumns = new HashSet<>(
Arrays.asList("id", "name", "order_num"));
private final Set<String> allowedOrders = new HashSet<>(Arrays.asList("asc", "desc"));
// 白名单字段
private static final Set<String> ALLOWED_COLUMNS = Set.of("id", "name", "order_num");
public String sanitizeColumn(String input) {
return allowedColumns.contains(input.toLowerCase()) ? input.toLowerCase() : "id";
// 白名单排序方式
private static final Set<String> ALLOWED_ORDERS = Set.of("asc", "desc");
/**
* 对排序字段进行白名单过滤和标准化
*
* @param column 原始字段名
* @return 安全的字段名若非法则返回 null
*/
public static String sanitizeColumn(String column) {
if (column == null) return null;
String lower = column.trim().toLowerCase();
return ALLOWED_COLUMNS.contains(lower) ? lower : null;
}
public String sanitizeOrder(String input) {
return allowedOrders.contains(input.toLowerCase()) ? input.toLowerCase() : "asc";
/**
* 对排序方式进行白名单过滤和标准化
*
* @param order 原始排序方式
* @return 安全的排序方式"asc" "desc"若非法则返回 null
*/
public static String sanitizeOrder(String order) {
if (order == null) return null;
String lower = order.trim().toLowerCase();
return ALLOWED_ORDERS.contains(lower) ? lower : null;
}
}

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.AuthorCodeDO;
@ -20,7 +20,7 @@ public interface AuthorCodeDao {
AuthorCodeDO get(Long id);
List<AuthorCodeDO> list(@ValidateSortOrder Map<String,Object> map);
List<AuthorCodeDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.AuthorDO;
import java.util.Date;
@ -20,7 +20,7 @@ public interface AuthorDao {
AuthorDO get(Long id);
List<AuthorDO> list(@ValidateSortOrder Map<String,Object> map);
List<AuthorDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.BookCommentDO;
@ -20,7 +20,7 @@ public interface BookCommentDao {
BookCommentDO get(Long id);
List<BookCommentDO> list(@ValidateSortOrder Map<String,Object> map);
List<BookCommentDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.BookContentDO;
import org.apache.ibatis.annotations.Mapper;
@ -20,7 +20,7 @@ public interface BookContentDao {
BookContentDO get(Long id);
List<BookContentDO> list(@ValidateSortOrder Map<String, Object> map);
List<BookContentDO> list(@SanitizeMap Map<String, Object> map);
int count(Map<String, Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.BookDO;
import org.apache.ibatis.annotations.Mapper;
@ -21,7 +21,7 @@ public interface BookDao {
BookDO get(Long id);
List<BookDO> list(@ValidateSortOrder Map<String, Object> map);
List<BookDO> list(@SanitizeMap Map<String, Object> map);
int count(Map<String, Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.BookIndexDO;
import org.apache.ibatis.annotations.Mapper;
@ -20,7 +20,7 @@ public interface BookIndexDao {
BookIndexDO get(Long id);
List<BookIndexDO> list(@ValidateSortOrder Map<String, Object> map);
List<BookIndexDO> list(@SanitizeMap Map<String, Object> map);
int count(Map<String, Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.BookSettingDO;
@ -20,7 +20,7 @@ public interface BookSettingDao {
BookSettingDO get(Long id);
List<BookSettingDO> list(@ValidateSortOrder Map<String,Object> map);
List<BookSettingDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.CategoryDO;
@ -20,7 +20,7 @@ public interface CategoryDao {
CategoryDO get(Integer id);
List<CategoryDO> list(@ValidateSortOrder Map<String,Object> map);
List<CategoryDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.FriendLinkDO;
@ -20,7 +20,7 @@ public interface FriendLinkDao {
FriendLinkDO get(Integer id);
List<FriendLinkDO> list(@ValidateSortOrder Map<String,Object> map);
List<FriendLinkDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.NewsDO;
@ -20,7 +20,7 @@ public interface NewsDao {
NewsDO get(Long id);
List<NewsDO> list(@ValidateSortOrder Map<String,Object> map);
List<NewsDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.PayDO;
@ -21,7 +21,7 @@ public interface PayDao {
PayDO get(Long id);
List<PayDO> list(@ValidateSortOrder Map<String,Object> map);
List<PayDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.UserDO;
import org.apache.ibatis.annotations.Mapper;
@ -19,7 +19,7 @@ public interface UserDao {
UserDO get(Long id);
List<UserDO> list(@ValidateSortOrder Map<String, Object> map);
List<UserDO> list(@SanitizeMap Map<String, Object> map);
int count(Map<String, Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.UserFeedbackDO;
@ -20,7 +20,7 @@ public interface UserFeedbackDao {
UserFeedbackDO get(Long id);
List<UserFeedbackDO> list(@ValidateSortOrder Map<String,Object> map);
List<UserFeedbackDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.novel.domain.WebsiteInfoDO;
@ -20,7 +20,7 @@ public interface WebsiteInfoDao {
WebsiteInfoDO get(Long id);
List<WebsiteInfoDO> list(@ValidateSortOrder Map<String,Object> map);
List<WebsiteInfoDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.system.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.system.domain.DataPermDO;
@ -21,7 +21,7 @@ public interface DataPermDao {
DataPermDO get(Long id);
List<DataPermDO> list(@ValidateSortOrder Map<String,Object> map);
List<DataPermDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.system.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.system.domain.DeptDO;
@ -21,7 +21,7 @@ public interface DeptDao {
DeptDO get(Long deptId);
List<DeptDO> list(@ValidateSortOrder Map<String,Object> map);
List<DeptDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.system.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.system.domain.MenuDO;
@ -20,7 +20,7 @@ public interface MenuDao {
MenuDO get(Long menuId);
List<MenuDO> list(@ValidateSortOrder Map<String,Object> map);
List<MenuDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.system.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.system.domain.RoleDO;
@ -20,7 +20,7 @@ public interface RoleDao {
RoleDO get(Long roleId);
List<RoleDO> list(@ValidateSortOrder Map<String,Object> map);
List<RoleDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.system.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.system.domain.RoleDataPermDO;
@ -20,7 +20,7 @@ public interface RoleDataPermDao {
RoleDataPermDO get(Long id);
List<RoleDataPermDO> list(@ValidateSortOrder Map<String,Object> map);
List<RoleDataPermDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.system.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.system.domain.RoleMenuDO;
@ -20,7 +20,7 @@ public interface RoleMenuDao {
RoleMenuDO get(Long id);
List<RoleMenuDO> list(@ValidateSortOrder Map<String,Object> map);
List<RoleMenuDO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -1,6 +1,6 @@
package com.java2nb.system.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.system.domain.UserDO;
@ -8,7 +8,6 @@ import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author xiongxy
@ -20,7 +19,7 @@ public interface SysUserDao {
UserDO get(Long userId);
List<UserDO> list(@ValidateSortOrder Map<String, Object> map);
List<UserDO> list(@SanitizeMap Map<String, Object> map);
int count(Map<String, Object> map);
@ -34,7 +33,7 @@ public interface SysUserDao {
Long[] listAllDept();
List<UserDO> listByPerm(@ValidateSortOrder Map<String, Object> map);
List<UserDO> listByPerm(@SanitizeMap Map<String, Object> map);
int countByPerm(Map<String, Object> map);
}

View File

@ -1,6 +1,6 @@
package com.java2nb.system.dao;
import com.java2nb.common.annotation.ValidateSortOrder;
import com.java2nb.common.annotation.SanitizeMap;
import com.java2nb.system.domain.UserRoleDO;
@ -21,7 +21,7 @@ public interface UserRoleDao {
UserRoleDO get(Long id);
List<UserRoleDO> list(@ValidateSortOrder Map<String, Object> map);
List<UserRoleDO> list(@SanitizeMap Map<String, Object> map);
int count(Map<String, Object> map);

View File

@ -18,7 +18,7 @@ public interface ${className}Dao {
${className}DO get(${pk.javaType} ${pk.attrname});
List<${className}DO> list(@ValidateSortOrder Map<String,Object> map);
List<${className}DO> list(@SanitizeMap Map<String,Object> map);
int count(Map<String,Object> map);

View File

@ -44,7 +44,7 @@ public interface ${className}Mapper {
"limit #{offset}, #{limit}" +
"</if>"+
"</script>")
List<${className}DO> list(@ValidateSortOrder Map<String,Object> map);
List<${className}DO> list(@SanitizeMap Map<String,Object> map);
@Select("<script>" +
"select count(*) from ${tableName} " +

View File

@ -1,13 +0,0 @@
package com.java2nb.novel.core.annotation;
import java.lang.annotation.*;
/**
* @author xiongxiaoyang
* @date 2025/7/17
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidateSortOrder {
}

View File

@ -1,101 +0,0 @@
package com.java2nb.novel.core.aspect;
import com.java2nb.novel.core.annotation.ValidateSortOrder;
import com.java2nb.novel.core.utils.SortWhitelistUtil;
import com.java2nb.novel.core.vo.SortOrderVO;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author xiongxiaoyang
* @date 2025/7/17
*/
@Aspect
//@Component
@RequiredArgsConstructor
public class SortOrderValidationAspect {
/**
* 拦截所有的mapper方法
*/
@SneakyThrows
@Around("execution(* com.java2nb.novel.mapper.*Mapper.*(..))")
public Object processSortOrderFields(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (int i = 0; i < parameterAnnotations.length; i++) {
boolean hasAnnotation = Arrays.stream(parameterAnnotations[i])
.anyMatch(a -> a.annotationType().equals(ValidateSortOrder.class));
if (hasAnnotation && args[i] != null) {
handleAnnotatedParameter(args[i]);
}
}
return joinPoint.proceed(args);
}
@SneakyThrows
private void handleAnnotatedParameter(Object obj) {
if (obj instanceof SortOrderVO sortOrderVO){
processSortOrderVO(sortOrderVO);
} else if (obj instanceof Map<?, ?> map) {
processMap(map);
} else {
processGenericObject(obj);
}
}
private void processSortOrderVO(SortOrderVO sortOrderVO) {
if(sortOrderVO.getSort() != null){
sortOrderVO.setSort(SortWhitelistUtil.sanitizeColumn(sortOrderVO.getSort()));
}
if(sortOrderVO.getOrder() != null){
sortOrderVO.setOrder(SortWhitelistUtil.sanitizeOrder(sortOrderVO.getOrder()));
}
}
private void processMap(Map map) {
if (map.get("sort") instanceof String sortStr) {
map.put("sort", SortWhitelistUtil.sanitizeColumn(sortStr));
}
if (map.get("order") instanceof String orderStr) {
map.put("order", SortWhitelistUtil.sanitizeOrder(orderStr));
}
}
@SneakyThrows
private void processGenericObject(Object obj) {
for (Field field : obj.getClass().getDeclaredFields()) {
switch (field.getName()) {
case "sort", "order" -> {
field.setAccessible(true);
Object value = field.get(obj);
if (value instanceof String strValue) {
String sanitized = "sort".equals(field.getName())
? SortWhitelistUtil.sanitizeColumn(strValue)
: SortWhitelistUtil.sanitizeOrder(strValue);
field.set(obj, sanitized);
}
}
default -> {
}
}
}
}
}

View File

@ -1,28 +0,0 @@
package com.java2nb.novel.core.utils;
import lombok.experimental.UtilityClass;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* @author xiongxiaoyang
* @date 2025/7/17
*/
@UtilityClass
public class SortWhitelistUtil {
private final Set<String> allowedColumns = new HashSet<>(
Arrays.asList("id", "name", "create_time", "update_time", "last_index_update_time", "word_count",
"visit_count"));
private final Set<String> allowedOrders = new HashSet<>(Arrays.asList("asc", "desc"));
public String sanitizeColumn(String input) {
return allowedColumns.contains(input.toLowerCase()) ? input.toLowerCase() : "id";
}
public String sanitizeOrder(String input) {
return allowedOrders.contains(input.toLowerCase()) ? input.toLowerCase() : "asc";
}
}

View File

@ -1,16 +0,0 @@
package com.java2nb.novel.core.vo;
import lombok.Data;
/**
* @author xiongxiaoyang
* @date 2025/7/17
*/
@Data
public class SortOrderVO {
private String sort;
private String order;
}

View File

@ -1,6 +1,5 @@
package com.java2nb.novel.mapper;
import com.java2nb.novel.core.annotation.ValidateSortOrder;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.vo.BookSpVO;
import com.java2nb.novel.vo.BookVO;

View File

@ -1,6 +1,5 @@
package com.java2nb.novel.vo;
import com.java2nb.novel.core.vo.SortOrderVO;
import jakarta.validation.constraints.Pattern;
import lombok.Data;