Статьи

Как создавать HTML письма в Java с помощью Spring и Velocity

В этом посте я расскажу, как вы можете форматировать и отправлять автоматические электронные письма с помощью Spring и Velocity. Spring предлагает только возможность создавать простые текстовые электронные письма, что хорошо для простых случаев, но в типичном корпоративном приложении вы не захотите делать это по ряду причин:

  • создание содержимого электронной почты на основе HTML в коде Java утомительно и подвержено ошибкам
  • нет четкого разделения между логикой отображения и бизнес-логикой
  • изменение структуры отображения электронной почты требует написания кода Java, перекомпиляции, повторного развертывания и т. д.

Обычно подход к решению этих проблем заключается в использовании библиотеки шаблонов, такой как FreeMarker или Velocity, для определения структуры отображения содержимого электронной почты. Для Podcastpedia я выбрал Velocity, бесплатный движок шаблонов на основе Java с открытым исходным кодом от Apache. В конце моей единственной задачей кодирования будет создание данных, которые должны быть отображены в шаблоне электронной почты, и отправка электронного письма.

Я буду основывать демонстрацию на реальном сценарии от Podcastpedia.org

сценарий

На странице Podcastpedia.org « Подкаст» мы рекомендуем нашим посетителям и производителям подкастов отправлять свои подкасты для включения в наш каталог подкастов. Как только подкаст будет отправлен, будет сгенерировано автоматическое электронное письмо, чтобы уведомить меня (adrianmatei [AT] gmail DOT com) и персонал Podcastpedia (свяжитесь с [AT] podcastpedia DOT org) об этом.

Посмотрим теперь, как Spring и Velocity играют вместе:

1. Предпосылки

1.1. Настройка весны

«Spring Framework предоставляет полезную служебную библиотеку для отправки электронной почты, которая защищает пользователя от особенностей базовой почтовой системы и отвечает за низкоуровневую обработку ресурсов от имени клиента». [1]

1.1.1. Библиотечные зависимости

Следующие дополнительные файлы jar должны находиться в пути к классу вашего приложения, чтобы иметь возможность использовать библиотеку электронной почты Spring Framework.

  • Библиотека JavaMail mail.jar
  • Библиотека JAF activation.jar

Я загружаю эти зависимости с Maven, так что вот фрагмент конфигурации из pom.xml :

Spring mail зависимости

01
02
03
04
05
06
07
08
09
10
11
12
<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>jaf</groupId>
    <artifactId>activation</artifactId>
    <version>1.0.2</version>
    <scope>provided</scope>
</dependency>

1.2. Настройка скорости

Чтобы использовать Velocity для создания шаблонов электронной почты, в первую очередь вам необходимо иметь библиотеки Velocity, доступные на вашем пути к классам.

С Maven у вас есть следующие зависимости в файле pom.xml:

Скоростные зависимости в Maven

01
02
03
04
05
06
07
08
09
10
11
<!-- velocity -->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-tools</artifactId>
    <version>2.0</version>
</dependency>

2. Сервис уведомлений по электронной почте

Я определил интерфейс EmailNotificationService для уведомления по электронной почте после успешной отправки подкаста. У него есть только одна операция, а именно, чтобы уведомить персонал Podcastpedia о предлагаемом подкасте.

Код ниже представляет EmailNotificationServiceImpl , который является реализацией интерфейса, упомянутого выше:

Java-код для отправки уведомления по электронной почте

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package org.podcastpedia.web.suggestpodcast;
  
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
  
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
  
import org.apache.velocity.app.VelocityEngine;
import org.podcastpedia.common.util.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.ui.velocity.VelocityEngineUtils;
  
public class EmailNotificationServiceImpl implements EmailNotificationService {
     
    @Autowired
    private ConfigService configService;   
    private JavaMailSender mailSender;
    private VelocityEngine velocityEngine;
     
    public void sendSuggestPodcastNotification(final SuggestedPodcast suggestedPodcast) {
          MimeMessagePreparator preparator = new MimeMessagePreparator() {
                @SuppressWarnings({ "rawtypes", "unchecked" })
                public void prepare(MimeMessage mimeMessage) throws Exception {
                     MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
                     message.setTo(configService.getValue("EMAIL_TO_SUGGEST_PODCAST"));
                     message.setBcc("[email protected]");
                     message.setFrom(new InternetAddress(suggestedPodcast.getEmail()) );
                     message.setSubject("New suggested podcast");
                     message.setSentDate(new Date());
                     Map model = new HashMap();                
                     model.put("newMessage", suggestedPodcast);
                      
                     String text = VelocityEngineUtils.mergeTemplateIntoString(
                        velocityEngine, "velocity/suggestPodcastNotificationMessage.vm", "UTF-8", model);
                     message.setText(text, true);
                  }
               };
               mailSender.send(preparator);           
    }
     
//getters and setters omitted for brevity
     
}

