diff --git a/riis-system/src/main/java/com/yfd/platform/utils/wrapper/QueryCondition.java b/riis-system/src/main/java/com/yfd/platform/utils/wrapper/QueryCondition.java new file mode 100644 index 0000000..bbb2542 --- /dev/null +++ b/riis-system/src/main/java/com/yfd/platform/utils/wrapper/QueryCondition.java @@ -0,0 +1,15 @@ +package com.yfd.platform.utils.wrapper; + +import lombok.Data; +import org.springframework.data.domain.Sort; + +import java.util.Map; + +@Data +public class QueryCondition { + private Integer page; + private Integer size; + private Map filters; + private Sort sort; + +} diff --git a/riis-system/src/main/java/com/yfd/platform/utils/wrapper/QueryWrapperBuilder.java b/riis-system/src/main/java/com/yfd/platform/utils/wrapper/QueryWrapperBuilder.java new file mode 100644 index 0000000..5df1b99 --- /dev/null +++ b/riis-system/src/main/java/com/yfd/platform/utils/wrapper/QueryWrapperBuilder.java @@ -0,0 +1,148 @@ +package com.yfd.platform.utils.wrapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.springframework.data.domain.Sort; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +public class QueryWrapperBuilder { + // 字段缓存:类 -> 字段名集合(包含驼峰和下划线格式) + private static final Map, Set> FIELD_CACHE = new ConcurrentHashMap<>(); + /** + * 将 QueryCondition 转换为 MyBatis-Plus 的 QueryWrapper + * + * @param condition 查询条件 + * @param entityClass 实体类(用于字段合法性校验) + * @return QueryWrapper + */ + public static QueryWrapper build(QueryCondition condition, Class entityClass) { + QueryWrapper wrapper = new QueryWrapper<>(); + + + // 修改 build 方法中的过滤条件处理部分 + condition.getFilters().forEach((field, value) -> { + if (isValidField(field, entityClass)) { + String column = camelToUnderline(field); + + // 解析运算符(示例格式:age_gt=30) + if (field.contains("__")) { // 使用双下划线分隔符更安全 + String[] parts = field.split("__"); + if (parts.length == 2) { + String realField = parts[0]; + String operator = parts[1]; + column = camelToUnderline(realField); + applyOperator(wrapper, column, operator, value); + return; + } + } + + // 默认等值查询 + wrapper.eq(column, value); + } + }); + + // 处理排序 + if (condition.getSort() != null) { + condition.getSort().forEach(order -> { + String column = camelToUnderline(order.getProperty()); + if (order.isAscending()) { + wrapper.orderByAsc(column); + } else { + wrapper.orderByDesc(column); + } + }); + } + + return wrapper; + } + + // 在字段校验时增加格式检查 + private static boolean isValidField(String field) { + // 只允许字母、数字和下划线 + return field.matches("^[a-zA-Z0-9_]+$"); + } + + // 运算符处理方法 + private static void applyOperator(QueryWrapper wrapper, String column, String operator, Object value) { + switch (operator.toLowerCase()) { + case "eq": + wrapper.eq(column, value); + break; + case "ne": + wrapper.ne(column, value); + break; + case "gt": + wrapper.gt(column, value); + break; + case "ge": + wrapper.ge(column, value); + break; + case "lt": + wrapper.lt(column, value); + break; + case "le": + wrapper.le(column, value); + break; + case "like": + wrapper.like(column, value); + break; + case "notlike": + wrapper.notLike(column, value); + break; + case "in": + if (value instanceof Collection) { + wrapper.in(column, (Collection) value); + } + break; + default: + throw new IllegalArgumentException("不支持的运算符: " + operator); + } + } + + // 驼峰转下划线(工具方法) + private static String camelToUnderline(String str) { + return str.replaceAll("([a-z0-9])([A-Z])", "$1_$2").toLowerCase(); + } + + // 下划线转驼峰(支持反向校验) + private static String underlineToCamel(String str) { + if (!str.contains("_")) { + return str; + } + + StringBuilder sb = new StringBuilder(); + String[] parts = str.split("_"); + sb.append(parts[0]); + for (int i = 1; i < parts.length; i++) { + if (!parts[i].isEmpty()) { + sb.append(Character.toUpperCase(parts[i].charAt(0))); + sb.append(parts[i].substring(1)); + } + } + return sb.toString(); + } + + // 字段合法性校验(扩展点) + private static boolean isValidField(String field, Class entityClass) { + // 双重校验:1.原始字段 2.驼峰转下划线反向校验 + return containsField(entityClass, field) || + containsField(entityClass, underlineToCamel(field)); + } + + private static boolean containsField(Class entityClass, String fieldName) { + // 获取或缓存字段集合 + Set fields = FIELD_CACHE.computeIfAbsent(entityClass, clazz -> + Arrays.stream(clazz.getDeclaredFields()) + .map(Field::getName) + .collect(Collectors.toSet()) + ); + + return fields.contains(fieldName); + } +}