OGNL是一种功能强大的表达式,和$表达式类似。但是功能更强。
又叫导航图语言。即一层一层的查找。
1. OGNL的应用场景:例如
标签中:和标签绑定时用的最多
<s:property value=”user.name”/>
前台传参:user.password,user.name都是OGNL表达式
配置文件中:这里不是$表达式,这是OGNL动态传递参数
<result
Type=”redirect”>/main.jsp?name=${name}
</result>
2. 包含的内容如下:
访问属性
访问方法
访问静态属性和方法
访问构造方法 不是重点
访问数组
访问集合
Lambda 不是重点
3. 详细讲解à访问属性
和标签中访问属性方法一样。
详细讲解à访问Action类中的静态方法
@+包名.类名@+静态方法
详细讲解à访问值栈中的普通方法(即非Action类中的方法)
类对象.静态方法
详细讲解à访问JDK类中的静态方法
@@+方法()
或者@+包名+@+方法()
详细讲解à访问普通类中的公有的静态属性(私有不能访问的)
@+包名.类名@+属性名
详细讲解à访问普通类中的构造方法
New 包.类名().属性 类名()表示构造方法,里面要写内容,用单引号隔开
重点:
详细讲解à访问数组
数组获取方法和集合一样。获取单个元素通过下标即可。但是开发中一般用List代替数组,因为数组是固定值的。没有可变的List方便。
详细讲解à访问集合
<s:property value=”集合对象名”/>会获取集合中所有内容
获取集合中的某一个元素:集合对象名[0] 即通过下标的方式:但是这种方法是数组专用的,仅限于 集合List 使用这种方式。(另外list里面可以存放重复数据)
那么对于Set (他不能存放重复数据,重复的会只显示一个元素,且无顺序显示,当然就不能通过下标取值了) 即不能用下标的方式获取某一个元素。但是可以通过迭代的方式来获取单个元素。
对于Map想获取单个元素的方法:集合对象名[‘键名称’] 例如: testMap['m1']
总结:这3种集合获取所有元素的方法一致:<s:property value=”集合对象名”/>
获取单个元素方法都不相同。
访问集合的另一个重点:投影,选择(?^ $)
1. 投影
他相当于数据库中的数据,但是他可以取出某一列的数据。例如单单取出姓名,年龄等等。语法:对象名。{username};例如:stus。{username};即取出原有集合中的所有name组成一个新集合。好处是不用写任何循环的java语句就可以取出多个值。
如果想取出姓名这个集合中的某一个姓名。可以通过下标获取。例如:stus。{username} [0] 即取出第一个名字。
2. 选择
即在投影的基础上,添加条件。例如获取List中成绩及格的对象。1.只显示真假stus.{#this.grade>=60};2.显示及格分数和其他信息stus.{?#this.grade>=60};其中?就代表选择;3.只显示及格的姓名stus.{?#this.grade>=60}.{username}
其中#this表示当前的元素,其中3表示选择和投影的混合使用。
4.获取及格的第一个对象的username:stus.{?#this.grade>=60}.{username}[0]
但是这种方式不太好,如果取得值不存在会报越界的异常。如果grade>100会错。
改进的方法:stus.{^#this.grade>=60}.{username}[0].这两种方法都表示取得第一个元素。但是有区别:前者得到的是字符串 张三,后者得到的是链表 [张三]。后者的好处是还可以取得size:stus.{^#this.grade>=60}.{username}.size 如果条件是grade>=600;会得到 0;表示这样的值不存在。如果有存在满足条件的值则会得到1. 即可以对数据的存在性做出判断。但是前者没有这个功能。^表示取得第一个对象,$表示取得最后一个对象。
如果直接打印对象会输出一个内存地址的哈希值。如果想显示正常值,需要重写toString()方法 publicString toString(){}
集合的伪属性
OGNL能够引用集合的一些特殊的属性,这些属性并不是javaBeans模式,例如size(),length()等等。当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性
集合 | 特别属性 |
继承by(Map,List,Set) | size,isEcpty |
List | iterator |
Map | keys , values |
Set | iterator |
Iterator | next , hasNext |
Enumeration | next, hasNext, nextElement, hasMoreElements |
例如要获取List大小:对象名.size();同理获取Set大小:对象名.size()
获取Map中所有的键:对象名.keys;同理获取Map所有值:对象名.values;
OGNL中#的使用
#可以取出堆栈上下文中的存放的对象
名称 | 作用 | 例子 |
Parameters | 包含当前HTTP请求参数的Map | #parameters.id[0]作用相当于request.getParameter(“id”) |
request | 包含当前HttpServletRequest的属性 (attribute)的Map | #request.userName相当于 request.getAttribute(“userName”) |
session | 包含当前HttpSession的属性 (attribute)的Map | #session.userName相当于 session.getAttribute(“userName”) |
application | 包含当前应用的ServletContext的属性 (attribute)的Map | #application.userName相当于 application.getAttribute(“userName”) |
attr (一般用不到这个) | 用于按request > session > application 顺序访问其属性(attribute) | #attr.userName相当于 application.getAttribute(“userName”) |
OGNL中的%的使用:
1. 用%{}可以取出存在值栈中的Action对象,直接调用它的方法。
2. 例如你的Action如果继承了ActionSupport。那么在页面标签中,用%{getText(‘key’)}的方式可以拿出国际化信息。
OGNL中的%的使用:
1.$有两个主要用途
.用于在国际化资源文件中,引用OGNL表达式。${}
.在struts2配置文件中,应用OGNL表达式:例如在struts.xml文件中,当使用客户端redirect跳转时,可以用$传递参数。
<result
Type=”redirect”>/main.jsp?name=${name}
</result>
OGNL的核心—>值栈:
ValueStack对象。这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当struts2接受道一个.action的请求后,会先建立Action类的对象实例,但并不会调用Action方法,而是先将Action类的相应属性方的Valuestack对象的顶层节点(Valuestack对象相当于一个栈)。值栈是OGNL中上下文Context中的 根对象。有个优点。取值时可以省略 #。例如:
名字属性的获取:<s:property value=”user.username”/>这里user前面就没有#,因为user是放在值栈中的一个对象。
当2个action跳转时,并且是服务器跳转,(chain方式,一次请求)可以体现这方面。栈就是后进先出。可以用debug(AJAX技术)去查看栈。但是如果我们使用客户端跳转(2次请求不相关),既不能获取栈中的信息了。可以用Debug取查看。
当然,如果这2个Action我们都用redirectAction和redirect跳转可以通过传参的方式v2.jsp?username=${username}获取参数,但是这种方法太麻烦。
值栈
1. Top语法解决重名问题,例如我们在Action1,和Action2中都定义了学生类的一个对象s,按正常方式,栈是后进先出。那么我们会取到Action2(栈顶)中的 S。但是我们想要先去的Action1中的S 即:打破栈的规则。这里的[1]表示第2个,[2]表示第3个,以此类推。没有[0]
2. 使用Top获取值栈中的第2个对象(栈底):<s:propertyvalue=”[1].top.s”/>
3. 使用N语法获取值栈中第2个对象中的属性:<s:propertyvalue=”[1].s”/>则这两个结果一样。
4. @语法