一.Ognl表达式语言
1.初步了解Ognl表达式
1).Object Graphic Navigation Language:对象图导航语言,是开源项目.
struts2标签取值,默认使用OGNL作为默认的表达式.
2).OGNL优势
a.支持对象方法调用;b.支持类静态的方法调用和值访问,表达式的格式:
@[类型(包括包路径)]@[方法名|值名]
如:@java.lang.String@format('foo%s','bar')
或@tutorial.MyConstant@APP_NAME;
c.支持赋值操作和表达式串联如:price=100,discount=0.8,calculatePrice();表达式返回结果为80;d.访问OGNL上下文(OgnlContext)和ActionContext;e.操作集合对象.
3).OGNL的上下文(OgnlContext),是Map集合结构,它实现了java.utils.Map接口.
2.OgnlContext:OGNL上下文对象
OGNL上下文对象是Ognl表达式语言的核心.
<span style="font-size:14px;">//在类中初步了解OgnlContext对象</span></span>
<span style="font-size:14px;"> public class OgnlContextDemo { // 模拟数据,user对象 private static User user = new User(); static { user.setId(100); user.setName("老张"); //Address是一个对象 Address address = new Address(); address.setProvince("广东省"); address.setCity("广州"); user.setAddress(address); } /* * Ognl取值: * # 获取根元素的值,不需要写#号, 直接写对象或对象的属性即可! * # 非根元素取值,需要用#号! * */ @Test public void testApp() throws Exception { OgnlContext context = new OgnlContext(); // 当成map使用 context.put("cn", "China"); // 获取数据 Object value = context.get("cn"); System.out.println(value); /* * 1. 用其他方法设置值,如往根元素设置数据 */ // 往根元素设置值 context.setRoot(user); // 使用Ognl表达式语言取值 // 构建一个表达式对象 Object ognl = Ognl.parseExpression("address.province"); // 解析表达式,取值 value = Ognl.getValue(ognl, context, context.getRoot()); // 测试 System.out.println(value); } // 非根元素取值 @Test public void testApp2() throws Exception { OgnlContext context = new OgnlContext(); // 往map中存放数据,即非根元素存放数据 context.put("users", user); /* * ognl表达式取值 */ Object ognl = Ognl.parseExpression("#users.address.province"); Object value = Ognl.getValue(ognl, context, context.getRoot()); System.out.println(value); } // 其他, @Test public void testApp3() throws Exception { OgnlContext context = new OgnlContext(); /* * 构建ognl表达式, 支持静态方法调用 * 调用类的静态方法,语法:@Math@floor(10.19) * 如果是Math类的静态方法,因为比较常用,可以省略类名称! : @@floor(10.19) */ Object ognl = Ognl.parseExpression("@@floor(10.19)"); // 解析 Object value = Ognl.getValue(ognl, context, context.getRoot()); System.out.println(value); } }</span></span>
3.ValueStack值栈对象
struts框架在后台运行的数据,都被保存在值栈中.
值栈:(list集合/map集合)
1).值栈是struts数据存储的中转站,struts运行的数据都会存储在值栈中.
包括,Action对象的数据与Map域中存放的数据.
2).每次用户访问struts的Aciton:
创建一个Action对象、创建一个ValueStack对象、创建一个ActionContext对象,然后,把Action对象放入值栈,以及其他数据也会放入值栈中,可以通过ActionContext对象取值栈中的值.
3).jsp页面取值
struts会把整个值栈保存到request域对象中(request.setAttribute('struts.valueStack',valueStack));值栈保存所有的值.
可用request对象/ActionContext对象取值
二.struts标签
用于在jsp页面取值,类似jstl标签.使用Ognl表达式语言取值.
1.jsp中Ognl表达式和struts标签的使用
ognl表达式语言取值, 根元素取值<br/>
<!-- property标签取值,没有指定表达式,默认取栈顶元素值! -->
<s:property/>
<s:property value="user"/>
<s:property value="user.id"/>
<s:property value="user.name"/>
<br/> ognl表达式语言取值, 非根元素取值<br/>
<s:property value="#request.request_data"/>
<s:property value="#session.session_data"/>
<s:property value="#application.application_data"/>
<!--
获取请求数据
地址:http://localhost:8080/day30/ognl?name=testName
-->
<s:property value="#parameters.name"/>
<!--
attr 自动获取request/session/application 中map数据
--><br/>
<s:property value="#attr.request_data"/>
<s:property value="#attr.session_data"/>
<s:property value="#attr.application_data"/>
<!-- 调试标签: 查看struts运行的数据(ValueStack),也可以了解值栈的结构 -->
<s:debug></s:debug></span>
2.Struts框架中的几种取值符号
<span style="font-size:14px;"><strong>$ struts在xml中取值符号</strong>
<action name="demo" class="cn.struts.c.DemoAction">
<!-- 取DemoAction中的name字段的值-->
<result name="success">/c.jsp?name=${name}</result>
</action>
<strong># 非根元素, 或动态构建map集合</strong>
<s:property value="#session.session_data"/>
<s:property value="#application.application_data"/>
<strong>% 提供一个Ognl表达式运行环境</strong>
<s:property value="%{#request.request_data}"/>
<s:iterator var="file" value="#fileNames" status="st">
<!-- 构建Gognl表达式环境,去迭代器中file的值-->
<s:a href="down_down?fileName=%{#file}">下载</s:a></span>
3.几个常用的Struts标签
<span style="font-size:12px;"> </span><span style="font-size:14px;"> <strong> <!-- 引入struts标签库,可以用Ognl获取域对象中的值 --></strong>
<%@taglib uri="/struts-tags" prefix="s" %>
<br/>1. if-else 标签 <br/>
<s:if test="userName != null">
根,取值,成功!
</s:if>
<s:else>
没有获取到userName!
</s:else>
<br/>2. 迭代标签 list <br/>
<!-- 方式1: 迭代的数据,会存放到map集合,所有获取每一个数据要用#符号! -->
<!-- 方式2: 迭代的数据,会存放到map集合,同时会存放到值栈的根元素中; 当前迭代结束,移除值! -->
<s:iterator var="user" value="#request.list"><!-- list是Action-->
<s:property value="#user.id"/>
<s:property value="#user.name"/> <br/>
</s:iterator>
<br/>3. 迭代map集合<br/>
<s:iterator var="en" value="#request.map">
<s:property value="#en.key"/>
<s:property value="#en.value.name"/> <br/>
</s:iterator>
<hr/>4. 迭代结合的另外的方式<hr/>
<!-- 每次迭代出来的对象都会放到值栈的栈顶(根) -->
<s:iterator value="#request.list">
<s:property value="id"/>
<s:property value="name"/> <br/>
</s:iterator>
<s:iterator value="#request.map">
<s:property value="key"/>
<s:property value="value.name"/> <br/>
</s:iterator>
***********************************************
<!-- 取值
若取根元素的值,可以直接写该元素名称,不要 #
-->
<s:property value="#parameters.name"/>
<!-- 动态构建list集合 -->
<s:iterator var="str" value="{'a','b','c'}">
<s:property value="#str"/>
</s:iterator>
<HR/>
<!-- 动态构建map集合 --><hr/>
<s:iterator var="en" value="#{'cn':'China', 'usa':'America'}">
<s:property value="#en.key"/>=
<s:property value="#en.value"/> <br/>
</s:iterator>
<hr/>
<!--
本身就是一个字符串指向该对象/属性,而是一个可取值的Ognl表达式
即,value后面的字符串是指向对象或属性/字段,
此时可以不构建Ognl表达式环境.
当然,写上肯定是不会错的.
-->
<s:property value="%{name}"/>
<s:property value="%{#cn}"/>
<!-- 本文框 theme="simple" 一般定义常量实现!-->
<!--
value后面的值就是一个普通字符串,要用其取值,就要构建OGnl表达式环境,
用 % 构建.
name后面也是一个对象类型的字符串,即可以看做是Ognl表达式,取值.
-->
<s:textfield name="name" value="%{#cn}" theme="simple"></s:textfield></span>