介绍:
OGNL表达式 什么是表达式? 具有特殊意义的一串由数字、英文、和符号组成的式子
OGNL 存放东西用的 对象 变量 表达式 来快速的定位到整个变量
maven中央仓库地址
<!-- https://mvnrepository.com/artifact/ognl/ognl -->
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.1.10</version>
</dependency>
OgnlContext类 存放数据用
硬编码方式,了解OgnlContext对象,因为OgnlContext对象实现是Map接口,所有OgnlContext本质就是一个Map,可以使用map方法:
OgnlContext context = new OgnlContext();
context.put("uesr",user); //Map域
context.put("address",address); //Map域
context.setRoot(address); //Root域
代码如下
@Test
public void study01() throws OgnlException {
//存放OgnlContext context=new OgnlContext();
Study study=new Study();
context.setRoot(study);//根节点
context.put("text","在长期的服务过程中,我们经常会遇到前来咨询的用户与我们反馈以下这种情况:咨询者是一个前端人员,在项目开发的过程中需要与后端进行对接,遇到后端还没完成数据输出的情况下,他只好写静态模拟数据,在遇到大型项目的情况下,数据冗长、代码复杂、多样的数据类型包括IP、图片,地址,函数等,在极短的项目周期及验收时");
context.put("study",study);//往map域中存放数据
//获取
Object expression1 = Ognl.parseExpression("sid");
Object expression2 = Ognl.parseExpression("sname");
Object expression3 = Ognl.parseExpression("#study.Names.one");
Object value = Ognl.getValue(expression3, context,context.getRoot());
System.out.println(value);
//调用静态方法
Math.random();
Object expression = Ognl.parseExpression("@java.lang.Math@random()");
Object random = Ognl.getValue(expression, context,context.getRoot());
System.out.println(random);
//调用我自己的方法
Object expression4 = Ognl.parseExpression("@com.oracle.ognl.StringPlus@subString(#text)");
Object text = Ognl.getValue(expression4, context,context.getRoot());
System.out.println(text);
//OGNL表达式 支持 自动构建map和List
//构建一个List {1,2,3,4,5} List<Integer>
Object listExpression = Ognl.parseExpression("{1,2,3,4,5}");
List dataList= (List)Ognl.getValue(listExpression, context,context.getRoot());
System.out.println(dataList);
Object mapExpression = Ognl.parseExpression("#{'1':'张三','2':'李四'}");
Map dataMap= (Map)Ognl.getValue(mapExpression, context,context.getRoot());
System.out.println(dataMap);
}
Ognl表达式语言几个符号
% 符号的用法
• 强制字符串解析成OGNL表达式。
例如:在request域中存入值,然后在文本框(<s:textfield>)中取值,写在value里。<s:textfield value="%{#request.msg}"/>
• { }中值用引号引起来,此时不再是ognl表达式,而是普通的字符串,到底使用单引号还是双引号是由外层引号决定的。
<s:property value="%{'#request.msg'}"/>
$ 符号的用法 在配置文件中可以使用OGNL表达式,例如:文件下载的配置文件。EL表达式也是使用$
<action name="download1" class="cn.itcast.demo2.DownloadAction">
<result name="success" type="stream">
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachment;filename=${downFilename}</param>
</result>
</action>
OGNL 访问对象属性
< s:property value ="subject" />< s:property value ="person.name" />
< s:property value ="person.idcard.number" />
OGNL 调用方法
< s:property value ="person.getName()" />< s:property value ="person.name.toUpperCase()" />
OGNL 调用静态属性
< s:property value ="@fan.tutorial.model.Person@VERSION" />OGNL 调用静态方法
<!-- 在 struts.xml 中添加下面这行配置 --><!-- <constant name="struts.ognl.allowStaticMethodAccess" value="true"/> -->
< s:property value ="@fan.tutorial.model.Person@getVersion()" />
OGNL 调用构造方法
< s:property value ="new fan.tutorial.model.Address('广东茂名').name" />OGNL 使用索引访问数组和列表
< s:property value ="array[0]" />< s:property value ="personList[0].name" />
OGNL 操作符运算
< s:property value ="array[0] + 1" />< s:property value ="array[0] - 1" />
< s:property value ="array[0] * 2" />
< s:property value ="array[0] / 2" />
< s:property value ="array[0] % 3" />
OGNL 逻辑运算符
< s:set name ="x" value ="5" />< s:property value ="#x in array" />
< s:property value ="#x not in array" />
< s:property value ="#x > array[0]" />
< s:property value ="#x >= array[0]" />
< s:property value ="#x < array[0]" />
< s:property value ="#x <= array[0]" />
< s:property value ="#x == array[0]" />
< s:property value ="#x != array[0]" />
OGNL 访问命名对象 ( parameters、request、session、application、attr )
< s:property value ="#parameters.author" />< s:property value ="#request.message" />
< s:property value ="#session.message" />
< s:property value ="#application.message" />
< s:property value ="#attr.message" />
OGNL 访问集合的伪属性
点击这里 | 点击这里 | 点击这里 |
---|---|---|
类型 | 伪属性 | 伪属性对应的 Java 方法 |
List Set Map | size isEmpty | List.size() List.isEmpty() Set.size() Set.isEmpty() Map.size() Map.isEmpty() |
List Set | iterator | List.iterator() Set.iterator() |
Map | keys values | Map.keySet() Map.values() |
Iterator | next hasNext | Iterator.next() Iterator.hasNext() |
< s:property value ="personList.isEmpty" />
< s:property value ="map.keys" />
< s:property value ="map.values" />
< s:property value ="personList.iterator.hasNext" />
< s:property value ="personList.iterator.next.name" />
< s:property value ="person.addressSet.iterator.hasNext" />
< s:property value ="person.addressSet.iterator.next.name" />
OGNL 迭代集合
点击这里 | 点击这里 | 点击这里 |
---|---|---|
类型 | 伪属性 | 伪属性的作用描述 |
IteratorStatus | index | 当前元素的索引 |
IteratorStatus | first | 当前元素是否是集合的第一个元素 |
IteratorStatus | last | 当前元素是否是集合的最后一个元素 |
IteratorStatus | count | 当前迭代元素的数量,count = index + 1 |
IteratorStatus | even | index + 1 是否为偶数 |
IteratorStatus | odd | index + 1 是否为奇数 |
< tr align ="center" >
< td width ="2%" >索引 </ td >
< td width ="5%" >值 </ td >
< td width ="8%" >当前迭代的数量 </ td >
< td width ="8%" >迭代奇偶性 </ td >
< td width ="8%" >集合第一个元素 </ td >
< td width ="8%" >集合最后一个元素 </ td >
</ tr >
< s:iterator value ="array" var ="a" status ="status" >
< tr align ="center" >
< td >
< s:property value ="#status.index" />
</ td >
< td >
< s:property />
</ td >
< td >
< s:property value ="#status.count" />
</ td >
< td >
< s:if test ="#status.even" >偶 </ s:if >
< s:if test ="#status.odd" >奇 </ s:if >
</ td >
< td >
< s:if test ="#status.first" >是 </ s:if >
< s:else >否 </ s:else >
</ td >
< td >
< s:if test ="#status.last" >是 </ s:if >
< s:else >否 </ s:else >
</ td >
</ tr >
</ s:iterator >
</ table >
OGNL 投影
如果把集合中的数据想象成是数据库表中的数据,那么,投影就是从这张表中选取某一列所构成的一个新的集合。投影的语法:collection.{expression} < s:property value ="personList.{name}" />OGNL 过滤
OGNL 过滤也称为选择,就是把满足 OGNL 表达式的结果选择出来构成一个新的集合。过滤的语法:collection.{?expression} 或 collection.{^expression} 或 collection.{$expression}
点击这里 | 点击这里 |
---|---|
符号 | 作用 |
? | 选取与逻辑表达式匹配的所有结果 |
^ | 选取与逻辑表达式匹配的第一个结果 |
$ | 选择与逻辑表达式匹配的最后一个结果 |
#this | 代表当前迭代的元素 |
< s:property value ="array.{^#this > 5}" />
< s:property value ="array.{$#this > 5}" />
OGNL 投影和过滤
< s:property value ="personList.{?#this.sex.equals('female')}.{name}" />< s:property value ="personList.{^#this.sex.equals('female')}.{name}" />
< s:property value ="personList.{$#this.sex.equals('female')}.{name}" />
OGNL %{ } 语法
对于 ${ } 也许你并不会陌生,${ } 是 EL 表达式的语法,这里的 %{ } 是 OGNL 表达式的语法。也许你开始困惑,上面示例不是都在使用 OGNL 表达式吗?!没见 %{ } 出现过啊!好眼力!凡是属于 OGNL 表达式的串,你都可以使用 %{ } 来将它们包裹住,但这不是必须的。例如 <s:property value="expression" /> 中的 expression 在任何时候都是被当做 OGNL 表达式来处理的。 < s:property value ="subject" /> <!-- subject被OGNL进行表达式求值输出 -->
< s:property value ="i love java so much" /> <!-- 什么都不输出 --> 第2行之所以什么都不输出,是因为执行时环境把 i love java so much 这个字符串也当做是一个 OGNL 表达式来处理了,但在 OGNL 上下文中并找不到与这个 KEY 对应的值,因此什么都没有输出。
这是由于 <s:property /> 标签的 value 属性是 Object 类型引起的,凡是 Object 类型的标签属性的值,都会被当做是一个 OGNL 表达式来处理。
这种情况下的解决办法是:使用单引号将它们引起来,表明这是一个普通的字符串,而不是 OGNL 表达式。 < s:property value ="'subject'" /> <!-- 输出 subject -->
< s:property value ="'i love java so much'" /> <!-- 输出 i love java so much --> 再如 <s:textfield value="expression" /> 中的 expression 什么时候被当做 OGNL 表达式来处理就要取决于你是否使用了 %{ } 语法,如果使用了,那么它就是一个 OGNL 表达式,如果没有使用,那么它就只是一个普通的字符串而已。 < s:textfield value ="author" /> <!-- author被当做普通字符串原样输出 -->
< s:textfield value ="%{author}" /> <!-- author被OGNL进行表达式求值输出 -->
< s:textfield value ="person.name" /> <!-- person.name被当做普通字符串原样输出 -->
< s:textfield value ="%{person.name}" /> <!-- person.name被OGNL进行表达式求值输出 --> 这是由于 <s:textfield /> 标签的 value 属性是 String 类型引起的,凡是非 Object 类型的标签属性的值,是不会被当做一个 OGNL 表达式来处理的,
除非你使用了 %{ expression } 语法,执行时环境才会将 expression 当做是一个 OGNL 表达式来处理。
只有当你理解了上面的2个案例,你才能正确的使用 OGNL 表达式。
实际上规则非常简单,当标签属性的类型为 Object 类型时,标签属性的值就会被当做是一个 OGNL 表达式来处理,因此可省略 %{} ;
当标签属性的类型为 String 类型时,除非你使用了 %{ } 语法告诉执行时环境这是一个 OGNL 表达式,否则,标签属性的值会被当做是一个普通的字符串来处理。