文章目录
  1. 1. 使用模板语言(Velocity)定义、发送邮件

使用模板语言(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<String, Object> model) throws MailException {

          sendMime(nameOfTo + “<” + emailOfTo + “>”, model);

     }

    

     /**

     *  发送Mime邮件简易方法。

     *

     * 以Mime的方式发送邮件,这主要是为能够支持发送html或类似功能(非简单文本)的邮件

     *

     * @param to 邮件接收人邮件地址以及可能的收件人姓名或昵称

     * @param model 邮件velocity模板中变量的值

     */

     public void sendMime(String to, Map<String, Object> 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<String, Object> 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

文章目录
  1. 1. 使用模板语言(Velocity)定义、发送邮件