您的位置:首页 > 其它

在web项目中使用线程池发送邮件实例

2013-05-22 13:25 537 查看


在普通的web应用中,发送邮件应该只能算小任务,而使用jms来发送邮件有点杀鸡用牛刀的味道,那么如果能建立一个线程池来管理这些小线程并重复使用他们,应该来说是一个简单有效的方案,我们可以使用concurrent包中的Executors来建立线程池,Executors是一个工厂,也是一个工具类,我把它的api的介绍简单的翻译了一下(如果翻译有误请大家不要吝啬手中的砖头)

/**
* 由spring管理的线程池类,返回的ExecutorService就是给我们来执行线程的
*如果不交给spring管理也是可以的,可以使用单例模式来实现同样功能,但是poolSize   *要hardcode了
* @author 张荣华(ahuaxuan)
* @version $Id$
*/
public class EasyMailExecutorPool implements InitializingBean {

//线程池大小,spring配置文件中配置
private int poolSize;
private ExecutorService service;

public ExecutorService getService() {
return service;
}

public int getPoolSize() {
return poolSize;
}

public void setPoolSize(int poolSize) {
this.poolSize = poolSize;
}

/**
* 在 bean 被初始化成功之后初始化线程池大小
*/
public void afterPropertiesSet() throws Exception {
service = Executors.newFixedThreadPool(poolSize);
}
}


这样我们就初始化了线程池的大小,接下来就是如何使用这个线程池中的线程了,我们看看MailService是如何来使用线程池中的线程的,这个类中的代码我已经作了详细的解释 
代码

/**
* 用来发送 mail 的 service, 其中有一个内部类专门用来供线程使用
* @author 张荣华(ahuaxuan)
* @since 2007-7-11
* @version $Id$
*/
public class EasyMailServieImpl implements EasyMailService{
private static transient Log logger = LogFactory.getLog(EasyMailServieImpl.class);

//注入MailSender
private JavaMailSender javaMailSender;

//注入线程池
private EasyMailExecutorPool easyMailExecutorPool;

//设置发件人
private String from;

public void setEasyMailExecutorPool(EasyMailExecutorPool easyMailExecutorPool) {
this.easyMailExecutorPool = easyMailExecutorPool;
}

public void setJavaMailSender(JavaMailSender javaMailSender) {
this.javaMailSender = javaMailSender;
}

public void setFrom(String from) {
this.from = from;
}

/**
* 简单的邮件发送接口,感兴趣的同学可以在这个基础上继续添加
* @param to
* @param subject
* @param text
*/
public void sendMessage(EmailEntity email){
if (null == email) {
if (logger.isDebugEnabled()) {
logger.debug("something you need to tell here");
}
return;
}
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();

simpleMailMessage.setTo(email.getTo());
simpleMailMessage.setSubject(email.getSubject());
simpleMailMessage.setText(email.getText());
simpleMailMessage.setFrom(from);

easyMailExecutorPool.getService().execute(new MailRunner(simpleMailMessage));
}

/**
* 发送复杂格式邮件的接口,可以添加附件,图片,等等,但是需要修改这个方法,
* 如何做到添加附件和图片论坛上有例子了,需要的同学搜一下,
* 事实上这里的text参数最好是来自于模板,用模板生成html页面,然后交给javamail去发送,
* 如何使用模板来生成html见 {@link http://www.iteye.com/topic/71430 }
*
* @param to
* @param subject
* @param text
* @throws MessagingException
*/
public void sendMimeMessage(EmailEntity email) throws MessagingException {
if (null == email) {
if (logger.isDebugEnabled()) {
logger.debug("something you need to tell here");
}
return;
}
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);

helper.setTo(email.getTo());
helper.setFrom(from);
helper.setSubject(email.getSubject());

this.addAttachmentOrImg(helper, email.getAttachment(), true);
this.addAttachmentOrImg(helper, email.getImg(), false);

//这里的text是html格式的, 可以使用模板引擎来生成html模板, velocity或者freemarker都可以做到
helper.setText(email.getText(),true);

easyMailExecutorPool.getService().execute(new MailRunner(message));
}

/**
* 添加附件或者是图片
* @param helper
* @param map
* @param isAttachment
* @throws MessagingException
*/
private void addAttachmentOrImg(MimeMessageHelper helper, Map map, boolean isAttachment) throws MessagingException {
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(value)) {
FileSystemResource file = new FileSystemResource(new File(value));
if (!file.exists()) continue;
if (isAttachment) {
helper.addAttachment(key, file);
} else {
helper.addInline(key, file);
}
}
}
}

/**
* 用来发送邮件的 Runnable, 该类是一个内部类,之所以使用内部类,而没有使用嵌套类(静态内部类),
* 是因为内部类可以之间得到 service 的 javaMailSender
* 每次发送邮件都会从线程池中取一个线程, 然后进行发邮件操作
* @author ahuaxuan
*/
private class MailRunner implements Runnable {
SimpleMailMessage simpleMailMessage;
MimeMessage mimeMessage;

/**
* 构造简单文本邮件
* @param simpleMailMessage
*/
public MailRunner(SimpleMailMessage simpleMailMessage) {
if (mimeMessage == null) {
this.simpleMailMessage = simpleMailMessage;
}
}

/**
* 构造复杂邮件,可以添加附近,图片,等等
* @param mimeMessage
*/
public MailRunner(MimeMessage mimeMessage) {
if (simpleMailMessage == null) {
this.mimeMessage = mimeMessage;
}
}

/**
* 该方法将在线程池中的线程中执行
*/
public void run() {
try {
if (simpleMailMessage != null) {
javaMailSender.send(this.simpleMailMessage);
} else if (mimeMessage != null) {
javaMailSender.send(this.mimeMessage);
}

} catch (Exception e) {
if (logger.isDebugEnabled()) {
logger.debug("logger something here", e);
}
}
}
}
}


MailService中的EmailEntity是对邮件的抽象(我只使用了失血模型,事实上我们也可以让这个EmailEntity来实现Runnable接口,这样Service中的内部类就可以去掉了,同时service中的大部分代码就要搬到EmailEntity及其父类里了,大家更倾向于怎么做呢?),代码如下: 
代码

/** 

 * 该类是对邮件的抽象,邮件有哪些属性,这个类就有哪些属性 显然这个只是一个例子, 

 * 这个例子中附带mimemessage发送所需的附件或者图片(如果有的话) 

 * 需要使用的同学自己扩展 

 *  

 * @author 张荣华(ahuaxuan) 

* @version $Id$ 

 */  
public class EmailEntity {  

  

  String to;  

  

  String subject;  

  

  String text;  

  

  //邮件附件  
  Map  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  邮件 线程池