diff --git a/pom.xml b/pom.xml
index e7e8d74f..d741ee69 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,6 +39,9 @@
1.18.30
1.4.2
1.5.0
+ 2.1.2
+ 2.0.2
+ 2.0.1
@@ -166,6 +169,25 @@
${mybatis.gen.version}
+
+
+ jakarta.mail
+ jakarta.mail-api
+ ${jakarta.mail.version}
+
+
+
+
+ org.eclipse.angus
+ jakarta.mail
+ ${angus.mail.version}
+
+
+ org.eclipse.angus
+ angus-activation
+ ${angus.activation.version}
+
+
com.ruoyi
diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml
index cd96eb5b..14ea2e5f 100644
--- a/ruoyi-common/ruoyi-common-core/pom.xml
+++ b/ruoyi-common/ruoyi-common-core/pom.xml
@@ -124,6 +124,12 @@
${mybatis.dynamic.version}
+
+
+ jakarta.mail
+ jakarta.mail-api
+
+
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailMessage.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailMessage.java
new file mode 100644
index 00000000..6ea5f5af
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailMessage.java
@@ -0,0 +1,124 @@
+package com.ruoyi.common.core.mail;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 邮件发送参数
+ *
+ * @since 2022/8/17
+ */
+@Data
+@Accessors(chain = true)
+public class MailMessage {
+
+ /**
+ * 邮件头信息(标题、收件人、抄送等)
+ */
+ private MailMessageHead headInfo = new MailMessageHead();
+
+ /**
+ * 正文
+ */
+ private String content;
+
+ /**
+ * 正文里的多媒体文件
+ */
+ private Map inLineMap;
+
+ /**
+ * 正文是否为html。true代表是
+ */
+ private boolean isHtml = false;
+
+ /**
+ * 附件
+ */
+ private final Map attachments = new LinkedHashMap<>();
+
+ public void clearHeadInfo() {
+ headInfo.setFrom(null);
+ headInfo.setTo(null);
+ headInfo.setCc(null);
+ headInfo.setSubject(null);
+ }
+
+ public MailMessage setFrom(String fromAddress) {
+ headInfo.setFrom(fromAddress);
+ return this;
+ }
+
+ public MailMessage setTo(String toAddress) {
+ headInfo.setTo(toAddress);
+ return this;
+ }
+
+ public MailMessage setCc(String cc) {
+ headInfo.setCc(cc);
+ return this;
+ }
+
+ public MailMessage setSubject(String subject) {
+ headInfo.setSubject(subject);
+ return this;
+ }
+
+ public String getFrom() {
+ return headInfo.getFrom();
+ }
+
+ public String getTo() {
+ return headInfo.getTo();
+ }
+
+ public String getCc() {
+ return headInfo.getCc();
+ }
+
+ public String getSubject() {
+ return headInfo.getSubject();
+ }
+
+ public MailMessage addAttachment(String fileKey, File attachment) {
+ attachments.put(fileKey, attachment);
+ return this;
+ }
+
+ public MailMessage addAttachment(File attachment) {
+ attachments.put(attachment.getName(), attachment);
+ return this;
+ }
+
+ public MailMessage addAttachments(List attachments) {
+ if (attachments != null) {
+ for (File attachment : attachments) {
+ this.attachments.put(attachment.getName(), attachment);
+ }
+ }
+ return this;
+ }
+
+ public void clearAttachments() {
+ attachments.clear();
+ }
+
+ public File getAttachment(String fileKey) {
+ return attachments.get(fileKey);
+ }
+
+ public List getAttachmentsList() {
+ List list = new ArrayList<>();
+ for (Map.Entry entry : attachments.entrySet()) {
+ list.add(entry.getValue());
+ }
+ return list;
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailMessageHead.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailMessageHead.java
new file mode 100644
index 00000000..bc782bea
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailMessageHead.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.core.mail;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * 邮件头信息
+ *
+ * @since 2022/8/17
+ */
+@Data
+@Accessors(chain = true)
+public class MailMessageHead {
+
+ /**
+ * 发件人
+ */
+ private String from;
+
+ /**
+ * 收件人
+ */
+ private String to;
+
+ /**
+ * 抄送
+ */
+ private String cc;
+
+ /**
+ * 邮件标题(Subject)
+ */
+ private String subject;
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSendAccount.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSendAccount.java
new file mode 100644
index 00000000..90f7d89d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSendAccount.java
@@ -0,0 +1,43 @@
+package com.ruoyi.common.core.mail;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * 邮箱账号信息(发邮件用)
+ * @since 2021/6/25
+ */
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+public class MailSendAccount {
+
+ /**
+ * SMTP服务器地址
+ */
+ private String host;
+
+ /**
+ * SMTP服务器端口号
+ */
+ private Integer port;
+
+ /**
+ * 用户名
+ */
+ private String username;
+
+ /**
+ * 密码/授权码
+ */
+ private String password;
+
+ /**
+ * 是否用SSL加密
+ */
+ private boolean sslFlag = false;
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSendResult.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSendResult.java
new file mode 100644
index 00000000..2e47fbfd
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSendResult.java
@@ -0,0 +1,51 @@
+package com.ruoyi.common.core.mail;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * 邮件发送结果
+ *
+ * @since 2022/8/18
+ */
+@Data
+@Accessors(chain = true)
+public class MailSendResult {
+
+ /**
+ * 是否成功,true代表成功
+ */
+ private boolean success;
+
+ /**
+ * 错误信息
+ */
+ private String errMsg;
+
+ /**
+ * 如果有抛出异常,则此为抛出的异常对象
+ */
+ private Throwable errObj;
+
+ public MailSendResult setFailure(Throwable errObj) {
+ this.success = false;
+ if (errObj != null) {
+ this.errMsg = errObj.toString();
+ this.errObj = errObj;
+ }
+ return this;
+ }
+
+ public static MailSendResult success() {
+ return new MailSendResult().setSuccess(true);
+ }
+
+ public static MailSendResult failure(String errMsg) {
+ return new MailSendResult().setSuccess(false).setErrMsg(errMsg);
+ }
+
+ public static MailSendResult failure(Throwable errObj) {
+ return new MailSendResult().setFailure(errObj);
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSender.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSender.java
new file mode 100644
index 00000000..d70a7532
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSender.java
@@ -0,0 +1,87 @@
+package com.ruoyi.common.core.mail;
+
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * 邮件发送工具
+ * date 2021/8/18
+ */
+public interface MailSender {
+
+ String ADDRESS_SPLIT = ";";
+
+ //======================================= ↓↓↓ 快速构建 ↓↓↓ =======================================
+
+ /**
+ * 构建发送工具
+ *
+ * @param senderAccount 发送账号
+ * @param enableDebug 是否开启debug信息输出
+ */
+ static MailSender build(MailSendAccount senderAccount, int timeout, boolean enableDebug) {
+ return new SpringMailSender(senderAccount, timeout, enableDebug);
+ }
+
+ static MailSender build(MailSendAccount senderAccount, boolean enableDebug) {
+ return new SpringMailSender(senderAccount, 20000, enableDebug);
+ }
+
+ static MailSender build(MailSendAccount senderAccount) {
+ return new SpringMailSender(senderAccount);
+ }
+
+ //======================================= ↓↓↓ 主要API ↓↓↓ =======================================
+
+ /**
+ * 发送MIME邮件
+ *
+ * @param form 发送参数
+ * @return 发送结果
+ */
+ MailSendResult sendMail(MailMessage form);
+
+ default MailSendResult sendMail(String from, String to, String cc, String subject, String text, List attachments) {
+ MailMessage message = new MailMessage()
+ .setFrom(from)
+ .setTo(to)
+ .setCc(cc)
+ .setSubject(subject)
+ .setContent(text)
+ .addAttachments(attachments);
+ return sendMail(message);
+ }
+
+ default MailSendResult sendMail(String to, String cc, String subject, String text, List attachments) {
+ return sendMail(null, to, cc, subject, text, attachments);
+ }
+
+ default MailSendResult sendMail(String to, String subject, String text, List attachments) {
+ return sendMail(null, to, null, subject, text, attachments);
+ }
+
+ default MailSendResult sendMail(String to, String cc, String subject, String text) {
+ return sendMail(null, to, cc, subject, text, null);
+ }
+
+ default MailSendResult sendMail(String to, String subject, String text) {
+ return sendMail(null, to, null, subject, text, null);
+ }
+
+ //======================================= ↓↓↓ 其他API ↓↓↓ =======================================
+
+ MailSendAccount getSenderAccount();
+
+ JavaMailSenderImpl getExecutor();
+
+ void resetSenderAccount(MailSendAccount senderAccount);
+
+ default void resetSenderAccount(String host, int port, String username, String password) {
+ resetSenderAccount(new MailSendAccount(host, port, username, password, (password != null && !password.isEmpty())));
+ }
+
+ boolean available();
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/SpringMailSender.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/SpringMailSender.java
new file mode 100644
index 00000000..0a3e6d50
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/SpringMailSender.java
@@ -0,0 +1,184 @@
+package com.ruoyi.common.core.mail;
+
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+import org.springframework.mail.javamail.MimeMessageHelper;
+
+import jakarta.mail.MessagingException;
+import jakarta.mail.internet.MimeMessage;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * 邮件发送器
+ *
+ * @since 2021/8/18
+ */
+public class SpringMailSender implements MailSender {
+
+ //发送执行者
+ private final JavaMailSenderImpl executor;
+
+ private MailSendAccount senderAccount;
+
+ public SpringMailSender(MailSendAccount senderAccount) {
+ this(senderAccount, 20000, false);
+ }
+
+ public SpringMailSender(MailSendAccount senderAccount, int timeout, boolean enableDebug) {
+ this.senderAccount = senderAccount;
+ //创建发送执行者
+ executor = buildExecutor(senderAccount, timeout, enableDebug);
+ }
+
+ /**
+ * 创建发送执行者
+ *
+ * @param account 发送账号
+ * @return 发送执行者
+ */
+ private JavaMailSenderImpl buildExecutor(MailSendAccount account, int timeout, boolean enableDebug) {
+ //邮箱设定
+ JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
+ Properties mailProperties = new Properties();
+ //邮件发送时输出debug信息
+ mailProperties.setProperty("mail.debug", enableDebug ? "true" : "false");
+ //发送服务器需要身份验证
+ mailProperties.setProperty("mail.smtp.auth", "true");
+ //发送邮件协议名称 这里使用的是smtp协议
+ mailProperties.setProperty("mail.transport.protocol", "smtp");
+ //默认开启starttls
+ mailProperties.setProperty("mail.smtp.starttls.enable", "true");
+ //超时设置
+ mailProperties.setProperty("mail.smtp.connectiontimeout", timeout + "");//与邮件服务器建立连接的超时
+ mailProperties.setProperty("mail.smtp.writetimeout", timeout + "");//邮件发送时间限制
+ if (account.isSslFlag()) {
+ //开启ssl
+ System.out.println("****** enable ssl for mail send ******");
+ mailProperties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+ mailProperties.setProperty("mail.smtp.socketFactory.port", account.getPort().toString());
+ mailProperties.setProperty("mail.smtp.ssl.enable", "true");
+ } else {
+ System.out.println("****** disable ssl for mail send ******");
+ javaMailSender.setPort(account.getPort());
+ }
+ javaMailSender.setJavaMailProperties(mailProperties);
+ javaMailSender.setHost(account.getHost());
+ javaMailSender.setUsername(account.getUsername());
+ javaMailSender.setPassword(account.getPassword());
+ javaMailSender.setDefaultEncoding("UTF-8");
+ System.setProperty("mail.mime.splitlongparameters", "false"); //注意:不截断base64编码后的长附件名
+ return javaMailSender;
+ }
+
+
+ /**
+ * 创建邮件信息
+ *
+ * @param executor 发送执行者
+ * @param form 发送参数
+ * @return 邮件信息
+ * @throws MessagingException 邮件信息创建失败
+ */
+ private MimeMessage createMimeMessage(JavaMailSenderImpl executor, MailMessage form) throws MessagingException {
+ MailMessageHead headInfo = form.getHeadInfo();
+ Map inLineMap = form.getInLineMap();
+ Map attachments = form.getAttachments();
+
+ MimeMessage mimeMessage = executor.createMimeMessage();
+ //创建发送MIME邮件的工具类
+ MimeMessageHelper messageHelper = getMimeMessageHelper(form, mimeMessage, headInfo);
+ //设置正文多媒体信息
+ if (inLineMap != null) {
+ for (Map.Entry inLine : inLineMap.entrySet()) {
+ messageHelper.addInline(inLine.getKey(), inLine.getValue());
+ }
+ }
+ //添加附件
+ if (attachments != null) {
+ for (Map.Entry entry : attachments.entrySet()) {
+ String fileName = entry.getKey();
+ File file = entry.getValue();
+ messageHelper.addAttachment(fileName, file);
+ }
+ }
+ return mimeMessage;
+ }
+
+ private MimeMessageHelper getMimeMessageHelper(MailMessage form, MimeMessage mimeMessage, MailMessageHead headInfo) throws MessagingException {
+ MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
+ //发件人
+ if (form.getFrom() == null || form.getFrom().isEmpty()) {
+ form.setFrom(senderAccount.getUsername());
+ } else {
+ form.setFrom(form.getFrom());
+ }
+ //收件人 这里的参数可以是多个收件人,用英文分号分割
+ messageHelper.setTo(headInfo.getTo().split(ADDRESS_SPLIT));
+ //抄送 这里的参数可以是多个抄送人,用英文分号分割
+ if (headInfo.getCc() != null && !headInfo.getCc().isEmpty()) {
+ messageHelper.setCc(headInfo.getCc().split(ADDRESS_SPLIT));
+ }
+ //邮件主题
+ messageHelper.setSubject(headInfo.getSubject());
+ //邮件正文
+ if (form.getContent() != null && !form.getContent().isEmpty()) {
+ messageHelper.setText(form.getContent(), form.isHtml());
+ }
+ return messageHelper;
+ }
+
+ /**
+ * 发送邮件
+ *
+ * @param form 发送参数
+ * @return 发送结果
+ */
+ @Override
+ public MailSendResult sendMail(MailMessage form) {
+ try {
+ MimeMessage mimeMessage = createMimeMessage(executor, form);
+ executor.send(mimeMessage);
+ return MailSendResult.success();
+ } catch (Exception e) {
+ return MailSendResult.failure(e);
+ }
+ }
+
+ @Override
+ public MailSendAccount getSenderAccount() {
+ return senderAccount;
+ }
+
+ @Override
+ public JavaMailSenderImpl getExecutor() {
+ return executor;
+ }
+
+ @Override
+ public void resetSenderAccount(MailSendAccount senderAccount) {
+ checkAccount(senderAccount);
+ this.senderAccount = senderAccount;
+ }
+
+ private void checkAccount(MailSendAccount account) {
+ if (account == null) {
+ throw new IllegalArgumentException("account is null");
+ }
+ if (account.getHost() == null || account.getHost().isEmpty()) {
+ throw new IllegalArgumentException("host is blank");
+ }
+ if (account.getPort() == null) {
+ throw new IllegalArgumentException("port is null");
+ }
+ if (account.getPort() <= 0 || account.getPort() > 65535) {
+ throw new IllegalArgumentException("port is invalid (0-65535)");
+ }
+ }
+
+ @Override
+ public boolean available() {
+ return (senderAccount.getHost() != null && !senderAccount.getHost().isEmpty() ) && senderAccount.getPort() != null;
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java
index c2f4a2c0..d3c946c1 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java
@@ -38,7 +38,7 @@ public final class SpringUtils implements BeanFactoryPostProcessor {
* 获取类型为requiredType的对象
*/
public static T getBean(Class clz) throws BeansException {
- T result = (T) beanFactory.getBean(clz);
+ T result = beanFactory.getBean(clz);
return result;
}
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java
index 2c8d18d6..780a87c4 100644
--- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java
@@ -1,7 +1,5 @@
package com.ruoyi.common.security.utils;
-import java.util.Collection;
-import java.util.List;
import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.utils.SpringUtils;
@@ -9,35 +7,47 @@ import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.api.domain.SysDictData;
+import java.util.Collection;
+import java.util.List;
+
/**
* 字典工具类
- *
+ *
* @author ruoyi
*/
-public class DictUtils
-{
+public class DictUtils {
+
+ private DictUtils() {
+ throw new IllegalStateException("Utility class cannot be instantiated");
+ }
+
+ private static RedisService redisService;
+
/**
* 设置字典缓存
- *
- * @param key 参数键
- * @param dictDatas 字典数据列表
+ *
+ * @param key 参数键
+ * @param dictDataList 字典数据列表
*/
- public static void setDictCache(String key, List dictDatas)
- {
- SpringUtils.getBean(RedisService.class).setCacheObject(getCacheKey(key), dictDatas);
+ public static void setDictCache(String key, List dictDataList) {
+ if (redisService == null) {
+ redisService = SpringUtils.getBean(RedisService.class);
+ }
+ redisService.setCacheObject(getCacheKey(key), dictDataList);
}
/**
* 获取字典缓存
- *
+ *
* @param key 参数键
- * @return dictDatas 字典数据列表
+ * @return dictDataList 字典数据列表
*/
- public static List getDictCache(String key)
- {
- JSONArray arrayCache = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key));
- if (StringUtils.isNotNull(arrayCache))
- {
+ public static List getDictCache(String key) {
+ if (redisService == null) {
+ redisService = SpringUtils.getBean(RedisService.class);
+ }
+ JSONArray arrayCache = redisService.getCacheObject(getCacheKey(key));
+ if (StringUtils.isNotNull(arrayCache)) {
return arrayCache.toList(SysDictData.class);
}
return null;
@@ -45,31 +55,34 @@ public class DictUtils
/**
* 删除指定字典缓存
- *
+ *
* @param key 字典键
*/
- public static void removeDictCache(String key)
- {
- SpringUtils.getBean(RedisService.class).deleteObject(getCacheKey(key));
+ public static void removeDictCache(String key) {
+ if (redisService == null) {
+ redisService = SpringUtils.getBean(RedisService.class);
+ }
+ redisService.deleteObject(getCacheKey(key));
}
/**
* 清空字典缓存
*/
- public static void clearDictCache()
- {
- Collection keys = SpringUtils.getBean(RedisService.class).keys(CacheConstants.SYS_DICT_KEY + "*");
- SpringUtils.getBean(RedisService.class).deleteObject(keys);
+ public static void clearDictCache() {
+ if (redisService == null) {
+ redisService = SpringUtils.getBean(RedisService.class);
+ }
+ Collection keys = redisService.keys(CacheConstants.SYS_DICT_KEY + "*");
+ redisService.deleteObject(keys);
}
/**
* 设置cache key
- *
+ *
* @param configKey 参数键
* @return 缓存键key
*/
- public static String getCacheKey(String configKey)
- {
+ public static String getCacheKey(String configKey) {
return CacheConstants.SYS_DICT_KEY + configKey;
}
}
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SysConfigUtils.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SysConfigUtils.java
new file mode 100644
index 00000000..b129c29c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SysConfigUtils.java
@@ -0,0 +1,81 @@
+package com.ruoyi.common.security.utils;
+
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.redis.service.RedisService;
+
+import java.util.Collection;
+
+/**
+ * 系统参数工具类 (sys_config)
+ *
+ * @author Alan Scipio
+ * created on 2024/3/1
+ */
+public class SysConfigUtils {
+
+ private SysConfigUtils() {
+ throw new IllegalStateException("Utility class cannot be instantiated");
+ }
+
+ private static RedisService redisService;
+
+ /**
+ * 设置参数缓存
+ *
+ * @param configKey 参数键
+ * @param configValue 参数值
+ */
+ public static void setConfigCache(String configKey, String configValue) {
+ if (redisService == null) {
+ redisService = SpringUtils.getBean(RedisService.class);
+ }
+ redisService.setCacheObject(getCacheKey(configKey), configValue);
+ }
+
+ /**
+ * 获取参数缓存
+ *
+ * @param configKey 参数键
+ * @return configValue 参数值
+ */
+ public static String getConfigCache(String configKey) {
+ if (redisService == null) {
+ redisService = SpringUtils.getBean(RedisService.class);
+ }
+ return redisService.getCacheObject(getCacheKey(configKey));
+ }
+
+ /**
+ * 删除指定参数缓存
+ *
+ * @param key 字典键
+ */
+ public static void removeConfigCache(String key) {
+ if (redisService == null) {
+ redisService = SpringUtils.getBean(RedisService.class);
+ }
+ redisService.deleteObject(getCacheKey(key));
+ }
+
+ /**
+ * 清空所有参数缓存
+ */
+ public static void clearConfigCaches() {
+ if (redisService == null) {
+ redisService = SpringUtils.getBean(RedisService.class);
+ }
+ Collection keys = redisService.keys(CacheConstants.SYS_CONFIG_KEY + "*");
+ redisService.deleteObject(keys);
+ }
+
+ /**
+ * 设置cache key
+ *
+ * @param configKey 参数键
+ * @return 缓存键key
+ */
+ public static String getCacheKey(String configKey) {
+ return CacheConstants.SYS_CONFIG_KEY + configKey;
+ }
+}
diff --git a/ruoyi-modules/ruoyi-system/pom.xml b/ruoyi-modules/ruoyi-system/pom.xml
index 6fb84408..d9539459 100644
--- a/ruoyi-modules/ruoyi-system/pom.xml
+++ b/ruoyi-modules/ruoyi-system/pom.xml
@@ -64,6 +64,16 @@
mysql-connector-j
+
+
+ org.eclipse.angus
+ jakarta.mail
+
+
+ org.eclipse.angus
+ angus-activation
+
+
com.ruoyi
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/config/MailConfig.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/config/MailConfig.java
new file mode 100644
index 00000000..964bb075
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/config/MailConfig.java
@@ -0,0 +1,64 @@
+package com.ruoyi.system.config;
+
+import com.ruoyi.common.core.mail.MailSendAccount;
+import com.ruoyi.common.core.mail.MailSender;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.security.utils.SysConfigUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 邮件配置
+ *
+ * @author Alan Scipio
+ * created on 2024/2/29
+ */
+@Slf4j
+@Configuration
+public class MailConfig {
+
+ @Value("${spring.mail.host:#{null}}")
+ private String host;
+ @Value("${spring.mail.port:#{null}}")
+ private Integer port;
+ @Value("${spring.mail.username:#{null}}")
+ private String username;
+ @Value("${spring.mail.password:#{null}}")
+ private String password;
+
+ @Bean
+ public MailSender mailSender() {
+ MailSendAccount account = new MailSendAccount();
+
+ // 加载配置文件中的邮件配置
+ account.setHost(host);
+ account.setPort(port);
+ account.setUsername(username);
+ account.setPassword(password);
+
+ // 加载数据库中的邮件配置(会缓存到redis中,并覆盖前面的配置)
+ String hostCache = SysConfigUtils.getConfigCache("sys.mail.smtpHost");
+ String portCache = SysConfigUtils.getConfigCache("sys.mail.smtpPort");
+ String usernameCache = SysConfigUtils.getConfigCache("sys.mail.username");
+ String passwordCache = SysConfigUtils.getConfigCache("sys.mail.password");
+ if (StringUtils.isNotBlank(hostCache) && StringUtils.isNotBlank(portCache)) {
+ account.setHost(hostCache);
+ account.setPort(Integer.parseInt(portCache));
+ if (StringUtils.isNotBlank(usernameCache)) {
+ account.setUsername(usernameCache);
+ }
+ if (StringUtils.isNotBlank(passwordCache)) {
+ account.setPassword(passwordCache);
+ }
+ } else {
+ log.warn("Mail configuration from database table 'sys_config' is empty. Use the configuration from application.yaml instead.");
+ }
+
+ account.setSslFlag(account.getPassword() != null && !account.getPassword().isEmpty());
+ log.info("Mail configuration has been initialized. smtpHost: [{}], smtpPort: [{}], username: [{}]", account.getHost(), account.getPort(), account.getUsername());
+ return MailSender.build(account, true);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
index f4106a4c..46ec2909 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
@@ -1,6 +1,7 @@
package com.ruoyi.system.mapper;
import com.ruoyi.system.domain.SysConfig;
+import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -34,6 +35,14 @@ public interface SysConfigMapper {
*/
List selectConfigList(SysConfig config);
+ /**
+ * 查询参数配置列表
+ *
+ * @param configKeyList 参数键名集合
+ * @return 参数配置集合
+ */
+ List selectConfigListByKeys(@Param("configKeyList") List configKeyList);
+
/**
* 根据键名查询参数配置信息
*
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
index 1532576b..666b5dc3 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
@@ -34,6 +34,14 @@ public interface ISysConfigService {
*/
List selectConfigList(SysConfig config);
+ /**
+ * 根据键名查询参数配置信息
+ *
+ * @param configKeyList 参数键名集合
+ * @return 参数配置集合
+ */
+ List selectConfigListByKeys(List configKeyList);
+
/**
* 新增参数配置
*
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
index f9ad4890..718b277a 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
@@ -83,6 +83,11 @@ public class SysConfigServiceImpl implements ISysConfigService {
return configMapper.selectConfigList(config);
}
+ @Override
+ public List selectConfigListByKeys(List configKeyList) {
+ return configMapper.selectConfigListByKeys(configKeyList);
+ }
+
/**
* 新增参数配置
*
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
index 791db697..8a17d428 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
@@ -1,110 +1,101 @@
package com.ruoyi.system.service.impl;
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
import com.ruoyi.common.security.utils.DictUtils;
import com.ruoyi.system.api.domain.SysDictData;
import com.ruoyi.system.mapper.SysDictDataMapper;
import com.ruoyi.system.service.ISysDictDataService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
/**
* 字典 业务层处理
- *
+ *
* @author ruoyi
*/
@Service
-public class SysDictDataServiceImpl implements ISysDictDataService
-{
- @Autowired
+public class SysDictDataServiceImpl implements ISysDictDataService {
+ @Resource
private SysDictDataMapper dictDataMapper;
/**
* 根据条件分页查询字典数据
- *
+ *
* @param dictData 字典数据信息
* @return 字典数据集合信息
*/
@Override
- public List selectDictDataList(SysDictData dictData)
- {
+ public List selectDictDataList(SysDictData dictData) {
return dictDataMapper.selectDictDataList(dictData);
}
/**
* 根据字典类型和字典键值查询字典数据信息
- *
- * @param dictType 字典类型
+ *
+ * @param dictType 字典类型
* @param dictValue 字典键值
* @return 字典标签
*/
@Override
- public String selectDictLabel(String dictType, String dictValue)
- {
+ public String selectDictLabel(String dictType, String dictValue) {
return dictDataMapper.selectDictLabel(dictType, dictValue);
}
/**
* 根据字典数据ID查询信息
- *
+ *
* @param dictCode 字典数据ID
* @return 字典数据
*/
@Override
- public SysDictData selectDictDataById(Long dictCode)
- {
+ public SysDictData selectDictDataById(Long dictCode) {
return dictDataMapper.selectDictDataById(dictCode);
}
/**
* 批量删除字典数据信息
- *
+ *
* @param dictCodes 需要删除的字典数据ID
*/
@Override
- public void deleteDictDataByIds(Long[] dictCodes)
- {
- for (Long dictCode : dictCodes)
- {
+ public void deleteDictDataByIds(Long[] dictCodes) {
+ for (Long dictCode : dictCodes) {
SysDictData data = selectDictDataById(dictCode);
dictDataMapper.deleteDictDataById(dictCode);
- List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
- DictUtils.setDictCache(data.getDictType(), dictDatas);
+ List dictData = dictDataMapper.selectDictDataByType(data.getDictType());
+ DictUtils.setDictCache(data.getDictType(), dictData);
}
}
/**
* 新增保存字典数据信息
- *
+ *
* @param data 字典数据信息
* @return 结果
*/
@Override
- public int insertDictData(SysDictData data)
- {
+ public int insertDictData(SysDictData data) {
int row = dictDataMapper.insertDictData(data);
- if (row > 0)
- {
- List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
- DictUtils.setDictCache(data.getDictType(), dictDatas);
+ if (row > 0) {
+ List dictData = dictDataMapper.selectDictDataByType(data.getDictType());
+ DictUtils.setDictCache(data.getDictType(), dictData);
}
return row;
}
/**
* 修改保存字典数据信息
- *
+ *
* @param data 字典数据信息
* @return 结果
*/
@Override
- public int updateDictData(SysDictData data)
- {
+ public int updateDictData(SysDictData data) {
int row = dictDataMapper.updateDictData(data);
- if (row > 0)
- {
- List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
- DictUtils.setDictCache(data.getDictType(), dictDatas);
+ if (row > 0) {
+ List dictData = dictDataMapper.selectDictDataByType(data.getDictType());
+ DictUtils.setDictCache(data.getDictType(), dictData);
}
return row;
}
diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/com/ruoyi/system/mapper/SysConfigMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/com/ruoyi/system/mapper/SysConfigMapper.xml
index 6865ddf9..a4cfd9bd 100644
--- a/ruoyi-modules/ruoyi-system/src/main/resources/com/ruoyi/system/mapper/SysConfigMapper.xml
+++ b/ruoyi-modules/ruoyi-system/src/main/resources/com/ruoyi/system/mapper/SysConfigMapper.xml
@@ -78,6 +78,18 @@
where config_key = #{configKey} limit 1
+
+
insert into sys_config (
config_name,
diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/com/ruoyi/system/mapper/SysDictTypeMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/com/ruoyi/system/mapper/SysDictTypeMapper.xml
index e761d96c..9aa7ca98 100644
--- a/ruoyi-modules/ruoyi-system/src/main/resources/com/ruoyi/system/mapper/SysDictTypeMapper.xml
+++ b/ruoyi-modules/ruoyi-system/src/main/resources/com/ruoyi/system/mapper/SysDictTypeMapper.xml
@@ -74,7 +74,7 @@
-
+
update sys_dict_type
dict_name = #{dictName},
@@ -87,7 +87,7 @@
where dict_id = #{dictId}
-
+
insert into sys_dict_type(
dict_name,
dict_type,