企业项目中经常使用到邮件发送,尤其在流程审批伴随大量的触发邮件,为提供效率邮件自然设置为异步发送,但单纯多线程异步又造成了先后混乱的现象。所以做了个简单的单线程异步发送队列来处理。
1、把原有的邮件发送服务类做了个修改
ublic class MailSendService {
private @Value("${system.sendmail.from}") String mailForm;
@Autowired
private JavaMailSender javaMailSender; // 邮件发送对象,采用的是spring中的实现类org.springframework.mail.javamail.JavaMailSenderImpl
@Autowired
private MailBoxDao mailBoxDao; //邮件信息记录处理DAO
@Autowired
private MailTemplateDao mailTemplateDao; //邮件模板处理DAO
/**
* 一个默认的邮件发送线程对象
*/
private static MailSendTask mailSendTask;
/**
* 发送简单邮件
* @Methods Name sendByTempate
* @Create In 2014年11月11日 By lee
* @param templateCode
* @param to
* @param titleParam
* @param contextParam
*/
public void sendByTempate(String templateCode, String to,
Map<String,String> titleParam, Map<String,String> contentParam){
sendByTempate(templateCode, to, null, null, titleParam, contentParam, null);
}
/**
* 发送邮件
* @Methods Name sendByTempate
* @Create In 2014年11月11日 By lee
* @param templateCode
* @param to
* @param cc
* @param bcc
* @param titleParam
* @param contextParam
* @param fileParam
*/
public void sendByTempate(String templateCode, String to, String cc, String bcc,
Map<String,String> titleParam, Map<String,String> contentParam, List<String> fileParam){
MailTemplate template = mailTemplateDao.findByCode(templateCode);
MailBox mailBox = new MailBox();
mailBox.setTouser(to);
mailBox.setCc(bcc);
mailBox.setBcc(bcc);
mailBox.setTitle(emailParam(template.getTitle(),titleParam));
mailBox.setContent(emailParam(template.getContent(),contentParam));
mailBox.setFilePath(StrUtils.join(fileParam, ";"));
mailBox.setSendState(MailBox.STATE_READY);
mailBox = mailBoxDao.save(mailBox);
readSend(mailBox);
}
private String emailParam(String str, Map<String,String> paramMap) {
if (paramMap != null && !paramMap.isEmpty()) {
for(String paramKey : paramMap.keySet()){
String paramValue = paramMap.get(paramKey);
str = StrUtils.replace(str, "{"+paramKey+"}", paramValue);
}
}
return str;
}
/**
* 准备发送,进去发送队列
* @Methods Name readSend
* @Create In 2014年11月11日 By lee
* @param mailBox
*/
private void readSend(MailBox mailBox){
if(mailSendTask==null){
mailSendTask = new MailSendTask(mailForm,javaMailSender,mailBoxDao);
new Thread(mailSendTask).start();
List<MailBox> boxs = mailBoxDao.findBySendState(MailBox.STATE_READY);
for(MailBox box : boxs){
mailSendTask.addItem(box);
}
}else{
mailSendTask.addItem(mailBox);
}
}
}
新增一个邮件发送任务类
/**
* 邮件发送任务
* @ClassName: MailSendTask
* @Description: TODO
* @Create In 2014年11月11日 By lee
*/
public class MailSendTask implements Runnable {
private static Log logger = LogFactory.getLog(MailSendTask.class);
private static BlockingQueue<MailBox> calls = new LinkedBlockingQueue<MailBox>(500);
private String mailForm = "lee";
private JavaMailSender javaMailSender; // 邮件发送对象,采用的是spring中的实现类org.springframework.mail.javamail.JavaMailSenderImpl
private MailBoxDao mailBoxDao;
public MailSendTask(String mailForm, JavaMailSender javaMailSender,MailBoxDao mailBoxDao) {
this.javaMailSender = javaMailSender;
this.mailBoxDao = mailBoxDao;
this.mailForm = mailForm;
}
@Override
public void run() {
logger.info("邮件发送线程启动");
while (true) {
try {
MailBox mailBox = calls.take();
sendMail(mailBox);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void addItem(MailBox mailBox) {
try {
calls.put(mailBox);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void sendMail(MailBox mailBox){
JavaMailSenderImpl senderImpl = new JavaMailSenderImpl();
MimeMessage mimeMessage = senderImpl.createMimeMessage();
try{
// 设置utf-8或GBK编码,否则邮件会有乱码
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
if (StrUtils.isNotEmpty(mailBox.getTouser())) { //设定收件人
mimeMessage.setRecipients(Message.RecipientType.TO, getAddressArray(mailBox.getTouser()));
}
if (StrUtils.isNotEmpty(mailBox.getCc())) { //设定抄送
mimeMessage.setRecipients(Message.RecipientType.CC, getAddressArray(mailBox.getCc()));
}
if (StrUtils.isNotEmpty(mailBox.getBcc())) { //设定密送
mimeMessage.setRecipients(Message.RecipientType.BCC, getAddressArray(mailBox.getBcc()));
}
messageHelper.setFrom(mailForm);// 发送者
messageHelper.setSubject(mailBox.getTitle());// 主题
// 邮件内容,注意加参数true
messageHelper.setText(mailBox.getContent(), true);
// 附件内容
if (StrUtils.isNotEmpty(mailBox.getFilePath())) {
String[] filePaths = mailBox.getFilePath().split(";");
for (String filePath : filePaths) {
File file = new File(filePath);
//使用MimeUtility.encodeWord()来解决附件名称的中文问题
messageHelper.addAttachment(MimeUtility.encodeWord(file.getName()), file);
}
}
javaMailSender.send(mimeMessage);
mailBox.setSendState(MailBox.STATE_FINISH);
mailBox.setSendTime(DateUtils.getCurrentDateTimeStr());
mailBoxDao.save(mailBox);
}catch(Exception e){
logger.error("邮件发送失败");
}
}
/**
* 组装收件地址
* @Methods Name getAddressArray
* @Create In 2014年11月10日 By lee
* @param addressStr
* @return
* @throws AddressException
*/
private InternetAddress[] getAddressArray(String addressStr) throws AddressException{
String[] abcc = addressStr.split(";");
InternetAddress[] adds = new InternetAddress[abcc.length];
for (int i = 0; i < abcc.length; i++) {
adds[i] = new InternetAddress(abcc[i]);
}
return adds;
}
两个相关实体类
public class MailBox extends IdEntity {
public static final int STATE_READY = 0; //待发送
public static final int STATE_FINISH = 1; //已发送
private String title; //邮件标题
private String content; // 邮件内容
private Integer sendState; // 发送状态 0,待发 1,已发送
private String sendTime; // 发送时间
private String sendNums; // 发送次数
private String touser; // 收件人
private String cc; // 抄送人
private String bcc; // 密送人
private String filePath; // 文件路径
public class MailTemplate extends IdEntity {
public static final int USED = 1; //在用
public static final int UNUSED = 0; //未用
private String code; //关键字
private String descn; //描述
private String title; //模板标题
private String content; //模板内容