ApplicationEventPublisher:定义可以参考其他博客
在spring boot项目中用到需要发送邮件功能,以往只是简单抛个线程去做,现在看还有许多欠妥当地方,现在记录下来,先贴代码
ApplicationEventPublisher使用步骤
1.自定义一个邮箱事件 需要继承 ApplicationEvent
import org.springframework.context.ApplicationEvent;
/**
* <自定义邮箱事件>
*
* @author
*/
public class EmailEvent extends ApplicationEvent {
private String subject;//标题
private String content;//内容
private String sender;//发件人
private String authorizationCode;//授权码
private String receiver;//收件人
/**
* @param source
*/
public EmailEvent(Object source) {
super(source);
}
public EmailEvent(Object source,String subject, String content, String receiver) {
super(source);
this.subject = subject;
this.content = content;
this.receiver = receiver;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getAuthorizationCode() {
return authorizationCode;
}
public void setAuthorizationCode(String authorizationCode) {
this.authorizationCode = authorizationCode;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
}
2.创建监听器,监听自定义的邮箱事件
package com.qgnjjl.organization.listener;
import com.qgnjjl.common.utils.EmailUtils;
import com.qgnjjl.common.utils.StringUtils;
import com.qgnjjl.organization.domain.EmailEvent;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
import java.security.GeneralSecurityException;
/**
* 〈邮箱发送〉<br>
* 发送邮件
*
* @author Administrator
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
@Component
public class SendmailListener implements ApplicationListener<EmailEvent> {
@Value("${email.sender}")
private String sender;
@Value("${email.authorizationCode}")
private String authorizationCode;
@Override
@Async("taskExecutor")
@Transactional(rollbackFor = Exception.class)
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void onApplicationEvent(EmailEvent emailEvent) {
if (emailEvent == null || StringUtils.isEmpty(sender) || StringUtils.isEmpty(authorizationCode) || StringUtils.isEmpty(emailEvent.getReceiver()) ) {
return ;
}
emailEvent.setSender(sender);
emailEvent.setAuthorizationCode(authorizationCode);
try {
EmailUtils.sendMail(emailEvent);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
}
}
3.推送邮箱事件
package com.qgnjjl.organization.publisher;
import com.qgnjjl.organization.domain.EmailEvent;
import com.qgnjjl.organization.domain.OrganizationDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
/**
*ApplicationEventPublisher邮件推送
*
* @author xzx
*/
@Component
public class SendmaillEventPublisher {
@Autowired
private ApplicationEventPublisher publisher;
public void sendmail2MachineryEquipment(OrganizationDO organizationDO) {
String sign = organizationDO.getUniquelyIdentifies();
String key = organizationDO.getUniqueKey();
//邮件内容
String content = "内容"
//邮件标题
String subject ="主题";
String email = organizationDO.getEmail();
publisher.publishEvent(new EmailEvent(this,subject, content, email));
}
}
4,在控制层调用邮箱推送
5.javaMail 工具类
package com.qgnjjl.common.utils;
import com.qgnjjl.organization.domain.EmailEvent;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.security.GeneralSecurityException;
import java.util.Properties;
/**
* 〈一句话功能简述〉<br>
* 〈功能详细描述〉
*
* @author liuc
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class EmailUtils {
public static String sendMail(EmailEvent event) throws GeneralSecurityException {
String flag="发送成功!";
System.out.println("=====邮件发送========");
//使用MailSSLSocketFactory避免了需要添加证书
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
Properties prop = new Properties();
prop.put("mail.host", "smtp.163.com");
prop.put("mail.transport.protocol", "smtp");
prop.put("mail.smtp.auth", false);
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
String nick="";
try {
// 使用java发送邮件5步骤
// 1.创建sesssion
Session session = Session.getInstance(prop);
// 开启session的调试模式,可以查看当前邮件发送状态
// session.setDebug(true);
// 2.通过session获取Transport对象(发送邮件的核心API)
Transport ts = session.getTransport();
// 3.通过邮件用户名密码链接
ts.connect(event.getSender(), event.getAuthorizationCode());
// 4.创建邮件
nick = MimeUtility.encodeText("昵称");
Message msg = createSimpleMail(session, event.getSubject(), event.getContent(), event.getSender(), event.getReceiver());
msg.setFrom(new InternetAddress(nick+"<"+event.getSender()+">"));
// 5.发送电子邮件
ts.sendMessage(msg, msg.getAllRecipients());
} catch (Exception e) {
e.printStackTrace();
flag="发送失败!";
}
return flag;
}
public static MimeMessage createSimpleMail(Session session, String subject, String content, String from, String to)
throws AddressException, MessagingException {
// 创建邮件对象
MimeMessage mm = new MimeMessage(session);
// 设置发件人
mm.setFrom(new InternetAddress(from));
// 设置收件人
mm.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
// 设置抄送人
// mm.setRecipient(Message.RecipientType.CC, new InternetAddress("[email protected]"));
mm.setSubject(subject);
mm.setContent(content, "text/html;charset=utf-8");
return mm;
}
}
6.线程池配置
package com.qgnjjl.common.config;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* 〈线程池配置类〉<br>
*
* @author lz
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
@EnableAsync
@Configuration
public class ExecutorConfig {
/** 核心线程数 */
private int corePoolSize = 10;
/** 最大线程数 */
private int maxPoolSize = 50;
/** 队列大小 */
private int queueCapacity = 10;
/** 线程最大空闲时间 */
private int keepAliveSeconds = 150;
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("taskExecutor-");
executor.setKeepAliveSeconds(keepAliveSeconds);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}