1. 什么是OGNL?什么是ValueStack?
OGNL(Object Graphic Navigation Language)是一种表达式语言,是一个开源的框架,它可以存取对象的任意属性,调用对象方法。Struts2框架使用OGNL 在页面实现对数据的操作。
ValueStack 在Struts2中充当数据传递的媒介,包含OGNL可访问的数据集合,在JSP中可通过OGNL表达式对ValueStack中的数据进行访问。
2.OGNL能做什么?
OGNL的作用与EL表达式大同小异。总结了一下他能实现以下常用功能:
获取Action中的属性(访问JavaBean)。
调用对象方法。
调用静态方法。
访问ActionContext
2.1获取Action中的属性
需要提供Bean属性的getter和setter
因为当前Action在ValueStack的root栈中,所以直接取,不需要“#”
public class ValueStackAction extends ActionSupport{
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String demo(){
name = "good";
return SUCCESS;
}
}
在页面中获取:
<body>
<s:property value="name"/>
<s:debug/>
</body>
2.2调用对象方法
我们不仅可以访问对象属性,还可以通过OGNL表达式调用对象拥有的方法。同样,由于Action位于root栈,所以不需要操作符“#”
public String getHello(String name){
return "Hello," + name;
}
在页面中调用:
<body>
<s:property value="getHello('Cindy')"/>
<s:debug/>
</body>
2.3调用静态方法和访问静态数据
OGNL表达式支持调用静态方法,调用静态方法的格式为”@类的全名@方法名”、访问静态数据的格式为”@类的全名@变量名“
注意:如果要执行静态方法,需要在struts.xml中开启允许执行静态方法的配置:
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
在页面中调用Math的random方法,访问Integer的MAX_VALUE值:
<body>
<s:property value="@java.lang.Math@random()"/>
<s:property value="@java.lang.Integer@MAX_VALUE"/>
<s:debug/>
</body>
2.4访问ActionContext
在ActionContext中我们可以得到四个数据域:request、session、application、parameters,因此,我们可以通过OGNL表达式访问参数域中保存的数据。其中获取ActionContext中的东西需要使用操作符“#”。”#”即表示从ActionContext中取数据
public String demo(){
ServletActionContext.getRequest().setAttribute("req", "reqValue");
return SUCCESS;
}
取出Request域中的值
<body>
<s:property value="#request.req"/>
<s:debug/>
</body>
2.5“%”的用法
当标签的属性为字符串类型时,可以使用%{xxx}的方式来标识其为OGNL表达式,从而计算表达式,而不是直接使用内容。
<body>
<%
String value="确定";
pageContext.setAttribute("val", value);
%>
不使用%符号,会按原样显示<br>
<s:submit value="#attr.val"/><br>
使用%符号,会计算OGNL表达式的值<br>
<s:submit value="%{#attr.val}"/>
</body>
3.OGNL相对于其他表达式有什么优势?
前提:在Struts2用OGNL表达式,需要用到标签。如<s:property value=""/>
- 支持对象方法调用,如xxx.doSomeSpecial();
- 支持类静态的方法调用和值访问
- 支持赋值操作和表达式串联
- 访问OGNL上下文(OGNL context)和ActionContext(很重要)
- 操作集合对象
- 将页面数据与后台数据绑定在一起。能实现互相传递。
4.Struts2的OGNL是如何工作的?
OGNL取的数据都是放在ValueStack和ActionContext中的,而ValueStack又包含了对ActionContext的引用,所以,我们只需要了解ValueStack的结构和使用方法,就能够理解OGNL是怎么从里面取出数据的了。
首先,用一张图来展现ValueStack的结构:
4.1 root
4.1.1 通过set()设置的值
这个root是一个栈结构,他保存了ValueStack通过set方法设置的值,调用set方法的时候,会检测root栈中栈顶是否有HashMap,如果有,就直接将key、value压到这个map中,如果栈顶没有这个map,则创建一个HashMap,再将key、value压到这个map中。
public String demo(){
ValueStack vs = ActionContext.getContext().getValueStack();
vs.set("price", 500000);
return SUCCESS;
}
从<s:debug/>
中查看ValueStack中的东西,可以看到新建的map位于栈顶:
4.1.2 ValueStackAction
代表当前执行动作的Action,可以从这里取得Action的属性和方法,这就是为什么我们能够直接从OGNL表达式中取得属性和调用Action中方法的原因,OGNL会在这个root栈中自顶向下搜索,直到找到对应属性或方法为止。
public String demo(){
name="abcdefg";
return SUCCESS;
}
4.2 OGNLContext
OGNL上下文,包含了对valuestack的引用,以及request、seesion、application、parameter..等等的Map数据。在OGNL中通过”#“来操作其中的数据,如要取出session中的user对象的age属性:#request.user.age
public String demo(){
ServletActionContext.getRequest().getSession().setAttribute("username", "Cindy001");
return SUCCESS;
}