OGNL是Object Graphic Navigation Language 是操作对象属性的开源表达式。 Struts2框架使用OGNL作为默认的表达式语言。
在学习JSP的时候,我们已经学习过了EL表达式。EL表达式用起来也十分简单…我们在Struts2框架中也是可以使用EL表达式的…那么OGNL表达式好在哪里呢??
支持对象方法调用,如xxx.doSomeSpecial()支持类静态的方法调用和值访问,表达式的格式【例如:”@@floor(10.9)”就是调用Math.floor()的方法了】支持赋值操作和表达式串联【这个其实EL表达式也能做】访问OGNL上下文(OGNL context)和ActionContext操作集合对象【EL只能遍历集合,OGNL可以创建集合】OGNL是Struts2的默认表达式语言,OGNL是配搭Strut2的标签使用的..我们学习了OGNL表达式,就可以更好地理解Struts2标签的运行以及Struts2内部的存储结构.
在讲解OGNL表达式之前,我们先来看看valueStack对象…valueStack是Struts2数据存储的核心…我们首先要知道数据是怎么存的,存到哪里,然后才讲解OGNL表达式是怎么取出数据的。
valueStack也被称作值栈对象..
当用户访问Action,都会创建一个Action对象,ActionContext对象、valueStack对象..Struts2把Action对象放进valueStack对象之中。将valueStack放进request域中,传入JSP页面(key: struts.valueStack)JSP页面就可以使用OGNL表达式获取值栈中的数据了!上面已经说了,用户访问Action时,会创建Action对象,valueStack对象。Struts2内部会将Action对象存到valueStack对象之中…那么valueStack的存储结构是什么样的呢???我们来看看
Action对象和Action的成员属性等值都是存到CompoundRoot下的.该CompoundRoot继承着ArrayList,因此它是List结构的
public class CompoundRoot extends ArrayList {}OgnlContext对象存储着相关的域对象:request、response、session等数据,实现Map集合,是Map结构..
为了让request、response等域对象可以存储多个值,值也是使用Map结构…
public class OgnlContext implements Map {}CompoundRoot保存着这样的数据:
Action对象以及Action对象的成员属性数据使用ValueStack对象.push()进去的数据使用ValueStack对象.set()进去的数据其他代理对象的数据OgnlContext保存着这样的数据:
维护了CompoundRoot中所有的数据request、response等域对象所有的数据也就是说通过OgnlContext对象可以获取大部分我们需要的数据了。
那么OGNL表达式是怎么取出OgnlContext对象中数据的呢??下面我们通过硬编码的方式来讲解:
/** * 1. Ognl表达式语言语言取值,取非根元素的值,必须用#号 * @throws Exception */ @Test public void testOgnl() throws Exception { // 创建一个Ognl上下文对象 OgnlContext context = new OgnlContext(); // 放入数据 User user = new User(); user.setId(100); user.setName("Jack"); // 【往非根元素放入数据, 取值的时候表达式要用"#"】 context.put("user", user); // 获取数据(map) // 先构建一个Ognl表达式, 再解析表达式 Object ognl = Ognl.parseExpression("#user.name"); Object value = Ognl.getValue(ognl, context, context.getRoot()); System.out.println(value); } /** * 2. Ognl表达式语言语言取值,取根元素的值,不用带#号 * @throws Exception */ @Test public void testOgn2() throws Exception { // 创建一个Ognl上下文对象 OgnlContext context = new OgnlContext(); // 放入数据 User user = new User(); user.setId(100); user.setName("Jack"); // 【往根元素放入数据】 context.setRoot(user); // 获取数据(map) // 先构建一个Ognl表达式, 再解析表达式 Object ognl = Ognl.parseExpression("address.province"); Object value = Ognl.getValue(ognl, context, context.getRoot()); System.out.println(value); }也就是说,JSP页面中取出数据的时候,它会先构建一个OGNL表达式,再解析表达式
如果是CompoundRoot类的数据,表达式不需要带#号如果不是CompoundRoot类的数据,表达式需要带#号构建Map集合的时候,需要使用#号
#获取非根元素值 、 动态都建map集合 $ 在配置文件取值 % 提供一个ognl表达式运行环境
<body> <br/>获取request域数据<br/> <!-- property 标签是对象类型的标签,默认支持ognl表达式, 会从根元素去China名称对应的值 --> <s:property value="China"/> <br/> <!-- 如果直接赋值,需要用单引号 --> <s:property value="'China'"/> <br/> <s:property value="%{#request.cn}"/> <br/> <!-- 值类型的标签,value值默认就是值类型,不支持ognl表达式 --> 国家:<s:textfield name="txtCountry" value="%{#request.cn}"></s:textfield> </body>