【问题标题】:Spring and Thymeleaf - Cannot initialize: no template resolvers have been setSpring 和 Thymeleaf - 无法初始化:没有设置模板解析器
【发布时间】:2017-11-05 19:41:23
【问题描述】:

我目前正在开发 Spring Boot 应用程序。尝试创建电子邮件服务时出现错误。

application.properties:

spring.thymeleaf.prefix=classpath:/static/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=true

index.html 是在访问应用程序 url 时从主控制器解析的。但是电子邮件模板没有得到解析。

主控制器:

  @RequestMapping("/")
        public String home() {
            return "index";
        }

电子邮件服务:

JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        Locale locale = new Locale.Builder().setLanguage("en").setRegion("US").build();     
         // Prepare the evaluation context
        final Context ctx = new Context(locale);        
         ctx.setVariable("saveComplaints", saveComplaintEntity);

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

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


         // Send mail
         mailSender.send(mimeMessage);

“email”模板名称指的是email.html文件,该文件与index.html位于同一位置(类路径:/static/)

错误:

nested exception is org.thymeleaf.exceptions.ConfigurationException: Cannot initialize: no template resolvers have been set] with root cause:
org.thymeleaf.exceptions.ConfigurationException: Cannot initialize: no template resolvers have been set

编辑:

smtp 配置:

spring.mail.host=smtp.gmail.com
spring.mail.username= *****@gmail.com   
spring.mail.password= *****
spring.mail.port=587
spring.mail.defaultEncoding=UTF-8
spring.mail.properties.mail.smtp.starttls.enable=true

发送邮件时出错:

java.net.SocketException: Permission denied: connect; message exceptions (1) are:
Failed message 1: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
nested exception is:
java.net.SocketException: Permission denied: connect] with root cause

完整的错误跟踪:

 2017-11-06 03:48:57.827 ERROR 38292 --- [nio-9999-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
  nested exception is:
    java.net.ConnectException: Connection refused: connect. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
  nested exception is:
    java.net.ConnectException: Connection refused: connect; message exceptions (1) are:
Failed message 1: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
  nested exception is:
    java.net.ConnectException: Connection refused: connect] with root cause

java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.connect0(Native Method) ~[na:1.7.0_80]
    at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ~[na:1.7.0_80]
    at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[na:1.7.0_80]
    at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[na:1.7.0_80]
    at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[na:1.7.0_80]
    at java.net.PlainSocketImpl.connect(Unknown Source) ~[na:1.7.0_80]
    at java.net.SocksSocketImpl.connect(Unknown Source) ~[na:1.7.0_80]
    at java.net.Socket.connect(Unknown Source) ~[na:1.7.0_80]
    at java.net.Socket.connect(Unknown Source) ~[na:1.7.0_80]
    at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:331) ~[javax.mail-1.5.6.jar:1.5.6]
    at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:238) ~[javax.mail-1.5.6.jar:1.5.6]
    at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2084) ~[javax.mail-1.5.6.jar:1.5.6]
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:712) ~[javax.mail-1.5.6.jar:1.5.6]
    at javax.mail.Service.connect(Service.java:366) ~[javax.mail-1.5.6.jar:1.5.6]
    at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:501) ~[spring-context-support-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:421) ~[spring-context-support-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:345) ~[spring-context-support-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340) ~[spring-context-support-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at com.demo.email.service.EmailService.sendMail(EmailService.java:45) ~[classes/:na]
    at com.demo.email.controller.MailController.sendMail(MailController.java:32) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_80]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_80]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_80]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_80]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.7.0_80]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.7.0_80]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.20.jar:8.5.20]
    at java.lang.Thread.run(Unknown Source) [na:1.7.0_80]

解决方案:

@AutoWired 
TemplateEngine templateEngine 

创建新的 SpringTemplateEngine 对象。

@Autowired
JavaMailSenderImpl mailSender

创建新的 JavaMailSenderImpl 对象。

【问题讨论】:

    标签: java spring spring-boot thymeleaf


    【解决方案1】:

    您必须使用 autowire 使用 Spring Boot 使用 @AutoWired TemplateEngine templateEngine 创建的 autowire 而不是创建新模板引擎的 SpringTemplateEngine templateEngine = new SpringTemplateEngine();

    对于来自 Spring Boot 应用程序的电子邮件,我会推荐 this 库,它使发送电子邮件变得非常简单!!

    【讨论】:

    • 感谢您的帮助,它解决了我的问题,thymeleaf 解决了文件。但是在提供邮件时出现权限被拒绝错误。我已经编辑了帖子
    • @arunabraham 抱歉插入我自己的博文。我看到您使用 Gmail 作为 smtp 服务器。我曾在how to use gmail as smtp server 上写过博客。所以这可能会对你有所帮助。
    • 感谢您的回复,会查看帖子
    • 如果问题已解决,请将您的问题标记为已回答。
    • 有没有办法解决 Permission denied: error with the configuration I have provided in the post.I had googleed on this.-我在 VM 中设置了 Djava.net.preferIPv4Stack=true (eclipse ),但没有得到解决。你能告诉我为什么会出现这个问题吗?
    【解决方案2】:

    就我而言,我尝试了@MohamedSanaulla 的建议,并将以下内容添加到我的 Spring @Configuration 课程中:

    @Autowired
    public void configureSpringTemplateEngine(SpringTemplateEngine springTemplateEngine) {
        springTemplateEngine.addDialect(new LayoutDialect());
    }
    

    但后来我开始收到关于 LayoutDialect 被声明两次的重复方言相关异常。所以我只是将它完全删除(因此,既没有尝试实例化新的SpringTemplateEngine,也没有尝试通过添加LayoutDialect 来配置Boot 提供给我的那个)并且它工作正常。

    【讨论】:

      【解决方案3】:

      我做了一些类似的事情来避免这个问题。

      public PdfCreationServiceImpl(SpringTemplateEngine templateEngine) { this.templateEngine = templateEngine; ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setPrefix("templates/"); templateResolver.setSuffix(".html"); templateResolver.setTemplateMode(TemplateMode.HTML); templateEngine.setTemplateResolver(templateResolver); this.templateEngine = templateEngine; }

      【讨论】:

        猜你喜欢
        • 2017-09-10
        • 2019-02-20
        • 1970-01-01
        • 2017-05-10
        • 2016-01-27
        • 2021-09-25
        • 2019-01-22
        • 2020-05-14
        • 2020-03-14
        相关资源
        最近更新 更多