sync -- 同步 RuoYi-Vue-Plus(v4.3.0) 更新

This commit is contained in:
konbai
2022-09-18 23:27:06 +08:00
parent 4bc7e08889
commit ccf8393808
254 changed files with 3697 additions and 2679 deletions

View File

@@ -14,7 +14,6 @@ import org.springframework.cglib.core.Converter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* bean深拷贝工具(基于 cglib 性能优异)
@@ -79,11 +78,11 @@ public class BeanCopyUtils {
if (CollUtil.isEmpty(sourceList)) {
return CollUtil.newArrayList();
}
return sourceList.stream().map(source -> {
return StreamUtils.toList(sourceList, source -> {
V target = ReflectUtil.newInstanceIfPossible(desc);
copy(source, target);
return target;
}).collect(Collectors.toList());
});
}
/**

View File

@@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@@ -78,6 +79,9 @@ public class JsonUtils {
}
try {
return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType(Dict.class));
} catch (MismatchedInputException e) {
// 类型不匹配说明不是json
return null;
} catch (IOException e) {
throw new RuntimeException(e);
}

View File

@@ -3,6 +3,7 @@ package com.ruoyi.common.utils;
import cn.hutool.core.convert.Convert;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpStatus;
import com.ruoyi.common.constant.Constants;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.MediaType;
@@ -14,6 +15,9 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
@@ -117,7 +121,7 @@ public class ServletUtils extends ServletUtil {
public static boolean isAjaxRequest(HttpServletRequest request) {
String accept = request.getHeader("accept");
if (accept != null && accept.contains("application/json")) {
if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) {
return true;
}
@@ -139,4 +143,32 @@ public class ServletUtils extends ServletUtil {
return getClientIP(getRequest());
}
/**
* 内容编码
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncode(String str) {
try {
return URLEncoder.encode(str, Constants.UTF8);
} catch (UnsupportedEncodingException e) {
return StringUtils.EMPTY;
}
}
/**
* 内容解码
*
* @param str 内容
* @return 解码后的内容
*/
public static String urlDecode(String str) {
try {
return URLDecoder.decode(str, Constants.UTF8);
} catch (UnsupportedEncodingException e) {
return StringUtils.EMPTY;
}
}
}

View File

