From 387831ef73adcf96ce8782981df2228d02b367ca Mon Sep 17 00:00:00 2001 From: vivid <2390310671@qq.com> Date: Thu, 24 Jul 2025 18:26:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(email):=20=E4=BC=98=E5=8C=96=E9=82=AE?= =?UTF-8?q?=E4=BB=B6=E5=8F=91=E9=80=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 EmailSender 类中的 send 方法,修改了对email的非空判断 - 新增 RedisConfig 类,配置 RedisTemplate 以支持自定义序列化方式 - 添加 RedisUtils 工具类,提供丰富的 --- .../zsc/edu/dify/common/util/RedisUtils.java | 555 ++++++++++++++++++ .../framework/message/email/EmailSender.java | 2 +- .../edu/dify/framework/redis/RedisConfig.java | 34 ++ 3 files changed, 590 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/zsc/edu/dify/common/util/RedisUtils.java create mode 100644 src/main/java/com/zsc/edu/dify/framework/redis/RedisConfig.java diff --git a/src/main/java/com/zsc/edu/dify/common/util/RedisUtils.java b/src/main/java/com/zsc/edu/dify/common/util/RedisUtils.java new file mode 100644 index 0000000..05c6895 --- /dev/null +++ b/src/main/java/com/zsc/edu/dify/common/util/RedisUtils.java @@ -0,0 +1,555 @@ +package com.zsc.edu.dify.common.util; + +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.Cursor; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ScanOptions; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @author harry_yao + */ +@Component +public class RedisUtils { + + @Resource + private RedisTemplate redisTemplate; + + /** + * 指定缓存失效时间 + * @param key 键 + * @param time 时间(秒) + * @return true / false + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据 key 获取过期时间 + * @param key 键 + * @return + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断 key 是否存在 + * @param key 键 + * @return true / false + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * @SuppressWarnings("unchecked") 忽略类型转换警告 + * @param key 键(一个或者多个) + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { +// 传入一个 Collection 集合 +// redisTemplate.delete(CollectionUtils.arrayToList(key)); + redisTemplate.delete(Arrays.stream(key).collect(Collectors.toList())); + } + } + } + +// ============================== String ============================== + + /** + * 普通缓存获取 + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * @param key 键 + * @param value 值 + * @return true / false + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * @param key 键 + * @param value 值 + * @param time 时间(秒),如果 time < 0 则设置无限时间 + * @return true / false + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 递增 + * @param key 键 + * @param delta 递增大小 + * @return + */ + public long incr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递增因子必须大于 0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * @param key 键 + * @param delta 递减大小 + * @return + */ + public long decr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递减因子必须大于 0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + +// ============================== Map ============================== + + /** + * HashGet + * @param key 键(no null) + * @param item 项(no null) + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取 key 对应的 map + * @param key 键(no null) + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * @param key 键 + * @param map 值 + * @return true / false + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * @param key 键 + * @param map 值 + * @param time 时间 + * @return true / false + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张 Hash表 中放入数据,如不存在则创建 + * @param key 键 + * @param item 项 + * @param value 值 + * @return true / false + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张 Hash表 中放入数据,并设置时间,如不存在则创建 + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(如果原来的 Hash表 设置了时间,这里会覆盖) + * @return true / false + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除 Hash表 中的值 + * @param key 键 + * @param item 项(可以多个,no null) + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断 Hash表 中是否有该键的值 + * @param key 键(no null) + * @param item 值(no null) + * @return true / false + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * Hash递增,如果不存在则创建一个,并把新增的值返回 + * @param key 键 + * @param item 项 + * @param by 递增大小 > 0 + * @return + */ + public Double hincr(String key, String item, Double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * Hash递减 + * @param key 键 + * @param item 项 + * @param by 递减大小 + * @return + */ + public Double hdecr(String key, String item, Double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + +// ============================== Set ============================== + + /** + * 根据 key 获取 set 中的所有值 + * @param key 键 + * @return 值 + */ + public Set sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 从键为 key 的 set 中,根据 value 查询是否存在 + * @param key 键 + * @param value 值 + * @return true / false + */ + public boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将数据放入 set缓存 + * @param key 键值 + * @param values 值(可以多个) + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 将数据放入 set缓存,并设置时间 + * @param key 键 + * @param time 时间 + * @param values 值(可以多个) + * @return 成功放入个数 + */ + public long sSett(String key, long time, Object... values) { + try { + long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) { + expire(key, time); + } + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 获取 set缓存的长度 + * @param key 键 + * @return 长度 + */ + public long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 移除 set缓存中,值为 value 的 + * @param key 键 + * @param values 值 + * @return 成功移除个数 + */ + public long setRemove(String key, Object... values) { + try { + return redisTemplate.opsForSet().remove(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +// ============================== List ============================== + + /** + * 获取 list缓存的内容 + * @param key 键 + * @param start 开始 + * @param end 结束(0 到 -1 代表所有值) + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取 list缓存的长度 + * @param key 键 + * @return 长度 + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 根据索引 index 获取键为 key 的 list 中的元素 + * @param key 键 + * @param index 索引 + * 当 index >= 0 时 {0:表头, 1:第二个元素} + * 当 index < 0 时 {-1:表尾, -2:倒数第二个元素} + * @return 值 + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将值 value 插入键为 key 的 list 中,如果 list 不存在则创建空 list + * @param key 键 + * @param value 值 + * @return true / false + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将值 value 插入键为 key 的 list 中,并设置时间 + * @param key 键 + * @param value 值 + * @param time 时间 + * @return true / false + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将 values 插入键为 key 的 list 中 + * @param key 键 + * @param values 值 + * @return true / false + */ + public boolean lSetList(String key, List values) { + try { + redisTemplate.opsForList().rightPushAll(key, values); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将 values 插入键为 key 的 list 中,并设置时间 + * @param key 键 + * @param values 值 + * @param time 时间 + * @return true / false + */ + public boolean lSetList(String key, List values, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, values); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引 index 修改键为 key 的值 + * @param key 键 + * @param index 索引 + * @param value 值 + * @return true / false + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 在键为 key 的 list 中删除值为 value 的元素 + * @param key 键 + * @param count 如果 count == 0 则删除 list 中所有值为 value 的元素 + * 如果 count > 0 则删除 list 中最左边那个值为 value 的元素 + * 如果 count < 0 则删除 list 中最右边那个值为 value 的元素 + * @param value + * @return + */ + public long lRemove(String key, long count, Object value) { + try { + return redisTemplate.opsForList().remove(key, count, value); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + public Set scan(String matchKey) { + ScanOptions options = ScanOptions.scanOptions().match("*" + matchKey + "*").count(3000).build(); + return redisTemplate.execute((RedisCallback>) connection -> { + Set keysTmp = new HashSet<>(); + Cursor cursor = connection.scan(options); + while (cursor.hasNext()) { + keysTmp.add(new String(cursor.next())); + } + return keysTmp; + }); + } + +} \ No newline at end of file diff --git a/src/main/java/com/zsc/edu/dify/framework/message/email/EmailSender.java b/src/main/java/com/zsc/edu/dify/framework/message/email/EmailSender.java index 560e341..0c0ca22 100644 --- a/src/main/java/com/zsc/edu/dify/framework/message/email/EmailSender.java +++ b/src/main/java/com/zsc/edu/dify/framework/message/email/EmailSender.java @@ -42,7 +42,7 @@ public class EmailSender { @Async public void send(String email, Notice notice) { - if (StringUtils.hasText(email)) { + if (!StringUtils.hasText(email)) { return; } InternetAddress to; diff --git a/src/main/java/com/zsc/edu/dify/framework/redis/RedisConfig.java b/src/main/java/com/zsc/edu/dify/framework/redis/RedisConfig.java new file mode 100644 index 0000000..c597aac --- /dev/null +++ b/src/main/java/com/zsc/edu/dify/framework/redis/RedisConfig.java @@ -0,0 +1,34 @@ +package com.zsc.edu.dify.framework.redis; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; +/** + * @description redis配置类 + * @author vivid + * */ +@Configuration +public class RedisConfig { + + // 自定义 RedisTemplate Bean 配置 + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(factory); + + // 设置键的序列化方式为 String + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + // 设置值的序列化方式为 JSON + template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + + template.afterPropertiesSet(); + return template; + } + +}