一个简略的异步队列邮件发送实现
一个简单的异步队列邮件发送实现
企业项目中经常使用到邮件发送,尤其在流程审批伴随大量的触发邮件,为提供效率邮件自然设置为异步发送,但单纯多线程异步又造成了先后混乱的现象。所以做了个简单的单线程异步发送队列来处理。
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; //模板内容