Velocity模板在使用UTF-8时似乎会出现问题。

25

我一直在尝试使用以下内容的速度模板:

Sübjäct $ item

除了两个Unicode字符的翻译之外,一切正常。 在命令行上打印的结果字符串如下所示:

Sübjäct foo

我在velocity网站和网络上搜索了这个问题,并提出了不同的字体编码选项,我添加到了我的代码中。 但是这些都没有帮助。 这是实际的代码:

velocity.setProperty("file.resource.loader.path", absPath);
velocity.setProperty("input.encoding", "UTF-8");
velocity.setProperty("output.encoding", "UTF-8");

Template t = velocity.getTemplate("subject.vm");
t.setEncoding("UTF-8");

StringWriter sw = new StringWriter();

t.merge(null, sw);       
System.out.println(sw.getBuffer());

我该如何解决这个问题?
4个回答

47

你尝试使用过这个语法吗?

Template template = Velocity.getTemplate("subject.vm", "UTF-8");

看起来它应该做正确的事情。


嗨,非常感谢。关于另一个评论,速度实际上是VelocityEngine的一个实例。但是代码片段无论如何都是一个测试用例,适当的名称只存在于生产代码中;) - steve
@Stony:嗯,原帖作者似乎认为这对他们有效,所以听起来你可能在其他地方遇到了问题。我建议你提出一个新的问题,并附上一个 [mcve] 来展示你尝试过什么以及出了什么问题。 - Jon Skeet
很抱歉,我最终找到了根本原因。你的解决方案有效。我程序不能正常工作的原因是我使用了 ve.setProperty("eventhandler.referenceinsertion.class", "org.apache.velocity.app.event.implement.EscapeXmlReference"); 并且 EscapeXmlReference 使编码出错。 - Stony
@goblingift:如果单参数重载使用平台默认编码,那就不是特别的问题了,这在许多Java API中都是这样。 (我不知道是否如此,但这似乎是一个合理的推测...) - Jon Skeet
谢谢。通过你出色的回答,你在世界上做了和纳尔逊·曼德拉一样多的好事 :) - undefined

2
如果您正在使用VelocityEngine和JavaMailSenderImpl类,请不要忘记设置defaultEncoding属性。此外,如上所述,请尝试为VelocityEngine类配置input.encoding和output.encoding属性。我在下面留下一个示例。

配置文件

<bean id="smtpSession" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:jboss/example/jndiName"/>
    </bean>
<bean id="javaMailSenderImpl" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="session" ref="smtpSession"/>
        <property name="defaultEncoding" value="UTF-8"/>
</bean>

<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
        <property name="velocityProperties">
            <props>
                <prop key="input.encoding">UTF-8</prop>
                <prop key="output.encoding">UTF-8</prop>
                <prop key="response.encoding">UTF-8</prop>
                <prop key="resource.loader">file</prop>
                <prop key="file.resource.loader.class">org.apache.velocity.runtime.resource.loader.FileResourceLoader
                </prop>
                <prop key="file.resource.loader.path">${relative.path}/email-templates</prop>
                <prop key="file.resource.loader.cache">false</prop>                    
            </props>
        </property>
    </bean>

1
我的解决方案是在jvm选项中添加"-Dfile.encoding=UTF-8"(不包括引号)。
我尝试了上述可能的解决方案,但都没有成功。
经过数天的搜索和探索,我猜想我的问题出现在velocity渲染html文件时,因为我发现一些错误显示的文本实际上是以GB2312编码的,我意识到当页面被渲染时,vm文件的编码不正确(我猜测)。

那个做得很好。这是否应该打开Velocity模板引擎的问题?该参数应该强制执行所需的编码。 - wdavilaneto
虽然这样做可以起作用,但它会改变整个JVM中许多事物的默认设置,这可能不是您想要的。当有更具针对性的选项可用时,请注意不要更改默认设置。 - Christopher Schultz

0
如果您手动创建一个JavaMailSenderImpl实例,可以通过以下方式设置编码属性:
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
Properties mailProperties = new Properties();
mailProperties.put("defaultEncoding", "UTF-8");
mailSender.setJavaMailProperties(mailProperties);

如果您正在使用MimeMessageHelper,请按以下方式设置编码:

MimeMessageHelper helper = new MimeMessageHelper(mailSender.createMimeMessage(), true, "UTF-8");

最后,对于Velocity引擎,有两种方法可以在设置编码时获取/应用模板:

Template template = Velocity.getTemplate("template", "UTF-8");
// or
velocityEngine.mergeTemplate("template", "UTF-8", velocityContext, stringWriter);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接