首先让我说使用Struts2 + Freemarker是一个真正的爆炸。 然而,有些东西让我发疯,因为我无法理解为什么会这样。我在这里问,也许其他人有想法分享它。
我有一个属性的行动。 说
private String myText;
然后我有一个二传手和一个吸气者:
public void setMyText(String myText)
{
this.myText = myText;
}
public String getMyText()
{
if (myText == null)
myText = "(empty)";
return this.myText;
}
结果(在struts.xml中)是 freemarker 结果。 所以在我的Freemarker模板中有一行如下:
<p>The text is: ${myText}</p>
现在考虑我在没有任何文本参数的情况下调用操作:说url是
http:localhost:8080/myapp/myaction
由于getter提供了一个默认值,当处理动作并将结果传递给我的模板时,该属性被设置为默认值;所以我得到(浏览器端的HTML)
<p>The text is: (empty)</p>
如果我用参数集调用我的动作,而不是(我的意思是:
http:localhost:8080/myapp/myaction?myText=hallo
事情出了问题。 Freemarker触发以下异常:
Exception occurred during processing request: For "${...}" content:
Expected a string or something automatically convertible to string
(number, date or boolean), but this has evaluated to a
sequence+extended_hash (String[] wrapped into f.e.b.ArrayModel)
似乎“myText”被发现两次...... 我究竟做错了什么?或者,至少,有没有人可以向我解释它为什么会发生?
P.S。:真的发现了两次;以下是解决问题的方法:
<#if myText?is_sequence>${myText[0]}<#else>${myText}</#if>
然而,在我看来以这种方式包装每个变量是不可行的。
P.P.S:进一步提示:在freemarker模板中,之前有一些线路调用另一个动作。类似的东西:
<@s.action var="innerAction" name="getTable" namespace="/foo" />
如果我评论上面的一行,一切正常。
答案 0 :(得分:0)
myText
可以是freemarker上下文中的变量,但是如果你想使用action属性
<p>The text is: ${action.myText}</p>
请注意,访问操作属性不需要action
前缀。解析freemarker变量时会应用property resolution方法:
财产重新解决
您的操作属性会自动解析 - 就像在a中一样 速度视图。
例如
${name}
会产生stack.findValue("name")
,这就是action.getName()
通常导致TreeMap
被执行。搜索过程用于解析变量,搜索变量 按顺序执行以下范围,直到找到值:
- freemarker variables
- 价值堆栈
- 请求属性
- 会话属性
- servlet上下文属性
稍后您可以阅读上下文中可以访问的对象。
上下文中的对象
FreeMarker视图中存在以下变量
- req - 当前的HttpServletRequest
- res - 当前的HttpServletResponse
- stack - 当前的OgnlValueStack
- ognl - OgnlTool实例 此类包含用于对任意对象执行OGNL表达式的有用方法,以及使用生成选择列表的方法 模式。 (即取名单属性的名称,a listKey和listValue)
- struts - StrutsBeanWrapper的一个实例
action - 当前的Struts操作
- exception - 如果视图是JSP异常或Servlet异常视图,则可选Exception实例
错误可能是由值堆栈中的搜索引起的,并返回一些您不希望的内容,具体取决于执行时堆栈的结构。在变量中添加前缀以指出属性的确切位置应该在值堆栈中搜索时修复代码中的冗余。