From ca06a2311da20502ad54f4593f1f18a177c07c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 13 Aug 2024 13:32:34 +0800 Subject: [PATCH 01/12] =?UTF-8?q?update=20hutool=205.8.29=20=3D>=205.8.31?= =?UTF-8?q?=20=E8=A7=A3=E5=86=B3hutool=E4=B8=8D=E5=85=BC=E5=AE=B9jakarta?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../common/mail/config/MailConfig.java | 2 +- .../common/mail/utils/GlobalMailAccount.java | 46 -- .../common/mail/utils/InternalMailUtil.java | 108 --- .../org/dromara/common/mail/utils/Mail.java | 483 ------------- .../common/mail/utils/MailAccount.java | 659 ------------------ .../common/mail/utils/MailException.java | 40 -- .../dromara/common/mail/utils/MailUtils.java | 12 +- .../mail/utils/UserPassAuthenticator.java | 33 - 9 files changed, 9 insertions(+), 1376 deletions(-) delete mode 100644 ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/GlobalMailAccount.java delete mode 100644 ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/InternalMailUtil.java delete mode 100644 ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/Mail.java delete mode 100644 ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailAccount.java delete mode 100644 ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailException.java delete mode 100644 ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/UserPassAuthenticator.java diff --git a/pom.xml b/pom.xml index bbb394ea7..7772834d6 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ 1.38.0 3.5.7 3.9.1 - 5.8.29 + 5.8.31 4.10.0 3.2.3 3.34.1 diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/MailConfig.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/MailConfig.java index 1b51c272c..0ea3007b9 100644 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/MailConfig.java +++ b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/MailConfig.java @@ -1,7 +1,7 @@ package org.dromara.common.mail.config; +import cn.hutool.extra.mail.MailAccount; import org.dromara.common.mail.config.properties.MailProperties; -import org.dromara.common.mail.utils.MailAccount; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/GlobalMailAccount.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/GlobalMailAccount.java deleted file mode 100644 index fdae86975..000000000 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/GlobalMailAccount.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.dromara.common.mail.utils; - -import cn.hutool.core.io.IORuntimeException; - -/** - * 全局邮件帐户,依赖于邮件配置文件{@link MailAccount#MAIL_SETTING_PATHS} - * - * @author looly - */ -public enum GlobalMailAccount { - INSTANCE; - - private final MailAccount mailAccount; - - /** - * 构造 - */ - GlobalMailAccount() { - mailAccount = createDefaultAccount(); - } - - /** - * 获得邮件帐户 - * - * @return 邮件帐户 - */ - public MailAccount getAccount() { - return this.mailAccount; - } - - /** - * 创建默认帐户 - * - * @return MailAccount - */ - private MailAccount createDefaultAccount() { - for (String mailSettingPath : MailAccount.MAIL_SETTING_PATHS) { - try { - return new MailAccount(mailSettingPath); - } catch (IORuntimeException ignore) { - //ignore - } - } - return null; - } -} diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/InternalMailUtil.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/InternalMailUtil.java deleted file mode 100644 index b755e7370..000000000 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/InternalMailUtil.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.dromara.common.mail.utils; - -import cn.hutool.core.util.ArrayUtil; -import jakarta.mail.internet.AddressException; -import jakarta.mail.internet.InternetAddress; -import jakarta.mail.internet.MimeUtility; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * 邮件内部工具类 - * - * @author looly - * @since 3.2.3 - */ -public class InternalMailUtil { - - /** - * 将多个字符串邮件地址转为{@link InternetAddress}列表
- * 单个字符串地址可以是多个地址合并的字符串 - * - * @param addrStrs 地址数组 - * @param charset 编码(主要用于中文用户名的编码) - * @return 地址数组 - * @since 4.0.3 - */ - public static InternetAddress[] parseAddressFromStrs(String[] addrStrs, Charset charset) { - final List resultList = new ArrayList<>(addrStrs.length); - InternetAddress[] addrs; - for (String addrStr : addrStrs) { - addrs = parseAddress(addrStr, charset); - if (ArrayUtil.isNotEmpty(addrs)) { - Collections.addAll(resultList, addrs); - } - } - return resultList.toArray(new InternetAddress[0]); - } - - /** - * 解析第一个地址 - * - * @param address 地址字符串 - * @param charset 编码,{@code null}表示使用系统属性定义的编码或系统编码 - * @return 地址列表 - */ - public static InternetAddress parseFirstAddress(String address, Charset charset) { - final InternetAddress[] internetAddresses = parseAddress(address, charset); - if (ArrayUtil.isEmpty(internetAddresses)) { - try { - return new InternetAddress(address); - } catch (AddressException e) { - throw new MailException(e); - } - } - return internetAddresses[0]; - } - - /** - * 将一个地址字符串解析为多个地址
- * 地址间使用" "、","、";"分隔 - * - * @param address 地址字符串 - * @param charset 编码,{@code null}表示使用系统属性定义的编码或系统编码 - * @return 地址列表 - */ - public static InternetAddress[] parseAddress(String address, Charset charset) { - InternetAddress[] addresses; - try { - addresses = InternetAddress.parse(address); - } catch (AddressException e) { - throw new MailException(e); - } - //编码用户名 - if (ArrayUtil.isNotEmpty(addresses)) { - final String charsetStr = null == charset ? null : charset.name(); - for (InternetAddress internetAddress : addresses) { - try { - internetAddress.setPersonal(internetAddress.getPersonal(), charsetStr); - } catch (UnsupportedEncodingException e) { - throw new MailException(e); - } - } - } - - return addresses; - } - - /** - * 编码中文字符
- * 编码失败返回原字符串 - * - * @param text 被编码的文本 - * @param charset 编码 - * @return 编码后的结果 - */ - public static String encodeText(String text, Charset charset) { - try { - return MimeUtility.encodeText(text, charset.name(), null); - } catch (UnsupportedEncodingException e) { - // ignore - } - return text; - } -} diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/Mail.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/Mail.java deleted file mode 100644 index 6ca4b69ec..000000000 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/Mail.java +++ /dev/null @@ -1,483 +0,0 @@ -package org.dromara.common.mail.utils; - -import cn.hutool.core.builder.Builder; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import jakarta.activation.DataHandler; -import jakarta.activation.DataSource; -import jakarta.activation.FileDataSource; -import jakarta.activation.FileTypeMap; -import jakarta.mail.*; -import jakarta.mail.internet.MimeBodyPart; -import jakarta.mail.internet.MimeMessage; -import jakarta.mail.internet.MimeMultipart; -import jakarta.mail.internet.MimeUtility; -import jakarta.mail.util.ByteArrayDataSource; - -import java.io.*; -import java.nio.charset.Charset; -import java.util.Date; - -/** - * 邮件发送客户端 - * - * @author looly - * @since 3.2.0 - */ -public class Mail implements Builder { - @Serial - private static final long serialVersionUID = 1L; - - /** - * 邮箱帐户信息以及一些客户端配置信息 - */ - private final MailAccount mailAccount; - /** - * 收件人列表 - */ - private String[] tos; - /** - * 抄送人列表(carbon copy) - */ - private String[] ccs; - /** - * 密送人列表(blind carbon copy) - */ - private String[] bccs; - /** - * 回复地址(reply-to) - */ - private String[] reply; - /** - * 标题 - */ - private String title; - /** - * 内容 - */ - private String content; - /** - * 是否为HTML - */ - private boolean isHtml; - /** - * 正文、附件和图片的混合部分 - */ - private final Multipart multipart = new MimeMultipart(); - /** - * 是否使用全局会话,默认为false - */ - private boolean useGlobalSession = false; - - /** - * debug输出位置,可以自定义debug日志 - */ - private PrintStream debugOutput; - - /** - * 创建邮件客户端 - * - * @param mailAccount 邮件帐号 - * @return Mail - */ - public static Mail create(MailAccount mailAccount) { - return new Mail(mailAccount); - } - - /** - * 创建邮件客户端,使用全局邮件帐户 - * - * @return Mail - */ - public static Mail create() { - return new Mail(); - } - - // --------------------------------------------------------------- Constructor start - - /** - * 构造,使用全局邮件帐户 - */ - public Mail() { - this(GlobalMailAccount.INSTANCE.getAccount()); - } - - /** - * 构造 - * - * @param mailAccount 邮件帐户,如果为null使用默认配置文件的全局邮件配置 - */ - public Mail(MailAccount mailAccount) { - mailAccount = (null != mailAccount) ? mailAccount : GlobalMailAccount.INSTANCE.getAccount(); - this.mailAccount = mailAccount.defaultIfEmpty(); - } - // --------------------------------------------------------------- Constructor end - - // --------------------------------------------------------------- Getters and Setters start - - /** - * 设置收件人 - * - * @param tos 收件人列表 - * @return this - * @see #setTos(String...) - */ - public Mail to(String... tos) { - return setTos(tos); - } - - /** - * 设置多个收件人 - * - * @param tos 收件人列表 - * @return this - */ - public Mail setTos(String... tos) { - this.tos = tos; - return this; - } - - /** - * 设置多个抄送人(carbon copy) - * - * @param ccs 抄送人列表 - * @return this - * @since 4.0.3 - */ - public Mail setCcs(String... ccs) { - this.ccs = ccs; - return this; - } - - /** - * 设置多个密送人(blind carbon copy) - * - * @param bccs 密送人列表 - * @return this - * @since 4.0.3 - */ - public Mail setBccs(String... bccs) { - this.bccs = bccs; - return this; - } - - /** - * 设置多个回复地址(reply-to) - * - * @param reply 回复地址(reply-to)列表 - * @return this - * @since 4.6.0 - */ - public Mail setReply(String... reply) { - this.reply = reply; - return this; - } - - /** - * 设置标题 - * - * @param title 标题 - * @return this - */ - public Mail setTitle(String title) { - this.title = title; - return this; - } - - /** - * 设置正文
- * 正文可以是普通文本也可以是HTML(默认普通文本),可以通过调用{@link #setHtml(boolean)} 设置是否为HTML - * - * @param content 正文 - * @return this - */ - public Mail setContent(String content) { - this.content = content; - return this; - } - - /** - * 设置是否是HTML - * - * @param isHtml 是否为HTML - * @return this - */ - public Mail setHtml(boolean isHtml) { - this.isHtml = isHtml; - return this; - } - - /** - * 设置正文 - * - * @param content 正文内容 - * @param isHtml 是否为HTML - * @return this - */ - public Mail setContent(String content, boolean isHtml) { - setContent(content); - return setHtml(isHtml); - } - - /** - * 设置文件类型附件,文件可以是图片文件,此时自动设置cid(正文中引用图片),默认cid为文件名 - * - * @param files 附件文件列表 - * @return this - */ - public Mail setFiles(File... files) { - if (ArrayUtil.isEmpty(files)) { - return this; - } - - final DataSource[] attachments = new DataSource[files.length]; - for (int i = 0; i < files.length; i++) { - attachments[i] = new FileDataSource(files[i]); - } - return setAttachments(attachments); - } - - /** - * 增加附件或图片,附件使用{@link DataSource} 形式表示,可以使用{@link FileDataSource}包装文件表示文件附件 - * - * @param attachments 附件列表 - * @return this - * @since 4.0.9 - */ - public Mail setAttachments(DataSource... attachments) { - if (ArrayUtil.isNotEmpty(attachments)) { - final Charset charset = this.mailAccount.getCharset(); - MimeBodyPart bodyPart; - String nameEncoded; - try { - for (DataSource attachment : attachments) { - bodyPart = new MimeBodyPart(); - bodyPart.setDataHandler(new DataHandler(attachment)); - nameEncoded = attachment.getName(); - if (this.mailAccount.isEncodefilename()) { - nameEncoded = InternalMailUtil.encodeText(nameEncoded, charset); - } - // 普通附件文件名 - bodyPart.setFileName(nameEncoded); - if (StrUtil.startWith(attachment.getContentType(), "image/")) { - // 图片附件,用于正文中引用图片 - bodyPart.setContentID(nameEncoded); - } - this.multipart.addBodyPart(bodyPart); - } - } catch (MessagingException e) { - throw new MailException(e); - } - } - return this; - } - - /** - * 增加图片,图片的键对应到邮件模板中的占位字符串,图片类型默认为"image/jpeg" - * - * @param cid 图片与占位符,占位符格式为cid:${cid} - * @param imageStream 图片文件 - * @return this - * @since 4.6.3 - */ - public Mail addImage(String cid, InputStream imageStream) { - return addImage(cid, imageStream, null); - } - - /** - * 增加图片,图片的键对应到邮件模板中的占位字符串 - * - * @param cid 图片与占位符,占位符格式为cid:${cid} - * @param imageStream 图片流,不关闭 - * @param contentType 图片类型,null赋值默认的"image/jpeg" - * @return this - * @since 4.6.3 - */ - public Mail addImage(String cid, InputStream imageStream, String contentType) { - ByteArrayDataSource imgSource; - try { - imgSource = new ByteArrayDataSource(imageStream, ObjectUtil.defaultIfNull(contentType, "image/jpeg")); - } catch (IOException e) { - throw new IORuntimeException(e); - } - imgSource.setName(cid); - return setAttachments(imgSource); - } - - /** - * 增加图片,图片的键对应到邮件模板中的占位字符串 - * - * @param cid 图片与占位符,占位符格式为cid:${cid} - * @param imageFile 图片文件 - * @return this - * @since 4.6.3 - */ - public Mail addImage(String cid, File imageFile) { - InputStream in = null; - try { - in = FileUtil.getInputStream(imageFile); - return addImage(cid, in, FileTypeMap.getDefaultFileTypeMap().getContentType(imageFile)); - } finally { - IoUtil.close(in); - } - } - - /** - * 设置字符集编码 - * - * @param charset 字符集编码 - * @return this - * @see MailAccount#setCharset(Charset) - */ - public Mail setCharset(Charset charset) { - this.mailAccount.setCharset(charset); - return this; - } - - /** - * 设置是否使用全局会话,默认为true - * - * @param isUseGlobalSession 是否使用全局会话,默认为true - * @return this - * @since 4.0.2 - */ - public Mail setUseGlobalSession(boolean isUseGlobalSession) { - this.useGlobalSession = isUseGlobalSession; - return this; - } - - /** - * 设置debug输出位置,可以自定义debug日志 - * - * @param debugOutput debug输出位置 - * @return this - * @since 5.5.6 - */ - public Mail setDebugOutput(PrintStream debugOutput) { - this.debugOutput = debugOutput; - return this; - } - // --------------------------------------------------------------- Getters and Setters end - - @Override - public MimeMessage build() { - try { - return buildMsg(); - } catch (MessagingException e) { - throw new MailException(e); - } - } - - /** - * 发送 - * - * @return message-id - * @throws MailException 邮件发送异常 - */ - public String send() throws MailException { - try { - return doSend(); - } catch (MessagingException e) { - if (e instanceof SendFailedException) { - // 当地址无效时,显示更加详细的无效地址信息 - final Address[] invalidAddresses = ((SendFailedException) e).getInvalidAddresses(); - final String msg = StrUtil.format("Invalid Addresses: {}", ArrayUtil.toString(invalidAddresses)); - throw new MailException(msg, e); - } - throw new MailException(e); - } - } - - // --------------------------------------------------------------- Private method start - - /** - * 执行发送 - * - * @return message-id - * @throws MessagingException 发送异常 - */ - private String doSend() throws MessagingException { - final MimeMessage mimeMessage = buildMsg(); - Transport.send(mimeMessage); - return mimeMessage.getMessageID(); - } - - /** - * 构建消息 - * - * @return {@link MimeMessage}消息 - * @throws MessagingException 消息异常 - */ - private MimeMessage buildMsg() throws MessagingException { - final Charset charset = this.mailAccount.getCharset(); - final MimeMessage msg = new MimeMessage(getSession()); - // 发件人 - final String from = this.mailAccount.getFrom(); - if (StrUtil.isEmpty(from)) { - // 用户未提供发送方,则从Session中自动获取 - msg.setFrom(); - } else { - msg.setFrom(InternalMailUtil.parseFirstAddress(from, charset)); - } - // 标题 - msg.setSubject(this.title, (null == charset) ? null : charset.name()); - // 发送时间 - msg.setSentDate(new Date()); - // 内容和附件 - msg.setContent(buildContent(charset)); - // 收件人 - msg.setRecipients(MimeMessage.RecipientType.TO, InternalMailUtil.parseAddressFromStrs(this.tos, charset)); - // 抄送人 - if (ArrayUtil.isNotEmpty(this.ccs)) { - msg.setRecipients(MimeMessage.RecipientType.CC, InternalMailUtil.parseAddressFromStrs(this.ccs, charset)); - } - // 密送人 - if (ArrayUtil.isNotEmpty(this.bccs)) { - msg.setRecipients(MimeMessage.RecipientType.BCC, InternalMailUtil.parseAddressFromStrs(this.bccs, charset)); - } - // 回复地址(reply-to) - if (ArrayUtil.isNotEmpty(this.reply)) { - msg.setReplyTo(InternalMailUtil.parseAddressFromStrs(this.reply, charset)); - } - - return msg; - } - - /** - * 构建邮件信息主体 - * - * @param charset 编码,{@code null}则使用{@link MimeUtility#getDefaultJavaCharset()} - * @return 邮件信息主体 - * @throws MessagingException 消息异常 - */ - private Multipart buildContent(Charset charset) throws MessagingException { - final String charsetStr = null != charset ? charset.name() : MimeUtility.getDefaultJavaCharset(); - // 正文 - final MimeBodyPart body = new MimeBodyPart(); - body.setContent(content, StrUtil.format("text/{}; charset={}", isHtml ? "html" : "plain", charsetStr)); - this.multipart.addBodyPart(body); - - return this.multipart; - } - - /** - * 获取默认邮件会话
- * 如果为全局单例的会话,则全局只允许一个邮件帐号,否则每次发送邮件会新建一个新的会话 - * - * @return 邮件会话 {@link Session} - */ - private Session getSession() { - final Session session = MailUtils.getSession(this.mailAccount, this.useGlobalSession); - - if (null != this.debugOutput) { - session.setDebugOut(debugOutput); - } - - return session; - } - // --------------------------------------------------------------- Private method end -} diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailAccount.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailAccount.java deleted file mode 100644 index 2a732a1a9..000000000 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailAccount.java +++ /dev/null @@ -1,659 +0,0 @@ -package org.dromara.common.mail.utils; - -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.setting.Setting; - -import java.io.Serial; -import java.io.Serializable; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -/** - * 邮件账户对象 - * - * @author Luxiaolei - */ -public class MailAccount implements Serializable { - @Serial - private static final long serialVersionUID = -6937313421815719204L; - - private static final String MAIL_PROTOCOL = "mail.transport.protocol"; - private static final String SMTP_HOST = "mail.smtp.host"; - private static final String SMTP_PORT = "mail.smtp.port"; - private static final String SMTP_AUTH = "mail.smtp.auth"; - private static final String SMTP_TIMEOUT = "mail.smtp.timeout"; - private static final String SMTP_CONNECTION_TIMEOUT = "mail.smtp.connectiontimeout"; - private static final String SMTP_WRITE_TIMEOUT = "mail.smtp.writetimeout"; - - // SSL - private static final String STARTTLS_ENABLE = "mail.smtp.starttls.enable"; - private static final String SSL_ENABLE = "mail.smtp.ssl.enable"; - private static final String SSL_PROTOCOLS = "mail.smtp.ssl.protocols"; - private static final String SOCKET_FACTORY = "mail.smtp.socketFactory.class"; - private static final String SOCKET_FACTORY_FALLBACK = "mail.smtp.socketFactory.fallback"; - private static final String SOCKET_FACTORY_PORT = "smtp.socketFactory.port"; - - // System Properties - private static final String SPLIT_LONG_PARAMS = "mail.mime.splitlongparameters"; - //private static final String ENCODE_FILE_NAME = "mail.mime.encodefilename"; - //private static final String CHARSET = "mail.mime.charset"; - - // 其他 - private static final String MAIL_DEBUG = "mail.debug"; - - public static final String[] MAIL_SETTING_PATHS = new String[]{"config/mail.setting", "config/mailAccount.setting", "mail.setting"}; - - /** - * SMTP服务器域名 - */ - private String host; - /** - * SMTP服务端口 - */ - private Integer port; - /** - * 是否需要用户名密码验证 - */ - private Boolean auth; - /** - * 用户名 - */ - private String user; - /** - * 密码 - */ - private String pass; - /** - * 发送方,遵循RFC-822标准 - */ - private String from; - - /** - * 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 - */ - private boolean debug; - /** - * 编码用于编码邮件正文和发送人、收件人等中文 - */ - private Charset charset = CharsetUtil.CHARSET_UTF_8; - /** - * 对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名) - */ - private boolean splitlongparameters = false; - /** - * 对于文件名是否使用{@link #charset}编码,默认为 {@code true} - */ - private boolean encodefilename = true; - - /** - * 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 - */ - private boolean starttlsEnable = false; - /** - * 使用 SSL安全连接 - */ - private Boolean sslEnable; - - /** - * SSL协议,多个协议用空格分隔 - */ - private String sslProtocols; - - /** - * 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 - */ - private String socketFactoryClass = "javax.net.ssl.SSLSocketFactory"; - /** - * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true - */ - private boolean socketFactoryFallback; - /** - * 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 - */ - private int socketFactoryPort = 465; - - /** - * SMTP超时时长,单位毫秒,缺省值不超时 - */ - private long timeout; - /** - * Socket连接超时值,单位毫秒,缺省值不超时 - */ - private long connectionTimeout; - /** - * Socket写出超时值,单位毫秒,缺省值不超时 - */ - private long writeTimeout; - - /** - * 自定义的其他属性,此自定义属性会覆盖默认属性 - */ - private final Map customProperty = new HashMap<>(); - - // -------------------------------------------------------------- Constructor start - - /** - * 构造,所有参数需自行定义或保持默认值 - */ - public MailAccount() { - } - - /** - * 构造 - * - * @param settingPath 配置文件路径 - */ - public MailAccount(String settingPath) { - this(new Setting(settingPath)); - } - - /** - * 构造 - * - * @param setting 配置文件 - */ - public MailAccount(Setting setting) { - setting.toBean(this); - } - - // -------------------------------------------------------------- Constructor end - - /** - * 获得SMTP服务器域名 - * - * @return SMTP服务器域名 - */ - public String getHost() { - return host; - } - - /** - * 设置SMTP服务器域名 - * - * @param host SMTP服务器域名 - * @return this - */ - public MailAccount setHost(String host) { - this.host = host; - return this; - } - - /** - * 获得SMTP服务端口 - * - * @return SMTP服务端口 - */ - public Integer getPort() { - return port; - } - - /** - * 设置SMTP服务端口 - * - * @param port SMTP服务端口 - * @return this - */ - public MailAccount setPort(Integer port) { - this.port = port; - return this; - } - - /** - * 是否需要用户名密码验证 - * - * @return 是否需要用户名密码验证 - */ - public Boolean isAuth() { - return auth; - } - - /** - * 设置是否需要用户名密码验证 - * - * @param isAuth 是否需要用户名密码验证 - * @return this - */ - public MailAccount setAuth(boolean isAuth) { - this.auth = isAuth; - return this; - } - - /** - * 获取用户名 - * - * @return 用户名 - */ - public String getUser() { - return user; - } - - /** - * 设置用户名 - * - * @param user 用户名 - * @return this - */ - public MailAccount setUser(String user) { - this.user = user; - return this; - } - - /** - * 获取密码 - * - * @return 密码 - */ - public String getPass() { - return pass; - } - - /** - * 设置密码 - * - * @param pass 密码 - * @return this - */ - public MailAccount setPass(String pass) { - this.pass = pass; - return this; - } - - /** - * 获取发送方,遵循RFC-822标准 - * - * @return 发送方,遵循RFC-822标准 - */ - public String getFrom() { - return from; - } - - /** - * 设置发送方,遵循RFC-822标准
- * 发件人可以是以下形式: - * - *
-     * 1. user@xxx.xx
-     * 2.  name <user@xxx.xx>
-     * 
- * - * @param from 发送方,遵循RFC-822标准 - * @return this - */ - public MailAccount setFrom(String from) { - this.from = from; - return this; - } - - /** - * 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 - * - * @return 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 - * @since 4.0.2 - */ - public boolean isDebug() { - return debug; - } - - /** - * 设置是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 - * - * @param debug 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 - * @return this - * @since 4.0.2 - */ - public MailAccount setDebug(boolean debug) { - this.debug = debug; - return this; - } - - /** - * 获取字符集编码 - * - * @return 编码,可能为{@code null} - */ - public Charset getCharset() { - return charset; - } - - /** - * 设置字符集编码,此选项不会修改全局配置,若修改全局配置,请设置此项为{@code null}并设置: - *
-     * 	System.setProperty("mail.mime.charset", charset);
-     * 
- * - * @param charset 字符集编码,{@code null} 则表示使用全局设置的默认编码,全局编码为mail.mime.charset系统属性 - * @return this - */ - public MailAccount setCharset(Charset charset) { - this.charset = charset; - return this; - } - - /** - * 对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名) - * - * @return 对于超长参数是否切分为多份 - */ - public boolean isSplitlongparameters() { - return splitlongparameters; - } - - /** - * 设置对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名)
- * 注意此项为全局设置,此项会调用 - *
-     * System.setProperty("mail.mime.splitlongparameters", true)
-     * 
- * - * @param splitlongparameters 对于超长参数是否切分为多份 - */ - public void setSplitlongparameters(boolean splitlongparameters) { - this.splitlongparameters = splitlongparameters; - } - - /** - * 对于文件名是否使用{@link #charset}编码,默认为 {@code true} - * - * @return 对于文件名是否使用{@link #charset}编码,默认为 {@code true} - * @since 5.7.16 - */ - public boolean isEncodefilename() { - - return encodefilename; - } - - /** - * 设置对于文件名是否使用{@link #charset}编码,此选项不会修改全局配置
- * 如果此选项设置为{@code false},则是否编码取决于两个系统属性: - *
    - *
  • mail.mime.encodefilename 是否编码附件文件名
  • - *
  • mail.mime.charset 编码文件名的编码
  • - *
- * - * @param encodefilename 对于文件名是否使用{@link #charset}编码 - * @since 5.7.16 - */ - public void setEncodefilename(boolean encodefilename) { - this.encodefilename = encodefilename; - } - - /** - * 是否使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 - * - * @return 是否使用 STARTTLS安全连接 - */ - public boolean isStarttlsEnable() { - return this.starttlsEnable; - } - - /** - * 设置是否使用STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 - * - * @param startttlsEnable 是否使用STARTTLS安全连接 - * @return this - */ - public MailAccount setStarttlsEnable(boolean startttlsEnable) { - this.starttlsEnable = startttlsEnable; - return this; - } - - /** - * 是否使用 SSL安全连接 - * - * @return 是否使用 SSL安全连接 - */ - public Boolean isSslEnable() { - return this.sslEnable; - } - - /** - * 设置是否使用SSL安全连接 - * - * @param sslEnable 是否使用SSL安全连接 - * @return this - */ - public MailAccount setSslEnable(Boolean sslEnable) { - this.sslEnable = sslEnable; - return this; - } - - /** - * 获取SSL协议,多个协议用空格分隔 - * - * @return SSL协议,多个协议用空格分隔 - * @since 5.5.7 - */ - public String getSslProtocols() { - return sslProtocols; - } - - /** - * 设置SSL协议,多个协议用空格分隔 - * - * @param sslProtocols SSL协议,多个协议用空格分隔 - * @since 5.5.7 - */ - public void setSslProtocols(String sslProtocols) { - this.sslProtocols = sslProtocols; - } - - /** - * 获取指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 - * - * @return 指定实现javax.net.SocketFactory接口的类的名称, 这个类将被用于创建SMTP的套接字 - */ - public String getSocketFactoryClass() { - return socketFactoryClass; - } - - /** - * 设置指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 - * - * @param socketFactoryClass 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 - * @return this - */ - public MailAccount setSocketFactoryClass(String socketFactoryClass) { - this.socketFactoryClass = socketFactoryClass; - return this; - } - - /** - * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true - * - * @return 如果设置为true, 未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true - */ - public boolean isSocketFactoryFallback() { - return socketFactoryFallback; - } - - /** - * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true - * - * @param socketFactoryFallback 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true - * @return this - */ - public MailAccount setSocketFactoryFallback(boolean socketFactoryFallback) { - this.socketFactoryFallback = socketFactoryFallback; - return this; - } - - /** - * 获取指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 - * - * @return 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 - */ - public int getSocketFactoryPort() { - return socketFactoryPort; - } - - /** - * 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 - * - * @param socketFactoryPort 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 - * @return this - */ - public MailAccount setSocketFactoryPort(int socketFactoryPort) { - this.socketFactoryPort = socketFactoryPort; - return this; - } - - /** - * 设置SMTP超时时长,单位毫秒,缺省值不超时 - * - * @param timeout SMTP超时时长,单位毫秒,缺省值不超时 - * @return this - * @since 4.1.17 - */ - public MailAccount setTimeout(long timeout) { - this.timeout = timeout; - return this; - } - - /** - * 设置Socket连接超时值,单位毫秒,缺省值不超时 - * - * @param connectionTimeout Socket连接超时值,单位毫秒,缺省值不超时 - * @return this - * @since 4.1.17 - */ - public MailAccount setConnectionTimeout(long connectionTimeout) { - this.connectionTimeout = connectionTimeout; - return this; - } - - /** - * 设置Socket写出超时值,单位毫秒,缺省值不超时 - * - * @param writeTimeout Socket写出超时值,单位毫秒,缺省值不超时 - * @return this - * @since 5.8.3 - */ - public MailAccount setWriteTimeout(long writeTimeout) { - this.writeTimeout = writeTimeout; - return this; - } - - /** - * 获取自定义属性列表 - * - * @return 自定义参数列表 - * @since 5.6.4 - */ - public Map getCustomProperty() { - return customProperty; - } - - /** - * 设置自定义属性,如mail.smtp.ssl.socketFactory - * - * @param key 属性名,空白被忽略 - * @param value 属性值, null被忽略 - * @return this - * @since 5.6.4 - */ - public MailAccount setCustomProperty(String key, Object value) { - if (StrUtil.isNotBlank(key) && ObjectUtil.isNotNull(value)) { - this.customProperty.put(key, value); - } - return this; - } - - /** - * 获得SMTP相关信息 - * - * @return {@link Properties} - */ - public Properties getSmtpProps() { - //全局系统参数 - System.setProperty(SPLIT_LONG_PARAMS, String.valueOf(this.splitlongparameters)); - - final Properties p = new Properties(); - p.put(MAIL_PROTOCOL, "smtp"); - p.put(SMTP_HOST, this.host); - p.put(SMTP_PORT, String.valueOf(this.port)); - p.put(SMTP_AUTH, String.valueOf(this.auth)); - if (this.timeout > 0) { - p.put(SMTP_TIMEOUT, String.valueOf(this.timeout)); - } - if (this.connectionTimeout > 0) { - p.put(SMTP_CONNECTION_TIMEOUT, String.valueOf(this.connectionTimeout)); - } - // issue#2355 - if (this.writeTimeout > 0) { - p.put(SMTP_WRITE_TIMEOUT, String.valueOf(this.writeTimeout)); - } - - p.put(MAIL_DEBUG, String.valueOf(this.debug)); - - if (this.starttlsEnable) { - //STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 - p.put(STARTTLS_ENABLE, "true"); - - if (null == this.sslEnable) { - //为了兼容旧版本,当用户没有此项配置时,按照starttlsEnable开启状态时对待 - this.sslEnable = true; - } - } - - // SSL - if (null != this.sslEnable && this.sslEnable) { - p.put(SSL_ENABLE, "true"); - p.put(SOCKET_FACTORY, socketFactoryClass); - p.put(SOCKET_FACTORY_FALLBACK, String.valueOf(this.socketFactoryFallback)); - p.put(SOCKET_FACTORY_PORT, String.valueOf(this.socketFactoryPort)); - // issue#IZN95@Gitee,在Linux下需自定义SSL协议版本 - if (StrUtil.isNotBlank(this.sslProtocols)) { - p.put(SSL_PROTOCOLS, this.sslProtocols); - } - } - - // 补充自定义属性,允许自定属性覆盖已经设置的值 - p.putAll(this.customProperty); - - return p; - } - - /** - * 如果某些值为null,使用默认值 - * - * @return this - */ - public MailAccount defaultIfEmpty() { - // 去掉发件人的姓名部分 - final String fromAddress = InternalMailUtil.parseFirstAddress(this.from, this.charset).getAddress(); - - if (StrUtil.isBlank(this.host)) { - // 如果SMTP地址为空,默认使用smtp.<发件人邮箱后缀> - this.host = StrUtil.format("smtp.{}", StrUtil.subSuf(fromAddress, fromAddress.indexOf('@') + 1)); - } - if (StrUtil.isBlank(user)) { - // 如果用户名为空,默认为发件人(issue#I4FYVY@Gitee) - //this.user = StrUtil.subPre(fromAddress, fromAddress.indexOf('@')); - this.user = fromAddress; - } - if (null == this.auth) { - // 如果密码非空白,则使用认证模式 - this.auth = (false == StrUtil.isBlank(this.pass)); - } - if (null == this.port) { - // 端口在SSL状态下默认与socketFactoryPort一致,非SSL状态下默认为25 - this.port = (null != this.sslEnable && this.sslEnable) ? this.socketFactoryPort : 25; - } - if (null == this.charset) { - // 默认UTF-8编码 - this.charset = CharsetUtil.CHARSET_UTF_8; - } - - return this; - } - - @Override - public String toString() { - return "MailAccount [host=" + host + ", port=" + port + ", auth=" + auth + ", user=" + user + ", pass=" + (StrUtil.isEmpty(this.pass) ? "" : "******") + ", from=" + from + ", startttlsEnable=" - + starttlsEnable + ", socketFactoryClass=" + socketFactoryClass + ", socketFactoryFallback=" + socketFactoryFallback + ", socketFactoryPort=" + socketFactoryPort + "]"; - } -} diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailException.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailException.java deleted file mode 100644 index cc199d455..000000000 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailException.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.dromara.common.mail.utils; - -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.util.StrUtil; - -import java.io.Serial; - -/** - * 邮件异常 - * - * @author xiaoleilu - */ -public class MailException extends RuntimeException { - @Serial - private static final long serialVersionUID = 8247610319171014183L; - - public MailException(Throwable e) { - super(ExceptionUtil.getMessage(e), e); - } - - public MailException(String message) { - super(message); - } - - public MailException(String messageTemplate, Object... params) { - super(StrUtil.format(messageTemplate, params)); - } - - public MailException(String message, Throwable throwable) { - super(message, throwable); - } - - public MailException(String message, Throwable throwable, boolean enableSuppression, boolean writableStackTrace) { - super(message, throwable, enableSuppression, writableStackTrace); - } - - public MailException(Throwable throwable, String messageTemplate, Object... params) { - super(StrUtil.format(messageTemplate, params), throwable); - } -} diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailUtils.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailUtils.java index 040cc572a..a28701fbc 100644 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailUtils.java +++ b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailUtils.java @@ -5,6 +5,9 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.mail.JakartaMail; +import cn.hutool.extra.mail.JakartaUserPassAuthenticator; +import cn.hutool.extra.mail.MailAccount; import jakarta.mail.Authenticator; import jakarta.mail.Session; import lombok.AccessLevel; @@ -17,7 +20,7 @@ import java.io.InputStream; import java.util.Collection; import java.util.List; import java.util.Map; - +import java.util.Map.Entry; /** * 邮件工具类 @@ -385,7 +388,7 @@ public class MailUtils { public static Session getSession(MailAccount mailAccount, boolean isSingleton) { Authenticator authenticator = null; if (mailAccount.isAuth()) { - authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); + authenticator = new JakartaUserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); } return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // @@ -412,7 +415,7 @@ public class MailUtils { */ private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection tos, Collection ccs, Collection bccs, String subject, String content, Map imageMap, boolean isHtml, File... files) { - final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession); + final JakartaMail mail = JakartaMail.create(mailAccount).setUseGlobalSession(useGlobalSession); // 可选抄送人 if (CollUtil.isNotEmpty(ccs)) { @@ -431,7 +434,7 @@ public class MailUtils { // 图片 if (MapUtil.isNotEmpty(imageMap)) { - for (Map.Entry entry : imageMap.entrySet()) { + for (Entry entry : imageMap.entrySet()) { mail.addImage(entry.getKey(), entry.getValue()); // 关闭流 IoUtil.close(entry.getValue()); @@ -463,5 +466,4 @@ public class MailUtils { return result; } // ------------------------------------------------------------------------------------------------------------------------ Private method end - } diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/UserPassAuthenticator.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/UserPassAuthenticator.java deleted file mode 100644 index fbbe5e371..000000000 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/UserPassAuthenticator.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.dromara.common.mail.utils; - -import jakarta.mail.Authenticator; -import jakarta.mail.PasswordAuthentication; - -/** - * 用户名密码验证器 - * - * @author looly - * @since 3.1.2 - */ -public class UserPassAuthenticator extends Authenticator { - - private final String user; - private final String pass; - - /** - * 构造 - * - * @param user 用户名 - * @param pass 密码 - */ - public UserPassAuthenticator(String user, String pass) { - this.user = user; - this.pass = pass; - } - - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(this.user, this.pass); - } - -} From 77f44574c00b536ef21286f3898265829e446a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 11:53:15 +0800 Subject: [PATCH 02/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9spring=E6=BA=90=E7=A0=81=E4=B8=8A=E4=B8=8B=E6=96=87?= =?UTF-8?q?=E6=8C=81=E6=9C=89=E8=80=85=20=E6=94=AF=E6=8C=81=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E5=88=87=E6=8D=A2=E4=BC=A0=E9=80=92=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E6=96=87=E6=95=B0=E6=8D=AE=20=E6=94=AF=E6=8C=81=E4=B8=80?= =?UTF-8?q?=E5=88=87=E5=BC=82=E6=AD=A5=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E7=AD=89=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/listener/UserActionListener.java | 1 - .../dromara/web/service/SysLoginService.java | 1 - .../web/service/SysRegisterService.java | 2 - ruoyi-common/ruoyi-common-core/pom.xml | 7 + .../context/request/RequestContextHolder.java | 161 ++++++++++++++++++ .../dromara/common/log/aspect/LogAspect.java | 14 -- .../common/log/event/LogininforEvent.java | 7 - .../impl/SysLogininforServiceImpl.java | 2 +- .../service/impl/SysOperLogServiceImpl.java | 23 ++- 9 files changed, 189 insertions(+), 29 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/springframework/web/context/request/RequestContextHolder.java diff --git a/ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java b/ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java index 07595e092..a958de62d 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java @@ -71,7 +71,6 @@ public class UserActionListener implements SaTokenListener { logininforEvent.setUsername(username); logininforEvent.setStatus(Constants.LOGIN_SUCCESS); logininforEvent.setMessage(MessageUtils.message("user.login.success")); - logininforEvent.setRequest(ServletUtils.getRequest()); SpringUtils.context().publishEvent(logininforEvent); // 更新登录信息 loginService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip); diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index 52803663c..3ee67630b 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -139,7 +139,6 @@ public class SysLoginService { logininforEvent.setUsername(username); logininforEvent.setStatus(status); logininforEvent.setMessage(message); - logininforEvent.setRequest(ServletUtils.getRequest()); SpringUtils.context().publishEvent(logininforEvent); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java index ddab279bc..c7545fa65 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java @@ -11,7 +11,6 @@ import org.dromara.common.core.exception.user.CaptchaException; import org.dromara.common.core.exception.user.CaptchaExpireException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.MessageUtils; -import org.dromara.common.core.utils.ServletUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.log.event.LogininforEvent; @@ -108,7 +107,6 @@ public class SysRegisterService { logininforEvent.setUsername(username); logininforEvent.setStatus(status); logininforEvent.setMessage(message); - logininforEvent.setRequest(ServletUtils.getRequest()); SpringUtils.context().publishEvent(logininforEvent); } diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml index 5925c9b3c..f6f8c2556 100644 --- a/ruoyi-common/ruoyi-common-core/pom.xml +++ b/ruoyi-common/ruoyi-common-core/pom.xml @@ -99,6 +99,13 @@ transmittable-thread-local + + jakarta.faces + jakarta.faces-api + 4.1.0 + true + + diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/springframework/web/context/request/RequestContextHolder.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/springframework/web/context/request/RequestContextHolder.java new file mode 100644 index 000000000..7f9622dbc --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/springframework/web/context/request/RequestContextHolder.java @@ -0,0 +1,161 @@ +/* + * Copyright 2002-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.context.request; + +import com.alibaba.ttl.TransmittableThreadLocal; +import jakarta.faces.context.FacesContext; +import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; + +/** + * Holder class to expose the web request in the form of a thread-bound + * {@link RequestAttributes} object. The request will be inherited + * by any child threads spawned by the current thread if the + * {@code inheritable} flag is set to {@code true}. + * + *

Use {@link RequestContextListener} or + * {@link org.springframework.web.filter.RequestContextFilter} to expose + * the current web request. Note that + * already exposes the current request by default. + * + * 修改 spring 上下文存储方式 将 ThreadLocal 替换为 TransmittableThreadLocal + * 支持线程上下文切换变量传递 异步获取 spring 上下文 + * + * @author Juergen Hoeller + * @author Rod Johnson + * @since 2.0 + * @see RequestContextListener + * @see org.springframework.web.filter.RequestContextFilter + */ +public abstract class RequestContextHolder { + + private static final boolean jsfPresent = + ClassUtils.isPresent("jakarta.faces.context.FacesContext", RequestContextHolder.class.getClassLoader()); + + // ThreadLocal 替换为 TransmittableThreadLocal + private static final ThreadLocal requestAttributesHolder = + new TransmittableThreadLocal<>(); + + private static final ThreadLocal inheritableRequestAttributesHolder = + new TransmittableThreadLocal<>(); + + + /** + * Reset the RequestAttributes for the current thread. + */ + public static void resetRequestAttributes() { + requestAttributesHolder.remove(); + inheritableRequestAttributesHolder.remove(); + } + + /** + * Bind the given RequestAttributes to the current thread, + * not exposing it as inheritable for child threads. + * @param attributes the RequestAttributes to expose + * @see #setRequestAttributes(RequestAttributes, boolean) + */ + public static void setRequestAttributes(@Nullable RequestAttributes attributes) { + setRequestAttributes(attributes, false); + } + + /** + * Bind the given RequestAttributes to the current thread. + * @param attributes the RequestAttributes to expose, + * or {@code null} to reset the thread-bound context + * @param inheritable whether to expose the RequestAttributes as inheritable + * for child threads (using an {@link InheritableThreadLocal}) + */ + public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) { + if (attributes == null) { + resetRequestAttributes(); + } + else { + if (inheritable) { + inheritableRequestAttributesHolder.set(attributes); + requestAttributesHolder.remove(); + } + else { + requestAttributesHolder.set(attributes); + inheritableRequestAttributesHolder.remove(); + } + } + } + + /** + * Return the RequestAttributes currently bound to the thread. + * @return the RequestAttributes currently bound to the thread, + * or {@code null} if none bound + */ + @Nullable + public static RequestAttributes getRequestAttributes() { + RequestAttributes attributes = requestAttributesHolder.get(); + if (attributes == null) { + attributes = inheritableRequestAttributesHolder.get(); + } + return attributes; + } + + /** + * Return the RequestAttributes currently bound to the thread. + *

Exposes the previously bound RequestAttributes instance, if any. + * Falls back to the current JSF FacesContext, if any. + * @return the RequestAttributes currently bound to the thread + * @throws IllegalStateException if no RequestAttributes object + * is bound to the current thread + * @see #setRequestAttributes + * @see ServletRequestAttributes + * @see FacesRequestAttributes + * @see jakarta.faces.context.FacesContext#getCurrentInstance() + */ + public static RequestAttributes currentRequestAttributes() throws IllegalStateException { + RequestAttributes attributes = getRequestAttributes(); + if (attributes == null) { + if (jsfPresent) { + attributes = FacesRequestAttributesFactory.getFacesRequestAttributes(); + } + if (attributes == null) { + throw new IllegalStateException("No thread-bound request found: " + + "Are you referring to request attributes outside of an actual web request, " + + "or processing a request outside of the originally receiving thread? " + + "If you are actually operating within a web request and still receive this message, " + + "your code is probably running outside of DispatcherServlet: " + + "In this case, use RequestContextListener or RequestContextFilter to expose the current request."); + } + } + return attributes; + } + + + /** + * Inner class to avoid hard-coded JSF dependency. + */ + private static class FacesRequestAttributesFactory { + + @Nullable + public static RequestAttributes getFacesRequestAttributes() { + try { + FacesContext facesContext = FacesContext.getCurrentInstance(); + return (facesContext != null ? new FacesRequestAttributes(facesContext) : null); + } + catch (NoClassDefFoundError err) { + // typically for com/sun/faces/util/Util if only the JSF API jar is present + return null; + } + } + } + +} diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java index cdbd00f09..8e257a23c 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java @@ -13,7 +13,6 @@ import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; -import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.utils.ServletUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; @@ -21,7 +20,6 @@ import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessStatus; import org.dromara.common.log.event.OperLogEvent; -import org.dromara.common.satoken.utils.LoginHelper; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.http.HttpMethod; import org.springframework.validation.BindingResult; @@ -88,16 +86,6 @@ public class LogAspect { // *========数据库日志=========*// OperLogEvent operLog = new OperLogEvent(); - operLog.setTenantId(LoginHelper.getTenantId()); - operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); - // 请求的地址 - String ip = ServletUtils.getClientIP(); - operLog.setOperIp(ip); - operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); - LoginUser loginUser = LoginHelper.getLoginUser(); - operLog.setOperName(loginUser.getUsername()); - operLog.setDeptName(loginUser.getDeptName()); - if (e != null) { operLog.setStatus(BusinessStatus.FAIL.ordinal()); operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); @@ -106,8 +94,6 @@ public class LogAspect { String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); operLog.setMethod(className + "." + methodName + "()"); - // 设置请求方式 - operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); // 处理设置注解上的参数 getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); // 设置消耗时间 diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/event/LogininforEvent.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/event/LogininforEvent.java index 938eaadde..212bf18b5 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/event/LogininforEvent.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/event/LogininforEvent.java @@ -2,8 +2,6 @@ package org.dromara.common.log.event; import lombok.Data; -import jakarta.servlet.http.HttpServletRequest; - import java.io.Serial; import java.io.Serializable; @@ -39,11 +37,6 @@ public class LogininforEvent implements Serializable { */ private String message; - /** - * 请求体 - */ - private HttpServletRequest request; - /** * 其他参数 */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java index b95baf44b..dfd490ae9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java @@ -55,7 +55,7 @@ public class SysLogininforServiceImpl implements ISysLogininforService { @Async @EventListener public void recordLogininfor(LogininforEvent logininforEvent) { - HttpServletRequest request = logininforEvent.getRequest(); + HttpServletRequest request = ServletUtils.getRequest(); final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); final String ip = ServletUtils.getClientIP(request); // 客户端信息 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java index b78b9dcc8..45f263839 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java @@ -3,18 +3,23 @@ package org.dromara.system.service.impl; import cn.hutool.core.util.ArrayUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.core.utils.ServletUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.ip.AddressUtils; +import org.dromara.common.log.enums.BusinessStatus; import org.dromara.common.log.event.OperLogEvent; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.system.domain.SysOperLog; import org.dromara.system.domain.bo.SysOperLogBo; import org.dromara.system.domain.vo.SysOperLogVo; import org.dromara.system.mapper.SysOperLogMapper; import org.dromara.system.service.ISysOperLogService; -import lombok.RequiredArgsConstructor; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -44,6 +49,18 @@ public class SysOperLogServiceImpl implements ISysOperLogService { @EventListener public void recordOper(OperLogEvent operLogEvent) { SysOperLogBo operLog = MapstructUtils.convert(operLogEvent, SysOperLogBo.class); + operLog.setTenantId(LoginHelper.getTenantId()); + operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + // 请求的地址 + String ip = ServletUtils.getClientIP(); + operLog.setOperIp(ip); + HttpServletRequest request = ServletUtils.getRequest(); + operLog.setOperUrl(StringUtils.substring(request.getRequestURI(), 0, 255)); + LoginUser loginUser = LoginHelper.getLoginUser(); + operLog.setOperName(loginUser.getUsername()); + operLog.setDeptName(loginUser.getDeptName()); + // 设置请求方式 + operLog.setRequestMethod(request.getMethod()); // 远程查询操作地点 operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); insertOperlog(operLog); From 0ad52b18b8902d98856db2a3cb293505303202dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 14:09:20 +0800 Subject: [PATCH 03/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=80=82=E9=85=8Doss=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/generator/util/VelocityUtils.java | 3 +++ .../ruoyi-generator/src/main/resources/vm/java/vo.java.vm | 7 +++++++ .../ruoyi-generator/src/main/resources/vm/ts/types.ts.vm | 6 ++++++ .../ruoyi-generator/src/main/resources/vm/vue/index.vue.vm | 4 ++-- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java index f5db391b8..6e111e3a8 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java @@ -215,6 +215,9 @@ public class VelocityUtils { importList.add("com.fasterxml.jackson.annotation.JsonFormat"); } else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) { importList.add("java.math.BigDecimal"); + } else if (!column.isSuperColumn() && "imageUpload".equals(column.getHtmlType())) { + importList.add("org.dromara.common.translation.annotation.Translation"); + importList.add("org.dromara.common.translation.constant.TransConstant"); } } return importList; diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm index f99a2ed9a..c896afbe8 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm @@ -53,6 +53,13 @@ public class ${ClassName}Vo implements Serializable { #end private $column.javaType $column.javaField; +#if($column.htmlType == "imageUpload") + /** + * ${column.columnComment}Url + */ + @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "${column.javaField}") + private String ${column.javaField}Url"; +#end #end #end diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/ts/types.ts.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/ts/types.ts.vm index c3f6ed1f8..35a468e80 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/ts/types.ts.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/ts/types.ts.vm @@ -9,6 +9,12 @@ export interface ${BusinessName}VO { #elseif($column.javaType == 'Boolean') boolean; #else string; #end +#if($column.htmlType == "imageUpload") + /** + * ${column.columnComment}Url + */ + ${column.javaField}Url: string; +#end #end #end #if ($table.tree) diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm index 886f4ab71..a92d19adc 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -101,9 +101,9 @@ #elseif($column.list && $column.htmlType == "imageUpload") - + #elseif($column.list && $column.dictType && "" != $column.dictType) From 5bdffdb36828822b6090a559b5b47b45d559f0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 14:10:14 +0800 Subject: [PATCH 04/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=80=82=E9=85=8Doss=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/vm/vue/index-tree.vue.vm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm index d13ef2f27..caf3472e1 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -99,9 +99,9 @@ #elseif($column.list && $column.htmlType == "imageUpload") - + #elseif($column.list && $column.dictType && "" != $column.dictType) From e6847605cc90aa0ff35938509c260b62ab7e8c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 17:43:57 +0800 Subject: [PATCH 05/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=97=A0=E7=94=A8=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/mybatis/enums/DataScopeType.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java index 455cecb2e..9bb5a0dc7 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java @@ -32,29 +32,21 @@ public enum DataScopeType { /** * 自定数据权限 - * 使用 SpEL 表达式:`#{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} )` - * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ CUSTOM("2", " #{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} ) ", " 1 = 0 "), /** * 部门数据权限 - * 使用 SpEL 表达式:`#{#deptName} = #{#user.deptId}` - * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ DEPT("3", " #{#deptName} = #{#user.deptId} ", " 1 = 0 "), /** * 部门及以下数据权限 - * 使用 SpEL 表达式:`#{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )}` - * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ DEPT_AND_CHILD("4", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} )", " 1 = 0 "), /** * 仅本人数据权限 - * 使用 SpEL 表达式:`#{#userName} = #{#user.userId}` - * 如果不满足条件,则使用默认 SQL 表达式:`1 = 0` */ SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "); From eda882433aacd5e778a8f1713cd9dd890d59b2b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 17:45:06 +0800 Subject: [PATCH 06/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=8A=A5=E8=AD=A6=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/common/mybatis/enums/DataScopeType.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java index 9bb5a0dc7..981bd421b 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java @@ -13,9 +13,9 @@ import org.dromara.common.mybatis.helper.DataPermissionHelper; * 内置数据: * - {@code user}: 当前登录用户信息,参考 {@link LoginUser} * 内置服务: - * - {@code sdss}: 系统数据权限服务,参考 {@link ISysDataScopeService} + * - {@code sdss}: 系统数据权限服务,参考 ISysDataScopeService * 如需扩展数据,可以通过 {@link DataPermissionHelper} 进行操作 - * 如需扩展服务,可以通过 {@link ISysDataScopeService} 自行编写 + * 如需扩展服务,可以通过 ISysDataScopeService 自行编写 *

* * @author Lion Li From 0e1fcbfe9c8e148dbe63ffea1bfe9836abc6d7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 18:52:01 +0800 Subject: [PATCH 07/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E8=84=B1=E6=95=8F=E5=A2=9E=E5=8A=A0=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=A0=87=E8=AF=86=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/system/domain/vo/SysUserVo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java index d1f405919..86249d20e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java @@ -61,13 +61,13 @@ public class SysUserVo implements Serializable { /** * 用户邮箱 */ - @Sensitive(strategy = SensitiveStrategy.EMAIL) + @Sensitive(strategy = SensitiveStrategy.EMAIL, perms = "system:user:edit") private String email; /** * 手机号码 */ - @Sensitive(strategy = SensitiveStrategy.PHONE) + @Sensitive(strategy = SensitiveStrategy.PHONE, perms = "system:user:edit") private String phonenumber; /** From 19c83f02aa1c8ff82f38c45cef2248a908b2e5b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 19:14:51 +0800 Subject: [PATCH 08/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E7=BC=96=E8=BE=91=E7=8A=B6=E6=80=81=E6=9C=AA=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysRoleServiceImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index 31f949836..9b8b0ecbe 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -293,6 +293,10 @@ public class SysRoleServiceImpl implements ISysRoleService { @Transactional(rollbackFor = Exception.class) public int updateRole(SysRoleBo bo) { SysRole role = MapstructUtils.convert(bo, SysRole.class); + + if (UserConstants.ROLE_DISABLE.equals(role.getStatus()) && this.countUserRoleByRoleId(role.getRoleId()) > 0) { + throw new ServiceException("角色已分配,不能禁用!"); + } // 修改角色信息 baseMapper.updateById(role); // 删除角色与菜单关联 From bb4587fe05d30932d202474ab4b4151bc815dc23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 19:29:04 +0800 Subject: [PATCH 09/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=83=A8?= =?UTF-8?q?=E9=97=A8=E4=B8=8B=E5=AD=98=E5=9C=A8=E5=B2=97=E4=BD=8D=E4=B8=8D?= =?UTF-8?q?=E5=85=81=E8=AE=B8=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/system/SysDeptController.java | 5 +++++ .../org/dromara/system/service/ISysPostService.java | 8 ++++++++ .../system/service/impl/SysPostServiceImpl.java | 11 +++++++++++ 3 files changed, 24 insertions(+) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java index 4f5f23f32..968bbe906 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java @@ -12,6 +12,7 @@ import org.dromara.common.web.core.BaseController; import org.dromara.system.domain.bo.SysDeptBo; import org.dromara.system.domain.vo.SysDeptVo; import org.dromara.system.service.ISysDeptService; +import org.dromara.system.service.ISysPostService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -29,6 +30,7 @@ import java.util.List; public class SysDeptController extends BaseController { private final ISysDeptService deptService; + private final ISysPostService postService; /** * 获取部门列表 @@ -117,6 +119,9 @@ public class SysDeptController extends BaseController { if (deptService.checkDeptExistUser(deptId)) { return R.warn("部门存在用户,不允许删除"); } + if (postService.countPostByDeptId(deptId) > 0) { + return R.warn("部门存在岗位,不允许删除"); + } deptService.checkDeptDataScope(deptId); return toAjax(deptService.deleteDeptById(deptId)); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java index c43f0395c..3751b23be 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java @@ -80,6 +80,14 @@ public interface ISysPostService { */ long countUserPostById(Long postId); + /** + * 通过部门ID查询岗位使用数量 + * + * @param deptId 部门id + * @return 结果 + */ + long countPostByDeptId(Long deptId); + /** * 删除岗位信息 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java index b8a7e607a..2c38129ac 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java @@ -177,6 +177,17 @@ public class SysPostServiceImpl implements ISysPostService { return userPostMapper.selectCount(new LambdaQueryWrapper().eq(SysUserPost::getPostId, postId)); } + /** + * 通过部门ID查询岗位使用数量 + * + * @param deptId 部门id + * @return 结果 + */ + @Override + public long countPostByDeptId(Long deptId) { + return baseMapper.selectCount(new LambdaQueryWrapper().eq(SysPost::getDeptId, deptId)); + } + /** * 删除岗位信息 * From 96d57bd263db21e0e1d34bd1611d66ce51004adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 19:34:02 +0800 Subject: [PATCH 10/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E7=A7=9F?= =?UTF-8?q?=E6=88=B7=E5=A5=97=E9=A4=90=E9=87=8D=E5=90=8D=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/SysTenantPackageController.java | 6 ++++++ .../system/service/ISysTenantPackageService.java | 11 ++++++++--- .../service/impl/SysTenantPackageServiceImpl.java | 12 ++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantPackageController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantPackageController.java index 7d99916d0..acaf5f83c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantPackageController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantPackageController.java @@ -92,6 +92,9 @@ public class SysTenantPackageController extends BaseController { @RepeatSubmit() @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody SysTenantPackageBo bo) { + if (!tenantPackageService.checkPackageNameUnique(bo)) { + return R.fail("新增套餐'" + bo.getPackageName() + "'失败,套餐名称已存在"); + } return toAjax(tenantPackageService.insertByBo(bo)); } @@ -104,6 +107,9 @@ public class SysTenantPackageController extends BaseController { @RepeatSubmit() @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody SysTenantPackageBo bo) { + if (!tenantPackageService.checkPackageNameUnique(bo)) { + return R.fail("修改套餐'" + bo.getPackageName() + "'失败,套餐名称已存在"); + } return toAjax(tenantPackageService.updateByBo(bo)); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantPackageService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantPackageService.java index cdb887ca6..d060b68cd 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantPackageService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantPackageService.java @@ -1,9 +1,9 @@ package org.dromara.system.service; -import org.dromara.system.domain.vo.SysTenantPackageVo; -import org.dromara.system.domain.bo.SysTenantPackageBo; -import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.system.domain.bo.SysTenantPackageBo; +import org.dromara.system.domain.vo.SysTenantPackageVo; import java.util.Collection; import java.util.List; @@ -45,6 +45,11 @@ public interface ISysTenantPackageService { */ Boolean updateByBo(SysTenantPackageBo bo); + /** + * 校验套餐名称是否唯一 + */ + boolean checkPackageNameUnique(SysTenantPackageBo bo); + /** * 修改套餐状态 */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java index 5fd04af8e..d2a72f611 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java @@ -1,6 +1,7 @@ package org.dromara.system.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -116,6 +117,17 @@ public class SysTenantPackageServiceImpl implements ISysTenantPackageService { return baseMapper.updateById(update) > 0; } + /** + * 校验套餐名称是否唯一 + */ + @Override + public boolean checkPackageNameUnique(SysTenantPackageBo bo) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysTenantPackage::getPackageName, bo.getPackageName()) + .ne(ObjectUtil.isNotNull(bo.getPackageId()), SysTenantPackage::getPackageId, bo.getPackageId())); + return !exist; + } + /** * 修改套餐状态 * From 4de45ce1709ff2a5c033621edd8e0e397558cd1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 19:52:03 +0800 Subject: [PATCH 11/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=E9=83=A8=E5=88=86=E7=94=A8=E6=88=B7=E4=B8=8D=E6=83=B3?= =?UTF-8?q?=E7=BB=99=E7=94=A8=E6=88=B7=E5=88=86=E9=85=8D=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E4=B8=8E=E9=83=A8=E9=97=A8=E7=9A=84=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/web/service/SysLoginService.java | 13 +++++++++---- .../service/impl/SysDataScopeServiceImpl.java | 11 +++++++++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index 3ee67630b..9345c92fd 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -19,7 +19,10 @@ import org.dromara.common.core.enums.LoginType; import org.dromara.common.core.enums.TenantStatus; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.user.UserException; -import org.dromara.common.core.utils.*; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.core.utils.MessageUtils; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; import org.dromara.common.log.event.LogininforEvent; import org.dromara.common.mybatis.helper.DataPermissionHelper; import org.dromara.common.redis.utils.RedisUtils; @@ -155,9 +158,11 @@ public class SysLoginService { loginUser.setUserType(user.getUserType()); loginUser.setMenuPermission(permissionService.getMenuPermission(user.getUserId())); loginUser.setRolePermission(permissionService.getRolePermission(user.getUserId())); - Opt deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById); - loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY)); - loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY)); + if (ObjectUtil.isNotNull(user.getDeptId())) { + Opt deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById); + loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY)); + loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY)); + } List roles = roleService.selectRolesByUserId(user.getUserId()); loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class)); return loginUser; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java index a31c42635..018f9a07a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java @@ -2,6 +2,7 @@ package org.dromara.system.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import org.dromara.common.core.utils.StreamUtils; @@ -38,6 +39,9 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { */ @Override public String getRoleCustom(Long roleId) { + if (ObjectUtil.isNull(roleId)) { + return "-1"; + } List list = roleDeptMapper.selectList( new LambdaQueryWrapper() .select(SysRoleDept::getDeptId) @@ -45,7 +49,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { if (CollUtil.isNotEmpty(list)) { return StreamUtils.join(list, rd -> Convert.toStr(rd.getDeptId())); } - return null; + return "-1"; } /** @@ -56,6 +60,9 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { */ @Override public String getDeptAndChild(Long deptId) { + if (ObjectUtil.isNull(deptId)) { + return "-1"; + } List deptList = deptMapper.selectList(new LambdaQueryWrapper() .select(SysDept::getDeptId) .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); @@ -64,7 +71,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { if (CollUtil.isNotEmpty(ids)) { return StreamUtils.join(ids, Convert::toStr); } - return null; + return "-1"; } } From facbb7f28fb613b84ce1529c0bf63f1b77e576e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 15 Aug 2024 20:28:52 +0800 Subject: [PATCH 12/12] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=B8=AA?= =?UTF-8?q?=E4=BA=BA=E4=B8=AD=E5=BF=83=E7=BC=96=E8=BE=91=20=E5=BF=BD?= =?UTF-8?q?=E7=95=A5=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/system/SysProfileController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java index 559e1d59b..893b381e3 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java @@ -11,6 +11,7 @@ import org.dromara.common.encrypt.annotation.ApiEncrypt; import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.helper.DataPermissionHelper; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.web.core.BaseController; import org.dromara.system.domain.bo.SysUserBo; @@ -72,7 +73,8 @@ public class SysProfileController extends BaseController { if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return R.fail("修改用户'" + username + "'失败,邮箱账号已存在"); } - if (userService.updateUserProfile(user) > 0) { + int rows = DataPermissionHelper.ignore(() -> userService.updateUserProfile(user)); + if (rows > 0) { return R.ok(); } return R.fail("修改个人信息异常,请联系管理员");