商品模块代码提交

This commit is contained in:
谭凯凯
2025-02-11 15:16:43 +08:00
committed by Tankaikai
parent 0da6ec2890
commit 3b62eb6079
13 changed files with 472 additions and 82 deletions

View File

@@ -0,0 +1,95 @@
package com.czg.core.page;
import cn.hutool.core.util.StrUtil;
import io.micrometer.common.util.StringUtils;
/**
* 分页数据
*
* @author cashier
*/
public class PageDomain {
/**
* 当前记录起始索引
*/
private Integer pageNum;
/**
* 每页显示记录数
*/
private Integer pageSize;
/**
* 排序列
*/
private String orderByColumn;
/**
* 排序的方向desc或者asc
*/
private String isAsc = "asc";
/**
* 分页参数合理化
*/
private Boolean reasonable = true;
public String getOrderBy() {
if (StrUtil.isEmpty(orderByColumn)) {
return "";
}
return StrUtil.toUnderlineCase(orderByColumn) + " " + isAsc;
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public String getOrderByColumn() {
return orderByColumn;
}
public void setOrderByColumn(String orderByColumn) {
this.orderByColumn = orderByColumn;
}
public String getIsAsc() {
return isAsc;
}
public void setIsAsc(String isAsc) {
if (StringUtils.isNotEmpty(isAsc)) {
// 兼容前端排序类型
if ("ascending".equals(isAsc)) {
isAsc = "asc";
} else if ("descending".equals(isAsc)) {
isAsc = "desc";
}
this.isAsc = isAsc;
}
}
public Boolean getReasonable() {
if (reasonable == null) {
return Boolean.TRUE;
}
return reasonable;
}
public void setReasonable(Boolean reasonable) {
this.reasonable = reasonable;
}
}

View File

@@ -0,0 +1,77 @@
package com.czg.core.page;
import cn.hutool.core.convert.Convert;
import com.mybatisflex.core.paginate.Page;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 分页查询实体类
*
* @author Cashier
*/
@Data
public class PageQuery implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "pageNum";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
/**
* 分页大小
*/
private Integer pageSize;
/**
* 当前页数
*/
private Integer pageNum;
/**
* 排序列
*/
private String orderByColumn;
/**
* 排序的方向desc或者asc
*/
private String isAsc;
/**
* 当前记录起始索引 默认值
*/
public static final int DEFAULT_PAGE_NUM = 1;
/**
* 每页显示记录数 默认值 默认查全部
*/
public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
/**
* 构造分页查询参数
* @return
* @param <T>
*/
public static <T> Page<T> build() {
Integer pageNum = Convert.toInt(TableSupport.getHttpServletRequest().getParameter(PAGE_NUM), DEFAULT_PAGE_NUM);
Integer pageSize = Convert.toInt(TableSupport.getHttpServletRequest().getParameter(PAGE_SIZE), DEFAULT_PAGE_SIZE);
if (pageNum <= 0) {
pageNum = DEFAULT_PAGE_NUM;
}
Page<T> page = new Page<>(pageNum, pageSize);
return page;
}
}

View File

@@ -0,0 +1,69 @@
package com.czg.core.page;
import cn.hutool.core.convert.Convert;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 表格数据处理
*
* @author Cashier
*/
public class TableSupport
{
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "pageNum";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
/**
* 排序列
*/
public static final String ORDER_BY_COLUMN = "orderByColumn";
/**
* 排序的方向 "desc" 或者 "asc".
*/
public static final String IS_ASC = "isAsc";
/**
* 分页参数合理化
*/
public static final String REASONABLE = "reasonable";
/**
* 封装分页对象
*/
public static PageDomain getPageDomain()
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(Convert.toInt(getHttpServletRequest().getParameter(PAGE_NUM), 1));
pageDomain.setPageSize(Convert.toInt(getHttpServletRequest().getParameter(PAGE_SIZE), 10));
pageDomain.setOrderByColumn(getHttpServletRequest().getParameter(ORDER_BY_COLUMN));
pageDomain.setIsAsc(getHttpServletRequest().getParameter(IS_ASC));
pageDomain.setReasonable(Convert.toBool(getHttpServletRequest().getParameter(REASONABLE)));
return pageDomain;
}
public static PageDomain buildPageRequest()
{
return getPageDomain();
}
public static HttpServletRequest getHttpServletRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if(requestAttributes == null){
return null;
}
return ((ServletRequestAttributes) requestAttributes).getRequest();
}
}

View File

