OGNL表达式和ValueStack值栈
1.OGNL和ValueStack值栈简介
OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。Struts2框架内置了OGNL,OGNL本身也是一个项目,它是可以单独使用。
ValueStack基于ognl,作用是在struts2框架中来存储数据的容器.
valueStack存放数据,ognl从中取得数据.
2.ValueStack的内部结构:
ValueStack主要由两部分组成:
CompoundRoot root: 实质是一个ArrayList;
Map<String,Object> context: 实质是一个Map; //ognl获取context中数据要加#号
3.ValueStack的获取:
ValueStack valuestack = ActionContext.getContext().getValueStack();
这里的ActionContext是action的上下文,作用是管理context,当前Action类的ActionContext通过它的静态方法getContext() 获取
ActionContext actioncontext = ActionContext.getContext();
每有一次http请求,struts2就会创建对应的ActionContext,它和当前线程绑定.
浏览器发送request---创建ValueStack对象---创建ActionContext对象(管理context)---创建Action对象
4.数据的存取
(1)ValueStack存储数据.(主要是向root中存储)
手动存储:
push方法:直接将对象压入到ValueStack的root
set方法: 创建一个Map压入到root,再把数据以键值对<k,v>的形式存放到这个map中.
public String execute(){
ValueStack valuestack = ActionContext.getContext().getValueStack();
valuestack.push("aaa");//push方法
valuestack.set("username","aaa");//set方法
return "success";
}
自动存储:
在框架源码的DefaultActionInvocation类的init方法内:首先创建了当前访问的Action对象,然后通过stack.push(action)将当前访问的Action对象存放到valueStack的root中,也就是每次请求访问action的时候,都会构造出action对象并将这个action对象存储到valueStack的root(ArrayList)中。
在浏览器访问action的时候ModelDrivernInterceptor这个拦截器会执行如下代码:
也就是在访问action类时,会先判断action是否实现了ModelDriven接口,如果实现了这个接口,就通过action类里实现的getModel()方法获取model对象push到root中.
(2)ognl在jsp页面中的获取ValueStack中的数据:
(a).在jsp页面上加上taglib指令:
<% taglib uri="/struts-tags" prefix="s" %>
(b)使用ognl表达式获取数据:
<s : property value="username"/>可以查看root中存放的username
<s : property value="[0]"/> 可以查看root中从第0项(栈最顶端)开始向下的所有内容.
<s : property value="[0].top"/> 可以查看root中第0项的内容.
<s : property value="#parameters"/> 从context 中获取封装请求参数的map对象
获取自动存放的数据需要在action类中提供get方法.
(3)一些常见的获取数据标签:
(a) 获取错误信息:
让action类继承ActionSupport类,ActionSupport类中定义了addActionError方法,在页面中可以直接使用struts2提供的标签 <s : actionerror /> 来显示错误信息:
ActionSupport类中还有addActionMessage方法和addFieldError方法可以传递简单的字符串.
this.addActionMessage("用户名不能为空");
this.addFieldError("password","密码错误");
在页面上可以相应的使用<s: actionmessage/> <s: fielderror fieldName="password" />来获取
(b)使用<s: iterator>标签来完成遍历展示集合中的对象.
①<s: iterator value="存入root的集合名" var="xxx">
//带var属性,每次取得一个对象以 xxx 为key存放到context中.
//再从context中获取该对象,然后获取对象的属性.
<tr>
<td><s: property value="#xxx.属性名"></td>//注意加#号,因为此时是从context中取值
<td><s: property value="#xxx.属性名"></td>
</tr>
</s: iterator>
②<s: iterator value="存入root的集合名" >
//不带var属性,每次取得一个对象存放到root中
//再从root中获取该对象,然后获取对象的属性.
<tr>
<td><s: property value="[0].top.属性名"></td>//获取刚存入root顶部的元素
<td><s: property value="属性名"></td>
</tr>
</s: iterator>
③也可以将集合声明成action类的属性,并提供get方法,这样也能在页面获取到数据.
具体步骤等有时间再研究. _(:з」∠)_