Struts2学习笔记__OGNL

参考https://blog.csdn.net/tjcyjd/article/details/6850203

先需弄懂OGNL的一些知识:

1.OGNL表达式的计算是围绕OGNL上下文进行的。
OGNL上下文实际上就是一个Map对象,由ognl.OgnlContext类表示。它里面可以存放很多个JavaBean对象。它有一个上下文根对象。
上下文中的根对象可以直接使用名来访问或直接使用它的属性名访问它的属性值。否则要加前缀“#key”。

2.Struts2的标签库都是使用OGNL表达式来访问ActionContext中的对象数据的。如:<s:propertyvalue=“xxx”/>。

3.Struts2将ActionContext设置为OGNL上下文,并将值栈作为OGNL的根对象放置到ActionContext中。

4.值栈(ValueStack) :
可以在值栈中放入、删除、查询对象。访问值栈中的对象不用“#”。
Struts2总是把当前Action实例放置在栈顶。所以在OGNL中引用Action中的属性也可以省略“#”。

5.调用ActionContext的put(key,value)放入的数据,需要使用#访问。

OGNL中重要的3个符号:#、%、$:

"#"声明OGNL表达式

作用:访问OGNL上下文和Action上下文
− 主要有3种用途:
  1. 能够访问OGNL上下文ActionContext资源,相当于ActionContext.getContext()
    访问非根对象属性,例如#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。实际上,#相当于ActionContext. getContext();#session.msg表达式相当于ActionContext.getContext().getSession(). getAttribute(“msg”) 。

 parameters:包含当前HTTP请求参数的Map,#parameters.id[0]作用相当于request.getParameter(“id”)
例如:http://localhost:8080/struts2/ognl.action?id=1&id=2&id=3
#parameters.id输出:1,2,3
#parameters.id[0]输出:1

 request:包含当前HttpServletRequest的属性(attribute)的Map,#request.userName相当于request.getAttribute("userName")

 session:包含当前HttpSession的属性(attribute)的Map, #session.userName相当于session.getAttribute("userName")

 application:包含当前应用的ServletContext的属性的Map,#application.userName相当于application.getAttribute("userName")

 attr:用于按page->request->session->application顺序访问其属性。
#attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止 。

  1. 用于过滤或筛选集合,例如:books.{?#this.price<20},表示所有的price<20的书
    作用:用表达式从集合中选择某些元素,并将结果保存到新的集合中。
    特殊符号:

    ? – 所有满足选择逻辑的对象
    ^ - 第一个满足选择逻辑的对象
    $ - 最后一个满足选择逻辑的对象

  2. 构造Map,如#{‘foo1’:‘bar1’,‘foo2’:‘bar2’}
    创建set集合对象

    	\<s:set name="books" value="#{'book1':'23', 'book2':'55'}" />
    	
     	\<p>book1的价格是: <s:property value="#books['book1']" /></p>

注意:
Set由于是无序的,所以不能使用下标获取数据
即不能使用#books[0]

Struts2学习笔记__OGNL

“$” 操作符

用于在国际化资源文件中,引用OGNL表达式

<action name=“AddPhoto” class=“addPhoto”>
           <interceptor-ref name=“fileUploadStack” /> 
           <result type=“redirect”>
                       /register.jsp?name=${name}
           </result>
  </action> 

在Struts 2框架的配置文件中引用OGNL表达式

"%"显示声明OGNL表达式

%用于表示某字符串为一个OGNL表达式。
某些标签种既能接收字符串,又能接收OGNL表达式。
标记%的被当作OGNL表达式并被执行,没有标记%的被当作普通的字符串

<struts:label label=”#request.account”></struts:label>		
//普通字符串,输出#request.account

<strtus:label label=”%{#request.account}”</struts:label>	
//OGNL,输出request的account属性值

字符串常量

以单引号或双引号码括起的字符串,单个字符的字符串常量需用双引号。

例如:<s:property value=" 'You said,\"Hello World\"。’ ">
说明:不能少单引号,否则会当成根对象的属性名

数值常量

用单引号括起来的字符

逗号“,”操作符

作用:用于分隔两个以上独立的表达式,整个表达式的值是最后一个子表达式的值
例如:name, #manager.name

花括号{}操作符

作用:用于创建列表,其中元素之间使用逗号分隔。
例如:三个元素的列表{“李”,“张”,“王”}

in和not in操作符

作用:用于判断一个值是否在集合中
例如:判断一个对象是否存在List集合中?

     <s:if test="'foo' in {'foo','bar'}">
                 muhahaha
          </s:if>
          <s:else>
                   boo
          </s:else>

访问属性

名字属性获取:<s:property value=“user.username”/>

地址属性获取:<s:property value=“user.address.addr”/>

访问方法

调用值栈中对象的普通方法:<s:property value=“user.get()”/>

调用静态方法和静态字段

格式:@[email protected]() //调用静态方法
@[email protected] //调用静态字段

说明:class须给出完整的类名,若省略,默认值java.lang.Math
例如:@@max(5,3) //调用java.lang.Math的max方法

调用Action中的静态方法:<s:property value="@[email protected]()"/>

调用JDK中的类的静态方法:<s:property value="@[email protected](44.56)"/>

调用JDK中的类的静态方法(同上):<s:property value="@@floor(44.56)"/>

调用JDK中的类的静态方法:<s:property value="@[email protected]()"/>

调用普通类中的静态属性:<s:property value="@[email protected]"/>

在struts.xml中加入(<constant name="struts.OGNL.allowStaticMethodAccess" value="true"></constant> )表示可以访问静态方法

调用构造方法

作用:OGNL支持对构造方法的调用,从而创建一个新的对象
例如:new java.util.ArrayList() //须用完整的限定类名
调用普通类的构造方法:<s:property value=“new struts.vo.Student(‘李晓红’ , ‘美女’ , 3 , 25).username”/>

数组和列表索引

例如:数组:array[0],list[0] //得到第1元素
表达式:{‘wang’,‘zhang’,‘li’}[1] //得到结果是第2元素,即list.get(1)

获取List:<s:property value="testList"/><br>

获取List中的某一个元素(可以使用类似于数组中的下标获取List中的内容):

<s:property value="testList[0]"/><br>

获取Set:<s:property value="testSet"/><br>

获取Set中的某一个元素(Set由于没有顺序,所以不能使用下标获取数据):

<s:property value="testSet[0]"/><br> ×

获取Map:<s:property value="testMap"/><br>

获取Map中所有的键:<s:property value="testMap.keys"/><br>

获取Map中所有的值:<s:property value="testMap.values"/><br>

获取Map中的某一个元素(可以使用类似于数组中的下标获取List中的内容):

<s:property value="testMap['m1']"/><br>

获取List的大小:<s:property value="testSet.size"/><br>

参考:https://blog.csdn.net/tjcyjd/article/details/6850203

访问集合 – 投影、选择(? ^ $)

利用选择获取List中成绩及格的对象:<s:property value=“stus.{?#this.grade>=60}”/>

利用选择获取List中成绩及格的对象的username:

<s:property value=“stus.{?#this.grade>=60}.{username}”/>

利用选择获取List中成绩及格的第一个对象的username:

<s:property value=“stus.{?#this.grade>=60}.{username}[0]”/>

利用选择获取List中成绩及格的第一个对象的username:

<s:property value=“stus.{^#this.grade>=60}.{username}”/>

利用选择获取List中成绩及格的最后一个对象的username:

<s:property value=“stus.{$#this.grade>=60}.{username}”/>

利用选择获取List中成绩及格的第一个对象然后求大小:

<s:property value=“stus.{^#this.grade>=600}.{username}.size”/>

创建列表List

语法: {e1,e2,e3}
示例:

<s:select label="label" name="name"
        list="{'name1','name2','name3'}" value="%{'name2'}" />

结果:生成了一HTML Select对象,可选的内容为: name1,
name2,name3,默认值为:name2。

Struts2学习笔记__OGNL

创建数组

例如:new int[]{1,2,3}
new int[5] //数组中的元素初始化为0
索引:new int[]{1,2,3}[1]
注意:数组特殊的属性length,OGNL中可访问:array.length

.[N]语法

  1. 提问:访问employee的name属性,应该如何写表达式呢?
  2. 格式:[N].xxx (N是从0开始的整数)
  3. 作用:使用[N].xxx这样的语法来指定从哪一个位置开始向下查找对象的属性,表达式[1].name访问的就是employee对象的name属性。
  4. 注意:在使用[N].xxx语法时,要注意位置序号的含义,它并不是表示“获取栈中索引为N的对象”,而是截取从位置N开始的部分栈
  5. 示例:
    栈中有三个对象:Object0,Object1和Object2都有name属性
    表达式name访问的是Object0的name属性
    [1].name访问的是Object2的name属性,因为[1]是一个包含Object1和Object2的部分栈,而且只有Object2有name属性。
    Struts2学习笔记__OGNL

.top关键字

top用于获取栈顶的对象,结合[N].xxx语法,就可获取栈中任意位置的对象。
例如:

  1. [0].top获取Object0(等同于top),
    [1].top获取Object1
    [2].top获取Object2,
    [2].top.name访问Object2中的name属性

OGNL上下文中的根对象可以直接访问,
而引用上下文中的其他对象则需要使用“#”来标记
值栈中的任何对象都可以直接访问,而不需要使用 “#”

struts2标签的属性按照下列的三个规则进行计算。
(1)所有的字符串属性类型都会解析“%{…}”这样的语法。
(2)所有的非字符属性类型都不会被解析,而是直接被看作一个OGNL表达式进行求值
(3)对于第二个规则的例外情况是,如果非字符串属性使用了“%{…}”语法,那么%{…}将被忽略,花括号中的内容将作为表达式计算。
如果大家在使用标签时, 忘记了某个属性是字符串类型,还是非字符串类型,那么有一个简单的方法,那就是不考虑它是什么类型,统一使用“%{…}”语法。

Struts2 控制标签 【ControlTagLib】

控制标签主要用来完成流程的控制,如条件分支、循环操作,也可以实现对集合的排序和合并。
控制标签包含下面几个:

 if:用于控制选择输出。
 elseif:同if标签结合使用,用来控制选择输出。
 else:同if标签结合使用,用来控制选择输出。
 append:用来将多个集合拼接为一个新的集合。
 generator:为一个字符串解析器,用来将一个字符串解析为一个集合。
 iterator:迭代器,用来迭代输出集合数据。
 merge:用来将多个集合拼接为一个新的集合,同append有所区别。
 sort:用来对集合排序。
 subset:用来截取集合的部分集合,开成新的集合子集合。

 if/elseif/else标签 <ifTag.jsp>
if/elseif标签属性test:为必填属性,是一个Boolean类型值,决定是否显示if标签内容。

 iterator(迭代标签) <iterator-list.jsp>
iterator标签主要是对集合进行迭代操作,集合可以使List、Map、Set和数组。
使用iterator标签对集合进行迭代输出时,可以指定如下三个属性:
 value:这是一个可选的属性;用于指定被迭代的集合,被迭代的集合通常都使用OGNL表达式指定。如果没有指定value属性,则使用ValueStack栈顶的集合
 id:这是一个可选属性;指定了集合里元素的ID,可以用var代替
 status:这是一个可选的属性,指定迭代时的IteratorStatus实例,通过该实例可以判断当前迭代元素的属性
 该对象常用的方法有:
− int getCount():返回当前迭代元素的个数。
− int getIndex():返回当前迭代元素的索引值。
− boolean isEven():返回当前迭代元素的索引值是否为偶数。
− boolean isOdd():返回当前迭代元素的索引值是否为奇数。
− boolean isFirst():返回当前迭代元素的是否是第一个元素。
− boolean isLast():返回当前迭代元素的是否是最后一个元素。
使用iterator标签的属性status时,其实例对象包含以上的方法,而且也包含的有对应的属性,如#status.count、#status.even、#status.odd、#status.first等。

append标签
用来将多个集合拼接为一个新的集合。目的就是可以将多个集合使用一个标签完成迭代
 使用append标签时需要指定一个var属性(也可以使用id属性),该属性确定拼接生成的新集合的名字,该新集合被放入StackContext中。
 append标签可以接受多个<s:param>子标签,每个子标签指定一个集合,<s:append>标签负责将<s:param>标签指定的多个集合拼接成一个集合

merge标签 < merge.jsp>
merge标签和append标签所实现的功能一样,也是将多个集合连接成一个新集合,但是在两个标签生成的新集合中,元素的排序方式有所不同。Struts2学习笔记__OGNL

generator标签 <generator.jsp>
用来将指定的字符串按规定的分隔符分解为多个子字符串,生成的多个子字符串可以使用iterator标签输出。
 可以理解为generator将一个字符串转化成一个Iterator集合。有点类似于String对象的split()方法,但功能更加强大
 在该标签的标签体内,整个临时生成的集合将位于ValueStack的顶端,但一旦该标签结束,该集合将被移除ValueStack
 常见属性:
– count:可选,指定生成集合中元素的总数
– separator:必选,解析字符串的分隔符
– val:必选,被解析的字符串
– converter:可选,指定一个转换器,负责将集合中的每个字符串转换程对象。属性值必须是一个org.apache.Struts2.until.IteratorGenerator.Converter对象
– var:可选,如果指定该属性,将生成的Iterator对象放入StackContext中,必须通过#name形式访问;如果不指定,只能在标签内部进行访问

subset标签 <subset.jsp>
 subset标签用于筛选集合里元素,它使用一个Filter,将不合格的元素过滤掉,剩下原集合的一个子集
 可以由开发者自定义截取标准
 在subset标签内,生成的子集合放在ValueStack的栈顶;如果该标签结束后,生成的子集合将被移除ValueStack栈
 属性:
– count:可选属性,指定子集中元素的个数;如果不指定该属性,则默认取得资源集合的全部资源
– source:可选属性,指定源集合;如果不指定,默认取得ValueStack栈顶的集合
– start:可选属性,指定子集从源集合的第几个元素开始截取;默认从第一个元素(0)开始
– decider:可选属性,指定开发者自己决定是否选中该元素;该属性必须指定一个org.apache.strtuts2.util.SubsetIteratorFilter.Decider对象
– var:可选属性,如果指定则生成的Iterator对象设置成page范围的属性
 Struts2允许自定义截取标准,如果要实现自定义截取标准,则需要实现一个Decider类,Decider类需要实现SubsetIteratorFilter.Decider接口,并且实现一个boolean decide(Object element)方法,表示如果返回真,则该元素将被选入子集中。<subset-decider.jsp>

sort标签
 Sort标签根据comparator属性指定的比较器对集合进行排序,并将排序后的迭代器压入值栈的栈顶。在sort标签的内部,你可以使用iterator标签取出栈顶的迭代器对排序后的元素进行迭代。当sort标签结束时,栈顶的迭代器将被删除。
 sort标签进行排序时,必须提供自己的排序规则,即实现自己的Comparator,而且Comparator需要实现java.util.Comparator接口
 属性:
– comparator:必选属性,指定进行排序的Comparator对象
– source:可选属性,指定被排序的集合;如果不指定,则对ValueStack栈顶的集合进行排序
– var:可选属性,如果指定则生成的Iterator对象设置成page范围的属性