网站搭建怎么收费,保网微商城app下载,建筑师证报考条件,网站需要多大的空间目录 一、分页对象封装
分页数据对象
分页查询实体类
实体类用到的utils
ServiceException StringUtils SqlUtil BaseMapperPlus, BeanCopyUtils
二、示例
controller
service
dao 一、分页对象封装
分页数据对象 import cn.hutool.http.HttpStatus;
import com.…目录 一、分页对象封装
分页数据对象
分页查询实体类
实体类用到的utils
ServiceException StringUtils SqlUtil BaseMapperPlus, BeanCopyUtils
二、示例
controller
service
dao 一、分页对象封装
分页数据对象
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.util.List;/*** 分页数据对象** author chensir*/Data
NoArgsConstructor
public class TableDataInfoT implements Serializable {private static final long serialVersionUID 1L;/*** 总记录数*/private long total;/*** 列表数据*/private ListT rows;/*** 消息状态码*/private int code;/*** 消息内容*/private String msg;/*** 分页** param list 列表数据* param total 总记录数*/public TableDataInfo(ListT list, long total) {this.rows list;this.total total;}public static T TableDataInfoT build(IPageT page) {TableDataInfoT rspData new TableDataInfo();rspData.setCode(HttpStatus.HTTP_OK);rspData.setMsg(查询成功);rspData.setRows(page.getRecords());rspData.setTotal(page.getTotal());return rspData;}public static T TableDataInfoT build(ListT list) {TableDataInfoT rspData new TableDataInfo();rspData.setCode(HttpStatus.HTTP_OK);rspData.setMsg(查询成功);rspData.setRows(list);rspData.setTotal(list.size());return rspData;}public static T TableDataInfoT build() {TableDataInfoT rspData new TableDataInfo();rspData.setCode(HttpStatus.HTTP_OK);rspData.setMsg(查询成功);return rspData;}}分页查询实体类
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ict.lux.exception.ServiceException;
import com.ict.lux.utils.StringUtils;
import com.ict.lux.utils.sql.SqlUtil;
import lombok.Data;import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;/*** 分页查询实体类** author chensir*/Data
public class PageQuery implements Serializable {private static final long serialVersionUID 1L;/*** 分页大小*/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;public T PageT build() {Integer pageNum ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM);Integer pageSize ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE);if (pageNum 0) {pageNum DEFAULT_PAGE_NUM;}PageT page new Page(pageNum, pageSize);ListOrderItem orderItems buildOrderItem();if (CollUtil.isNotEmpty(orderItems)) {page.addOrder(orderItems);}return page;}/*** 构建排序** 支持的用法如下:* {isAsc:asc,orderByColumn:id} order by id asc* {isAsc:asc,orderByColumn:id,createTime} order by id asc,create_time asc* {isAsc:desc,orderByColumn:id,createTime} order by id desc,create_time desc* {isAsc:asc,desc,orderByColumn:id,createTime} order by id asc,create_time desc*/private ListOrderItem buildOrderItem() {if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) {return null;}String orderBy SqlUtil.escapeOrderBySql(orderByColumn);orderBy StringUtils.toUnderScoreCase(orderBy);// 兼容前端排序类型isAsc StringUtils.replaceEach(isAsc, new String[]{ascending, descending}, new String[]{asc, desc});String[] orderByArr orderBy.split(StringUtils.SEPARATOR);String[] isAscArr isAsc.split(StringUtils.SEPARATOR);if (isAscArr.length ! 1 isAscArr.length ! orderByArr.length) {throw new ServiceException(排序参数有误);}ListOrderItem list new ArrayList();// 每个字段各自排序for (int i 0; i orderByArr.length; i) {String orderByStr orderByArr[i];String isAscStr isAscArr.length 1 ? isAscArr[0] : isAscArr[i];if (asc.equals(isAscStr)) {list.add(OrderItem.asc(orderByStr));} else if (desc.equals(isAscStr)) {list.add(OrderItem.desc(orderByStr));} else {throw new ServiceException(排序参数有误);}}return list;}}实体类用到的utils
ServiceException
/*** 业务异常** author chensir*/
public final class ServiceException extends RuntimeException {private static final long serialVersionUID 1L;/*** 错误码*/private Integer code;/*** 错误提示*/private String message;/*** 错误明细内部调试错误* p* 和 {link CommonResult#getDetailMessage()} 一致的设计*/private String detailMessage;/*** 空构造方法避免反序列化问题*/public ServiceException() {}public ServiceException(String message) {this.message message;}public ServiceException(String message, Integer code) {this.message message;this.code code;}public String getDetailMessage() {return detailMessage;}Overridepublic String getMessage() {return message;}public Integer getCode() {return code;}public ServiceException setMessage(String message) {this.message message;return this;}public ServiceException setDetailMessage(String detailMessage) {this.detailMessage detailMessage;return this;}
}StringUtils
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.util.AntPathMatcher;import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;/*** 字符串工具类** author chensir*/
NoArgsConstructor(access AccessLevel.PRIVATE)
public class StringUtils extends org.apache.commons.lang3.StringUtils {public static final String SEPARATOR ,;/*** 获取参数不为空值** param str defaultValue 要判断的value* return value 返回值*/public static String blankToDefault(String str, String defaultValue) {return StrUtil.blankToDefault(str, defaultValue);}/*** * 判断一个字符串是否为空串** param str String* return true为空 false非空*/public static boolean isEmpty(String str) {return StrUtil.isEmpty(str);}/*** * 判断一个字符串是否为非空串** param str String* return true非空串 false空串*/public static boolean isNotEmpty(String str) {return !isEmpty(str);}/*** 去空格*/public static String trim(String str) {return StrUtil.trim(str);}/*** 截取字符串** param str 字符串* param start 开始* return 结果*/public static String substring(final String str, int start) {return substring(str, start, str.length());}/*** 截取字符串** param str 字符串* param start 开始* param end 结束* return 结果*/public static String substring(final String str, int start, int end) {return StrUtil.sub(str, start, end);}/*** 格式化文本, {} 表示占位符br* 此方法只是简单将占位符 {} 按照顺序替换为参数br* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可br* 例br* 通常使用format(this is {} for {}, a, b) - this is a for bbr* 转义{} format(this is \\{} for {}, a, b) - this is {} for abr* 转义\ format(this is \\\\{} for {}, a, b) - this is \a for bbr** param template 文本模板被替换的部分用 {} 表示* param params 参数值* return 格式化后的文本*/public static String format(String template, Object... params) {return StrUtil.format(template, params);}/*** 是否为http(s)://开头** param link 链接* return 结果*/public static boolean ishttp(String link) {return Validator.isUrl(link);}/*** 字符串转set** param str 字符串* param sep 分隔符* return set集合*/public static SetString str2Set(String str, String sep) {return new HashSet(str2List(str, sep, true, false));}/*** 字符串转list** param str 字符串* param sep 分隔符* param filterBlank 过滤纯空白* param trim 去掉首尾空白* return list集合*/public static ListString str2List(String str, String sep, boolean filterBlank, boolean trim) {ListString list new ArrayList();if (isEmpty(str)) {return list;}// 过滤空白字符串if (filterBlank isBlank(str)) {return list;}String[] split str.split(sep);for (String string : split) {if (filterBlank isBlank(string)) {continue;}if (trim) {string trim(string);}list.add(string);}return list;}/*** 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写** param cs 指定字符串* param searchCharSequences 需要检查的字符串数组* return 是否包含任意一个字符串*/public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {return StrUtil.containsAnyIgnoreCase(cs, searchCharSequences);}/*** 驼峰转下划线命名*/public static String toUnderScoreCase(String str) {return StrUtil.toUnderlineCase(str);}/*** 是否包含字符串** param str 验证字符串* param strs 字符串组* return 包含返回true*/public static boolean inStringIgnoreCase(String str, String... strs) {return StrUtil.equalsAnyIgnoreCase(str, strs);}/*** 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空则返回空字符串。 例如HELLO_WORLD-HelloWorld** param name 转换前的下划线大写方式命名的字符串* return 转换后的驼峰式命名的字符串*/public static String convertToCamelCase(String name) {return StrUtil.upperFirst(StrUtil.toCamelCase(name));}/*** 驼峰式命名法 例如user_name-userName*/public static String toCamelCase(String s) {return StrUtil.toCamelCase(s);}/*** 查找指定字符串是否匹配指定字符串列表中的任意一个字符串** param str 指定字符串* param strs 需要检查的字符串数组* return 是否匹配*/public static boolean matches(String str, ListString strs) {if (isEmpty(str) || CollUtil.isEmpty(strs)) {return false;}for (String pattern : strs) {if (isMatch(pattern, str)) {return true;}}return false;}/*** 判断url是否与规则配置:* ? 表示单个字符;* * 表示一层路径内的任意字符串不可跨层级;* ** 表示任意层路径;** param pattern 匹配规则* param url 需要匹配的url*/public static boolean isMatch(String pattern, String url) {AntPathMatcher matcher new AntPathMatcher();return matcher.match(pattern, url);}/*** 数字左边补齐0使之达到指定长度。注意如果数字转换为字符串后长度大于size则只保留 最后size个字符。** param num 数字对象* param size 字符串指定长度* return 返回数字的字符串格式该字符串为指定长度。*/public static String padl(final Number num, final int size) {return padl(num.toString(), size, 0);}/*** 字符串左补齐。如果原始字符串s长度大于size则只保留最后size个字符。** param s 原始字符串* param size 字符串指定长度* param c 用于补齐的字符* return 返回指定长度的字符串由原字符串左补齐或截取得到。*/public static String padl(final String s, final int size, final char c) {final StringBuilder sb new StringBuilder(size);if (s ! null) {final int len s.length();if (s.length() size) {for (int i size - len; i 0; i--) {sb.append(c);}sb.append(s);} else {return s.substring(len - size, len);}} else {for (int i size; i 0; i--) {sb.append(c);}}return sb.toString();}/*** 切分字符串(分隔符默认逗号)** param str 被切分的字符串* return 分割后的数据列表*/public static ListString splitList(String str) {return splitTo(str, Convert::toStr);}/*** 切分字符串** param str 被切分的字符串* param separator 分隔符* return 分割后的数据列表*/public static ListString splitList(String str, String separator) {return splitTo(str, separator, Convert::toStr);}/*** 切分字符串自定义转换(分隔符默认逗号)** param str 被切分的字符串* param mapper 自定义转换* return 分割后的数据列表*/public static T ListT splitTo(String str, Function? super Object, T mapper) {return splitTo(str, SEPARATOR, mapper);}/*** 切分字符串自定义转换** param str 被切分的字符串* param separator 分隔符* param mapper 自定义转换* return 分割后的数据列表*/public static T ListT splitTo(String str, String separator, Function? super Object, T mapper) {if (isBlank(str)) {return new ArrayList(0);}return StrUtil.split(str, separator).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());}}SqlUtil
import com.ict.lux.exception.UtilException;
import com.ict.lux.utils.StringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;/*** sql操作工具类** author chensir*/
NoArgsConstructor(access AccessLevel.PRIVATE)
public class SqlUtil {/*** 定义常用的 sql关键字*/public static final String SQL_REGEX select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ;/*** 仅支持字母、数字、下划线、空格、逗号、小数点支持多个字段排序*/public static final String SQL_PATTERN [a-zA-Z0-9_\\ \\,\\.];/*** 检查字符防止注入绕过*/public static String escapeOrderBySql(String value) {if (StringUtils.isNotEmpty(value) !isValidOrderBySql(value)) {throw new UtilException(参数不符合规范不能进行查询);}return value;}/*** 验证 order by 语法是否符合规范*/public static boolean isValidOrderBySql(String value) {return value.matches(SQL_PATTERN);}/*** SQL关键字检查*/public static void filterKeyword(String value) {if (StringUtils.isEmpty(value)) {return;}String[] sqlKeywords StringUtils.split(SQL_REGEX, \\|);for (String sqlKeyword : sqlKeywords) {if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) -1) {throw new UtilException(参数存在SQL注入风险);}}}
}BaseMapperPlusM, T, V
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.plm.common.utils.BeanCopyUtils;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;/*** 自定义 Mapper 接口, 实现 自定义扩展** param M mapper 泛型* param T table 泛型* param V vo 泛型* author chensir* since 2022-10-8*/
SuppressWarnings(unchecked)
public interface BaseMapperPlusM, T, V extends BaseMapperT {Log log LogFactory.getLog(BaseMapperPlus.class);default ClassV currentVoClass() {return (ClassV) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2);}default ClassT currentModelClass() {return (ClassT) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 1);}default ClassM currentMapperClass() {return (ClassM) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 0);}default ListT selectList() {return this.selectList(new QueryWrapper());}/*** 批量插入*/default boolean insertBatch(CollectionT entityList) {return Db.saveBatch(entityList);}/*** 批量更新*/default boolean updateBatchById(CollectionT entityList) {return Db.updateBatchById(entityList);}/*** 批量插入或更新*/default boolean insertOrUpdateBatch(CollectionT entityList) {return Db.saveOrUpdateBatch(entityList);}/*** 批量插入(包含限制条数)*/default boolean insertBatch(CollectionT entityList, int batchSize) {return Db.saveBatch(entityList, batchSize);}/*** 批量更新(包含限制条数)*/default boolean updateBatchById(CollectionT entityList, int batchSize) {return Db.updateBatchById(entityList, batchSize);}/*** 批量插入或更新(包含限制条数)*/default boolean insertOrUpdateBatch(CollectionT entityList, int batchSize) {return Db.saveOrUpdateBatch(entityList, batchSize);}/*** 插入或更新(包含限制条数)*/default boolean insertOrUpdate(T entity) {return Db.saveOrUpdate(entity);}default V selectVoById(Serializable id) {return selectVoById(id, this.currentVoClass());}/*** 根据 ID 查询*/default C C selectVoById(Serializable id, ClassC voClass) {T obj this.selectById(id);if (ObjectUtil.isNull(obj)) {return null;}return BeanCopyUtils.copy(obj, voClass);}default ListV selectVoBatchIds(Collection? extends Serializable idList) {return selectVoBatchIds(idList, this.currentVoClass());}/*** 查询根据ID 批量查询*/default C ListC selectVoBatchIds(Collection? extends Serializable idList, ClassC voClass) {ListT list this.selectBatchIds(idList);if (CollUtil.isEmpty(list)) {return CollUtil.newArrayList();}return BeanCopyUtils.copyList(list, voClass);}default ListV selectVoByMap(MapString, Object map) {return selectVoByMap(map, this.currentVoClass());}/*** 查询根据 columnMap 条件*/default C ListC selectVoByMap(MapString, Object map, ClassC voClass) {ListT list this.selectByMap(map);if (CollUtil.isEmpty(list)) {return CollUtil.newArrayList();}return BeanCopyUtils.copyList(list, voClass);}default V selectVoOne(WrapperT wrapper) {return selectVoOne(wrapper, this.currentVoClass());}/*** 根据 entity 条件查询一条记录*/default C C selectVoOne(WrapperT wrapper, ClassC voClass) {T obj this.selectOne(wrapper);if (ObjectUtil.isNull(obj)) {return null;}return BeanCopyUtils.copy(obj, voClass);}default ListV selectVoList(WrapperT wrapper) {return selectVoList(wrapper, this.currentVoClass());}/*** 根据 entity 条件查询全部记录*/default C ListC selectVoList(WrapperT wrapper, ClassC voClass) {ListT list this.selectList(wrapper);if (CollUtil.isEmpty(list)) {return CollUtil.newArrayList();}return BeanCopyUtils.copyList(list, voClass);}default P extends IPageV P selectVoPage(IPageT page, WrapperT wrapper) {return selectVoPage(page, wrapper, this.currentVoClass());}/*** 分页查询VO*/default C, P extends IPageC P selectVoPage(IPageT page, WrapperT wrapper, ClassC voClass) {IPageT pageData this.selectPage(page, wrapper);IPageC voPage new Page(pageData.getCurrent(), pageData.getSize(), pageData.getTotal());if (CollUtil.isEmpty(pageData.getRecords())) {return (P) voPage;}voPage.setRecords(BeanCopyUtils.copyList(pageData.getRecords(), voClass));return (P) voPage;}}BeanCopyUtils
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.SimpleCache;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.cglib.core.Converter;import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;/*** bean深拷贝工具(基于 cglib 性能优异)* p* 重点 cglib 不支持 拷贝到链式对象* 例如: 源对象 拷贝到 目标(链式对象)* 请区分好浅拷贝和深拷贝再做使用** author chensir*/
NoArgsConstructor(access AccessLevel.PRIVATE)
public class BeanCopyUtils {/*** 单对象基于class创建拷贝** param source 数据来源实体* param desc 描述对象 转换后的对象* return desc*/public static T, V V copy(T source, ClassV desc) {if (ObjectUtil.isNull(source)) {return null;}if (ObjectUtil.isNull(desc)) {return null;}final V target ReflectUtil.newInstanceIfPossible(desc);return copy(source, target);}/*** 单对象基于对象创建拷贝** param source 数据来源实体* param desc 转换后的对象* return desc*/public static T, V V copy(T source, V desc) {if (ObjectUtil.isNull(source)) {return null;}if (ObjectUtil.isNull(desc)) {return null;}BeanCopier beanCopier BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null);beanCopier.copy(source, desc, null);return desc;}/*** 列表对象基于class创建拷贝** param sourceList 数据来源实体列表* param desc 描述对象 转换后的对象* return desc*/public static T, V ListV copyList(ListT sourceList, ClassV desc) {if (ObjectUtil.isNull(sourceList)) {return null;}if (CollUtil.isEmpty(sourceList)) {return CollUtil.newArrayList();}return StreamUtils.toList(sourceList, source - {V target ReflectUtil.newInstanceIfPossible(desc);copy(source, target);return target;});}/*** bean拷贝到map** param bean 数据来源实体* return map对象*/SuppressWarnings(unchecked)public static T MapString, Object copyToMap(T bean) {if (ObjectUtil.isNull(bean)) {return null;}return BeanMap.create(bean);}/*** map拷贝到bean** param map 数据来源* param beanClass bean类* return bean对象*/public static T T mapToBean(MapString, Object map, ClassT beanClass) {if (MapUtil.isEmpty(map)) {return null;}if (ObjectUtil.isNull(beanClass)) {return null;}T bean ReflectUtil.newInstanceIfPossible(beanClass);return mapToBean(map, bean);}/*** map拷贝到bean** param map 数据来源* param bean bean对象* return bean对象*/public static T T mapToBean(MapString, Object map, T bean) {if (MapUtil.isEmpty(map)) {return null;}if (ObjectUtil.isNull(bean)) {return null;}BeanMap.create(bean).putAll(map);return bean;}/*** map拷贝到map** param map 数据来源* param clazz 返回的对象类型* return map对象*/public static T, V MapString, V mapToMap(MapString, T map, ClassV clazz) {if (MapUtil.isEmpty(map)) {return null;}if (ObjectUtil.isNull(clazz)) {return null;}MapString, V copyMap new LinkedHashMap(map.size());map.forEach((k, v) - copyMap.put(k, copy(v, clazz)));return copyMap;}/*** BeanCopier属性缓存br* 缓存用于防止多次反射造成的性能问题** author Looly* since 5.4.1*/public enum BeanCopierCache {/*** BeanCopier属性缓存单例*/INSTANCE;private final SimpleCacheString, BeanCopier cache new SimpleCache();/*** 获得类与转换器生成的key在{link BeanCopier}的Map中对应的元素** param srcClass 源Bean的类* param targetClass 目标Bean的类* param converter 转换器* return Map中对应的BeanCopier*/public BeanCopier get(Class? srcClass, Class? targetClass, Converter converter) {final String key genKey(srcClass, targetClass, converter);return cache.get(key, () - BeanCopier.create(srcClass, targetClass, converter ! null));}/*** 获得类与转换器生成的key** param srcClass 源Bean的类* param targetClass 目标Bean的类* param converter 转换器* return 属性名和Map映射的key*/private String genKey(Class? srcClass, Class? targetClass, Converter converter) {final StringBuilder key StrUtil.builder().append(srcClass.getName()).append(#).append(targetClass.getName());if (null ! converter) {key.append(#).append(converter.getClass().getName());}return key.toString();}}}二、示例
controller
BaseController可忽略 service dao