ognl表达式
概述
- OGNL 表达式
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
- OGNL 优势
- 支持对象方法调用,如xxx.doSomeSpecial();
- 支持类静态的方法调用和值访问,表达式的格式:
@[类全名(包括包路径)]@[方法名 | 值名],例如:
@java.lang.String@format('foo %s', 'bar')
或@tutorial.MyConstant@APP_NAME;
- 支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;
- 访问OGNL上下文(OGNL context)和ActionContext;
- 操作集合对象。
- 总结
OGNL 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了 java.utils.Map 的接口。
OgnlContext对象(了解)
- OgnlContext对象是ognl表达式语言的核心,OgnlContext是Struts2的数据中心
源码类:
public class OgnlContext extends Object implements Map{..}
- 硬编码方式,了解OgnlContext对象:
// OgnlContext用法
public class OgnlDemo1 {
/**
* 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);
}
/**
* 3.Ognl对 静态方法调用的支持
* @throws Exception
*/
@Test
public void testOgn3() throws Exception {
// 创建一个Ognl上下文对象
OgnlContext context = new OgnlContext();
// Ognl表单式语言,调用类的静态方法
//Object ognl = Ognl.parseExpression("@Math@floor(10.9)");
// 由于Math类在开发中比较常用,所以也可以这样写
Object ognl = Ognl.parseExpression("@@floor(10.9)");
Object value = Ognl.getValue(ognl, context, context.getRoot());
System.out.println(value);
}
}
ValueStack对象
- ValueStack,即值栈对象。
ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的 OgnlValueStack类,这个类是Struts2利用OGNL的基础。
是整个struts数据存储的核心,或者叫中转站。 用户每次访问struts的action,都会创建一个Action对象、值栈对象、ActionContext对象; 然后把Action对象放入值栈中; 最后再把值栈对象放入request中,传入jsp页面。 (key: struts.valueStack); 开发者只需要通过ActionContext对象就可以访问struts的其他的关键对象。 (ActionContext是给开发者用的,便于学习与使用。)
- ValueStack 存储对象
ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中--List
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application
- ValueStack 总结
值栈以struts.valueStack的名字存储在request请求中,值栈主要包含两个栈:对象栈和Map 栈。
对象栈存储的是用户的基本数据和对象数据 ; Map栈主要存储的是域对象属性。
用户每次一个请求就一个 Action 实例,对应一个值栈对象。
OGNL表达式之#号
- # 号的作用
#号主要用于访问访问Map栈信息,不使用#号主要用于访问List(对象栈)信息。
- 举例
<s:property value="#request.username"/>
<s:property value="#request.userpsw"/>
<s:property value="address"/> // 获取对象栈信息(默认从栈顶检索)
- OGNL表达式之深入理解对象栈检索顺序
OgnlValueStack类里有一个List类型的root变量,存放了一组对象,处于第一位的对象叫栈顶对象。 (list集合的 索引为0为栈顶)。通常我们在OGNL表达式里直接写上属性的名称即可访问root变量里对象 的属性,索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找, 如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。
- #号还有一个作用就是在JSP页面中构建Map集合。
格式:#{key:value,key:value...} 举例
<s:radio list="#{' male':' 男','female':'女'}" name=" gender"></s:
radio><br/>
运行结果源码:
<input type="radio" name=" gender" id="gendermale" value=" male"/> 男
<input type="radio" name="gender" id="genderfemale" value="female"/>
女
OGNL表达式之$号
- $ 号的作用
在国际化资源文件中,引用OGNL表达式(先不讲)
在 Struts2 配置文件中, , 引用 OGNL 表达式
举例
ognl.xml配置文件
<action name="ognlAction_*" class="cn.itcast.ognl.OgnlAction" method="{1}">
<result name="success">/ognl/ognl.jsp?username= ${#request.username} }</result>
</action>
在ognl.jsp中获取携带的参数:
<s:property value="%{#parameters.username[0]}"/>
OGNL表达式之%号
- 作用
提供一个ognl表达式运行环境;
即“%”符号的作用是在当Struts2标签的属性值为OGNL表达式时OGNL表达式却被理 解为字符串类型原样输出时,用于通知执行环境%{}里的是OGNL表达式。
OGNL标签
- property标签
property标签用于输出指定值
<s:property value=“#name" default="a default value" />
- default :可选属性, 如果需要输出的属性值为 null ,则显示该属性指定的值
- escape :可选属性,指定是否格式化 HTML 代码。
- value : 可选属性,指定需要输出的属性值,如果没有指定该属性,则默认输 出 ValueStack
- set标签
set 标签用于将某个值放入指定范围。 * var: 变量的名字 ,name,id 和 var 表达的含义是一样的 ,name,id 被 var 替代
- scope :指定变量被放置的范围,该属性可以接受 application 、 session 、 > > * request 、 page 或
- action 。如果没有设置该属性,则默认放置在 action 中。
- value :赋给变量的值. . 如果没有设置该属性, , 则将 ValueStack
<s:set value="#request.username" var="xxx“ scope=“request” /><br>
<s:property value=“#request.xxx" /><br>
<s:set value="#request.username" var="xxx" scope="page" /><br>
<s:property value="#attr.xxx" /><br>
<s:set value="#request.username" var="xxx" /><br>
<s:property value="xxx" /><br>
- push标签
push: 将对象放入栈顶, , 不能放入其他范围, , 当标签结束, , 会从栈顶删除。
- value : :要 push 到堆栈中的值
- bean标签(了解)
bean 标签 : 实例化一个符合 JavaBeans 规范的 class, 标签体内可以包含几个
- Param 元素, , 用于调用 setter 方法给此 class 的属性赋值. .
- name: 要被实例化的 class 名字( ( 必须符合 JavaBeans 规范) )
- var : 赋给变量的值. . 放置在 request 作用域中 如果没有设置该属性, , 则对象被放置到栈顶
<s:bean name="cn.itcast.bean.Person" var="myperson">
<s:param name="name" value="%{'zhang'}"></s:param>
<s:param name="age" value="34"></s:param>
</s:bean><br>
<s:property value="#myperson.name"/>
- action标签
Action: 通过指定命名空间和 action 名称, , 该标签允许在 jsp 页面直接调用 > Action
- name:action 名字( ( 不包括后缀, , 如 .action)
- namespace:action 所在命名空间
- executeResult:Action 的 result 是否需要被执行, , 默认值是 false 不执行
- iterator标签
Iterator: 标签用于对集合进行迭代,这里的集合包含 List 、 Set 和数组。
- value :可选属性,指定被迭代的集合,如果没有设置该属性,则使用 ValueStack 栈顶的集合。
- var : 可选属性,引用变量的名称. .
- status :可选属性,该属性指定迭代时的 IteratorStatus 实例。该实例包含如下几个方法:
- int getCount() ,返回当前迭代了几个元素。
- int getIndex() ,返回当前迭代元素的索引。
- boolean isEven() ,返回当前被迭代元素的索引是否是偶数
- boolean isOdd() ,返回当前被迭代元素的索引是否是奇数
- boolean isFirst() ,返回当前被迭代元素是否是第一个元素。
- boolean isLast()
<s:iterator value="allList" >
<s:property value="name"/><br>
</s:iterator>
<s:iterator value="allList" var="person" begin="2" end="7" step="2" >
<s:property value="#person.name"/><s:property value="#person.age"/><br>
</s:iterator>
<s:iterator value="allList" status="st" >
st.getCount():<s:property value="#st.count"/>
st.getIndex():<s:property value="#st.index"/>
st.isEven():<s:property value="#st.even"/>
st.isOdd():<s:property value="#st.odd"/>
st.isFirst:<s:property value="#st.first"/>
st.isLast():<s:property value="#st.last"/><br>
</s:iterator>
<table border="1">
<s:iterator value="allList" var="person" status="st">
<tr class= <s:property value="#st.even?'even':'odd'"/> >
<td><s:property value="#person.name"/></td>
</tr>
</s:iterator>
</table>
- if/elseif/else标签
- url标签
url: 该标签用于创建 url, 可以通过 "param" 标签提供 request 参数. .
- value: 如果不提供就用当前 action, 使用 value 后缀必须加 .action
- action: 用来生成 url 的 action, 如果没有则使用 value
- namespace : 命名空间
- var:引用变量的名称. .
- UI标签
即表单标签,使用UI标签可解决数据回显问题