Давайте теперь немного пройдемся по коду:

2.1. JavaMailSender и MimeMessagePreparator

Пакет org.springframework.mail является пакетом корневого уровня для поддержки электронной почты Spring Framework. Центральным интерфейсом для отправки электронной почты является интерфейс MailSender , но мы используем интерфейс org.springframework.mail.javamail.JavaMailSender (строки 22, 42), который добавляет специальные функции JavaMail, такие как поддержка сообщений MIME, в интерфейс MailSender (из которого это наследует). JavaMailSender также предоставляет интерфейс обратного вызова для подготовки сообщений JavaMail MIME, который называется org.springframework.mail.javamail.MimeMessagePreparator (lines 26-42)
org.springframework.mail.javamail.MimeMessagePreparator (lines 26-42)
,

2.2. MimeMessageHelper

Другой полезный класс при работе с сообщениями JavaMail — это класс org.springframework.mail.javamail.MimeMessageHelper , который защищает вас от необходимости использовать подробный JavaMail API. Как вы можете видеть, используя MimeMessageHelper , довольно просто создать MimeMessage:

Использование MimeMessageHelper

1
2
3
4
5
6
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo(configService.getValue("EMAIL_TO_SUGGEST_PODCAST"));
message.setBcc("[email protected]");
message.setFrom(new InternetAddress(suggestedPodcast.getEmail()) );
message.setSubject("New suggested podcast");
message.setSentDate(new Date());

2,3. VelocityEngine

Следующее, что нужно отметить, это то, как создается текст письма:

Создать текст письма с шаблоном Velocity

1
2
3
4
5
Map model = new HashMap();              
model.put("newPodcast", suggestedPodcast);                  
String text = VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine, "velocity/suggestPodcastNotificationMessage.vm", "UTF-8", model);
message.setText(text, true);
  • метод VelocityEngineUtils.mergeTemplateIntoString объединяет указанный шаблон ( suggestPodcastNotificationMessage.vm находящийся в папке suggestPodcastNotificationMessage.vm из пути к классам) с заданной моделью (модель — «newPodcast»), которая представляет собой карту с именами моделей в качестве ключей и объектами моделей в качестве значений.
  • вам также нужно указать скорость двигателя, с которым вы работаете
  • и, наконец, результат возвращается в виде строки

2.3.1. Создать шаблон скорости

Вы можете увидеть ниже шаблон Velocity, который используется в этом примере. Обратите внимание, что он основан на HTML, и поскольку он представляет собой простой текст, его можно создать с помощью вашего любимого HTML или текстового редактора.

Шаблон скорости

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<html>
    <body>
        <h3>Hi Adrian, you have a new suggested podcast!</h3>
        <p>
            From - ${newMessage.name} / ${newMessage.email}
        </p>
        <h3>
            Podcast metadataline
        </h3>
        <p>
            ${newMessage.metadataLine}
        </p>
        <h3>
            With the message
        </h3>
        <p>
            ${newMessage.message}
        </p>
    </body>
 
</html>

2,4. Конфигурация бобов

Посмотрим, как все настроено в контексте приложения:

Настройка почтовой службы

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<!-- ********************************* email service configuration ******************************* -->
<bean id="smtpSession" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/mail/Session"/>
</bean>         
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="session" ref="smtpSession" />
</bean>   
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
  <property name="velocityProperties">
     <value>
      resource.loader=class
      class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
     </value>
  </property>
</bean>  
<bean id="emailNotificationServiceSuggestPodcast" class="org.podcastpedia.web.suggestpodcast.EmailNotificationServiceImpl">
  <property name="mailSender" ref="mailSender"/>
  <property name="velocityEngine" ref="velocityEngine"/>
</bean>
  • JavaMailSender имеет ссылку JNDI на сеанс SMTP. Общий пример настройки сеанса электронной почты с учетной записью Google можно найти в файле Jetty9-gmail-account.xml.
  • VelocityEngineFactoryBean — это фабрика, которая настраивает VelocityEngine и предоставляет его в качестве ссылки на компонент.
  • ClasspathResourceLoader — это простой загрузчик, который загружает шаблоны из classpath

Резюме

В этом примере вы узнали, как создавать HTML-письма в Java с помощью Spring и Velocity. Все, что вам нужно, это библиотеки mail, spring и speed, составьте шаблон вашей электронной почты и используйте эти простые классы Spring, чтобы добавлять метаданные к письму и отправлять его.

Ресурсы

Исходный код — репозитории GitHub

Web

  1. Интеграция Spring Email
  2. Apache Velocity Project
Ссылка: Как создавать HTML-письма в Java с помощью Spring и Velocity от нашего партнера по JCG Адриана Матеи в блоге Codingpedia.org .