企业项目中经常使用到邮件发送,尤其在流程审批伴随大量的触发邮件,为提供效率邮件自然设置为异步发送,但单纯多线程异步又造成了先后混乱的现象。所以做了个简单的单线程异步发送队列来处理。
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; //模板内容
相关推荐
而Celery则是一个分布式任务队列,它使得开发者能够轻松地处理异步任务,提高应用的响应速度和用户体验。本篇文章将深入探讨如何结合Django与Celery实现异步发送邮件的功能。 首先,我们需要理解异步处理的重要性。...
标题中的“使用phpfpm作为一个简单的内置异步队列”是指利用PHP的FastCGI Process Manager(php-fpm)来实现一种轻量级的异步处理机制,这通常是为了处理那些耗时较长或者非阻塞的任务,比如发送邮件、文件上传、...
这会启动一个异步操作,允许程序在等待邮件发送时执行其他任务。 5. 处理结果:异步操作完成后,程序可以通过回调函数或`async/await`关键字捕获结果或异常。 示例代码(C#): ```csharp using System.Net; ...
106、使用doctrine队列异步发送邮件1
2. **异步处理**:通过集成ActiveMQ,可以创建一个消息生产者,将发送邮件的任务作为一个消息放入队列,由后台消费者处理。这样,主流程不会被邮件发送阻塞,提高了系统的响应速度。 3. **消费者端**:在消费者端,...
ActiveMQ作为一个开源的消息中间件,被广泛用于实现消息队列和发布/订阅模式,它允许应用将非实时任务如邮件发送等操作放到后台处理,从而提升系统的响应速度。在本项目中,ActiveMQ与SpringMVC框架结合,实现了邮件...
接着,这个消息被发送到一个JMS队列或者主题,此时邮件发送的任务就已经完成了,而实际的邮件发送操作则由消息中间件异步处理。 消息中间件会接收到这个邮件消息,并根据配置的邮件服务器信息,利用JavaMail API...
在本项目中,"SpringBoot整合ActiveMQ(消息中间件)实现邮件发送功能"是一个典型的企业级应用示例,它展示了如何将SpringBoot框架与Apache ActiveMQ集成,以实现基于消息队列的邮件发送服务。下面我们将详细探讨这个...
这个源码应该包含了一个实现了MailSender接口的类,可能使用了线程池进行异步发送,以及如何构建邮件模板和处理邮件列表的逻辑。通过阅读和分析源码,你可以学习到如何在Spring中实现批量邮件发送,并从中获取灵感...
然而,对于需要即时响应或者非阻塞操作的任务,如注册邮件发送、短信通知等,我们可以利用Swoole扩展来实现异步处理,从而提高系统效率。 Swoole是一个高性能的PHP扩展,它提供了底层的异步多线程服务器,支持TCP、...
在本示例中,我们将深入探讨如何使用ActiveMQ实现异步邮件发送,这通常涉及到生产者(Producer)和消费者(Consumer)的角色。 1. **ActiveMQ的基本概念**: - **生产者(Producer)**:负责创建和发送消息到队列...
本文将深入探讨如何设计一个基于多线程和异步操作的邮件发送系统。 **一、多线程技术** 1. **线程概念**:线程是操作系统分配CPU时间的基本单位,一个进程可以包含多个线程,它们共享同一内存空间,但各自有独立的...
标题提到的".net 一个通用邮件发送dll"是一个可重用的组件,它封装了邮件发送的相关功能,使得开发者可以直接调用来实现邮件服务,无需深入了解底层的SMTP协议细节。 邮件发送DLL(动态链接库)通常包含以下关键...
在`messenger.yaml`配置文件中,我们有两个transports(传输队列),一个是正常的邮件发送队列,另一个是`failed`传输队列,专门用来存储发送失败的消息。`failed`传输队列配置使用了`doctrine`传输,队列名为`...
本示例将探讨如何使用ActiveMQ实现异步邮件发送,这有助于提高应用性能,因为邮件发送通常是一个耗时的操作。 首先,我们来看"edu-demo-mqproducer"这个文件,它代表生产者部分,即负责发送消息到ActiveMQ的消息...
异步手机短信和邮件发送消息中心平台构建 本文提出了一种异步手机短信和邮件发送消息中心平台(MCP)的解决方案,以满足分布式环境下企业应用对性能、安全性、稳定性的要求。该平台能够异步传递消息,将彼此独立的...
aiosmtplib则引入了异步模式,利用asyncio库的协程(coroutine)和事件循环(event loop),实现了非阻塞的邮件发送,提高了程序的并发性能。 使用aiosmtplib库,开发者可以编写如下的异步代码来发送邮件: ```...
在Python的Web开发框架Flask中,异步发送...希望这篇教程能帮助你理解和实现Python Flask应用中的异步邮件发送功能。在实践中,你可能还需要处理更多细节,如错误处理、邮件队列等,以确保邮件发送的稳定性和可靠性。
本系统可能使用了如Celery这样的库来处理耗时任务,如邮件发送、数据分析等,避免了主线程阻塞,提升了用户体验。异步任务可以被分发到多个工作节点上,实现负载均衡和任务并行化。 5. **Django框架**:Django是一...
本工程类“邮件发送”专注于提供一个高效、便捷的邮件发送解决方案,它封装了邮件发送和邮件模板功能,使得开发者能够轻松地集成到自己的项目中。 邮件发送通常基于SMTP(Simple Mail Transfer Protocol)协议进行...