Java 未在@Async注释方法中发送电子邮件
我正在尝试为用户实现一个下载文件的功能。一般工作流程如下:Java 未在@Async注释方法中发送电子邮件,java,spring,spring-boot,email,Java,Spring,Spring Boot,Email,我正在尝试为用户实现一个下载文件的功能。一般工作流程如下: 用户单击前端的下载按钮 后端将从请求接收下载信息,从数据库获取数据,然后生成zip文件 该文件将被上传到云存储中(本例中为谷歌) 将向用户发送一封带有签名URL的电子邮件,以便从云下载zip文件 所有步骤2、3和4都将在带有@Async注释的方法中执行。 问题是,如果我重新启动后端服务器并只发送一个下载请求,则一切正常,这意味着可以接收电子邮件。 但是,它在发送更多下载请求后不起作用。 不再发送电子邮件。没有错误,没有警告,但所有需要的
public class AbstractEmailSender {
public MimeMessage mimeMessage;
public MimeMessageHelper mimeMessageHelper;
public JavaMailSender javaMailSender;
private final String SENDER = MY_SEND_EMAIL_ADDRESS;
public final String USER_NAME_KEY = "username";
public AbstractEmailSender(JavaMailSender javaMailSender) throws MessagingException {
// this.javaMailSender = new JavaMailSenderImpl();
this.javaMailSender = javaMailSender;
this.doInitialization();
}
public void doInitialization() throws MessagingException {
this.mimeMessage = this.javaMailSender.createMimeMessage();
this.mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
}
public void setEmailContext(String receiver, String subject) throws MessagingException {
this.mimeMessageHelper.setSubject(subject);
this.mimeMessageHelper.setFrom(SENDER);
this.mimeMessageHelper.setTo(receiver);
}
}
@Component
public class DownloadDataSuccessEmailSender extends AbstractEmailSender implements MailService{
private final TemplateEngine templateEngine;
private final static String DOWNLOAD_DATA_SUCCESS_EMAIL_SUBJECT = XXXXXX;
private final static String SIGNED_URL_KEY = "signedUrl";
private final static String DOWNLOAD_EMAIL_TEMPLATE_NAME = "downloadDataSuccessEmail.html";
private static final Logger logger = LogManager.getLogger(DownloadDataSuccessEmailSender.class);
public DownloadDataSuccessEmailSender(JavaMailSender javaMailSender, TemplateEngine templateEngine) throws MessagingException {
super(javaMailSender);
this.templateEngine = templateEngine;
}
@Override
public void sendEmailWithSignedUrlToDownloadFile(URL signedUrl, String username, String receiver) {
// print the result to make sure all data are processed correctly, nothing wrong with
//this step
System.out.println(signedUrl);
System.out.println(username);
System.out.println(receiver);
try{
super.setEmailContext(receiver, DOWNLOAD_DATA_SUCCESS_EMAIL_SUBJECT);
Context context = new Context();
context.setVariable(this.USER_NAME_KEY, username);
context.setVariable(SIGNED_URL_KEY, signedUrl);
String email = this.templateEngine.process(DOWNLOAD_EMAIL_TEMPLATE_NAME, context);
this.mimeMessageHelper.setText(email, true);
this.javaMailSender.send(mimeMessage);
}catch (MailException | MessagingException e) {
logger.error("Email with download data error: ", e);
throw new EmailSendException(ErrorInfo.EMAIL_SEND_EXCEPTION.getCode(), ErrorInfo.EMAIL_SEND_EXCEPTION.getMessage());
}
}
}
电子邮件配置文件:
spring:
mail:
host: smtp.gmail.com
username: MY_EMAIL_ADDRESS
password: MY_PASSWORD
properties.mail.smtp:
auth: true
connectiontimeout: 60000
timeout: 60000
writetimeout: 50000
starttls.enable: true
port: 587
protocol: smtp
thymeleaf:
prefix: classpath:/templates/
处理所有逻辑的异步方法
@Override
@Async
@Transactional(timeout = DOWNLOAD_DATA_TRANSACTION_TIME_LIMIT)
public void downloadFile(SearchQuery query, DownloadRequestRecord downloadRecord){
String username = downloadRecord.getUsername();
String emailAddress = this.userService.getUserEmailAddressByUsername(username);
try{
// here ignore the parts to get data from database and generate zip file and check if the file is uploaded to cloud space successfully here
// ......
if (uploadFile == null) { // check if file exists
logger.error("File: {} does not exist in cloud!", zipFileName);
downloadRecord.setSuccess(0);
this.downloadDataFailMessageEmailSender.sendEmailWithDownloadDataFail(emailAddress, username, downloadRecord.getQuery(), downloadRecord.getDownloadTime()); // send email to inform user the download is fail
} else {
// file exists, generate signed URL and send email with download link
this.downloadDataSuccessEmailSender.sendEmailWithSignedUrlToDownloadFile(signedUrl, username, emailAddress);
downloadRecord.setSuccess(1);
}
} catch (IOException | EmailSendException ex) {
logger.error("Exception from downloading data: ", ex);
downloadRecord.setSuccess(0);
} finally {
this.userService.recordDownloadHistoryOfUser(downloadRecord);
}
}
我的线程池配置
@Configuration
public class AsyncConfig implements AsyncConfigurer {
private static final int CORE_POOL_SIZE = 6;
private static final int MAX_POOL_SIZE = 10;
private static final int QUEUE_CAPACITY = 100;
private static final String THREAD_NAME_PREFIX = "ThreadPoolTaskExecutor-";
private static final Logger logger = LogManager.getLogger(AsyncConfig.class);
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(QUEUE_CAPACITY);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
logger.error("ERROR: ", throwable);
}
};
}
}
在sendEmailWithSignedUrlToDownloadFile中,使用 MimeMessage MimeMessage=mailssender.createMimeMessage()
而不是将一个MimeMessage实例作为超级类的成员谢谢!现在可以了。你能解释一下为什么会这样吗?