Thymeleaf Spring 邮件上下文错误

Thymeleaf Spring Mail context error

我正在尝试使用 thymeleaf 模板引擎配置 spring 邮件,但出现错误,我无法弄清楚为什么会发生。我已经看到了有关此问题的各种主题,但为解决该问题而提出的所有建议在我的项目中似乎都是正确的。

问题在于尝试使用 ServletContextTemplateResolver 解决的上下文。

我的配置是:

@Bean 
public TemplateResolver webTemplateResolver () { 
    final TemplateResolver templateResolver = new ServletContextTemplateResolver(); 
    templateResolver.setPrefix("/WEB-INF/views/"); 
    templateResolver.setSuffix(".html"); 
    templateResolver.setTemplateMode("HTML5"); 
    templateResolver.setOrder(2); 
    return templateResolver; 
}

@Bean 
public TemplateResolver emailTemplateResolver () { 
    TemplateResolver templateResolver = new ClassLoaderTemplateResolver(); 
    templateResolver.setPrefix("mail/"); 
    templateResolver.setSuffix(".html"); 
    templateResolver.setTemplateMode("HTML5"); 
    templateResolver.setOrder(1); 
    return templateResolver; 
} 

@Bean 
public SpringTemplateEngine templateEngine (IMessageResolver messageResolver) { 
    final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); 
    templateEngine.addTemplateResolver(webTemplateResolver()); 
    templateEngine.addTemplateResolver(emailTemplateResolver()); 
    templateEngine.addDialect(new LayoutDialect()); 
    templateEngine.addDialect(new SpringSecurityDialect()); 
    templateEngine.addMessageResolver(messageResolver); 
    return templateEngine; 
} 

密码是:

@Transactional(readOnly = true) 
public void sendContactEmail (final String recipientName, final String recipientEmail, final String imageResourceName, final byte[] imageBytes, final String imageContentType, final Locale locale) throws MessagingException 
{ 
    // Prepare the evaluation context 
    final Context ctx = new Context(locale); 
    ctx.setVariable("name", recipientName); 
    ctx.setVariable("subscriptionDate", new Date()); 
    ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music")); 
    ctx.setVariable("imageResourceName", imageResourceName); // so that we can reference it from HTML 

    // Prepare message using a Spring helper 
    final MimeMessage mimeMessage = this.mailSender.createMimeMessage(); 
    final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart 
    message.setSubject("Example HTML email with inline image"); 
    message.setFrom("thymeleaf@example.com"); 
    message.setTo(recipientEmail); 

    // Create the HTML body using Thymeleaf 
    final String htmlContent = this.templateEngine.process("contact.html", ctx);
    message.setText(htmlContent, true); // true = isHtml 

    // Add the inline image, referenced from the HTML code as "cid:${imageResourceName}" 
    final InputStreamSource imageSource = new ByteArrayResource(imageBytes); 
    message.addInline(imageResourceName, imageSource, imageContentType); 

    // Send mail 
    this.mailSender.send(mimeMessage); 
} 

最后是错误:

[THYMELEAF][http-bio-8080-exec-8] Exception processing template "contact.html": 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] 
Exception handled by GlobalExceptionHandler 
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] 
        at org.thymeleaf.resourceresolver.ServletContextResourceResolver.getResourceAsStream(ServletContextResourceResolver.java:78) 
        at org.thymeleaf.TemplateRepository.getTemplate(TemplateRepository.java:221) 
        at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1104) 
        at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060) 
        at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011) 
        at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:924) 
        at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:898) 
        at com.proeza.core.service.MailService.sendContactEmail(MailService.java:47) 
        at com.proeza.core.service.MailService$$FastClassBySpringCGLIB$$f139c878.invoke(<generated>) 
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:711) 
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
        at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:98) 
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) 
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) 
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644) 
        at com.proeza.core.service.MailService$$EnhancerBySpringCGLIB$cabd9f.sendContactEmail(<generated>) 
        at com.proeza.sgs.web.controller.RegisterController.register(RegisterController.java:69) 
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
        at java.lang.reflect.Method.invoke(Method.java:606) 
        at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215) 
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) 
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) 
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690) 
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) 
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945) 
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876) 
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) 
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863) 
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:647) 
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) 
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108) 
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) 
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) 
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:105) 
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57) 
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) 
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108) 
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) 
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) 
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) 
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) 
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) 
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) 
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) 
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) 
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041) 
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603) 
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
        at java.lang.Thread.run(Thread.java:744) 

希望有人能提供帮助。 提前致谢。

此致!

好的,调试 thymeleaf 我可以找到问题所在。 错误的是告诉引擎解析模板的方式。 这一行:

// Create the HTML body using Thymeleaf 
final String htmlContent = this.templateEngine.process("contact.html", ctx);

因为解析器是这样配置的

templateResolver.setSuffix(".html");

它正在尝试查找名为 "contant.html.html" 的模板,但由于显而易见的原因未找到它。

这样处理模板:

// Create the HTML body using Thymeleaf 
final String htmlContent = this.templateEngine.process("contact", ctx); //Note .html not present

应用程序完美运行。

奇怪的是,thymeleaf 文档中的示例有 html 后缀,但我试过了,它工作正常。

百里香版本会导致这种差异吗?

2.1.3.RELEASE 对比 2.1.4.RELEASE

问候。