今天早上一朋友向我咨询Struts2的Xwork2部分之OgnlValueStack的set与setValue的区别。
struts2版本:struts2.3.4.1
1、set(key, value)的实现
public void set(String key, Object o) { //set basically is backed by a Map pushed on the stack with a key being put on the map and the Object being the value Map setMap = retrieveSetMap(); setMap.put(key, o); } private Map retrieveSetMap() { Map setMap; Object topObj = peek(); if (shouldUseOldMap(topObj)) { setMap = (Map) topObj; } else { setMap = new HashMap(); setMap.put(MAP_IDENTIFIER_KEY, ""); push(setMap); } return setMap; }
set()的实现其实是构造一个Map(里边有一个特殊的key,MAP_IDENTIFIER_KEY),然后把key-value放入此map。通过如下代码可看出:
ActionContext ctx = ActionContext.getContext(); ValueStack vs = ctx.getValueStack(); vs.peek();
2、setValue(String expr, Object value)的实现其实最终委托给如下:
private void trySetValue(String expr, Object value, boolean throwExceptionOnFailure, Mapcontext, boolean evalExpression) throws OgnlException { context.put(XWorkConverter.CONVERSION_PROPERTY_FULLNAME, expr); context.put(REPORT_ERRORS_ON_NO_PROP, (throwExceptionOnFailure) ? Boolean.TRUE : Boolean.FALSE); ognlUtil.setValue(expr, context, root, value, evalExpression); }
javadoc:
/** * Attempts to set a property on a bean in the stack with the given expression using the default search order. * * @param expr the expression defining the path to the property to be set. * @param value the value to be set into the named property */
即从栈的顶部往下找,找到第一个匹配的赋值然后结束,不同于set()。
总结:
set(key, value):首先查找栈顶的一个特殊Map(里边有一个特殊的key,MAP_IDENTIFIER_KEY),如果找不到就创建一个,然后把对应的key-value放入。
setValue(String expr, Object value):从栈的顶部往下找,找到第一个匹配ognl表达式的赋值然后结束。
思考:
如下代码中我们往栈中添加了多少个对象?(不包括默认的添加的)
ActionContext ctx = ActionContext.getContext(); ValueStack vs = ctx.getValueStack(); UserModel user = new UserModel(); user.setUuid(123); vs.set("uuid", 456); vs.push(user); vs.set("uuid", 567);
答案:3个。
1、vs.set("uuid", 456); 第一个肯定往栈中压个Map
2、vs.push(user); 第二个 往栈中压user
3、vs.set("uuid", 567); 第三个 因为栈顶是user,所以再压一个
如何鉴定:可以通过vs.findValue("[0]")获取栈中数据,具体去参考struts2的官方文档。
ognl表达式中的:
[0]表示截取栈中从0位置开始的子集合; 假设栈中的数据是[a,b] 则结果就是[a,b]
[1]表示截取栈中从1位置开始的子集合; 假设栈中的数据是[a,b] 则结果就是[b]
以此类推。
[1].top表示截取栈中从1位置开始的子集合 并返回顶部对象(集合中的栈顶对象),即第一个。
此时大家可以在如jsp页面中使用:
s:debug 或者如下代码校验