无法使用Thymeleaf和Spring创建Rich Email

时间:2014-04-27 13:57:42

标签: java spring spring-mvc thymeleaf

我一直在尝试使用Thymeleaf创建和发送Rich HTML电子邮件。 在经历了多次打嗝之后,我遇到了我希望的最后一期。

org.springframework.web.util.NestedServletException: 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]
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:150)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:184)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)

我有以下WebConfig.java设置:

@Bean
public ServletContextTemplateResolver templateResolver() {
    ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
    resolver.setPrefix("/WEB-INF/pages/");
    resolver.setSuffix(".html");
    resolver.setTemplateMode("HTML5");
    resolver.setCacheable(false);
    resolver.setOrder(2);
    return resolver;

}

@Bean
public ClassLoaderTemplateResolver emailTemplateResolver() {
    ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
    resolver.setPrefix("mail/");
    resolver.setTemplateMode("HTML5");
    resolver.setCharacterEncoding("UTF-8");
    resolver.setOrder(1);
    return resolver;
}

@Bean
public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    Set<ITemplateResolver> resolvers = new HashSet<>();

    resolvers.add(templateResolver());
    resolvers.add(emailTemplateResolver());

    engine.setTemplateResolvers(resolvers);
    return engine;
}

@Bean
public ViewResolver viewResolver() {
    ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
    viewResolver.setTemplateEngine(templateEngine());
    viewResolver.setOrder(1);
    viewResolver.setViewNames(new String[]{"*"});
    viewResolver.setCache(false);
    return viewResolver;
}

通过AbstractAnnotationConfigDispatcherServletInitializer中的getRootConfigClasses()在root配置中调用。

最后,我的类CustomSendMailImplementation.java包含sendMail函数,该函数可以创建和发送电子邮件。

@Override
    public void sendMail(final String mailFrom, final String mailTo, final String subject, final String mailBody, final Locale locale) {

        final Context ctx = new Context(locale);
        ctx.setVariable("name", "JamesBond");
        ctx.setVariable("subscriptionDate", new Date());
        ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music"));


        final String htmlContent = this.templateEngine.process("testmail.html", ctx);

        try {
            mailSender.send(new MimeMessagePreparator() {
                public void prepare(MimeMessage mimeMessage)
                        throws Exception {
                    MimeMessageHelper message = new MimeMessageHelper(mimeMessage,
                            true, "UTF-8");
                    message.setFrom(mailFrom);
                    message.addTo(mailTo);
                    message.setSubject(subject);
                    message.setText(htmlContent, true);
                }
            });
        } catch (MailSendException e) {}
    }

我错过了什么导致此问题出现?

2 个答案:

答案 0 :(得分:0)

您不能使用servletTemplateResolver,因为在创建电子邮件期间没有(通常)可用的servletcontext。

我不确定您是否使用第二个templateEngine进行邮件生成,但您应该为此目的创建一个,然后创建一个用于网页呈现。

还要注意你的bean配置。如果您使用方法获取templateResolver,则不使用Spring管理的版本!所以你基本上创建了两个对象。一个春天管理,另一个春天管理&#34;工厂&#34;你自己。 而是使用方法参数自动装配所需的参数,或者甚至可以更好地创建托管bean,如果你需要它们由spring管理,在解析器的情况下不需要。 (很有可能)

答案 1 :(得分:0)

我得到了这个例子。你把/ mail文件夹放在src / java / resources目录中了吗?它属于那里,而不是WEB-INF,因为ClassLoaderTemplateResolver不会查找WEB-INF目录,如果它找不到模板,那么它会将buck传递给ServletContextTemplateResolver,这会给出你得到的错误。