Использование нескольких шаблонных решений с Spring 3.2 и Thymeleaf 2.1.3 для электронных писем

У меня проблема с определением ClassLoaderTemplateResolver для электронных писем и одним ServletContextTemplateResolver для просмотра веб-страниц. При попытке отправить электронные письма появляется следующая ошибка:

HTTP Status 500 - Request processing failed; nested exception is
org.thymeleaf.exceptions.TemplateProcessingException: Resource resolution by ServletContext with
org.thymeleaf.resourceresolver.ServletContextResourceResolver can only be performed when context
implements org.thymeleaf.context.IWebContext [current context: org.thymeleaf.context.Context]

Мой WebMvcConfig выглядит так:

private static final String VIEWS_PATH = "/WEB-INF/views/";
private static final String MAIL_PATH = "mail/";
@Bean
public ServletContextTemplateResolver templateResolver() { final ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); resolver.setPrefix(VIEWS_PATH); resolver.setSuffix(".html"); resolver.setTemplateMode("HTML5"); resolver.setCharacterEncoding("UTF-8"); resolver.setOrder(2); resolver.setCacheable(false); return resolver;
}
@Bean
public ClassLoaderTemplateResolver emailTemplateResolver() { final ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); resolver.setPrefix(MAIL_PATH); resolver.setSuffix(".html"); resolver.setTemplateMode("HTML5"); resolver.setCharacterEncoding("UTF-8"); resolver.setOrder(1); return resolver;
}
@Bean
public SpringTemplateEngine templateEngine() { final SpringTemplateEngine engine = new SpringTemplateEngine(); final Set<templateresolver> templateResolvers = new HashSet<templateresolver>(); templateResolvers.add(templateResolver()); templateResolvers.add(emailTemplateResolver()); engine.setTemplateResolvers(templateResolvers); engine.addDialect(new SpringSocialDialect()); engine.addDialect(new SpringSecurityDialect()); return engine;
}
</templateresolver></templateresolver>

И мой EmailService вот так:

@Service
public class EmailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private TemplateEngine templateEngine;
/* * Send HTML mail with inline image */
public void sendEmailToBookSeller( final ContactBookSellerForm form, final Locale locale) throws MessagingException { boolean multipart = true; boolean isHtml = true; // Prepare the evaluation context final Context ctx = new Context(locale); ctx.setVariable("message", form.getMessage()); ctx.setVariable("bookTitle", form.getBookTitle()); ctx.setVariable("email", form.getToEmail()); ctx.setVariable("logo", "logo"); ctx.setVariable("logoOnlyText", "logoOnlyText"); // Prepare message final MimeMessage mimeMessage = mailSender.createMimeMessage(); final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, multipart, "UTF-8"); message.setSubject("Regarding your book on Mimswell - " + form.getBookTitle()); message.setFrom(form.getFromEmail()); message.setTo(form.getToEmail()); // Create the HTML body using Thymeleaf final String htmlContent = templateEngine.process("email-buy-book.html", ctx); message.setText(htmlContent, isHtml); message.addInline("logo", new ClassPathResource("WEB-INF/views/mail/logo130130red.png"), "image/png"); message.addInline("logoOnlyText", new ClassPathResource("WEB-INF/views/mail/logo_only_text.png"), "image/png"); // Send mail this.mailSender.send(mimeMessage); }
}

Ошибка возникает в следующей строке:

final String htmlContent = templateEngine.process("email-buy-book.html", ctx);

Где он использует ServletContextResourceResolver вместо моего другого распознавателя. Я хочу, чтобы он использовал ClassLoaderTemplateResolver поскольку он может обрабатывать простые объекты Context вместо использования WebContext. Однако я мог бы попытаться использовать WebContext поскольку он реализует IWebContext и использует только один резольвер. Но тогда мне нужны HttpServletRequest, HttpServletResponse и ServletContext как параметры, которые кажутся беспорядочными.

Моя структура:

Любая идея, что не так в моем коде?

3 ответа

Поскольку вы (правильно) установили для ClassLoaderTemplateResolver приоритет над ServletContextTemplateResolver, Thymeleaf пытается использовать правильный порядок, но не может разрешить представление с помощью first, а затем пытается использовать последний. Я считаю, что проблема связана с параметрами префикса и суффикса, которые вы задаете в сочетании с именем вида, которое вы передаете методу templateEngine.process. Thymeleaf построит ваше имя вида, объединив суффикс + имя + суффикс, в результате получится "mail/email-buy-book.html.html". Попытайтесь передать только "электронную книгу-книгу" и посмотрите, разрешает ли она проблему.


Я отказался от этого и пошел на подход WebContext, хотя я все время нуждался в запросе, ответе и servletcontext каждый раз при отправке чего-либо. Вот как я это сделал:

1. Получите контекст сервлета:

@Autowired
ServletContext servletContext;

2. Получить запрос и ответ в качестве параметров метода sendmail:

HttpServletRequest request,
HttpServletResponse response

3. Создайте WebContext:

final WebContext ctx = new WebContext(request, response, servletContext, locale);

С этого момента он работал.


Поскольку вы используете ClassLoaderTemplateResolver, Spring использует префикс и добавляет его в WEB-INF/classes. Итак, проверить, является ли Maven (или любой другой инструмент построения, который вы используете) скопировал html файл в WEB-INF/classes/mail/email-buy-book.html. Если это не так, попробуйте скопировать его вручную и дать ему уйти. Глядя на ваш скриншот, я не вижу папку "mail" в разделе "classes", поэтому это может быть проблемой.

Кроме того, пропустите только "электронную книгу-книгу" и оставьте это расширение, как указано в @grid.

final String htmlContent = templateEngine.process("email-buy-book", ctx);

У меня есть работа с конфигурацией XML, а не с конфигурацией Java, но я не понимаю, почему это важно для вас.

licensed under cc by-sa 3.0 with attribution.