@@ -0,0 +1,251 @@
package com.ruoyi.common.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* stream 流工具类
*
* @author Lion Li
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class StreamUtils {
/**
* 将collection过滤
*
* @param collection 需要转化的集合
* @param function 过滤方法
* @return 过滤后的list
*/
public static <E> List<E> filter(Collection<E> collection, Predicate<E> function) {
if (CollUtil.isEmpty(collection)) {
return CollUtil.newArrayList();
}
return collection.stream().filter(function).collect(Collectors.toList());
}
/**
* 将collection拼接
*
* @param collection 需要转化的集合
* @param function 拼接方法
* @return 拼接后的list
*/
public static <E> String join(Collection<E> collection, Function<E, String> function) {
return join(collection, function, ",");
}
/**
* 将collection拼接
*
* @param collection 需要转化的集合
* @param function 拼接方法
* @param delimiter 拼接符
* @return 拼接后的list
*/
public static <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) {
if (CollUtil.isEmpty(collection)) {
return StringUtils.EMPTY;
}
return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter));
}
/**
* 将collection排序
*
* @param collection 需要转化的集合
* @param comparing 排序方法
* @return 排序后的list
*/
public static <E> List<E> sorted(Collection<E> collection, Comparator<E> comparing) {
if (CollUtil.isEmpty(collection)) {
return CollUtil.newArrayList();
}
return collection.stream().sorted(comparing).collect(Collectors.toList());
}
/**
* 将collection转化为类型不变的map<br>
* <B>{@code Collection<V> ----> Map<K,V>}</B>
*
* @param collection 需要转化的集合
* @param key V类型转化为K类型的lambda方法
* @param <V> collection中的泛型
* @param <K> map中的key类型
* @return 转化后的map
*/
public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) {
if (CollUtil.isEmpty(collection)) {
return MapUtil.newHashMap();
}
return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
}
/**
* 将Collection转化为map(value类型与collection的泛型不同)<br>
* <B>{@code Collection<E> -----> Map<K,V> }</B>
*
* @param collection 需要转化的集合
* @param key E类型转化为K类型的lambda方法
* @param value E类型转化为V类型的lambda方法
* @param <E> collection中的泛型
* @param <K> map中的key类型
* @param <V> map中的value类型
* @return 转化后的map
*/
public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) {
if (CollUtil.isEmpty(collection)) {
return MapUtil.newHashMap();
}
return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l));
}
/**
* 将collection按照规则(比如有相同的班级id)分类成map<br>
* <B>{@code Collection<E> -------> Map<K,List<E>> } </B>
*
* @param collection 需要分类的集合
* @param key 分类的规则
* @param <E> collection中的泛型
* @param <K> map中的key类型
* @return 分类后的map
*/
public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) {
if (CollUtil.isEmpty(collection)) {
return MapUtil.newHashMap();
}
return collection
.stream()
.collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
}
/**
* 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map<br>
* <B>{@code Collection<E> ---> Map<T,Map<U,List<E>>> } </B>
*
* @param collection 需要分类的集合
* @param key1 第一个分类的规则
* @param key2 第二个分类的规则
* @param <E> 集合元素类型
* @param <K> 第一个map中的key类型
* @param <U> 第二个map中的key类型
* @return 分类后的map
*/
public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1, Function<E, U> key2) {
if (CollUtil.isEmpty(collection)) {
return MapUtil.newHashMap();
}
return collection
.stream()
.collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList())));
}
/**
* 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map<br>
* <B>{@code Collection<E> ---> Map<T,Map<U,E>> } </B>
*
* @param collection 需要分类的集合
* @param key1 第一个分类的规则
* @param key2 第二个分类的规则
* @param <T> 第一个map中的key类型
* @param <U> 第二个map中的key类型
* @param <E> collection中的泛型
* @return 分类后的map
*/
public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection, Function<E, T> key1, Function<E, U> key2) {
if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) {
return MapUtil.newHashMap();
}
return collection
.stream()
.collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l)));
}
/**
* 将collection转化为List集合但是两者的泛型不同<br>
* <B>{@code Collection<E> ------> List<T> } </B>
*
* @param collection 需要转化的集合
* @param function collection中的泛型转化为list泛型的lambda表达式
* @param <E> collection中的泛型
* @param <T> List中的泛型
* @return 转化后的list
*/
public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) {
if (CollUtil.isEmpty(collection)) {
return CollUtil.newArrayList();
}
return collection
.stream()
.map(function)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
/**
* 将collection转化为Set集合但是两者的泛型不同<br>
* <B>{@code Collection<E> ------> Set<T> } </B>
*
* @param collection 需要转化的集合
* @param function collection中的泛型转化为set泛型的lambda表达式
* @param <E> collection中的泛型
* @param <T> Set中的泛型
* @return 转化后的Set
*/
public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) {
if (CollUtil.isEmpty(collection) || function == null) {
return CollUtil.newHashSet();
}
return collection
.stream()
.map(function)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
/**
* 合并两个相同key类型的map
*
* @param map1 第一个需要合并的 map
* @param map2 第二个需要合并的 map
* @param merge 合并的lambda将key value1 value2合并成最终的类型,注意value可能为空的情况
* @param <K> map中的key类型
* @param <X> 第一个 map的value类型
* @param <Y> 第二个 map的value类型
* @param <V> 最终map的value类型
* @return 合并后的map
*/
public static <K, X, Y, V> Map<K, V> merge(Map<K, X> map1, Map<K, Y> map2, BiFunction<X, Y, V> merge) {
if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) {
return MapUtil.newHashMap();
} else if (MapUtil.isEmpty(map1)) {
map1 = MapUtil.newHashMap();
} else if (MapUtil.isEmpty(map2)) {
map2 = MapUtil.newHashMap();
}
Set<K> key = new HashSet<>();
key.addAll(map1.keySet());
key.addAll(map2.keySet());
Map<K, V> map = new HashMap<>();
for (K t : key) {
X x = map1.get(t);
Y y = map2.get(t);
V z = merge.apply(x, y);
if (z != null) {
map.put(t, z);
}
}
return map;
}
}

