基于Freemarker模板技术的邮件发送模块设计

1.项目背景 设计一个通用的邮件发送模块,为上层应用提供服务,对上层屏蔽掉发送邮件的细节,上层只需要简单的调用即可,要求可以实时发送但又不能影响效率,对发送失败的邮件系统可以记录下来,以便后期重发2.需求分析 关键点有 2.1邮件内容的存放 a)直接把邮件内容写死在代码里,然后拼接成一个很长的字符串,缺点也很明显,要改邮件的内容必修修改代码,重新编译打包 b)邮件内容与代码相分离.将邮件的内容文件化,java代码中只是引用模板的位置,然后解析模块中的内容输出,,这种方案有着更高的可维护性,扩展起来也更方便 2.2发送邮件的效率 发邮件是一件很耗费性能的操作,如果系统中会频繁用到邮件发送,邮件发送不要影响正常的业务操作 2.3自动记录错误和重发 邮件发送失败时,出错的邮件要保存起来,以便日后重发3.关键技术点 3.1.email发送可以通过javamail api实现 3.2邮件内容模板采用的是freemarker技术来实现 3.3异步发送邮件,采用的是java的多线程机制4.设计细节

4.1整体类图

4.2类描述

EmailServer:邮件服务器,用来进行邮件服务器的配置和实际的邮件发送,这里调用底层的javamail实现,核心方法

send(EmailInfo emailInfo)这个是个邮件发送的模板方法

EmailSendListener:邮件发送器监听程序,一个observer模式的实现,当有邮件要发送时触发,可以为邮件服务器配置一个或多个监听程序,定义了三个核心接口方法

before(EmailContext emailContext)邮件发送前做的操作

after(EmailContext emailContext)邮件发送结束后做的操作

afterThrowable(EmailContext emailContext)邮件发送出现异常时做的处理

EmailTemplateService:邮件的内容采用了模板技术来实现, 定义一个统一的顶层接口getText,对于不同的模板技术实现Freemarker或Velocity分别实现该方法

EmailSendFacade:邮件发送模块对外暴露的外部接口,用来封装各个底层实现细节

EmailContext:邮件监听器用到的邮件发送上线文信息,主要有EmailInfo邮件基本信息和Throwable两个字段

4.3系统时序图

4.4项目整体目录结构

4.5核心类源码解读

package com.crazycoder2010.email;import java.util.ArrayList;import java.util.List;import java.util.Properties;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import javax.mail.Authenticator;import javax.mail.BodyPart;import javax.mail.Message;import javax.mail.MessagingException;import javax.mail.Multipart;import javax.mail.PasswordAuthentication;import javax.mail.Session;import javax.mail.Transport;import javax.mail.internet.AddressException;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;/** * 郵件服務器 * * @author Kevin * */public class EmailServer {private static final int POOL_SIZE = 5;private Session session;private ExecutorService theadPool;/** * 郵件監聽器 */private List<EmailSendListener> emailSendListeners = new ArrayList<EmailSendListener>();public void init() {final Properties properties = SysConfig.getConfiguration();this.theadPool = Executors.newFixedThreadPool(POOL_SIZE);this.session = Session.getDefaultInstance(properties,new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(properties.getProperty("mail.smtp.username"), properties.getProperty("mail.smtp.password"));}});this.session.setDebug(true);//生产环境把其设置为false}/** * 發送單條email * * @param emailInfo */public void send(final EmailInfo emailInfo) {this.theadPool.execute(new Runnable() {public void run() {EmailContext emailContext = new EmailContext();emailContext.setEmailInfo(emailInfo);doBefore(emailContext);try {Message msg = buildEmailMessage(emailInfo);Transport.send(msg);doAfter(emailContext);} catch (Exception e) {emailContext.setThrowable(e);doAfterThrowable(emailContext);}}});}private Message buildEmailMessage(EmailInfo emailInfo)throws AddressException, MessagingException {MimeMessage message = new MimeMessage(this.session);message.setFrom(convertString2InternetAddress(emailInfo.getFrom()));message.setRecipients(Message.RecipientType.TO,converStrings2InternetAddresses(emailInfo.getTo()));message.setRecipients(Message.RecipientType.CC,converStrings2InternetAddresses(emailInfo.getCc()));Multipart multipart = new MimeMultipart();BodyPart messageBodyPart = new MimeBodyPart();messageBodyPart.setContent(emailInfo.getContent(), "text/html;charset=UTF-8");multipart.addBodyPart(messageBodyPart);message.setContent(multipart);message.setSubject(emailInfo.getTitle());message.saveChanges();return message;}private InternetAddress convertString2InternetAddress(String address)throws AddressException {return new InternetAddress(address);}private InternetAddress[] converStrings2InternetAddresses(String[] addresses)throws AddressException {final int len = addresses.length;InternetAddress[] internetAddresses = new InternetAddress[len];for (int i = 0; i < len; i++) {internetAddresses[i] = convertString2InternetAddress(addresses[i]);}return internetAddresses;}public void addEmailListener(EmailSendListener emailSendListener) {this.emailSendListeners.add(emailSendListener);}/** * 發送多條email * * @param emailInfos */public void send(List<EmailInfo> emailInfos) {for (EmailInfo emailInfo : emailInfos) {send(emailInfo);}}private void doBefore(EmailContext emailContext) {for (EmailSendListener emailSendListener : this.emailSendListeners) {emailSendListener.before(emailContext);}}private void doAfter(EmailContext emailContext) {for (EmailSendListener emailSendListener : this.emailSendListeners) {emailSendListener.after(emailContext);}}private void doAfterThrowable(EmailContext emailContext) {for (EmailSendListener emailSendListener : this.emailSendListeners) {emailSendListener.afterThrowable(emailContext);}}}为何是一个人?也有善意的提醒:

基于Freemarker模板技术的邮件发送模块设计

相关文章:

你感兴趣的文章:

标签云: