使用模板语言(Velocity)定义、发送邮件
使用模板语言(Velocity)定义、发送邮件
使用模板语言(Velocity)定义、发送邮件
\
发送邮件时,比如激活邮件、订单邮件等等往往都需要动态数据的填入,比如客户名、订单号,或者密码。类似于web设计:
邮件的模板:是一个可能具有html格式或类似的模板,是View的角色;
邮件的数据:是Model的角色,填入模板,形成最后的邮件内容。
一个与用户交互加多的系统,邮件的种类是“啥都有的”:各种提醒,各种状态告知,。。。
所以基于配置做法相对比较能够统一模式以及省时省力。
我的做法是使用Velocity定义邮件,通过提供良好设计的API,和配置规定实现。最后使用代码大致如下:
/**
* 激活服务加密解密功能支持
*/
private Encryptor encryptor;
/**
* 激活邮件功能支持
*/
private VelocityMailSupport velocityMailSupport;
public void xxxx(User user) {
Map model = new HashMap();
model.put(“user”, user);
model.put(“token”, encryptor.encode(user));
** velocityMailSupport.sendMime(user.getRealname(), user.getEmail(),
model);
** }
velocityMailSupport是一个包含了模板和邮件标题信息的JavaMailSender实现类,sendMime是提供的简易方法,发送具有html样式的代码。\
同时,velocityMailSupport本身使用的内嵌的JavaMailSender是自己实现的PooledMailSender(异步邮件发送)。经过实战使用效果良好。
\
\
附件是核心代码(不是上面的示例代码)和配置:
VelocityMailSupport.java –
提供给程序使用,通过Spring配置注入到被需要的类中,利用本类可方便发送由Velocity模板生成的邮件内容。客户程序可以组合或继承本类,使具有发送邮件功能。
PoolMailSender.java –对Springframework
MailSender和JavaMailSender的装饰,
实现装饰器模式。PooledMailSender将要发送邮件进行排队,按FIFO方式发送得到的邮件消息。
applicationContext-mail-template.xml –
配置所有的邮件模板的VelocityMailSupport实例,比如激活,找回密码等具体velocity模板和邮件subject
applicationContext-mail.xml –
基础配置applicationContext-mail-template.xml依赖于它
mail_template.properties –
配置模板位置和subject文本
VelocityMailSupport.java
public class VelocityMailSupport implements MailSender,
JavaMailSender{
//
—————————————————————————–
private Properties mailHeaders = new Properties();
/**
*
邮件发送者,包括发送者姓名和地址,用于设置在邮件的from栏目中
*/
private String from;
/**
* 邮件主题
*/
private String subject;
/**
* 邮件内容模板地址/名称
*/
private String templateName;
/**
* velocity引擎
*/
private VelocityEngine velocityEngine;
/**
* mail发送器
*/
private MailSender mailSender;
//
—————————————————————————–
/**
* 日志
*/
protected static final Log log = LogFactory
.getLog(VelocityMailSupport.class);
//
—————————————————————————–
/**
* 使用提供的数据,套入velocity模板,生成最后文本信息。
*
* 大部分情况下,这个信息应该就是邮件的内容。
*/
public String renderText(Map model) throws VelocityException {
return
VelocityEngineUtils.mergeTemplateIntoString(getVelocityEngine(),
getTemplateName(), model);
}
//
—————————————————————————–
//省略getter和setter
/**
*
* 发送Mime邮件简易方法。
*
*
以Mime的方式发送邮件,这主要是为能够支持发送html或类似功能(非简单文本)的邮件
*
* param nameOfTo 邮件接收收人姓名 或 昵称
* param emailOfTo 邮件接收人邮件地址
* param model 邮件velocity模板中变量的值
* throws MailException
*/
public void sendMime(String nameOfTo, String emailOfTo, Map
model) throws MailException {
sendMime(nameOfTo + “<” + emailOfTo + “>”,
model);
}
/**
* 发送Mime邮件简易方法。
*
*
以Mime的方式发送邮件,这主要是为能够支持发送html或类似功能(非简单文本)的邮件
*
* param to 邮件接收人邮件地址以及可能的收件人姓名或昵称
* param model 邮件velocity模板中变量的值
*/
public void sendMime(String to, Map model) throws MailException
{
sendMime(mergeSimpleMessage(to, model));
}
/**
* 发送Mime邮件简易方法。
*
*
以Mime的方式发送SimpleMailMessage,这主要是为能够支持发送html或类似功能(非简单文本)的邮件
*
* param simpleMessage
* throws MailException
*/
public void sendMime(SimpleMailMessage simpleMessage) throws
MailException {
send(toMimeMessage(simpleMessage));
}
//———————————————————————————-
public SimpleMailMessage mergeSimpleMessage(String to, Map
model) {
//render text of mail from velocity template with the
data
String text = null;
try {
text = renderText(model);
} catch (VelocityException e) {
log.error(e);
e.printStackTrace();
}
//mail message setting
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject(getSubject());
message.setFrom(getFrom());
message.setTo(to);
message.setText(text);
return message;
}
/**
*
* param simpleMailMessage
* return
*/
public MimeMessage toMimeMessage(SimpleMailMessage
simpleMailMessage) {
MimeMessage mimeMessage =
createMimeMessage();
MimeMailMessage mmm = new
MimeMailMessage(mimeMessage);
simpleMailMessage.copyTo(mmm);
return mmm.getMimeMessage();
}
//———————————————————————————-
// MailSender接口实现 - 代理到配置的实际mailSender
–仅发布一个代理方法,其它省略
public void send(SimpleMailMessage simpleMessage) throws
MailException {
getMailSender().send(simpleMessage);
}
//———————————————————————————-
protected void injectMailHeader(MimeMessage mm){
for (Object name : mailHeaders.keySet()) {
try {
mm.setHeader((String)name,
mailHeaders.getProperty((String)name));
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
}//end
PooledMailSender.java
public class PooledMailSender implements MailSender, JavaMailSender,
Runnable {
//
————————————————————————-
/**
*
实际发送邮件的邮件发送器,可以是MailSender,或JavaMailSender
*/
private MailSender mailSender;
//
————————————————————————-
/**
* 日志
*/
protected static final Log log = LogFactory
.getLog(PooledMailSender.class);
/**
* 邮件排队点号、发送线程,
*/
private Thread thread;
/**
* 邮件排队队列
*/
private Queue
queue = new LinkedBlockingQueue
();
/**
* 锁,仅此而已
*
* see #run()
* see #add(Object)
*/
private Object mutex = new Object();
//
————————————————————————-
/**
* 构造本类对象,同时启动侦听邮件的到达。
*
*
如果要阻止侦听和发送,应该调用close方法,在Spring的Context中”最好”配置destroy-method=”close”,不过这不是必须的。
*
*/
public PooledMailSender() {
thread = new Thread(this);
thread.setDaemon(true);
thread.start();
}
//
————————————————————————-
/**
* 邮件发送循环,它被作为thread runnable的run实现。
*
* see #add(Object)
*
*/
public void run() {
while (!isClose()) {
if (!isEmpty()) {
Object object = poll();
try {
//执行实际发送
doSend(object);
} catch (Exception ex) {
log.error(ex);
ex.printStackTrace();
}
}
//等~直到add方法的通知!
synchronized (mutex) {
try {
mutex.wait();
} catch (InterruptedException e)
{
}
}
}
}
//
————————————————————————-
public MailSender getMailSender() {
return mailSender;
}
/**
* 设置实际的邮件发送器
*
* param mailSender
*/
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
//
————————————————————————-
/**
* 关闭PooledMailSender!
*
* 关闭的PooledMailSender不可再接收和发送邮件
*/
public void close() {
queue.clear();
queue = null;
}
/**
* 已经关闭?
*
* 关闭的PooledMailSender不可再接收和发送邮件
*
* return
*/
public boolean isClose() {
return queue == null;
}
//
————————————————————————-
// 邮件排队机操作方法代理
protected boolean isEmpty() {
return queue != null && queue.isEmpty();
}
/**
* 邮件加入排队机
*
* param obj
* see #run()
*/
protected void add(Object obj) {
Assert.notNull(queue);
queue.add(obj);
//我来了!
synchronized (mutex) {
mutex.notify();
}
}
protected Object poll() {
Assert.notNull(queue);
return queue.poll();
}
protected Object peek() {
Assert.notNull(queue);
return queue.peek();
}
//
————————————————————————-
// MailSender接口实现-将邮件放入排队机
public void send(SimpleMailMessage simpleMessage) throws
MailException {
add(simpleMessage);
}
public void send(SimpleMailMessage[] simpleMessages) throws
MailException {
for (SimpleMailMessage message : simpleMessages) {
add(message);
}
}
//
————————————————————————-
// JavaMailSender接口实现-将邮件放入排队机
public void send(MimeMessage mimeMessage) throws MailException
{
add(mimeMessage);
}
public void send(MimeMessage[] mimeMessages) throws
MailException {
for (MimeMessage message : mimeMessages) {
add(message);
}
}
public void send(MimeMessagePreparator mimeMessagePreparator)
throws MailException {
add(mimeMessagePreparator);
}
public void send(MimeMessagePreparator[]
mimeMessagePreparators)
throws MailException {
for (MimeMessagePreparator preparator :
mimeMessagePreparators) {
add(preparator);
}
}
public MimeMessage createMimeMessage() {
return ((JavaMailSender)
mailSender).createMimeMessage();
}
public MimeMessage createMimeMessage(InputStream
contentStream)
throws MailException {
return ((JavaMailSender)
mailSender).createMimeMessage(contentStream);
}
//
————————————————————————-
// 实际发送代理方法
public void doSend(Object object) {
if (object instanceof SimpleMailMessage) {
doSend((SimpleMailMessage) object);
} else if (object instanceof MimeMessage) {
doSend((MimeMessage) object);
} else if (object instanceof MimeMessagePreparator) {
doSend((MimeMessagePreparator) object);
}
}
public void doSend(SimpleMailMessage simpleMessage) throws
MailException {
mailSender.send(simpleMessage);
}
public void doSend(MimeMessage mimeMessage) throws
MailException {
((JavaMailSender) mailSender).send(mimeMessage);
}
public void doSend(MimeMessagePreparator
mimeMessagePreparator)
throws MailException {
((JavaMailSender)
mailSender).send(mimeMessagePreparator);
}
}
\
\
\
\
在velocity.properties中设置输入输出编码,例如
input.encoding=GBK
output.encoding=GBK
default.contentType=text/html; charset=GBK
\
\
\
\
\
\