View File

@@ -0,0 +1,75 @@
package com.ruoyi.common.utils.redis;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.redisson.api.RMap;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import java.util.Set;
/**
* 缓存操作工具类 {@link }
*
* @author Michelle.Chung
* @date 2022/8/13
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@SuppressWarnings(value = {"unchecked"})
public class CacheUtils {
private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class);
/**
* 获取缓存组内所有的KEY
*
* @param cacheNames 缓存组名称
*/
public static Set<Object> keys(String cacheNames) {
RMap<Object, Object> rmap = (RMap<Object, Object>) CACHE_MANAGER.getCache(cacheNames).getNativeCache();
return rmap.keySet();
}
/**
* 获取缓存值
*
* @param cacheNames 缓存组名称
* @param key 缓存key
*/
public static <T> T get(String cacheNames, Object key) {
Cache.ValueWrapper wrapper = CACHE_MANAGER.getCache(cacheNames).get(key);
return wrapper != null ? (T) wrapper.get() : null;
}
/**
* 保存缓存值
*
* @param cacheNames 缓存组名称
* @param key 缓存key
* @param value 缓存值
*/
public static void put(String cacheNames, Object key, Object value) {
CACHE_MANAGER.getCache(cacheNames).put(key, value);
}
/**
* 删除缓存值
*
* @param cacheNames 缓存组名称
* @param key 缓存key
*/
public static void evict(String cacheNames, Object key) {
CACHE_MANAGER.getCache(cacheNames).evict(key);
}
/**
* 清空缓存值
*
* @param cacheNames 缓存组名称
*/
public static void clear(String cacheNames) {
CACHE_MANAGER.getCache(cacheNames).clear();
}
}

View File

@@ -5,7 +5,6 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.redisson.api.*;
import java.util.Comparator;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -30,6 +29,43 @@ public class QueueUtils {
return CLIENT;
}
/**
* 添加普通队列数据
*
* @param queueName 队列名
* @param data 数据
*/
public static <T> boolean addQueueObject(String queueName, T data) {
RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
return queue.offer(data);
}
/**
* 通用获取一个队列数据 没有数据返回 null(不支持延迟队列)
*
* @param queueName 队列名
*/
public static <T> T getQueueObject(String queueName) {
RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
return queue.poll();
}
/**
* 通用删除队列数据(不支持延迟队列)
*/
public static <T> boolean removeQueueObject(String queueName, T data) {
RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
return queue.remove(data);
}
/**
* 通用销毁队列 所有阻塞监听 报错(不支持延迟队列)
*/
public static <T> boolean destroyQueue(String queueName) {
RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
return queue.delete();
}
/**
* 添加延迟队列数据 默认毫秒
*
@@ -84,32 +120,6 @@ public class QueueUtils {
delayedQueue.destroy();
}
/**
* 尝试设置 优先队列比较器 用于排序优先级
*
* @param queueName 队列名
* @param comparator 比较器
*/
public static <T> boolean trySetPriorityQueueComparator(String queueName, Comparator<T> comparator) {
RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
return priorityBlockingQueue.trySetComparator(comparator);
}
/**
* 尝试设置 优先队列比较器 用于排序优先级
*
* @param queueName 队列名
* @param comparator 比较器
* @param destroy 已存在是否销毁
*/
public static <T> boolean trySetPriorityQueueComparator(String queueName, Comparator<T> comparator, boolean destroy) {
RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
if (priorityBlockingQueue.isExists() && destroy) {
destroyPriorityQueueObject(queueName);
}
return priorityBlockingQueue.trySetComparator(comparator);
}
/**
* 添加优先队列数据
*
@@ -121,32 +131,6 @@ public class QueueUtils {
return priorityBlockingQueue.offer(data);
}
/**
* 获取一个优先队列数据 没有数据返回 null
*
* @param queueName 队列名
*/
public static <T> T getPriorityQueueObject(String queueName) {
RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
return priorityBlockingQueue.poll();
}
/**
* 删除优先队列数据
*/
public static <T> boolean removePriorityQueueObject(String queueName, T data) {
RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
return priorityBlockingQueue.remove(data);
}
/**
* 销毁优先队列
*/
public static boolean destroyPriorityQueueObject(String queueName) {
RPriorityBlockingQueue<?> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
return priorityBlockingQueue.delete();
}
/**
* 尝试设置 有界队列 容量 用于限制数量
*
@@ -168,7 +152,7 @@ public class QueueUtils {
public static <T> boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) {
RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
if (boundedBlockingQueue.isExists() && destroy) {
destroyBoundedQueueObject(queueName);
destroyQueue(queueName);
}
return boundedBlockingQueue.trySetCapacity(capacity);
}
@@ -185,32 +169,6 @@ public class QueueUtils {
return boundedBlockingQueue.offer(data);
}
/**
* 获取一个有界队列数据 没有数据返回 null
*
* @param queueName 队列名
*/
public static <T> T getBoundedQueueObject(String queueName) {
RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
return boundedBlockingQueue.poll();
}
/**
* 删除有界队列数据
*/
public static <T> boolean removeBoundedQueueObject(String queueName, T data) {
RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
return boundedBlockingQueue.remove(data);
}
/**
* 销毁有界队列
*/
public static boolean destroyBoundedQueueObject(String queueName) {
RBoundedBlockingQueue<?> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
return boundedBlockingQueue.delete();
}
/**
* 订阅阻塞队列(可订阅所有实现类 例如: 延迟 优先 有界 等)
*/

