diff --git a/continew-starter-data/continew-starter-data-core/pom.xml b/continew-starter-data/continew-starter-data-core/pom.xml
index e48c7e15..73f5e3c5 100644
--- a/continew-starter-data/continew-starter-data-core/pom.xml
+++ b/continew-starter-data/continew-starter-data-core/pom.xml
@@ -18,5 +18,10 @@
cn.hutool
hutool-db
+
+
+ org.springframework.data
+ spring-data-commons
+
\ No newline at end of file
diff --git a/continew-starter-data/continew-starter-data-core/src/main/java/top/continew/starter/data/core/util/SqlInjectionUtils.java b/continew-starter-data/continew-starter-data-core/src/main/java/top/continew/starter/data/core/util/SqlInjectionUtils.java
new file mode 100644
index 00000000..0a441550
--- /dev/null
+++ b/continew-starter-data/continew-starter-data-core/src/main/java/top/continew/starter/data/core/util/SqlInjectionUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package top.continew.starter.data.core.util;
+
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+/**
+ * SQL 注入验证工具类
+ *
+ * @author hubin
+ * @since 2.5.2
+ */
+public class SqlInjectionUtils {
+
+ /**
+ * SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配
+ */
+ private static final Pattern SQL_SYNTAX_PATTERN = Pattern
+ .compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" + "\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)|(select\\s*\\*\\s*from\\s+)|(and|or)\\s+.*", Pattern.CASE_INSENSITIVE);
+
+ /**
+ * 使用'、;或注释截断SQL检查正则
+ */
+ private static final Pattern SQL_COMMENT_PATTERN = Pattern
+ .compile("'.*(or|union|--|#|/\\*|;)", Pattern.CASE_INSENSITIVE);
+
+ /**
+ * 检查参数是否存在 SQL 注入
+ *
+ * @param value 检查参数
+ * @return true:非法;false:合法
+ */
+ public static boolean check(String value) {
+ Objects.requireNonNull(value);
+ // 处理是否包含 SQL 注释字符 || 检查是否包含 SQ L注入敏感字符
+ return SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find();
+ }
+}
\ No newline at end of file
diff --git a/continew-starter-data/continew-starter-data-mybatis-flex/src/main/java/top/continew/starter/data/mybatis/flex/query/QueryWrapperHelper.java b/continew-starter-data/continew-starter-data-mybatis-flex/src/main/java/top/continew/starter/data/mybatis/flex/util/QueryWrapperHelper.java
similarity index 86%
rename from continew-starter-data/continew-starter-data-mybatis-flex/src/main/java/top/continew/starter/data/mybatis/flex/query/QueryWrapperHelper.java
rename to continew-starter-data/continew-starter-data-mybatis-flex/src/main/java/top/continew/starter/data/mybatis/flex/util/QueryWrapperHelper.java
index d286e119..ba0fcf68 100644
--- a/continew-starter-data/continew-starter-data-mybatis-flex/src/main/java/top/continew/starter/data/mybatis/flex/query/QueryWrapperHelper.java
+++ b/continew-starter-data/continew-starter-data-mybatis-flex/src/main/java/top/continew/starter/data/mybatis/flex/util/QueryWrapperHelper.java
@@ -14,21 +14,23 @@
* limitations under the License.
*/
-package top.continew.starter.data.mybatis.flex.query;
+package top.continew.starter.data.mybatis.flex.util;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.text.CharSequenceUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.text.CharSequenceUtil;
+import org.springframework.data.domain.Sort;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.core.util.ReflectUtils;
import top.continew.starter.core.util.validate.ValidationUtils;
import top.continew.starter.data.core.annotation.Query;
import top.continew.starter.data.core.annotation.QueryIgnore;
import top.continew.starter.data.core.enums.QueryType;
+import top.continew.starter.data.core.util.SqlInjectionUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -56,10 +58,9 @@ public class QueryWrapperHelper {
*
* @param query 查询条件
* @param 查询条件数据类型
- * @param 查询数据类型
* @return QueryWrapper
*/
- public static QueryWrapper build(Q query) {
+ public static QueryWrapper build(Q query) {
QueryWrapper queryWrapper = QueryWrapper.create();
// 没有查询条件,直接返回
if (null == query) {
@@ -70,6 +71,34 @@ public class QueryWrapperHelper {
return build(query, fieldList, queryWrapper);
}
+ /**
+ * 构建 QueryWrapper
+ *
+ * @param query 查询条件
+ * @param sort 排序条件
+ * @param 查询条件数据类型
+ * @return QueryWrapper
+ * @since 2.5.2
+ */
+ public static QueryWrapper build(Q query, Sort sort) {
+ QueryWrapper queryWrapper = QueryWrapper.create();
+ // 没有查询条件,直接返回
+ if (null == query) {
+ return queryWrapper;
+ }
+ // 设置排序条件
+ if (sort != null && sort.isSorted()) {
+ for (Sort.Order order : sort) {
+ String field = CharSequenceUtil.toUnderlineCase(order.getProperty());
+ ValidationUtils.throwIf(SqlInjectionUtils.check(field), "排序字段包含非法字符");
+ queryWrapper.orderBy(field, order.isAscending());
+ }
+ }
+ // 获取查询条件中所有的字段
+ List fieldList = ReflectUtils.getNonStaticFields(query.getClass());
+ return build(query, fieldList, queryWrapper);
+ }
+
/**
* 构建 QueryWrapper
*
diff --git a/continew-starter-data/continew-starter-data-mybatis-plus/src/main/java/top/continew/starter/data/mybatis/plus/query/QueryWrapperHelper.java b/continew-starter-data/continew-starter-data-mybatis-plus/src/main/java/top/continew/starter/data/mybatis/plus/util/QueryWrapperHelper.java
similarity index 89%
rename from continew-starter-data/continew-starter-data-mybatis-plus/src/main/java/top/continew/starter/data/mybatis/plus/query/QueryWrapperHelper.java
rename to continew-starter-data/continew-starter-data-mybatis-plus/src/main/java/top/continew/starter/data/mybatis/plus/util/QueryWrapperHelper.java
index c79cbf10..fbe48ed7 100644
--- a/continew-starter-data/continew-starter-data-mybatis-plus/src/main/java/top/continew/starter/data/mybatis/plus/query/QueryWrapperHelper.java
+++ b/continew-starter-data/continew-starter-data-mybatis-plus/src/main/java/top/continew/starter/data/mybatis/plus/util/QueryWrapperHelper.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package top.continew.starter.data.mybatis.plus.query;
+package top.continew.starter.data.mybatis.plus.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -23,18 +23,17 @@ import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import org.springframework.data.domain.Sort;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.core.util.ReflectUtils;
import top.continew.starter.core.util.validate.ValidationUtils;
import top.continew.starter.data.core.annotation.Query;
import top.continew.starter.data.core.annotation.QueryIgnore;
import top.continew.starter.data.core.enums.QueryType;
+import top.continew.starter.data.core.util.SqlInjectionUtils;
import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
import java.util.function.Consumer;
/**
@@ -60,11 +59,33 @@ public class QueryWrapperHelper {
* @return QueryWrapper
*/
public static QueryWrapper build(Q query) {
+ return build(query, Sort.unsorted());
+ }
+
+ /**
+ * 构建 QueryWrapper
+ *
+ * @param query 查询条件
+ * @param sort 排序条件
+ * @param 查询条件数据类型
+ * @param 查询数据类型
+ * @return QueryWrapper
+ * @since 2.5.2
+ */
+ public static QueryWrapper build(Q query, Sort sort) {
QueryWrapper queryWrapper = new QueryWrapper<>();
// 没有查询条件,直接返回
if (null == query) {
return queryWrapper;
}
+ // 设置排序条件
+ if (sort != null && sort.isSorted()) {
+ for (Sort.Order order : sort) {
+ String field = CharSequenceUtil.toUnderlineCase(order.getProperty());
+ ValidationUtils.throwIf(SqlInjectionUtils.check(field), "排序字段包含非法字符");
+ queryWrapper.orderBy(true, order.isAscending(), field);
+ }
+ }
// 获取查询条件中所有的字段
List fieldList = ReflectUtils.getNonStaticFields(query.getClass());
return build(query, fieldList, queryWrapper);
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/pom.xml b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/pom.xml
index 3fe0c7d7..a0cc9d88 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/pom.xml
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/pom.xml
@@ -24,6 +24,12 @@
spring-data-commons
+
+
+ top.continew
+ continew-starter-web
+
+
top.continew
@@ -36,16 +42,16 @@
+
+
+ top.continew
+ continew-starter-data-core
+
+
top.continew
continew-starter-file-excel
-
-
-
- top.continew
- continew-starter-web
-
\ No newline at end of file
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/model/query/PageQuery.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/query/PageQuery.java
similarity index 100%
rename from continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/model/query/PageQuery.java
rename to continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/query/PageQuery.java
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/query/SortQuery.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/query/SortQuery.java
index 8d4683ea..28bbb62c 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/query/SortQuery.java
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/query/SortQuery.java
@@ -21,6 +21,8 @@ import cn.hutool.core.util.ArrayUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.data.domain.Sort;
import top.continew.starter.core.constant.StringConstants;
+import top.continew.starter.core.util.validate.ValidationUtils;
+import top.continew.starter.data.core.util.SqlInjectionUtils;
import java.io.Serial;
import java.io.Serializable;
@@ -54,20 +56,17 @@ public class SortQuery implements Serializable {
if (ArrayUtil.isEmpty(sort)) {
return Sort.unsorted();
}
-
+ ValidationUtils.throwIf(sort.length < 2, "排序条件非法");
List orders = new ArrayList<>(sort.length);
if (CharSequenceUtil.contains(sort[0], StringConstants.COMMA)) {
// e.g "sort=createTime,desc&sort=name,asc"
for (String s : sort) {
List sortList = CharSequenceUtil.splitTrim(s, StringConstants.COMMA);
- Sort.Order order = new Sort.Order(Sort.Direction.valueOf(sortList.get(1).toUpperCase()), sortList
- .get(0));
- orders.add(order);
+ orders.add(this.getOrder(sortList.get(0), sortList.get(1)));
}
} else {
// e.g "sort=createTime,desc"
- Sort.Order order = new Sort.Order(Sort.Direction.valueOf(sort[1].toUpperCase()), sort[0]);
- orders.add(order);
+ orders.add(this.getOrder(sort[0], sort[1]));
}
return Sort.by(orders);
}
@@ -75,4 +74,16 @@ public class SortQuery implements Serializable {
public void setSort(String[] sort) {
this.sort = sort;
}
+
+ /**
+ * 获取排序条件
+ *
+ * @param field 字段
+ * @param direction 排序方向
+ * @return 排序条件
+ */
+ private Sort.Order getOrder(String field, String direction) {
+ ValidationUtils.throwIf(SqlInjectionUtils.check(field), "排序字段包含非法字符");
+ return new Sort.Order(Sort.Direction.valueOf(direction.toUpperCase()), field);
+ }
}
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/resp/BasePageResp.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/resp/BasePageResp.java
new file mode 100644
index 00000000..3b731a69
--- /dev/null
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/resp/BasePageResp.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package top.continew.starter.extension.crud.model.resp;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 分页信息
+ *
+ * @param 列表数据类型
+ * @author Charles7c
+ * @since 2.5.2
+ */
+@Schema(description = "分页信息")
+public class BasePageResp implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 列表数据
+ */
+ @Schema(description = "列表数据")
+ private List list;
+
+ /**
+ * 总记录数
+ */
+ @Schema(description = "总记录数", example = "10")
+ private long total;
+
+ public BasePageResp() {
+ }
+
+ public BasePageResp(final List list, final long total) {
+ this.list = list;
+ this.total = total;
+ }
+
+ public List getList() {
+ return list;
+ }
+
+ public void setList(List list) {
+ this.list = list;
+ }
+
+ public long getTotal() {
+ return total;
+ }
+
+ public void setTotal(long total) {
+ this.total = total;
+ }
+}
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/model/resp/PageResp.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/model/resp/PageResp.java
index ece21115..552057c4 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/model/resp/PageResp.java
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/model/resp/PageResp.java
@@ -22,7 +22,6 @@ import com.mybatisflex.core.paginate.Page;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serial;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -35,22 +34,17 @@ import java.util.List;
* @since 1.0.0
*/
@Schema(description = "分页信息")
-public class PageResp implements Serializable {
+public class PageResp extends BasePageResp {
@Serial
private static final long serialVersionUID = 1L;
- /**
- * 列表数据
- */
- @Schema(description = "列表数据")
- private List list;
+ public PageResp() {
+ }
- /**
- * 总记录数
- */
- @Schema(description = "总记录数", example = "10")
- private long total;
+ public PageResp(final List list, final long total) {
+ super(list, total);
+ }
/**
* 基于 MyBatis Plus 分页数据构建分页信息,并将源数据转换为指定类型数据
@@ -65,10 +59,7 @@ public class PageResp implements Serializable {
if (null == page) {
return empty();
}
- PageResp pageResp = new PageResp<>();
- pageResp.setList(BeanUtil.copyToList(page.getRecords(), targetClass));
- pageResp.setTotal(page.getTotalRow());
- return pageResp;
+ return new PageResp<>(BeanUtil.copyToList(page.getRecords(), targetClass), page.getTotalRow());
}
/**
@@ -82,10 +73,7 @@ public class PageResp implements Serializable {
if (null == page) {
return empty();
}
- PageResp pageResp = new PageResp<>();
- pageResp.setList(page.getRecords());
- pageResp.setTotal(page.getTotalRow());
- return pageResp;
+ return new PageResp<>(page.getRecords(), page.getTotalRow());
}
/**
@@ -123,24 +111,6 @@ public class PageResp implements Serializable {
* @return 分页信息
*/
private static PageResp empty() {
- PageResp pageResp = new PageResp<>();
- pageResp.setList(Collections.emptyList());
- return pageResp;
- }
-
- public List getList() {
- return list;
- }
-
- public void setList(List list) {
- this.list = list;
- }
-
- public long getTotal() {
- return total;
- }
-
- public void setTotal(long total) {
- this.total = total;
+ return new PageResp<>(Collections.emptyList(), 0L);
}
}
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
index ce4bbc9c..34a5e8a3 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
@@ -20,7 +20,6 @@ import cn.crane4j.core.support.OperateTemplate;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.text.CharSequenceUtil;
@@ -35,7 +34,7 @@ import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.util.ReflectUtils;
import top.continew.starter.core.util.validate.ValidationUtils;
import top.continew.starter.data.mybatis.flex.base.BaseMapper;
-import top.continew.starter.data.mybatis.flex.query.QueryWrapperHelper;
+import top.continew.starter.data.mybatis.flex.util.QueryWrapperHelper;
import top.continew.starter.data.mybatis.flex.service.impl.ServiceImpl;
import top.continew.starter.extension.crud.annotation.TreeField;
import top.continew.starter.extension.crud.model.query.PageQuery;
@@ -73,6 +72,7 @@ public abstract class BaseServiceImpl, T extends BaseIdD
@Override
public PageResp page(Q query, PageQuery pageQuery) {
QueryWrapper queryWrapper = this.buildQueryWrapper(query);
+ this.sort(queryWrapper, pageQuery);
Page page = mapper.paginate(pageQuery.getPage(), pageQuery.getSize(), queryWrapper);
PageResp pageResp = PageResp.build(page, listClass);
pageResp.getList().forEach(this::fill);
@@ -185,12 +185,12 @@ public abstract class BaseServiceImpl, T extends BaseIdD
* @param sortQuery 排序查询条件
*/
protected void sort(QueryWrapper queryWrapper, SortQuery sortQuery) {
- Sort sort = Opt.ofNullable(sortQuery).orElseGet(SortQuery::new).getSort();
+ if (sortQuery == null || sortQuery.getSort().isUnsorted()) {
+ return;
+ }
+ Sort sort = sortQuery.getSort();
List entityFields = ReflectUtils.getNonStaticFields(this.entityClass);
for (Sort.Order order : sort) {
- if (null == order) {
- continue;
- }
String property = order.getProperty();
String checkProperty;
// 携带表别名则获取 . 后面的字段名
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/model/query/PageQuery.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/model/query/PageQuery.java
deleted file mode 100644
index 563c95ce..00000000
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/model/query/PageQuery.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
- *
- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.gnu.org/licenses/lgpl.html
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package top.continew.starter.extension.crud.model.query;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.text.CharSequenceUtil;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.metadata.OrderItem;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.Min;
-import org.hibernate.validator.constraints.Range;
-import org.springdoc.core.annotations.ParameterObject;
-import org.springframework.data.domain.Sort;
-
-import java.io.Serial;
-
-/**
- * 分页查询条件
- *
- * @author Charles7c
- * @since 1.0.0
- */
-@ParameterObject
-@Schema(description = "分页查询条件")
-public class PageQuery extends SortQuery {
-
- @Serial
- private static final long serialVersionUID = 1L;
- /**
- * 默认页码:1
- */
- private static final int DEFAULT_PAGE = 1;
- /**
- * 默认每页条数:10
- */
- private static final int DEFAULT_SIZE = 10;
-
- /**
- * 页码
- */
- @Schema(description = "页码", example = "1")
- @Min(value = 1, message = "页码最小值为 {value}")
- private Integer page = DEFAULT_PAGE;
-
- /**
- * 每页条数
- */
- @Schema(description = "每页条数", example = "10")
- @Range(min = 1, max = 1000, message = "每页条数(取值范围 {min}-{max})")
- private Integer size = DEFAULT_SIZE;
-
- /**
- * 基于分页查询条件转换为 MyBatis Plus 分页条件
- *
- * @param 列表数据类型
- * @return MyBatis Plus 分页条件
- */
- public IPage toPage() {
- Page mybatisPage = new Page<>(this.getPage(), this.getSize());
- Sort pageSort = this.getSort();
- if (CollUtil.isNotEmpty(pageSort)) {
- for (Sort.Order order : pageSort) {
- OrderItem orderItem = new OrderItem();
- orderItem.setAsc(order.isAscending());
- orderItem.setColumn(CharSequenceUtil.toUnderlineCase(order.getProperty()));
- mybatisPage.addOrder(orderItem);
- }
- }
- return mybatisPage;
- }
-
- public Integer getPage() {
- return page;
- }
-
- public void setPage(Integer page) {
- this.page = page;
- }
-
- public Integer getSize() {
- return size;
- }
-
- public void setSize(Integer size) {
- this.size = size;
- }
-}
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/model/resp/PageResp.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/model/resp/PageResp.java
index ade02623..8483bf7b 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/model/resp/PageResp.java
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/model/resp/PageResp.java
@@ -22,8 +22,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serial;
-import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -34,22 +34,17 @@ import java.util.List;
* @since 1.0.0
*/
@Schema(description = "分页信息")
-public class PageResp implements Serializable {
+public class PageResp extends BasePageResp {
@Serial
private static final long serialVersionUID = 1L;
- /**
- * 列表数据
- */
- @Schema(description = "列表数据")
- private List list;
+ public PageResp() {
+ }
- /**
- * 总记录数
- */
- @Schema(description = "总记录数", example = "10")
- private long total;
+ public PageResp(final List list, final long total) {
+ super(list, total);
+ }
/**
* 基于 MyBatis Plus 分页数据构建分页信息,并将源数据转换为指定类型数据
@@ -64,10 +59,7 @@ public class PageResp implements Serializable {
if (null == page) {
return empty();
}
- PageResp pageResp = new PageResp<>();
- pageResp.setList(BeanUtil.copyToList(page.getRecords(), targetClass));
- pageResp.setTotal(page.getTotal());
- return pageResp;
+ return new PageResp<>(BeanUtil.copyToList(page.getRecords(), targetClass), page.getTotal());
}
/**
@@ -81,10 +73,7 @@ public class PageResp implements Serializable {
if (null == page) {
return empty();
}
- PageResp pageResp = new PageResp<>();
- pageResp.setList(page.getRecords());
- pageResp.setTotal(page.getTotal());
- return pageResp;
+ return new PageResp<>(page.getRecords(), page.getTotal());
}
/**
@@ -122,24 +111,6 @@ public class PageResp implements Serializable {
* @return 分页信息
*/
private static PageResp empty() {
- PageResp pageResp = new PageResp<>();
- pageResp.setList(new ArrayList<>(0));
- return pageResp;
- }
-
- public List getList() {
- return list;
- }
-
- public void setList(List list) {
- this.list = list;
- }
-
- public long getTotal() {
- return total;
- }
-
- public void setTotal(long total) {
- this.total = total;
+ return new PageResp<>(Collections.emptyList(), 0L);
}
}
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
index 3ace52b1..9e955632 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
@@ -20,15 +20,15 @@ import cn.crane4j.core.support.OperateTemplate;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.text.CharSequenceUtil;
+import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;
@@ -38,21 +38,24 @@ import top.continew.starter.core.util.ReflectUtils;
import top.continew.starter.core.util.validate.CheckUtils;
import top.continew.starter.core.util.validate.ValidationUtils;
import top.continew.starter.data.mybatis.plus.base.BaseMapper;
-import top.continew.starter.data.mybatis.plus.query.QueryWrapperHelper;
import top.continew.starter.data.mybatis.plus.service.impl.ServiceImpl;
+import top.continew.starter.data.mybatis.plus.util.QueryWrapperHelper;
import top.continew.starter.extension.crud.annotation.DictField;
import top.continew.starter.extension.crud.annotation.TreeField;
import top.continew.starter.extension.crud.model.entity.BaseIdDO;
+import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.extension.crud.model.query.SortQuery;
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.extension.crud.service.BaseService;
import top.continew.starter.extension.crud.util.TreeUtils;
-import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.file.excel.util.ExcelUtils;
import java.lang.reflect.Field;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
/**
* 业务实现基类
@@ -76,7 +79,8 @@ public abstract class BaseServiceImpl, T extends BaseIdD
@Override
public PageResp page(Q query, PageQuery pageQuery) {
QueryWrapper queryWrapper = this.buildQueryWrapper(query);
- IPage page = baseMapper.selectPage(pageQuery.toPage(), queryWrapper);
+ this.sort(queryWrapper, pageQuery);
+ IPage page = baseMapper.selectPage(new Page<>(pageQuery.getPage(), pageQuery.getSize()), queryWrapper);
PageResp pageResp = PageResp.build(page, this.getListClass());
pageResp.getList().forEach(this::fill);
return pageResp;
@@ -253,23 +257,24 @@ public abstract class BaseServiceImpl, T extends BaseIdD
* @param sortQuery 排序查询条件
*/
protected void sort(QueryWrapper queryWrapper, SortQuery sortQuery) {
- Sort sort = Opt.ofNullable(sortQuery).orElseGet(SortQuery::new).getSort();
+ if (sortQuery == null || sortQuery.getSort().isUnsorted()) {
+ return;
+ }
+ Sort sort = sortQuery.getSort();
for (Sort.Order order : sort) {
- if (null != order) {
- String property = order.getProperty();
- String checkProperty;
- // 携带表别名则获取 . 后面的字段名
- if (property.contains(StringConstants.DOT)) {
- checkProperty = CollUtil.getLast(CharSequenceUtil.split(property, StringConstants.DOT));
- } else {
- checkProperty = property;
- }
- Optional optional = super.getEntityFields().stream()
- .filter(field -> checkProperty.equals(field.getName()))
- .findFirst();
- ValidationUtils.throwIf(optional.isEmpty(), "无效的排序字段 [{}]", property);
- queryWrapper.orderBy(true, order.isAscending(), CharSequenceUtil.toUnderlineCase(property));
+ String property = order.getProperty();
+ String checkProperty;
+ // 携带表别名则获取 . 后面的字段名
+ if (property.contains(StringConstants.DOT)) {
+ checkProperty = CollUtil.getLast(CharSequenceUtil.split(property, StringConstants.DOT));
+ } else {
+ checkProperty = property;
}
+ Optional optional = super.getEntityFields().stream()
+ .filter(field -> checkProperty.equals(field.getName()))
+ .findFirst();
+ ValidationUtils.throwIf(optional.isEmpty(), "无效的排序字段 [{}]", property);
+ queryWrapper.orderBy(true, order.isAscending(), CharSequenceUtil.toUnderlineCase(property));
}
}