使用Spring 3.2和Thymeleaf 2.1.3的多个模板解析器来处理电子邮件

时间:2014-10-28 13:09:53

标签: spring spring-mvc thymeleaf

我在为电子邮件定义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;
}

我的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并且只使用一个解析器。但是我需要HttpServletRequestHttpServletResponseServletContext作为参数,这似乎很麻烦。

我的结构:

File structure

我的代码中有什么想法错了吗?

3 个答案:

答案 0 :(得分:1)

我放弃了这个并转而采用WebContext方法,即使我每次发送内容时都需要请求,响应和servletcontext。我就这样做了:

<强> 1。获取servlet上下文:

@Autowired
ServletContext servletContext;

<强> 2。获取请求和响应作为sendmail方法的参数:

HttpServletRequest request,
HttpServletResponse response

第3。改为创建WebContext:

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

从现在开始工作。

答案 1 :(得分:1)

由于您(正确地)将ClassLoaderTemplateResolver设置为优先于ServletContextTemplateResolver,因此Thymeleaf尝试使用正确的顺序,但无法使用前者解析视图,然后尝试后者。
我相信问题在于您设置的前缀和后缀参数与传递给templateEngine.process方法的视图名称相结合。 Thymeleaf将通过连接后缀+ viewname +后缀来构建您的视图名称,结果为&#34; mail / email-buy-book.html.html&#34;
尝试仅传递&#34; email-buy-book&#34; ,看看它是否解决了问题。

答案 2 :(得分:0)

由于您正在使用ClassLoaderTemplateResolver,因此Spring将使用该前缀并将其附加到WEB-INF / classes。因此,要检查的是Maven(或您正在使用的任何构建工具)是否将html文件复制到WEB-INF / classes / mail / email-buy-book.html。如果没有,请尝试手动复制并试一试。看看你的截图,我没有看到&#34; mail&#34; &#34;类&#34;下的文件夹所以这可能是个问题。

此外,只需通过&#34;电子邮件购买书&#34;并且在@grid提到时省略了扩展名。

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

我使用XML配置而不是Java配置,但我不明白为什么这对你来说很重要。