View File

@@ -1,10 +1,10 @@
package com.ruoyi.common.utils.redis;
import cn.hutool.core.collection.IterUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.redisson.api.*;
import org.redisson.config.Config;
import java.time.Duration;
import java.util.Collection;
@@ -12,6 +12,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* redis 工具类
@@ -25,6 +27,14 @@ public class RedisUtils {
private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
public static NameMapper getNameMapper() {
Config config = CLIENT.getConfig();
if (config.isClusterConfig()) {
return config.useClusterServers().getNameMapper();
}
return config.useSingleServer().getNameMapper();
}
/**
* 限流
*
@@ -100,14 +110,13 @@ public class RedisUtils {
* @since Redis 6.X 以上使用 setAndKeepTTL 兼容 5.X 方案
*/
public static <T> void setCacheObject(final String key, final T value, final boolean isSaveTtl) {
RBucket<Object> bucket = CLIENT.getBucket(key);
RBucket<T> bucket = CLIENT.getBucket(key);
if (isSaveTtl) {
try {
bucket.setAndKeepTTL(value);
} catch (Exception e) {
long timeToLive = bucket.remainTimeToLive();
bucket.set(value);
bucket.expire(Duration.ofMillis(timeToLive));
setCacheObject(key, value, Duration.ofMillis(timeToLive));
}
} else {
bucket.set(value);
@@ -122,9 +131,11 @@ public class RedisUtils {
* @param duration 时间
*/
public static <T> void setCacheObject(final String key, final T value, final Duration duration) {
RBucket<T> result = CLIENT.getBucket(key);
result.set(value);
result.expire(duration);
RBatch batch = CLIENT.createBatch();
RBucketAsync<T> bucket = batch.getBucket(key);
bucket.setAsync(value);
bucket.expireAsync(duration);
batch.execute();
}
/**
@@ -415,8 +426,17 @@ public class RedisUtils {
* @return 对象列表
*/
public static Collection<String> keys(final String pattern) {
Iterable<String> iterable = CLIENT.getKeys().getKeysByPattern(pattern);
return IterUtil.toList(iterable);
Stream<String> stream = CLIENT.getKeys().getKeysStreamByPattern(getNameMapper().map(pattern));
return stream.map(key -> getNameMapper().unmap(key)).collect(Collectors.toList());
}
/**
* 删除缓存的基本对象列表
*
* @param pattern 字符串前缀
*/
public static void deleteKeys(final String pattern) {
CLIENT.getKeys().deleteByPattern(getNameMapper().map(pattern));
}
/**
@@ -426,6 +446,6 @@ public class RedisUtils {
*/
public static Boolean hasKey(String key) {
RKeys rKeys = CLIENT.getKeys();
return rKeys.countExists(key) > 0;
return rKeys.countExists(getNameMapper().map(key)) > 0;
}
}