【问题标题】:How to use velocity 1.7 with Spring如何在 Spring 中使用速度 1.7
【发布时间】:2012-03-22 15:51:51
【问题描述】:

我正在使用速度 1.7 和 spring 3.1 框架来发送电子邮件。速度用于电子邮件模板。

下面是配置

<bean id="velocityEngine"
    class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
    <property name="velocityProperties">
        <props>
            <prop key="resource.loader">class</prop>
            <prop key="class.resource.loader.class">
                org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
            </prop>
        </props>
    </property>
</bean>

下面是我的代码

 @Component
 public class EmailUtils {

    @Autowired
    private static VelocityEngine velocityEngine;

    public static void sendMail(String subject, Map data, String template,
            String toName, String toAddress) {


        HtmlEmail email = new HtmlEmail();

        try {
            email.setHostName(hostName);
            email.setSmtpPort(smtpPort);
            email.setSubject(subject);

            System.out.println(template +" template");
            System.out.println(data +" data ");
            System.out.println(velocityEngine +" velocityEngine ");

            String message = VelocityEngineUtils.mergeTemplateIntoString(
                    velocityEngine, template, data);

            System.out.println(message +" message message ");

            email.setMsg(message);
            email.addTo(toAddress, toName);
            email.setFrom(fromAddress, fromName);
            email.send();
        } catch (EmailException e) {
            // TODO Auto-generated catch block

            e.printStackTrace();
        }
    }
}

当我运行应用程序时出现以下错误。

java.lang.NullPointerException
at org.springframework.ui.velocity.VelocityEngineUtils.mergeTemplate(VelocityEngineUtils.java:58)

因为速度引擎为空。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

<bean id="velocityEngine"
    class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
    <property name="velocityProperties">
        <props>
            <prop key="resource.loader">class</prop>
            <prop key="class.resource.loader.class">
                org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
            </prop>
        </props>
    </property>
</bean>

请帮助我。我还需要做其他配置吗?

【问题讨论】:

  • 您是否正确配置 Spring 以使用 XML 配置以及注释配置?
  • 你为你的模板传递了什么?我怀疑那里可能有问题。
  • Ashish,你看到 nico_ekito 关于注解配置的评论了吗?你的 XML 中有 &lt;context:annotation-config /&gt; 吗?它不在您的示例 XML 配置 sn-ps 中。

标签: spring velocity


【解决方案1】:

我在将项目升级到 Java 11 + Spring Boot 2.1.8 时遇到了同样的问题。我可以通过以下方式解决它:

@Configuration
public class AppConfig {
    @Bean
    public VelocityEngine velocityEngine() throws Exception {
        Properties properties = new Properties();
        properties.setProperty("input.encoding", "UTF-8");
        properties.setProperty("output.encoding", "UTF-8");
        properties.setProperty("resource.loader", "class");
        properties.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        VelocityEngine velocityEngine = new VelocityEngine(properties);
        return velocityEngine;
    }
}

【讨论】:

    【解决方案2】:

    这是我的尝试,我通过 ClassPathXmlApplicationContext 手动初始化“velocityEngine”bean:

    Spring application-context.xml

    <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
      <property name="velocityProperties">
        <value>
          resource.loader=class
          class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
        </value>
      </property>
    </bean>
    

    这是我的template_text.vm,放在classpath中,和application-context.xml同级。

    Dear $userName,
    
    You have made the following request on $userTime.
    
    #if( $isFileMissing )
    Missing file(s) found in home directory:
    #foreach( $missingFile in $missingFiles )
    - $missingFile
    #end
    #end
    
    Best regards,
    

    这是Java代码:

    public static void main(String[] args) throws Exception {
        String[] springConfig = {"application-context.xml"};
        org.springframework.context.ApplicationContext context = new org.springframework.context.support.ClassPathXmlApplicationContext(springConfig);
    
        java.util.Map<String, Object> model = new java.util.HashMap<String, Object>();
        model.put("userName", "John Low");
        model.put("userTime", "2015-10-28 23:59:59");
        model.put("isFileMissing", true);
        model.put("missingFiles", new String[] {"line 1", "line 2", "line 3"});
        String text = org.springframework.ui.velocity.VelocityEngineUtils.mergeTemplateIntoString((VelocityEngine)context.getBean("velocityEngine"), "/template_text.vm", "UTF-8", model);
        System.out.println(text);
    }
    

    输出:

    Dear John Low,
    
    You have made the following request on 2015-10-28 23:59:59.
    
    Missing file(s) found in home directory:
    - file 1
    - file AAA
    - line 3
    
    Best regards,
    

    【讨论】:

      【解决方案3】:

      我在使用时遇到了同样的问题。我可以通过以下方式解决它:

      @Configuration
      public class ApplicationConfiguration {
      
          @Bean
          public VelocityEngine getVelocityEngine() throws VelocityException, IOException{
              VelocityEngineFactory factory = new VelocityEngineFactory();
              Properties props = new Properties();
              props.put("resource.loader", "class");
              props.put("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
              factory.setVelocityProperties(props);
              return factory.createVelocityEngine();      
          }
      }
      

      但是相反 - 因为我在视图中使用速度模板并且已经声明了 VelocityConfigurer,所以我改为在 VelocityConfigurer 声明中自动装配并在其上调用 getVelocityEngine()。

      我确实发现,如果它被自动连接到 @Service-s 或 @Component-s 并且您已在共享的 applicationContext.xml 文件中声明,那么 xml 声明也必须在该共享的 applicationContext.xml 中而不是 xxx-servlet.xml 配置。

      我认为这是因为 applicationContext.xml 在应用程序中的所有 servlet 之间共享,因此必须在 xxx-servlet.xml 文件之前对其进行完全处理。

      或者,您可以启用 spring bean 工厂调试并查看实例化它是否有任何问题:

      log4j.category.org.springframework.beans.factory=DEBUG
      

      【讨论】:

        【解决方案4】:

        我认为您不能将@Autowired 与静态字段一起使用。您可以使用非静态设置器解决此问题:

        @Autowired
        public void setVelocityEngine(VelocityEngine ve) {
          EmailUtils.velocityEngine = ve;
        }
        

        或者以另一种方式,但我强烈建议将EmailUtils 转换为非静态bean。 Spring 可以更好地处理非静态组件(不需要丑陋的 hack),可以交换实现,并且您的代码将坚持 DI 理念。

        【讨论】:

        • 嗨谢谢你的回答。正如你所说,我删除了静电。现在我得到 No matching bean of type of [org.apache.velocity.app.VelocityEngine] found for dependency: expected 至少 1 个 bean 有资格作为此依赖项的自动装配候选者。在部署应用程序时。请帮忙。
        • VelocityEngineFactoryBean 产生VelocityEngine 类型的对象。如何指示要加载的上下文文件?
        • 你的 bean "velocityEngine" 实例化了吗?如果您为“org.springframework”启用信息日志记录,您应该会看到它列出来。
        • 不,我没有在列表中看到它。但我可以在列表中看到 EmailUtils。
        • 你确定它定义的文件被加载了吗?它还应该记录在 INFO 级别。我认为它是INFO [XmlBeanDefinitionReader] Loading XML bean definitions from URL [file:/C:/Projects/my_project/springContext.xml]
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-26
        • 1970-01-01
        • 2018-01-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多