package com.xueyi.job.api.utils;
import org.quartz.CronExpression;
import java.text.ParseException;
import java.util.Date;
/**
* cron表达式工具类
*
* @author xueyi
*/
public class CronUtils {
/**
* 返回一个布尔值代表一个给定的Cron表达式的有效性
*
* @param cronExpression Cron表达式
* @return boolean 表达式是否有效
*/
public static boolean isValid(String cronExpression) {
return CronExpression.isValidExpression(cronExpression);
}
/**
* 返回一个字符串值,表示该消息无效Cron表达式给出有效性
*
* @param cronExpression Cron表达式
* @return String 无效时返回表达式错误描述,如果有效返回null
*/
public static String getInvalidMessage(String cronExpression) {
try {
new CronExpression(cronExpression);
return null;
} catch (ParseException pe) {
return pe.getMessage();
}
}
/**
* 返回下一个执行时间根据给定的Cron表达式
*
* @param cronExpression Cron表达式
* @return Date 下次Cron表达式执行时间
*/
public static Date getNextExecution(String cronExpression) {
try {
CronExpression cron = new CronExpression(cronExpression);
return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
} catch (ParseException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
package com.xueyi.common.cache.utils;
import com.xueyi.common.cache.constant.CacheConstants;
import com.xueyi.common.cache.service.CacheService;
import com.xueyi.common.core.constant.basic.DictConstants;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.context.SecurityContextHolder;
import com.xueyi.common.core.utils.core.ConvertUtil;
import com.xueyi.common.core.utils.core.ObjectUtil;
import com.xueyi.common.core.utils.core.SpringUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import com.xueyi.system.api.dict.domain.dto.SysConfigDto;
import com.xueyi.system.api.dict.domain.dto.SysDictDataDto;
import com.xueyi.system.api.dict.domain.dto.SysDictTypeDto;
import com.xueyi.system.api.dict.feign.RemoteConfigService;
import com.xueyi.system.api.dict.feign.RemoteDictService;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 字典缓存管理工具类
*
* @author xueyi
*/
public class DictUtil {
private static CacheService cacheService;
private static CacheService getCacheService() {
if (ObjectUtil.isNull(cacheService)) {
cacheService = SpringUtil.getBean(CacheService.class);
}
return cacheService;
}
/**
* 获取参数缓存
*
* @param type 参数类型
* @return 参数数据
*/
public static <T> T getConfigCache(CacheConstants.ConfigType type) {
return getCusConfigCache(type.getCode(), type.getClazz(), type.getDefaultValue());
}
/**
* 获取参数缓存
*
* @param code 参数编码
* @return 参数数据
*/
public static <T> T getCusConfigCache(String code) {
return getCusConfigCache(code, String.class, StrUtil.EMPTY);
}
/**
* 获取参数缓存
*
* @param code 参数编码
* @param clazz 数据类型
* @param defaultValue 默认值
* @return 参数数据
*/
@SuppressWarnings(value = {"unchecked"})
public static <T> T getCusConfigCache(String code, Class<?> clazz, Object defaultValue) {
SysConfigDto config = getCacheService().getCacheObject(CacheConstants.CacheType.ROUTE_CONFIG_KEY, code);
if (ObjectUtil.isNull(config)) {
return null;
}
String value;
if (StrUtil.equals(DictConstants.DicCacheType.TENANT.getCode(), config.getCacheType())) {
value = getCacheService().getCacheObject(CacheConstants.CacheType.SYS_CONFIG_KEY, code);
if (ObjectUtil.isNull(value)) {
SpringUtil.getBean(RemoteConfigService.class).syncCacheInner();
value = getCacheService().getCacheObject(CacheConstants.CacheType.SYS_CONFIG_KEY, code);
}
} else {
SecurityContextHolder.setEnterpriseId(SecurityConstants.COMMON_TENANT_ID.toString());
value = getCacheService().getCacheObject(CacheConstants.CacheType.TE_CONFIG_KEY, code);
SecurityContextHolder.rollLastEnterpriseId();
}
return (T) ConvertUtil.convert(clazz, value, defaultValue);
}
/**
* 获取字典缓存
*
* @param codes 字典编码集合
* @return 字典数据列表
*/
public static Map<String, List<SysDictDataDto>> getDictCache(Collection<String> codes) {
Map<String, List<SysDictDataDto>> map = new HashMap<>();
codes.forEach(code -> map.put(code, getDictCache(code)));
return map;
}
/**
* 获取字典缓存
*
* @param code 字典编码
* @return 字典数据列表
*/
public static List<SysDictDataDto> getDictCache(String code) {
SysDictTypeDto type = getCacheService().getCacheObject(CacheConstants.CacheType.ROUTE_DICT_KEY, code);
if (ObjectUtil.isNull(type)) {
return null;
}
List<SysDictDataDto> dictList;
if (StrUtil.equals(DictConstants.DicCacheType.TENANT.getCode(), type.getCacheType())) {
dictList = getCacheService().getCacheObject(CacheConstants.CacheType.SYS_DICT_KEY, code);
if (ObjectUtil.isNull(dictList)) {
SpringUtil.getBean(RemoteDictService.class).syncCacheInner();
dictList = getCacheService().getCacheObject(CacheConstants.CacheType.SYS_DICT_KEY, code);
}
} else {
SecurityContextHolder.setEnterpriseId(SecurityConstants.COMMON_TENANT_ID.toString());
dictList = getCacheService().getCacheObject(CacheConstants.CacheType.TE_DICT_KEY, code);
SecurityContextHolder.rollLastEnterpriseId();
}
return dictList;
}
}
package com.xueyi.common.core.utils.core.pool;
/**
* 常用数字常量
*
* @author xueyi
*/
public interface NumberPool {
int Ne_One = -1;
int Zero = 0;
int One = 1;
int Two = 2;
int Three = 3;
int Four = 4;
int Five = 5;
int Six = 6;
int Seven = 7;
int Eight = 8;
int Nine = 9;
int Ten = 10;
}
package com.xueyi.common.core.utils.core.pool;
/**
* 常用字符串常量
*
* @author xueyi
*/
public interface StrPool {
String UNKNOWN = "unknown";
String TRUE = "true";
String FALSE = "false";
String SINGLE_QUOTES = "'";
String DOUBLE_QUOTES = "\"";
String PARENTHESES = "()";
String PARENTHESES_START = "(";
String PARENTHESES_END = ")";
String DELIM = "{}";
String BRACKET = "[]";
String SEMICOLON = ";";
String EQUAL = "=";
String AMPERSAND = "&";
String ASTERISK = "*";
}
package com.xueyi.common.core.utils.core;
/**
* 数组工具类
*
* @author xueyi
*/
public class ArrayUtil extends cn.hutool.core.util.ArrayUtil {
}
package com.xueyi.common.core.utils.core;
/**
* Boolean类型工具类
*
* @author xueyi
*/
public class BooleanUtil extends cn.hutool.core.util.BooleanUtil {
}
package com.xueyi.common.core.utils.core;
/**
* 字符集工具类
*
* @author xueyi
*/
public class CharsetUtil extends cn.hutool.core.util.CharsetUtil {
}
package com.xueyi.common.core.utils.core;
import java.util.Collection;
/**
* 类工具类
*
* @author xueyi
*/
public class ClassUtil extends cn.hutool.core.util.ClassUtil {
public static boolean notEqual(Class<?> clazz1, Class<?> clazz2) {
return !equals(clazz1, clazz2);
}
public static boolean equals(Class<?> clazz1, Class<?> clazz2) {
if (ObjectUtil.hasNull(clazz1, clazz2) && !ObjectUtil.isAllEmpty(clazz1, clazz2)) {
return Boolean.FALSE;
}
ClassLoader loader1 = clazz1.getClassLoader();
ClassLoader loader2 = clazz2.getClassLoader();
return ObjectUtil.equals(loader1, loader2) && ObjectUtil.equals(clazz1.getName(), clazz2.getName()) && ObjectUtil.equals(clazz1.getPackageName(), clazz2.getPackageName());
}
/**
* 判断是否非数组类型
*
* @param clazz 类型
* @return 结果
*/
public static boolean isNotArray(Class<?> clazz) {
return !isArray(clazz);
}
/**
* 判断是否是数组类型
*
* @param clazz 类型
* @return 结果
*/
public static boolean isArray(Class<?> clazz) {
return clazz.isArray();
}
/**
* 判断是否是集合类型
*
* @param clazz 类型
* @return 结果
*/
public static boolean isNotCollection(Class<?> clazz) {
return !isCollection(clazz);
}
/**
* 判断是否是集合类型
*
* @param clazz 类
* @return 是否为基本类型
*/
public static boolean isCollection(Class<?> clazz) {
return Collection.class.isAssignableFrom(clazz);
}
/**
* 判断是否非基本类型(包括包装类和原始类)或String
*
* @param clazz 类型
* @return 是否非基本类型或String
*/
public static boolean isSimpleType(Class<?> clazz) {
return isBasicType(clazz) || isSimpleValueType(clazz);
}
/**
* 判断是否非基本类型(包括包装类和原始类)或String
*
* @param clazz 类型
* @return 是否非基本类型或String
*/
public static boolean isNotSimpleType(Class<?> clazz) {
return !isSimpleType(clazz);
}
/**
* 是否非标准的类
* 这个类必须:
* 1、非接口
* 2、非抽象类
* 3、非Enum枚举
* 4、非数组
* 5、非注解
* 6、非原始类型(int, long等)
*
* @param clazz 类
* @return 是否非标准类
*/
public static boolean isNotNormalClass(Class<?> clazz) {
return !isNormalClass(clazz);
}
/**
* 检查目标类是否不可以从原类转化
* 转化包括:
* 1、原类是对象,目标类型是原类型实现的接口
* 2、目标类型是原类型的父类
* 3、两者是原始类型或者包装类型(相互转换)
*
* @param targetType 目标类型
* @param sourceType 原类型
* @return 是否不可转化
*/
public static boolean isNotAssignable(Class<?> targetType, Class<?> sourceType) {
return !isAssignable(targetType, sourceType);
}
}
package com.xueyi.common.core.utils.core;
import java.util.Collection;
/**
* 集合工具类
*
* @author xueyi
*/
public class CollUtil extends cn.hutool.core.collection.CollUtil {
public static boolean isNotNull(Collection<?> collection) {
return !isNull(collection);
}
public static boolean isNull(Collection<?> collection) {
return collection == null;
}
public static boolean notContains(Collection<?> collection, Object value) {
return !contains(collection, value);
}
/**
* 集合是否为非空
*
* @param collection 集合
* @return 是否为非空
*/
public static boolean isNotEmpty(Collection<?> collection) {
return !isEmpty(collection);
}
}
package com.xueyi.common.core.utils.core;
/**
* 类型转换工具类
*
* @author xueyi
*/
public class ConvertUtil extends cn.hutool.core.convert.Convert {
}
package com.xueyi.common.core.utils.core;
/**
* 信息脱敏工具类
*
* @author xueyi
*/
public class DesensitizedUtil extends cn.hutool.core.util.DesensitizedUtil {
}
package com.xueyi.common.core.utils.core;
import com.xueyi.common.core.exception.UtilException;
import java.util.List;
/**
* 枚举工具类
*
* @author xueyi
*/
public class EnumUtil extends cn.hutool.core.util.EnumUtil {
/**
* 根据编码获取枚举对象
*
* @param clazz 枚举class
* @param code 内容
* @return 枚举对象
*/
public static <E extends Enum<E>> E getByCode(Class<E> clazz, String code) {
return getByFieldName(clazz, "code", code, false);
}
/**
* 根据编码获取枚举对象
*
* @param clazz 枚举class
* @param code 内容
* @return 枚举对象
*/
public static <E extends Enum<E>> E getByCodeElseNull(Class<E> clazz, String code) {
return getByFieldName(clazz, "code", code, true);
}
/**
* 根据内容获取枚举对象
*
* @param clazz 枚举class
* @param info 内容
* @return 枚举对象
*/
public static <E extends Enum<E>> E getByInfo(Class<E> clazz, String info) {
return getByFieldName(clazz, "info", info, false);
}
/**
* 根据指定字段获取枚举对象
*
* @param clazz 枚举class
* @param fieldName 字段名
* @param code 字段内容
* @param defaultNull 是否默认为空
* @return 枚举对象
*/
public static <E extends Enum<E>> E getByFieldName(Class<E> clazz, String fieldName, String code, boolean defaultNull) {
List<Object> codes = getFieldValues(clazz, fieldName);
int[] indexArray = ListUtil.indexOfAll(codes, code::equals);
if (ArrayUtil.isEmpty(indexArray))
if (defaultNull) {
return null;
} else {
throw new UtilException("未匹配到枚举值!");
}
else if (indexArray.length > NumberUtil.One)
throw new UtilException("匹配到多个枚举值!");
return getEnumAt(clazz, indexArray[NumberUtil.Zero]);
}
}
package com.xueyi.common.core.utils.core;
/**
* 唯一ID工具类
*
* @author xueyi
*/
public class IdUtil extends cn.hutool.core.util.IdUtil {
}
package com.xueyi.common.core.utils.core;
/**
* List集合工具类
*
* @author xueyi
*/
public class ListUtil extends cn.hutool.core.collection.ListUtil {
}
package com.xueyi.common.core.utils.core;
import java.time.LocalDate;
/**
* LocalDateTime工具类
*
* @author xueyi
*/
public class LocalDateTimeUtil extends cn.hutool.core.date.LocalDateTimeUtil {
public static LocalDate parseDate(String time) {
if (StrUtil.isBlank(time)) {
return null;
}
LocalDate date = null;
try {
date = cn.hutool.core.date.LocalDateTimeUtil.parseDate(time);
} catch (Exception e) {
try {
String replacement = "$1";
String regex = ".*(\\d{4}-\\d{2}-\\d{2}).*";
if (time.matches(regex)) {
time = time.replaceAll(regex, replacement);
date = LocalDateTimeUtil.parseDate(time, "yyyy-MM-dd");
}
if (ObjectUtil.isNotNull(date)) {
return date;
}
regex = ".*(\\d{4}/\\d{2}/\\d{2}).*";
if (time.matches(regex)) {
time = time.replaceAll(regex, replacement);
date = LocalDateTimeUtil.parseDate(time, "yyyy/MM/dd");
}
if (ObjectUtil.isNotNull(date)) {
return date;
}
regex = ".*(\\d{4}年\\d{2}月\\d{2}日).*";
if (time.matches(regex)) {
time = time.replaceAll(regex, replacement);
date = LocalDateTimeUtil.parseDate(time, "yyyy年MM月dd日");
}
if (ObjectUtil.isNotNull(date)) {
return date;
}
regex = ".*(\\d{4}年\\d月\\d{2}日).*";
if (time.matches(regex)) {
time = time.replaceAll(regex, replacement);
date = LocalDateTimeUtil.parseDate(time, "yyyy年M月dd日");
}
if (ObjectUtil.isNotNull(date)) {
return date;
}
regex = ".*(\\d{4}年\\d{2}月\\d日).*";
if (time.matches(regex)) {
time = time.replaceAll(regex, replacement);
date = LocalDateTimeUtil.parseDate(time, "yyyy年MM月d日");
}
if (ObjectUtil.isNotNull(date)) {
return date;
}
regex = ".*(\\d{4}年\\d月\\d日).*";
if (time.matches(regex)) {
time = time.replaceAll(regex, replacement);
date = LocalDateTimeUtil.parseDate(time, "yyyy年M月d日");
}
} catch (Exception ignored) {
}
}
return date;
}
}
package com.xueyi.common.core.utils.core;
import java.util.Map;
/**
* Map工具类
*
* @author xueyi
*/
public class MapUtil extends cn.hutool.core.map.MapUtil {
public static boolean isNotNull(Map<?, ?> map) {
return !isNull(map);
}
public static boolean isNull(Map<?, ?> map) {
return null == map;
}
}
package com.xueyi.common.core.utils.core;
import com.xueyi.common.core.utils.core.pool.NumberPool;
/**
* 数字工具类
*
* @author xueyi
*/
public class NumberUtil extends cn.hutool.core.util.NumberUtil implements NumberPool {
}
package com.xueyi.common.core.utils.core;
/**
* 对象工具类
*
* @author xueyi
*/
public class ObjectUtil extends cn.hutool.core.util.ObjectUtil {
public static boolean isAllNotNull(Object... objs) {
return !hasNull(objs);
}
}
package com.xueyi.common.core.utils.core;
/**
* 反射工具类
*
* @author xueyi
*/
public class ReflectUtil extends cn.hutool.core.util.ReflectUtil {
}
package com.xueyi.common.core.utils.core;
/**
* 正则工具类
*
* @author xueyi
*/
public class ReUtil extends cn.hutool.core.util.ReUtil {
}
package com.xueyi.common.core.utils.core;
/**
* 加密算法工具类
*
* @author xueyi
*/
public class SecureUtil extends cn.hutool.crypto.SecureUtil {
}
package com.xueyi.common.core.utils.core;
import org.springframework.stereotype.Component;
/**
* spring工具类
*
* @author xueyi
*/
@Component
public class SpringUtil extends cn.hutool.extra.spring.SpringUtil {
}
package com.xueyi.common.core.utils.core;
import cn.hutool.core.text.AntPathMatcher;
import com.xueyi.common.core.utils.core.pool.StrPool;
import org.springframework.lang.Nullable;
/**
* 字符串工具类
*
* @author xueyi
*/
public class StrUtil extends cn.hutool.core.util.StrUtil implements StrPool {
public static boolean notEquals(CharSequence str1, CharSequence str2) {
return !equals(str1, str2, false);
}
/**
* 截取分隔字符串之前的字符串 | 不包括分隔字符串
*
* @param str 字符串
* @param separator 分隔字符串
* @return 字符串
*/
public static String subBefore(CharSequence str, CharSequence separator) {
return subBefore(str, separator, false);
}
/**
* 截取最后一个分隔字符串之前的字符串 | 不包括分隔字符串
*
* @param str 字符串
* @param separator 分隔字符串
* @return 字符串
*/
public static String subBeforeLast(CharSequence str, CharSequence separator) {
return subBefore(str, separator, true);
}
/**
* 截取分隔字符串之后的字符串 | 不包括分隔字符串
*
* @param str 字符串
* @param separator 分隔字符串
* @return 字符串
*/
public static String subAfter(CharSequence str, CharSequence separator) {
return subAfter(str, separator, false);
}
/**
* 截取最后一个分隔字符串之后的字符串 | 不包括分隔字符串
*
* @param str 字符串
* @param separator 分隔字符串
* @return 字符串
*/
public static String subAfterLast(CharSequence str, CharSequence separator) {
return subAfter(str, separator, true);
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strArr 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strArr) {
if (str != null && strArr != null)
for (String s : strArr)
if (str.equalsIgnoreCase(trim(s)))
return true;
return false;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name) {
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty()) {
// 没必要转换
return EMPTY;
} else if (!name.contains(UNDERLINE)) {
// 不含下划线,仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split(UNDERLINE);
for (String camel : camels) {
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty()) {
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
/**
* 字符串全部大写 例如:HelLo->HELLO
*
* @param str 字符串
* @return 字符串
*/
public static String upperCase(String str) {
return str == null ? null : str.toUpperCase();
}
/**
* 首字母大写 例如:hello->Hello
*
* @param str 字符串
* @return 字符串
*/
public static String capitalize(String str) {
return upperFirst(str);
}
/**
* 首字母小写 例如:Hello->hello
*
* @param str 字符串
* @return 字符串
*/
public static String uncapitalize(String str) {
return lowerFirst(str);
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strList 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, String... strList) {
if (isEmpty(str) || ArrayUtil.isEmpty(strList))
return false;
for (String pattern : strList)
if (isMatch(pattern, str))
return true;
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串,不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return 结果
*/
public static boolean isMatch(String pattern, String url) {
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
public static boolean hasText(@Nullable CharSequence str) {
return str != null && str.length() > 0 && containsText(str);
}
public static boolean hasText(@Nullable String str) {
return str != null && !str.isEmpty() && containsText(str);
}
private static boolean containsText(CharSequence str) {
int strLen = str.length();
for (int i = 0; i < strLen; ++i)
if (!Character.isWhitespace(str.charAt(i)))
return true;
return false;
}
}
package com.xueyi.common.core.utils.core;
import java.lang.reflect.Type;
/**
* 类型工具类
*
* @author xueyi
*/
public class TypeUtil extends cn.hutool.core.util.TypeUtil {
/**
* 获取class
*
* @return class
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getClazz(Type type, int index) {
return (Class<T>) TypeUtil.getTypeArgument(type, index);
}
}
package com.xueyi.common.core.utils.file;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.Objects;
/**
* 文件类型工具类
*
* @author xueyi
*/
public class FileTypeUtil {
/**
* 获取文件类型
*
* 例如: xueyi.txt, 返回: txt
*
* @param file 文件名
* @return 后缀(不含".")
*/
public static String getFileType(File file) {
if (null == file) {
return StringUtils.EMPTY;
}
return getFileType(file.getName());
}
/**
* 获取文件类型
*
* 例如: xueyi.txt, 返回: txt
*
* @param fileName 文件名
* @return 后缀(不含".")
*/
public static String getFileType(String fileName) {
int separatorIndex = fileName.lastIndexOf(".");
if (separatorIndex < 0) {
return "";
}
return fileName.substring(separatorIndex + 1).toLowerCase();
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static String getExtension(MultipartFile file) {
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension)) {
extension = MimeTypeUtil.getExtension(Objects.requireNonNull(file.getContentType()));
}
return extension;
}
/**
* 获取文件类型
*
* @param photoByte 文件字节码
* @return 后缀(不含".")
*/
public static String getFileExtendName(byte[] photoByte) {
String strFileExtendName = "JPG";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {
strFileExtendName = "GIF";
} else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {
strFileExtendName = "JPG";
} else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
strFileExtendName = "BMP";
} else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
strFileExtendName = "PNG";
}
return strFileExtendName;
}
}
package com.xueyi.common.core.utils.file;
import com.xueyi.common.core.utils.core.ArrayUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* 文件处理工具类
*
* @author xueyi
*/
public class FileUtil extends cn.hutool.core.io.FileUtil {
/**
* 字符常量:斜杠 {@code '/'}
*/
public static final char SLASH = '/';
/**
* 字符常量:反斜杠 {@code '\\'}
*/
public static final char BACKSLASH = '\\';
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
* 输出指定文件的byte数组
*
* @param filePath 文件路径
* @param os 输出流
*/
public static void writeBytes(String filePath, OutputStream os) throws IOException {
FileInputStream fis = null;
try {
File file = new File(filePath);
if (!file.exists()) {
throw new FileNotFoundException(filePath);
}
fis = new FileInputStream(file);
byte[] b = new byte[1024];
int length;
while ((length = fis.read(b)) > 0) {
os.write(b, 0, length);
}
} catch (IOException e) {
throw e;
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
/**
* 删除文件
*
* @param filePath 文件
* @return 结果
*/
public static boolean deleteFile(String filePath) {
boolean flag = false;
File file = new File(filePath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists()) {
file.delete();
flag = true;
}
return flag;
}
/**
* 文件名称验证
*
* @param filename 文件名称
* @return true 正常 false 非法
*/
public static boolean isValidFilename(String filename) {
return filename.matches(FILENAME_PATTERN);
}
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public static boolean checkAllowDownload(String resource) {
// 禁止目录上跳级别
if (StrUtil.contains(resource, "..")) {
return false;
}
// 检查允许下载的文件规则
return ArrayUtil.contains(MimeTypeUtil.DEFAULT_ALLOWED_EXTENSION, FileTypeUtil.getFileType(resource));
}
/**
* 下载文件名重新编码
*
* @param request 请求对象
* @param fileName 文件名
* @return 编码后的文件名
*/
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
final String agent = request.getHeader("USER-AGENT");
String filename = fileName;
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
filename = new String(fileName.getBytes(), "ISO8859-1");
} else if (agent.contains("Chrome")) {
// google浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
/**
* 返回文件名
*
* @param filePath 文件
* @return 文件名
*/
public static String getName(String filePath) {
if (null == filePath) {
return null;
}
int len = filePath.length();
if (0 == len) {
return filePath;
}
if (isFileSeparator(filePath.charAt(len - 1))) {
// 以分隔符结尾的去掉结尾分隔符
len--;
}
int begin = 0;
char c;
for (int i = len - 1; i > -1; i--) {
c = filePath.charAt(i);
if (isFileSeparator(c)) {
// 查找最后一个路径分隔符(/或者\)
begin = i + 1;
break;
}
}
return filePath.substring(begin, len);
}
/**
* 是否为Windows或者Linux(Unix)文件分隔符
* Windows平台下分隔符为\,Linux(Unix)为/
*
* @param c 字符
* @return 是否为Windows或者Linux(Unix)文件分隔符
*/
public static boolean isFileSeparator(char c) {
return SLASH == c || BACKSLASH == c;
}
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
String percentEncodedFileName = percentEncode(realFileName);
String contentDispositionValue = "attachment; filename=" +
percentEncodedFileName +
";" +
"filename*=" +
"utf-8''" +
percentEncodedFileName;
response.setHeader("Content-disposition", contentDispositionValue);
response.setHeader("download-filename", percentEncodedFileName);
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public static String percentEncode(String s) throws UnsupportedEncodingException {
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
}
package com.xueyi.common.core.utils.file;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
/**
* 图片处理工具类
*
* @author xueyi
*/
@Slf4j
public class ImageUtil {
public static byte[] getImage(String imagePath) {
InputStream is = getFile(imagePath);
try {
return IOUtils.toByteArray(is);
} catch (Exception e) {
log.error("图片加载异常 {}", e);
return null;
} finally {
IOUtils.closeQuietly(is);
}
}
public static InputStream getFile(String imagePath) {
try {
byte[] result = readFile(imagePath);
result = Arrays.copyOf(result, result.length);
return new ByteArrayInputStream(result);
} catch (Exception e) {
log.error("获取图片异常 {}", e);
}
return null;
}
/**
* 读取文件为字节数据
*
* @param url 地址
* @return 字节数据
*/
public static byte[] readFile(String url) {
InputStream in = null;
try {
// 网络地址
URL urlObj = new URL(url);
URLConnection urlConnection = urlObj.openConnection();
urlConnection.setConnectTimeout(30 * 1000);
urlConnection.setReadTimeout(60 * 1000);
urlConnection.setDoInput(true);
in = urlConnection.getInputStream();
return IOUtils.toByteArray(in);
} catch (Exception e) {
log.error("访问文件异常 {}", e);
return null;
} finally {
IOUtils.closeQuietly(in);
}
}
}
package com.xueyi.common.core.utils.file;
/**
* 媒体类型工具类
*
* @author xueyi
*/
public class MimeTypeUtil {
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
public static final String[] FLASH_EXTENSION = {"swf", "flv"};
public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb"};
public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf"};
public static String getExtension(String prefix) {
switch (prefix) {
case IMAGE_PNG:
return "png";
case IMAGE_JPG:
return "jpg";
case IMAGE_JPEG:
return "jpeg";
case IMAGE_BMP:
return "bmp";
case IMAGE_GIF:
return "gif";
default:
return "";
}
}
}
package com.xueyi.common.core.utils.html;
import com.xueyi.common.core.utils.core.StrUtil;
/**
* 转义和反转义工具类
*
* @author xueyi
*/
public class EscapeUtil {
public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
private static final char[][] TEXT = new char[64][];
static {
for (int i = 0; i < 64; i++) {
TEXT[i] = new char[]{(char) i};
}
// special HTML characters
TEXT['\''] = "'".toCharArray(); // 单引号
TEXT['"'] = """.toCharArray(); // 双引号
TEXT['&'] = "&".toCharArray(); // &符
TEXT['<'] = "<".toCharArray(); // 小于号
TEXT['>'] = ">".toCharArray(); // 大于号
}
/**
* 转义文本中的HTML字符为安全的字符
*
* @param text 被转义的文本
* @return 转义后的文本
*/
public static String escape(String text) {
return encode(text);
}
/**
* 还原被转义的HTML特殊字符
*
* @param content 包含转义符的HTML内容
* @return 转换后的字符串
*/
public static String unescape(String content) {
return decode(content);
}
/**
* 清除所有HTML标签,但是不删除标签内的内容
*
* @param content 文本
* @return 清除标签后的文本
*/
public static String clean(String content) {
return new HTMLFilter().filter(content);
}
/**
* Escape编码
*
* @param text 被编码的文本
* @return 编码后的字符
*/
private static String encode(String text) {
if (StrUtil.isEmpty(text)) {
return StrUtil.EMPTY;
}
final StringBuilder tmp = new StringBuilder(text.length() * 6);
char c;
for (int i = 0; i < text.length(); i++) {
c = text.charAt(i);
if (c < 256) {
tmp.append("%");
if (c < 16) {
tmp.append("0");
}
tmp.append(Integer.toString(c, 16));
} else {
tmp.append("%u");
if (c <= 0xfff) {
// issue#I49JU8@Gitee
tmp.append("0");
}
tmp.append(Integer.toString(c, 16));
}
}
return tmp.toString();
}
/**
* Escape解码
*
* @param content 被转义的内容
* @return 解码后的字符串
*/
public static String decode(String content) {
if (StrUtil.isEmpty(content)) {
return content;
}
StringBuilder tmp = new StringBuilder(content.length());
int lastPos = 0, pos = 0;
char ch;
while (lastPos < content.length()) {
pos = content.indexOf("%", lastPos);
if (pos == lastPos) {
if (content.charAt(pos + 1) == 'u') {
ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
tmp.append(ch);
lastPos = pos + 6;
} else {
ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
tmp.append(ch);
lastPos = pos + 3;
}
} else {
if (pos == -1) {
tmp.append(content.substring(lastPos));
lastPos = content.length();
} else {
tmp.append(content.substring(lastPos, pos));
lastPos = pos;
}
}
}
return tmp.toString();
}
}