我一直在尝试使用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) {}
}
我错过了什么导致此问题出现?
答案 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,这会给出你得到的错误。