OGNL的使用
- 本人独立博客https://chenjiabing666.github.io
OGNL简介
- OGNI是一种对象图导航语言(object graphics navigation language) ,这也是一种表达式语言,这个和EL表达式一样,但是EL表达式只能在JSTL标签库中使用,这个OGNL只能在struts标签库中使用。
值栈(valueStack)
- 值栈就是存储Action的信息,包括其中定义的成员变量和其他的一些自己的属性,比如error,fieldError,如果想要让action中属性在值栈中显示或者获取,一定要为这些属性设置get,set方法
- 值栈是存储的action的栈,同时可以存储多个action,先执行的先进栈
- 值栈中的元素是根元素,访问值栈中的元素不需要使用
#
(#是访问非根元素的值,比如#session.username
) - 在jsp页面可以使用struts标签库
<s:debug/>
,查看值栈中的内容
实验
- 我们新建一个Action类,用表单传递数据请求action,最后action跳转到success.jsp页面,我们在success.jsp使用
<s:debug>
查看此时值栈中的数据- 其中的属性必须要有get,set方法
- LoginAction
//实现ModelDriven接口<>指定的泛型为JavaBean类
public class LoginAction extends ActionSupport {
private User user;
private String tips;
public String getTips(){
return tips;
}
public void setTips(String tips){
this.tips=tips;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() {
System.out.println("执行execute方法");
System.out.println(this.getUser().getName() "------" this.getUser().getPassword());
return SUCCESS;
}
- success.jsp页面
- 其中要引用struts2的标签库
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<s:debug></s:debug>
</body>
</html>
- 此时我们可以看到在值栈中有个user属性,并且有LoginAction
常量
- 我们现在先接触一下
<s:property value="">
标签,struts2中的标签在后面再详细讲解,这个标签的意思是输出属性的值- 这个标签中的value属性填写的是OGNL表达式,如果我们要输出一个常量,那么我们必须使用单引号
- 引用struts2中的标签库
<%@ taglib prefix="s" uri="/struts-tags" %>
字符常量
- 如果我们仍然使用上面的实例,但是我们要在success.jsp页面中使用OGNL使用显示表单传递过来的值,其中我们还输出自己的一个常量字符串
- success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1><s:property value="user.name" default="如果为null,输出这个字段"/></h1>
<h1><s:property value="user.password" default="如果为null,输出这个字段" /></h1>
<h1>输出一个字符串常量: <s:property value="'jack'"/></h1>
<s:debug></s:debug>
</body>
</html>
数值常量
- int 1,2,3
- double 1.24d或者1.24
- float 1.23f
- long 122l 最后一个是字母l
- BigDecimal 123b
- BigInteger 123h
- 在其中直接输出即可:
<s:property value="1"/>
布尔常量
- 直接输出即可
<s:property value="true"/>
总结
- 当需要输出一个字符串常量的时候,一定要使用单引号,否则就会默认的将其作为OGNL表达式,输出的就为空
集合list
- OGNL中的list相当于数组,其中存放的可以是任意类型的数据
- 读取的时候直接使用数组的形式读取即可,使用索引读取即可
- 我们的创建形式是使用
<s:set>
标签,因此这个变量不是值栈中的,需要使用#
<!-- 创建list -->
<s:set var="list" value="{1,2,3,'jack',true}"></s:set>
<s:property value="#list[0]"/><br>
<s:property value="#list[4]"/>
Map
- 使用
#{}
的形式创建,其中存放的是键值对(key-value)的形式 - 读取的方式有两种
- map['key']
- map.key
<s:set var="map" value="#{'name':'jack','age':22}"></s:set>
<s:property value="#map['name']"/>
<s:property value="#map.age"/>
访问action中的属性值
- action都是存放在值栈中,我们可以使用OGNL读取值栈中的数据
- 使用上面的LoginAction类,我们通过表单提交到这个LoginAction中,跳转到success.jsp页面中,那么我们就可以在success.jsp页面中访问LoginAction属性的值(前提是属性必须有get,set方法)
- LoginAction中的属性是一个User对象,那么我们既可以获取这个User对象,之后在获取User对象中的数据了,这个相当于链式操作,前提还是有get,set方法
<!-- 这里的user一定要和LoginAction中的成员变量User的对象字段相同 -->
User对象中的name属性:<s:property value="user.name"/>
User对象中的age属性:<s:property value="user.age"/>
操作符
#
- 值栈中的的属性称为是根属性,
#
访问的是非根属性,就不是值栈中的值,比如#session.username 相当于调用ActionContext.getContext.getSession.getAttribute("username")
- 创建Map
- 过滤和投影
$符号
- 在国际化文件中使用OGNL表达式,例如年龄必须在到{max}之间
- 在Struts配置文件中使用OGNL表达式,例如两个Action之间进行跳转,并且附带参数
% 符号
- 当标签的属性为字符串类型时,计算OGNL表达式的值。
<s:url value="#map.name"/>
<br>
<s:url value="%{#map.name}"/>
大括号 {}
- 用来创建一个Map,其中存放的是键值对
- 创建一个list集合
<s:set var="map" value="#{'name':'jack','age':22}"></s:set>
<s:property value="#map['name']"/>
in ,not in
- 判断某一个值是否存在一个集合中,返回的是布尔值
- 不过经过自己测试,只有数字类型的可以判断出来,字符串不能判断出来,如果哪位能够测出来,和我说说原因
<!-- 创建一个集合list -->
<s:set var="list" value="{1,2,3,'jack','Tom'}"></s:set>
<s:property value="1 in #list"/><br>
<s:property value="1 not in #list"/><br>
<!-- 没有结果 -->
<s:property value=" 'jack' in #list"/><br>
- 这个和java是一样的,如果两个整数相加就执行整数相加,如果字符串相加就拼接
<s:property value="2 3"/>
<s:property value="'ce' 22"/>
集合的伪属性
集合的伪属性是用来代替java集合API的方法的属性,比如迭代器的使用
- List
- list.iterator
- list.size
- Set
- set.iterator
- set.isEmpty
- Map
- map.keys (map.keySet)
- map.values (map.values)
- Iterator
- Iterator.next
- Iterator.hasNext
- Enumeration
- enum.next
- enum.hasNext
<%--创建列表 --%>
<s:set var="list" value="{1,'陈加兵'}"></s:set>
<%-- 创建Map --%>
<s:set var="map" value="#{'one':'陈加兵','tow':'郑元梅'}"></s:set>
<%-- 创建数组 --%>
<s:set var="number" value="new String[]{'aaa','bbb','ccc']"></s:set>
<%-- 获取list的迭代器对象 --%>
<s:set var="iter" value="#list.iterator"></s:set>
list的大小:<s:property value="#list.size"/>
<s:if test="#iter.hasNext">
list中的第一个元素的值:<s:property value="#iter.next"/>
</s:if>
<hr>
<%-- #map.keys返回的是set类型,然后使用迭代器输出即可 --%>
<s:property value="#map.keys.iterator.next" default="NULL"/>
<s:property value="#map.values"/>
投影
- 在OGNL中,投影是对一个集合中对每一个元素调用相同的方法,或者抽取相同的属性,并将一个结果保存为一个新的集合。
- 下面的例子是将集合list中的元素转换成字符串
<%--创建列表 --%>
<s:set var="list" value="{1,'陈加兵'}"></s:set>
<%-- 这个{#}首先会取list中的每一个元素然后赋值给tihs,接着调用toString方法转换为字符串 --%>
<s:property value="#list.{#this.toString()}"/>
选择
- 在OGNL中使用表达式从集合中选择某一些元素,并将这些元素保存到新的集合中
<%--创建列表 --%>
<s:set var="list" value="{1,2,3}"></s:set>
<%-- 选取大于2的元素组成一个新的集合 --%>
<s:property value="#list.{?#this>2}"/>
[N]语法
- 我们知道一次请求值栈中可以存放两个或者多个action(只需要设置result跳转类型为chain即可完成在action之间的跳转),那么我们一般取值栈中的值默认是获取栈顶的action,但是如果有多个action呢,此时我们需要获取其他action中的数据,这下就要用到
[N]
语法了 [N].propertyName
可以用来指定从值栈中的从上向下数位置N的action的属性值,N从事0开始的。
实现
- 假设我们有两个Action,一个是SimpleAction,一个是LoginAction(上面的,有一个属性为user),我们在在配置的时候,发出请求给SimpleAction,之后跳转到LoginAction(result的type类型为chain即可),之后跳转到success.jsp,那么此时的值栈中的action就有两个了,栈顶的是SimpleAction,第二个是LoginAction。
- 我们想要获取LoginAction属性user的值,在值栈中的位置是第二个,那么此时使用
[1].propertName
- 我们想要获取LoginAction属性user的值,在值栈中的位置是第二个,那么此时使用
User对象中的name:<s:property value="[1].user.name"/>
User对象中的age:<s:property value="[1].user.age"/>
top 语法
- 我们知道[N]语法中,如果想要访问栈顶的action属性使用
[0].propertyName
,我们也可以使用top,直接top.propertyName
即可
Struts2的命名对象
- 这些对象都不是值栈中的数据,因此需要使用
#
来获取 parameters
用来访问请求参数,比如#parameters.name
,# parameters [‘name’]
相当与request.getParameters(“name”)
request
用来访问request的属性,比如#request.name
或者# request [‘name’]
相当于request,getAttrubute(“name”)session
用来访问session属性,例如#session.name
或者#session[‘name’]
相当于 session.getAttribute(“name”)application
用来访问application属性,比如:#application.name
相当于application.getAttribute(“name”)attr
用来访问PageContext,如果PageContext不可用,则一次搜索request,session,application对象