From 1274f925449e12f4fff9105d52cfc698ff5e3592 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 18 Apr 2024 22:19:26 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=20job=20=E8=B0=83?= =?UTF-8?q?=E5=BA=A6=EF=BC=9A=201.=20=E6=96=B0=E5=A2=9E=E6=88=96=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20job=20=E9=85=8D=E7=BD=AE=E6=97=B6=EF=BC=8C=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=20handlerName=20=E5=AF=B9=E5=BA=94=E7=9A=84=20Spring?= =?UTF-8?q?=20Bean=20=E5=AD=98=E5=9C=A8=202.=20=E5=88=A0=E9=99=A4=20job=20?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E9=A2=9D=E5=A4=96=E6=9A=82=E5=81=9C=20Trigge?= =?UTF-8?q?r=E3=80=81=E5=8F=96=E6=B6=88=E8=B0=83=E5=BA=A6=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/scheduler/SchedulerManager.java | 6 +- .../infra/enums/ErrorCodeConstants.java | 2 + .../infra/service/job/JobServiceImpl.java | 39 +++++++---- .../infra/service/job/JobServiceImplTest.java | 65 ++++++++++++------- 4 files changed, 76 insertions(+), 36 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java index cb2dad455..d56682e0c 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java @@ -48,7 +48,7 @@ public class SchedulerManager { .withIdentity(jobHandlerName).build(); // 创建 Trigger 对象 Trigger trigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval); - // 新增调度 + // 新增 Job 调度 scheduler.scheduleJob(jobDetail, trigger); } @@ -80,6 +80,10 @@ public class SchedulerManager { */ public void deleteJob(String jobHandlerName) throws SchedulerException { validateScheduler(); + // 暂停 Trigger 对象 + scheduler.pauseTrigger(new TriggerKey(jobHandlerName)); + // 取消并删除 Job 调度 + scheduler.unscheduleJob(new TriggerKey(jobHandlerName)); scheduler.deleteJob(new JobKey(jobHandlerName)); } diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index 19aa4e718..3385596ad 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -22,6 +22,8 @@ public interface ErrorCodeConstants { ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1_001_001_003, "定时任务已经处于该状态,无需修改"); ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1_001_001_004, "只有开启状态的任务,才可以修改"); ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1_001_001_005, "CRON 表达式不正确"); + ErrorCode JOB_HANDLER_BEAN_NOT_EXISTS = new ErrorCode(1_001_001_006, "定时任务的处理器 Bean 不存在"); + ErrorCode JOB_HANDLER_BEAN_TYPE_ERROR = new ErrorCode(1_001_001_007, "定时任务的处理器 Bean 类型不正确,未实现 JobHandler 接口"); // ========== API 错误日志 1-001-002-000 ========== ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1_001_002_000, "API 错误日志不存在"); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java index 094177202..dd887e165 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.infra.service.job; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager; import cn.iocoder.yudao.framework.quartz.core.util.CronUtils; import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobPageReqVO; @@ -9,13 +11,12 @@ import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper; import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; +import jakarta.annotation.Resource; import org.quartz.SchedulerException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; - import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.containsAny; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; @@ -39,24 +40,25 @@ public class JobServiceImpl implements JobService { @Transactional(rollbackFor = Exception.class) public Long createJob(JobSaveReqVO createReqVO) throws SchedulerException { validateCronExpression(createReqVO.getCronExpression()); - // 校验唯一性 + // 1.1 校验唯一性 if (jobMapper.selectByHandlerName(createReqVO.getHandlerName()) != null) { throw exception(JOB_HANDLER_EXISTS); } - // 插入 + // 1.2 校验 JobHandler 是否存在 + validateJobHandlerExists(createReqVO.getHandlerName()); + + // 2. 插入 JobDO JobDO job = BeanUtils.toBean(createReqVO, JobDO.class); job.setStatus(JobStatusEnum.INIT.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); - // 添加 Job 到 Quartz 中 + // 3.1 添加 Job 到 Quartz 中 schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression(), createReqVO.getRetryCount(), createReqVO.getRetryInterval()); - // 更新 + // 3.2 更新 JobDO JobDO updateObj = JobDO.builder().id(job.getId()).status(JobStatusEnum.NORMAL.getStatus()).build(); jobMapper.updateById(updateObj); - - // 返回 return job.getId(); } @@ -64,22 +66,35 @@ public class JobServiceImpl implements JobService { @Transactional(rollbackFor = Exception.class) public void updateJob(JobSaveReqVO updateReqVO) throws SchedulerException { validateCronExpression(updateReqVO.getCronExpression()); - // 校验存在 + // 1.1 校验存在 JobDO job = validateJobExists(updateReqVO.getId()); - // 只有开启状态,才可以修改.原因是,如果出暂停状态,修改 Quartz Job 时,会导致任务又开始执行 + // 1.2 只有开启状态,才可以修改.原因是,如果出暂停状态,修改 Quartz Job 时,会导致任务又开始执行 if (!job.getStatus().equals(JobStatusEnum.NORMAL.getStatus())) { throw exception(JOB_UPDATE_ONLY_NORMAL_STATUS); } - // 更新 + // 1.3 校验 JobHandler 是否存在 + validateJobHandlerExists(updateReqVO.getHandlerName()); + + // 2. 更新 JobDO JobDO updateObj = BeanUtils.toBean(updateReqVO, JobDO.class); fillJobMonitorTimeoutEmpty(updateObj); jobMapper.updateById(updateObj); - // 更新 Job 到 Quartz 中 + // 3. 更新 Job 到 Quartz 中 schedulerManager.updateJob(job.getHandlerName(), updateReqVO.getHandlerParam(), updateReqVO.getCronExpression(), updateReqVO.getRetryCount(), updateReqVO.getRetryInterval()); } + private void validateJobHandlerExists(String handlerName) { + Object handler = SpringUtil.getBean(handlerName); + if (handler == null) { + throw exception(JOB_HANDLER_BEAN_NOT_EXISTS); + } + if (!(handler instanceof JobHandler)) { + throw exception(JOB_HANDLER_BEAN_TYPE_ERROR); + } + } + @Override @Transactional(rollbackFor = Exception.class) public void updateJobStatus(Long id, Integer status) throws SchedulerException { diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImplTest.java index eedbb1d50..7cd160c3d 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImplTest.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.infra.service.job; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; @@ -8,7 +9,9 @@ import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper; import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; +import cn.iocoder.yudao.module.infra.job.job.JobLogCleanJob; import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; import org.quartz.SchedulerException; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -23,6 +26,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.verify; @Import(JobServiceImpl.class) @@ -35,6 +39,9 @@ public class JobServiceImplTest extends BaseDbUnitTest { @MockBean private SchedulerManager schedulerManager; + @MockBean + private JobLogCleanJob jobLogCleanJob; + @Test public void testCreateJob_cronExpressionValid() { // 准备参数。Cron 表达式为 String 类型,默认随机字符串。 @@ -48,11 +55,15 @@ public class JobServiceImplTest extends BaseDbUnitTest { public void testCreateJob_jobHandlerExists() throws SchedulerException { // 准备参数 指定 Cron 表达式 JobSaveReqVO reqVO = randomPojo(JobSaveReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(reqVO.getHandlerName()))) + .thenReturn(jobLogCleanJob); - // 调用 - jobService.createJob(reqVO); - // 调用,并断言异常 - assertServiceException(() -> jobService.createJob(reqVO), JOB_HANDLER_EXISTS); + // 调用 + jobService.createJob(reqVO); + // 调用,并断言异常 + assertServiceException(() -> jobService.createJob(reqVO), JOB_HANDLER_EXISTS); + } } @Test @@ -60,18 +71,22 @@ public class JobServiceImplTest extends BaseDbUnitTest { // 准备参数 指定 Cron 表达式 JobSaveReqVO reqVO = randomPojo(JobSaveReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")) .setId(null); + try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(reqVO.getHandlerName()))) + .thenReturn(jobLogCleanJob); - // 调用 - Long jobId = jobService.createJob(reqVO); - // 断言 - assertNotNull(jobId); - // 校验记录的属性是否正确 - JobDO job = jobMapper.selectById(jobId); - assertPojoEquals(reqVO, job, "id"); - assertEquals(JobStatusEnum.NORMAL.getStatus(), job.getStatus()); - // 校验调用 - verify(schedulerManager).addJob(eq(job.getId()), eq(job.getHandlerName()), eq(job.getHandlerParam()), - eq(job.getCronExpression()), eq(reqVO.getRetryCount()), eq(reqVO.getRetryInterval())); + // 调用 + Long jobId = jobService.createJob(reqVO); + // 断言 + assertNotNull(jobId); + // 校验记录的属性是否正确 + JobDO job = jobMapper.selectById(jobId); + assertPojoEquals(reqVO, job, "id"); + assertEquals(JobStatusEnum.NORMAL.getStatus(), job.getStatus()); + // 校验调用 + verify(schedulerManager).addJob(eq(job.getId()), eq(job.getHandlerName()), eq(job.getHandlerParam()), + eq(job.getCronExpression()), eq(reqVO.getRetryCount()), eq(reqVO.getRetryInterval())); + } } @Test @@ -109,15 +124,19 @@ public class JobServiceImplTest extends BaseDbUnitTest { o.setId(job.getId()); o.setCronExpression("0 0/1 * * * ? *"); }); + try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(updateReqVO.getHandlerName()))) + .thenReturn(jobLogCleanJob); - // 调用 - jobService.updateJob(updateReqVO); - // 校验记录的属性是否正确 - JobDO updateJob = jobMapper.selectById(updateReqVO.getId()); - assertPojoEquals(updateReqVO, updateJob); - // 校验调用 - verify(schedulerManager).updateJob(eq(job.getHandlerName()), eq(updateReqVO.getHandlerParam()), - eq(updateReqVO.getCronExpression()), eq(updateReqVO.getRetryCount()), eq(updateReqVO.getRetryInterval())); + // 调用 + jobService.updateJob(updateReqVO); + // 校验记录的属性是否正确 + JobDO updateJob = jobMapper.selectById(updateReqVO.getId()); + assertPojoEquals(updateReqVO, updateJob); + // 校验调用 + verify(schedulerManager).updateJob(eq(job.getHandlerName()), eq(updateReqVO.getHandlerParam()), + eq(updateReqVO.getCronExpression()), eq(updateReqVO.getRetryCount()), eq(updateReqVO.getRetryInterval())); + } } @Test From 5d58037d05ccf8623cba01a5b539d69bd00cabeb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 22 Apr 2024 19:01:25 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E5=B0=86=20huto?= =?UTF-8?q?ol-all=206.0=20=E7=89=88=E6=9C=AC=E6=9B=BF=E6=8D=A2=E6=88=90=20?= =?UTF-8?q?hutool-extra=EF=BC=8C=E5=87=8F=E5=B0=91=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 2 +- yudao-framework/yudao-common/pom.xml | 4 ---- .../BpmTaskCandidateExpressionStrategy.java | 4 ++-- .../yudao-module-system-biz/pom.xml | 6 ++++++ .../convert/mail/MailAccountConvert.java | 21 ------------------- .../service/mail/MailSendServiceImpl.java | 15 ++++++++----- .../service/mail/MailSendServiceImplTest.java | 3 +-- 7 files changed, 20 insertions(+), 35 deletions(-) delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 09067a2a4..2ee3a3037 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -443,7 +443,7 @@ org.dromara.hutool - hutool-all + hutool-extra ${hutool-6.version} diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index e735856a8..b28da08fe 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -127,10 +127,6 @@ cn.hutool hutool-all - - org.dromara.hutool - hutool-all - com.alibaba diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategy.java index e51ab76e0..e0f9dabe5 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategy.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategy.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy; -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; +import cn.hutool.core.convert.Convert; import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; -import org.dromara.hutool.core.convert.Convert; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import org.flowable.engine.delegate.DelegateExecution; import org.springframework.stereotype.Component; diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index 6de1a58a1..082b6b470 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -127,6 +127,12 @@ com.xingyuv spring-boot-starter-captcha-plus + + + org.dromara.hutool + hutool-extra + + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java deleted file mode 100644 index f538197d7..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.mail; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; -import org.dromara.hutool.extra.mail.MailAccount; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface MailAccountConvert { - - MailAccountConvert INSTANCE = Mappers.getMapper(MailAccountConvert.class); - - default MailAccount convert(MailAccountDO account, String nickname) { - String from = StrUtil.isNotEmpty(nickname) ? nickname + " <" + account.getMail() + ">" : account.getMail(); - return new MailAccount().setFrom(from).setAuth(true) - .setUser(account.getUsername()).setPass(account.getPassword().toCharArray()) - .setHost(account.getHost()).setPort(account.getPort()).setSslEnable(account.getSslEnable()); - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImpl.java index 61ff83d8b..178a64aec 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.mail; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -12,13 +11,12 @@ import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; import cn.iocoder.yudao.module.system.service.member.MemberService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.google.common.annotations.VisibleForTesting; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.dromara.hutool.extra.mail.MailAccount; -import org.dromara.hutool.extra.mail.MailUtil; +import org.dromara.hutool.extra.mail.*; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -105,7 +103,7 @@ public class MailSendServiceImpl implements MailSendService { public void doSendMail(MailSendMessage message) { // 1. 创建发送账号 MailAccountDO account = validateMailAccount(message.getAccountId()); - MailAccount mailAccount = MailAccountConvert.INSTANCE.convert(account, message.getNickname()); + MailAccount mailAccount = buildMailAccount(account, message.getNickname()); // 2. 发送邮件 try { String messageId = MailUtil.send(mailAccount, message.getMail(), @@ -118,6 +116,13 @@ public class MailSendServiceImpl implements MailSendService { } } + private MailAccount buildMailAccount(MailAccountDO account, String nickname) { + String from = StrUtil.isNotEmpty(nickname) ? nickname + " <" + account.getMail() + ">" : account.getMail(); + return new MailAccount().setFrom(from).setAuth(true) + .setUser(account.getUsername()).setPass(account.getPassword().toCharArray()) + .setHost(account.getHost()).setPort(account.getPort()).setSslEnable(account.getSslEnable()); + } + @VisibleForTesting MailTemplateDO validateMailTemplate(String templateCode) { // 获得邮件模板。考虑到效率,从缓存中获取 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java index eaea39fe9..1ef1e1232 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java @@ -13,8 +13,7 @@ import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; import cn.iocoder.yudao.module.system.service.member.MemberService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import org.assertj.core.util.Lists; -import org.dromara.hutool.extra.mail.MailAccount; -import org.dromara.hutool.extra.mail.MailUtil; +import org.dromara.hutool.extra.mail.*; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks;