问题
We're using Freemarker version 2.3.16, and I've just tracked down a weird bug in one of our apps. It came down to there now being hyphens in some of our product code strings. The codes are used to pull hashes of localized text from the global scope using .vars
.
Reducing the issue brought me to an example that anyone can try:
${.vars["foo-bar"]}
in a template outputs0
${.vars["foo+bar"]}
outputsnullnull
${.vars["foobar"]}
correctly triggers an InvalidReferenceException
All three should trigger exceptions. Instead, it appears the .vars
parameter string is being evaluated! :-(
http://freemarker.sourceforge.net/docs/app_faq.html#faq_strange_variable_name implies this should work.
I saw mention of a similar issue a few weeks ago on the Freemarker mailing list, and it was suggested to prefix the parameter string with "@". That might work with other hashes, but it does NOT work with .vars
. I just took a working example (.vars["resources_title"]
) and changing it made it throw an InvalidReferenceException (.vars["@resources_title"]
). I also tried it on the hyphenated reference, and it also threw the exception.
Upgrading to 2.3.18 did not seem to make a difference.
回答1:
Works for me. And like already mentioned on the freemarker-user mailing list: maybe you use a strange data model, or even a fancy ObjectWrapper
. But a discussion like this is probably better suited for the freemarker-user mailing list...
回答2:
Sorry for the delay. After some good mailing-list help on places to put breakpoints, here's I wrote back to the list on June 10th:
Short story: It's not a Freemarker issue. Rather the Struts team chose to hard-wire Freemarker to treat .vars
names as OGNL expressions, and there seems no way to tell OGNL to not parse them. So under Struts, "-" and "+" (and possibly other characters) cannot appear in .vars
names.
Long story...
freemarker.core.BuiltinVariable
(line 192) is where Freemarker starts to process.vars
expressionsfreemarker.core.Environment
(line 1088) hands control over to the "rootDataModel" which the Struts team hard-wired to be an instance oforg.apache.struts2.views.freemarker.ScopesHashModel
line 70 of that class (using version 2.1.8.1 of Struts) calls "stack.findValue"; "stack" has been wired to be an instance of
com.opensymphony.xwork2.ognl.OgnlValueStack
at line 236 this class in turn asks an instance of
OgnlUtil
to find the object, and that's where the name is assumed to be an OGNL expression and is parsed, turning "foo-bar" into ( foo - bar )
At no point along the way does there seem to be a choice to NOT treat the .vars
name as an expression (a comment in FreemarkerResult
hints at the possibility, but the code doesn't follow through). In theory I could have my implementation of FreemarkerManager
create a variant of ScopesHashModel
, but that would take a lot of work to change all the associated classes with it.
(Nor does there seem to be a way to escape "-" characters in OGNL expressions. Seems there was discussion 5-6 years ago to do this, but.... .vars( "foo\\-bar" )
fails on finding "-" after "\", so presumably "-" isn't escapable?)
:-(
I'm not clear what the use-case is for treating .vars
names as expressions... but I don't think Struts is going to change, now. Rather than override a half dozen Struts classes, I instead changed the code that loads our ResourceBundles into the value stack: it now changes the names to replace "-" and "_", and likewise my .vars
names are changed the same way in the template and... tada. It works. Woo.
回答3:
It works if it added with escape foo\-bar. "Only single backslash"
回答4:
Since freemarker version 2.3.22 is it possible to use dot (.), minus sign (-) or colon (:) in a variable name (details here).
In my case, it fails if I tried to use with freemarker 2.3.21 variables like :
api["x-link"]
If I change freemarker to version 2.3.22 it works.
来源:https://stackoverflow.com/questions/6300454/freemarker-vars-names-cant-contain-dashes