From 1e35045f67b91010593bea2c1d9f0a5a5f9d75ee Mon Sep 17 00:00:00 2001 From: AlanScipio Date: Fri, 1 Mar 2024 13:46:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=9F=BA=E7=A1=80=E9=82=AE?= =?UTF-8?q?=E4=BB=B6=E5=8F=91=E9=80=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 22 +++ ruoyi-common/ruoyi-common-core/pom.xml | 6 + .../ruoyi/common/core/mail/MailMessage.java | 124 ++++++++++++ .../common/core/mail/MailMessageHead.java | 35 ++++ .../common/core/mail/MailSendAccount.java | 43 ++++ .../common/core/mail/MailSendResult.java | 51 +++++ .../ruoyi/common/core/mail/MailSender.java | 87 +++++++++ .../common/core/mail/SpringMailSender.java | 184 ++++++++++++++++++ .../ruoyi/common/core/utils/SpringUtils.java | 2 +- .../common/security/utils/DictUtils.java | 71 ++++--- .../common/security/utils/SysConfigUtils.java | 81 ++++++++ ruoyi-modules/ruoyi-system/pom.xml | 10 + .../com/ruoyi/system/config/MailConfig.java | 64 ++++++ .../ruoyi/system/mapper/SysConfigMapper.java | 9 + .../system/service/ISysConfigService.java | 8 + .../service/impl/SysConfigServiceImpl.java | 5 + .../service/impl/SysDictDataServiceImpl.java | 67 +++---- .../ruoyi/system/mapper/SysConfigMapper.xml | 12 ++ .../ruoyi/system/mapper/SysDictTypeMapper.xml | 4 +- 19 files changed, 815 insertions(+), 70 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailMessage.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailMessageHead.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSendAccount.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSendResult.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/MailSender.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/mail/SpringMailSender.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SysConfigUtils.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/config/MailConfig.java 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,