@@ -0,0 +1,54 @@
package com.czg.core.service;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.service.IService;
import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.core.util.SqlUtil;
import java.util.Collection;
/**
* 自定义的服务基类接口
*
* @author dataprince数据小王子
*/
public interface IBaseService<T> extends IService<T> {
/**
* <p>带主键保存实体类对象数据,适用于中间表有联合主键场合但是不通过主键生成器生成主键值,而是程序自己提供主键值。
*
* @param entity 实体类对象
* @return 受影响的行数
* @apiNote 默认调用的是 {@link BaseMapper#insertSelectiveWithPk(Object)} 方法,忽略实体类
* {@code null} 属性的数据,使数据库配置的默认值生效。
*/
default int saveWithPk(T entity) {
return getMapper().insertSelectiveWithPk(entity);
}
/**
* <p>带主键批量保存实体类对象数据适用于中间表有联合主键场合但是不通过主键生成器生成主键值而是程序自己提供主键值例如sys_role_menu。
*
* @param entities 实体类对象
* @return {@code true} 保存成功,{@code false} 保存失败。
* @apiNote 默认调用的是 {@link BaseMapper#insertSelectiveWithPk(Object)} 方法,忽略实体类
* {@code null} 属性的数据,使数据库配置的默认值生效。
*/
default boolean saveBatchWithPk(Collection<T> entities) {
return saveBatchWithPk(entities, DEFAULT_BATCH_SIZE);
}
/**
* <p>带主键批量保存实体类对象数据适用于中间表有联合主键场合但是不通过主键生成器生成主键值而是程序自己提供主键值例如sys_role_menu。
*
* @param entities 实体类对象
* @param batchSize 每次保存切分的数量
* @return {@code true} 保存成功,{@code false} 保存失败。
* @apiNote 默认调用的是 {@link BaseMapper#insertSelectiveWithPk(Object)} 方法,忽略实体类
* {@code null} 属性的数据,使数据库配置的默认值生效。
*/
default boolean saveBatchWithPk(Collection<T> entities, int batchSize) {
Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass());
return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::insertSelectiveWithPk));
}
}

View File

@@ -0,0 +1,32 @@
package com.czg.core.service.impl;
import cn.hutool.core.util.StrUtil;
import com.czg.core.page.PageDomain;
import com.czg.core.page.TableSupport;
import com.czg.core.service.IBaseService;
import com.czg.utils.SqlUtil;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
/**
* 自定义的服务基类接口实现
*
* @author dataprince数据小王子
*/
public class BaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M , T> implements IBaseService<T> {
/**
* 构造基本查询条件
* @return QueryWrapper
*/
protected QueryWrapper buildBaseQueryWrapper(){
QueryWrapper queryWrapper = query();
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StrUtil.isNotEmpty(pageDomain.getOrderBy())) {
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
queryWrapper.orderBy(orderBy);
}
return queryWrapper;
}
}

View File

@@ -1,35 +0,0 @@
package com.czg.page;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 分页工具类
*
* @author Tankaikai tankaikai@aliyun.com
*/
@Data
public class PageData<T> implements Serializable {
/**
* 总记录数
*/
private long total;
/**
* 列表数据
*/
private List<T> list;
/**
* 分页
*
* @param list 列表数据
* @param total 总记录数
*/
public PageData(List<T> list, long total) {
this.list = list;
this.total = (int) total;
}
}

View File

@@ -3,10 +3,10 @@
package com.czg.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.exception.CzgException;
import java.util.List;
import java.util.Map;
@@ -21,7 +21,7 @@ public class AssertUtil {
public static void isBlank(String str, String msg) {
if (StrUtil.isBlank(str)) {
throw new CzgException(msg);
throw new ValidateException(msg);
}
}
@@ -31,7 +31,7 @@ public class AssertUtil {
public static void isNull(Object object, String msg) {
if (object == null) {
throw new CzgException(msg);
throw new ValidateException(msg);
}
}
@@ -41,7 +41,7 @@ public class AssertUtil {
public static void isArrayEmpty(Object[] array, String msg) {
if (ArrayUtil.isEmpty(array)) {
throw new CzgException(msg);
throw new ValidateException(msg);
}
}
@@ -51,7 +51,7 @@ public class AssertUtil {
public static void isListEmpty(List<?> list, String msg) {
if (CollUtil.isEmpty(list)) {
throw new CzgException(msg);
throw new ValidateException(msg);
}
}
@@ -61,7 +61,7 @@ public class AssertUtil {
public static void isMapEmpty(Map map, String msg) {
if (MapUtil.isEmpty(map)) {
throw new CzgException(msg);
throw new ValidateException(msg);
}
}

View File

@@ -0,0 +1,71 @@
package com.czg.utils;
import cn.hutool.core.util.StrUtil;
import java.util.List;
/**
* sql操作工具类
*
* @author ruoyi
*/
public class SqlUtil
{
/**
* 定义常用的 sql关键字
*/
public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
/**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
*/
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
/**
* 限制orderBy最大长度
*/
private static final int ORDER_BY_MAX_LENGTH = 500;
/**
* 检查字符,防止注入绕过
*/
public static String escapeOrderBySql(String value)
{
if (StrUtil.isNotEmpty(value) && !isValidOrderBySql(value))
{
throw new IllegalArgumentException("参数不符合规范,不能进行查询");
}
if (StrUtil.length(value) > ORDER_BY_MAX_LENGTH)
{
throw new IllegalArgumentException("参数已超过最大限制,不能进行查询");
}
return value;
}
/**
* 验证 order by 语法是否符合规范
*/
public static boolean isValidOrderBySql(String value)
{
return value.matches(SQL_PATTERN);
}
/**
* SQL关键字检查
*/
public static void filterKeyword(String value)
{
if (StrUtil.isEmpty(value))
{
return;
}
List<String> sqlKeywords = StrUtil.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StrUtil.indexOfIgnoreCase(value, sqlKeyword) > -1)
{
throw new IllegalArgumentException("参数存在SQL注入风险");
}
}
}
}