我们正在使用Freemarker版本2.3.16,我刚刚在我们的某个应用程序中找到了一个奇怪的错误。它归结为现在我们的一些产品代码字符串中有连字符。这些代码用于使用.vars
从全局范围中提取本地化文本的哈希值。
减少这个问题让我想到了一个任何人都可以尝试的例子:
${.vars["foo-bar"]}
输出0
${.vars["foo+bar"]}
输出nullnull
${.vars["foobar"]}
正确触发InvalidReferenceException
这三个都应该触发异常。相反,似乎正在评估.vars
参数字符串! : - (
http://freemarker.sourceforge.net/docs/app_faq.html#faq_strange_variable_name意味着这应该有用。
几周前我在Freemarker邮件列表中看到过类似的问题,建议在参数字符串前加上“@”。这可能适用于其他哈希值,但它不适用于.vars
。我刚刚做了一个工作示例(.vars["resources_title"]
)并更改它使它抛出一个InvalidReferenceException(.vars["@resources_title"]
)。我也尝试了带连字符的引用,它也引发了异常。
升级到2.3.18似乎没有什么区别。
答案 0 :(得分:1)
适合我。就像已经mentioned on the freemarker-user mailing list:也许你使用了一个奇怪的数据模型,甚至是一个花哨的ObjectWrapper
。但是像这样的讨论可能更适合freemarker-user邮件列表......
答案 1 :(得分:1)
抱歉延误。在关于放置断点的地方的一些好的邮件列表帮助后,我在6月10日写回了列表:
短篇小说:这不是Freemarker问题。相反,Struts团队选择硬连线Freemarker将.vars
名称视为OGNL表达式,并且似乎没有办法告诉OGNL 不解析它们。因此,在Struts下,“ - ”和“+”(可能还有其他字符)不能出现在.vars
名称中。
长篇故事......
freemarker.core.BuiltinVariable
(第192行)是Freemarker开始处理.vars
表达式的地方
freemarker.core.Environment
(1088行)将控制权移交给“rootDataModel”,Struts团队将其作为org.apache.struts2.views.freemarker.ScopesHashModel
的实例
该类的第70行(使用Struts的2.1.8.1版本)调用“stack.findValue”; “stack”已被连线为com.opensymphony.xwork2.ognl.OgnlValueStack
在第236行,该类依次要求OgnlUtil
的实例找到该对象,并且该名称被假定为OGNL表达式并被解析,将“foo-bar”转换为(foo - bar)
在此过程中,似乎没有选择不将.vars
名称视为表达式(FreemarkerResult
中的注释提示可能性,但代码不遵循通过)。从理论上讲,我可以让FreemarkerManager
的实现创建ScopesHashModel
的变体,但是要用它来更改所有相关的类需要做很多工作。
(似乎没有办法逃避OGNL表达式中的“ - ”字符。似乎有5到6年前的讨论要做到这一点,但.... .vars( "foo\\-bar" )
未能找到“ - “在”之后,所以大概是“ - ”是不可避免的?)
: - (
我不清楚将.vars
名称作为表达式处理的用例是什么......但我认为Struts现在不会改变。我没有覆盖半打Struts类,而是更改了将ResourceBundles加载到值堆栈的代码:它现在更改了名称以替换“ - ”和“_”,同样我的.vars
名称也被更改了同样的方式在模板和... tada。有用。呜。
答案 2 :(得分:1)
如果添加了转义foo \ -bar,它就可以工作。 “仅单个反斜杠”
答案 3 :(得分:0)
由于freemarker版本2.3.22可以在变量名称(details here)中使用点(。),减号( - )或冒号(:)。
在我的情况下,如果我尝试使用freemarker 2.3.21变量,它会失败,如:
api["x-link"]
如果我将freemarker更改为版本2.3.22,则可以正常工作。