struts2对Ognl的打包-OgnlValueStack
Ognl的扩展点:
http://java12345678.iteye.com/blog/2031790
类OgnlValueStack 是struts2对Ognl的封装,提供了表达式取值或赋值方法,并不像ognl那样需要在方法参数中传递context,root 对象,因为context 、root对象已封状在OgnlValueStack 内部
Struts 对Ognl的封装,提供了setValue、set、setParameter等方法通过表达式赋值,findValue,findString 等方法取值。
构建器调用setRoot方法构建OgnlValueStack对象,并生成Ognl需要的相关对象:
protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot, boolean allowStaticMethodAccess) { this.root = compoundRoot; this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess); this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess); context.put(VALUE_STACK, this); Ognl.setClassResolver(context, accessor); ((OgnlContext) context).setTraceEvaluations(false); ((OgnlContext) context).setKeepLastEvaluation(false); }
1.ognl上下文:Map<String,Object> contex
this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess);
2. ognl的root对象:CompoundRoot root=CompoundRoot :,表达式从中取值或赋值
3:MemeberAccess: ognl的成员是否可以访问(SecurityMemberAccess)
this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess);
4.ognl的ClassResolver(用于加载类)(CompoundRootAccessor)
Ognl.setClassResolver(context, CompoundRootAccessor);
5.ognl的TypeConverter 用于类型转换(new OgnlTypeConverterWrapper(XWorkConverter))
6.PropertyAccessor
由工厂ValueStackFactory生成实例时,注入Container时,调用OgnlRuntime.setPropertyAccessor
7.MethodAccessor
由工厂ValueStackFactory生成实例时,注入Container时,调用OgnlRuntime.setMethodAccessor
8.NullHandler
由工厂ValueStackFactory生成实例时,注入Container时,调用OgnlRuntime.setNullHandler
ValueStackFactory类的方法:
@Inject public void setContainer(Container container) throws ClassNotFoundException { Set<String> names = container.getInstanceNames(PropertyAccessor.class); for (String name : names) { Class cls = Class.forName(name); if (cls != null) { if (Map.class.isAssignableFrom(cls)) { PropertyAccessor acc = container.getInstance(PropertyAccessor.class, name); } OgnlRuntime.setPropertyAccessor(cls, container.getInstance(PropertyAccessor.class, name)); if (compoundRootAccessor == null && CompoundRoot.class.isAssignableFrom(cls)) { compoundRootAccessor = (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, name); } } } names = container.getInstanceNames(MethodAccessor.class); for (String name : names) { Class cls = Class.forName(name); if (cls != null) { OgnlRuntime.setMethodAccessor(cls, container.getInstance(MethodAccessor.class, name)); } } names = container.getInstanceNames(NullHandler.class); for (String name : names) { Class cls = Class.forName(name); if (cls != null) { OgnlRuntime.setNullHandler(cls, new OgnlNullHandlerWrapper(container.getInstance(NullHandler.class, name))); } } if (compoundRootAccessor == null) { throw new IllegalStateException("Couldn't find the compound root accessor"); } this.container = container; } }
OgnlValueStack提供的findxxx方法,通过表达式取值,都会调用如下:
private Object tryFindValue(String expr) throws OgnlException { Object value; if (defaultType != null) { value = findValue(expr, defaultType); } else { value = getValueUsingOgnl(expr); if (value == null) {//在ognl中没有找到 value = findInContext(expr);//到上下文中查找 } } return value; } /** *使用Ognl获取表达式的值 参数contxt上下文,root对象 **/ private Object getValueUsingOgnl(String expr) throws OgnlException { try { return ognlUtil.getValue(expr, context, root); } finally { context.remove(THROW_EXCEPTION_ON_FAILURE); } } /** * ognlUtil类中的方法 * 使用Ognl获取表达式的值 */ public Object getValue(String name, Map<String, Object> context, Object root) throws OgnlException { return Ognl.getValue(compile(name, context), context, root); } /** *从上下文的Map对象中直接get */ private Object findInContext(String name) { return getContext().get(name); }
OgnlValueStack提供的setParameter和setValue方法,通过表达式赋值,都会调用如下:
private void trySetValue(String expr, Object value, boolean throwExceptionOnFailure, Map<String, Object> context, 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);
//调用ognl赋值,并传递context,root对象
}
/**
*调用ognl赋值
*/
protected void setValue(String name, Map<String, Object> context, Object root, Object value, boolean evalName) throws OgnlException {
Object tree = compile(name, context);
if (!evalName && isEvalExpression(tree, context)) {
throw new OgnlException("Eval expression cannot be used as parameter name");
}
Ognl.setValue(tree, context, root, value);
}
OgnlValueStack提供的peek,pop,push 方法,从root中提取元素或添加元素:
/** * @see com.opensymphony.xwork2.util.ValueStack#peek() */ public Object peek() { return root.peek(); } /** * @see com.opensymphony.xwork2.util.ValueStack#pop() */ public Object pop() { return root.pop(); } /** * @see com.opensymphony.xwork2.util.ValueStack#push(java.lang.Object) */ public void push(Object o) { root.push(o); }