Struts2之OGNL表达式语言

1.OGNL是Object-Graph Navigation Language的缩写,是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。其中OGNL用得最多的地方就是和Struts2的标签绑定,也可以在配置文件中通过${}使用OGNL表达式。

2.OGNL表达式中有几个常用的符号,下面介绍这三种符号的使用:

(1).OGNL中$号的使用:第一种,可以在国际化资源文件中引用OGNL表达式。第二种,可以在struts.xml配置文件中引用OGNL表达式。

(2).OGNL中%号的使用:%符号的用途是在标志属性为字符串类型时,计算OGNL表达式的值。

~使用%{}可以取出保存在值堆栈中的Action对象,直接调用它的方法。

~如果Action类继承了ActionSupport类,那么在页面标签中可以使用%{getText(‘key‘)}获取国际化信息。

(3).OGNL中#号的使用:OGNL中的#号可以取出堆栈上下文中存放的对象,访问OGNL上下文和Action上下文。#相当于ActionContext.getContext()。

~其中在栈的上下文中有5个对象(attr,request,session,application,parameters):

attr:用于按request>>session>>application顺序访问其属性,#attr.userName,相当于按顺序从三个范围读取userName属性,直到找到为止。

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

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

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

parameters:包含当前HTTP请求参数的Map,#parameters.id[0],相当于request.getParameter("id")。

3.获取Action中的属性值或者Action中的对象的某某属性值:

利用<s:property/>标签可以直接获取Action中的引用类型user里面的userName属性,同样可以通过user.address.addr获取user中引用类型address中的addr属性的值,像这种一层层往下传递的访问方式,即所谓的导航,也就是一步步往下调用。

4.调用Action的对象里面的普通方法:

默认的会把Action放到值栈里面去,而值栈在访问的时候,并不需要值栈的名字,当我们使用<s:property value="user.getVOMethod()"/>的时候,它会自动到值栈里面查找Action对象里面有没有user对象,如果发现有user对象,然后它就再找user里面有没有getVOMethod()方法,如果发现有,于是调用getVOMethod()这个方法。

实际上调用getVOMethod()方法的过程与获取表单中的姓名密码的方式都是相同的,都是到值栈里面去查找,找是否存在user对象,如果存在,接着查找user中是否存在某某属性或方法。

5.调用Action中的静态方法:

我们可以在JSP页面中使用OGNL表达式调用Action中的静态方法,调用Action中的静态方法时,与上面调用user对象的getVOMethod()方法的过程,是截然不同的。此时value的写法是固定的,以@开头,后面跟上具体的包名,然后@加上静态方法,比如<s:property value="@[email protected]()"/>。另外user对象只是LoginAction中的一个属性,这个属性会自动放到值栈里面,而值栈调用的时候,不用加上@或者包名等等,所以直接user.getVOMethod()就可以了。

6.调用JDK类中的静态方法:

可以使用<s:property value="@@floor(46.68)"/>输出floor()的执行结果,这就意味着如果不在@@中指定类的话,默认就表示java.lang.Math类,当前大多数情况下,都不会省略这个类,都会写全了的,然后在后面加上静态方法。

7.集合的伪属性:OGNL能够引用集合的一些特殊的属性,这些属性并不是JavaBean模式,例如size(),length(),当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性,比如获取一个List的大小,可以使用<s:property value="testList.size()"/>。

List的伪属性:size,isEmpty,iterator。

Set的伪属性:size,isEmpty,iterator。

Map的伪属性:size,isEmpty,keys,values。

Iterator(迭代)的伪属性:next,hasNext。

Enumeration(枚举)的伪属性:next,hasNext,nextElement,hasMoreElements。

8.获取集合中元素的实质就是调用它的toString()方法:

OGNL表达式还可以直接获取集合中的元素,事实上是在调用集合的toString()方法,所以我们可以根据实际情况通过重写集合的toString()方法来实现个性化输出,甚至它还可以像访问数组那样,直接testList[2]获取集合的元素,但这种方法只适用于List,不适用于Map。因为Map的索引是key,不是数值,另外,由于HashSet的元素是没有顺序的,所以也不能用下标获取单个元素。

9.利用投影获取属性:利用投影获取List中对象的userName属性时,其中{}表示的是一个集合,stus.{userName}就表示将stus中所有的userName属性取出组成一个新的列表。

10.利用选择获取属性:

OGNL表达式是很灵活的,可以同时使用选择技术与投影技术获得属性,#this代表当前元素, 问号?是把所有满足条件的元素都取出来,上箭头^是开始的意思,美元符号$是结束的意思,并且这三个符号返回的都是List列表。

11.补充:

(1).当OGNL取不到值的时候,它不会报错,而是什么都不显示

(2).<s:property value="[0]"/>返回的是ValueStack中从上至下的所有的Object,<s:property value="[1]"/>返回的是ValueStack中从上至下的第二个Objec。

(3).<s:property value="[0].username"/>返回的是成员变量username的值,假设ValueStack中存在两个Action的话,如果第一个Action如果没有username变量,那么它会继续找第二个Action。那么在什么情况下ValueStack中会存在两个Action呢?

答案是在struts.xml中配置的是从一个Action通过<result type="chain">跳转到另一个Action。

(4).<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>, 在Struts2.1.6中必须设置struts.ognl.allowStaticMethodAccess为true之后,才允许使用OGNL访问静态方法。而在Struts2.0.11则无需设置,即可直接访问。

12.接下来附上一个例子,通过这个例子可以了解如何通过OGNL表达式获取Action中的属性值或者Action对象中的某个属性值,也可以知道如何调用Action中对象里面的普通方法和Action类的普通方法:

(1).新建一个struts2项目,项目名为Struts2_OGNL,首先新建一个Action类,此类继承于ActionSupport类,代码如下:

package com.gk.action;

import com.gk.bean.Cat;
import com.gk.bean.User;
import com.opensymphony.xwork2.ActionSupport;

public class OgnlAction extends ActionSupport {
	private String username;
	private String password;
	private User user=new User();
	private Cat cat=new Cat();

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public Cat getCat() {
		return cat;
	}

	public void setCat(Cat cat) {
		this.cat = cat;
	}

	public String execute(){
		return SUCCESS;
	}

}

(2).其中又有几个JavaBean类,分别为User,Cat,Dog类,代码分别如下:

User.java文件代码:

package com.gk.bean;

public class User {
	private int age = 8;

	public User() {

	}

	public User(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "user"+age;
	}

}

Cat.java文件代码:

package com.gk.bean;

public class Cat {
	private Dog friend;

	public Dog getFriend() {
		return friend;
	}

	public void setFriend(Dog friend) {
		this.friend = friend;
	}

	public String miaomiao(){
		return "miaomiao";
	}

}

Dog.java文件代码:

package com.gk.bean;

public class Dog {
	private String name;

	public Dog(){

	}

	public Dog(String name){
		this.name=name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String toString(){
		return "dog"+name;
	}
}

(3).其中又有两个JSP页面,一个是index.jsp页面,一个为ognl.jsp页面,代码分别如下:

index.jsp文件代码:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>

  <body>
   <a href="ognl?username=u&password=p">ognl</a>
  </body>
</html>

ognl.jsp代码如下,通过struts2的标签和OGNL表达式来获取Action的属性:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>My JSP 'ognl.jsp' starting page</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

</head>

<body>
	<ol>
		<li>访问值栈中的:username = <s:property value="username " /></li>
		<li>访问值栈中的:password=<s:property value="password" /></li>
		<li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age" /></li>
		<li>访问值栈中对象的普通属性(get set方法):<s:property value="cat.friend.name" /></li>
		<li>访问值栈中对象的普通方法<s:property value="cat.miaomiao()"/></li>
	</ol>
	<s:debug></s:debug>
</body>
</html>

(4).struts.xml配置如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<constant name="struts.devMode" value="true"></constant>
	<package name="ognl" namespace="/" extends="struts-default">
		<action name="ognl" class="com.gk.action.OgnlAction">
			<result>/ognl.jsp</result>
		</action>
	</package>
</struts>

13.此时我们访问index.jsp页面,结果如下图所示:

点击此链接:

查看一下值栈的内容和上下文环境:

(1).我们可以看到通过超链接传入参数username和password,然后取出值栈里的username和password的属性,然后我们又看到值栈内容中有user属性,我们通过<s:property value="user.age" />获取到了8,原因是我们在User类里面把age初始化为8,在Action类中使用User user=new User这行代码实例化了user对象,然后通过toString方法输出来,所以值栈中user属性的值为user8。

(2).我们通过<s:property value="cat.friend.name" />想要获取cat对象中的friend属性的名字,但是取不出来,是因为我们没有把cat.friend.name这个参数传进去,如果我们输入地址:http://localhost:8083/Struts2_OGNL/ognl?username=u&password=p&cat.friend.name=Lc 的话,就可以取出来了,这也是OGNL如何访问值栈中的内容。

(3)如果我们输入http://localhost:8083/Struts2_OGNL/ognl?username=u&password=p&user.age=90 这个地址的话,年龄就会变为90岁了:

(4).如果我们把User.java文件中public User(){}这个无参构造方法删除掉,然后在OgnlAction中的代码中不实例化这个User类,即OgnlAction.java文件代码如下:

package com.gk.action;

import com.gk.bean.Cat;
import com.gk.bean.User;
import com.opensymphony.xwork2.ActionSupport;

public class OgnlAction extends ActionSupport {
	private String username;
	private String password;
	private User user;
	private Cat cat=new Cat();

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public Cat getCat() {
		return cat;
	}

	public void setCat(Cat cat) {
		this.cat = cat;
	}

	public String execute(){
		return SUCCESS;
	}

}

Use.java文件代码修改成:

package com.gk.bean;

public class User {
	private int age = 8;

	public User(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "user"+age;
	}

}

然后在输入http://localhost:8083/Struts2_OGNL/ognl?username=u&password=p 发现age内容为空了。

如果我们输入地址为:http://localhost:8083/Struts2_OGNL/ognl?username=u&password=p&user.age=23 看能否把age的值23传进去,发现报了个错误,这个错误是实例化User出错,所以一般我们的域模型,即JavaBean对象永远都要提供一个无参的构造方法,要不然就不知道实例化哪个类了。

(5).我们通过<s:property value="cat.miaomiao()"/>这个标签可以直接获取cat对象的miaomiao()方法。如果想取得OgnlAction类的普通方法的话,即Action类普通方法,假如Action类中有个返回类型为String的普通方法mm()的话,可以直接使用<s:property value="mm()"/>,这样就可以获得该Action类普通方法的返回值。

(6).其中为什么OGNL叫对象图导航语言呢?从上面这个例子来说,访问OgnlAction类的user对象的age属性,就可以使用user.age来取到,如果访问OgnlAction类中的cat对象的miaomiao方法,可以使用cat.miaomiao(),如果想访问cat对象的friend对象中的name属性,就用cat.friend.name,这样就可以取得Dog的friend对象的name属性,但是必须要传入参数值进去。

14.本来还想再附上多两个例子的,其中一个例子是使用OGNL来访问静态方法和静态属性的,但是昨天晚上写代码时发现了一些警告和错误,想专门写一篇博客来记录,所以就先写到这,基本的做法和说明都在上面已经讲述。后面我写好访问静态方法和静态属性的那篇文章后,在附上地址。

15.以上内容仅供大家学习和参考,谢谢!

时间: 2024-10-14 14:05:28

Struts2之OGNL表达式语言的相关文章

struts2的ognl表达式语言

1,ognl,即是object  graph navigation language 2. 目的是增强数据的访问功能,增加了valuestack 的功能 3.如果需要访问的属性属于根对象,那么可以直接访问这个属性:否则,必须使用一个对象名作为前缀修饰改属性,如:#person.name 4.struts 2 也可以直接访问属性,它提供了一个属性访问器 property accessor,它自动收索stack context上面的属性,直至有属性与它对应为止 如

Struts2标签库汇总和OGNL表达式语言

Struts2标签分类 UI标签:主要用于生成HTML元素的标签 非UI标签:主要用于数据访问.逻辑控制的标签 Ajax标签:用于支持Ajax的标签 表单标签(属于UI标签):用于生成HTML页面的form标签及普通表单元素的标签 非表单标签(属于UI标签):用于生产页面上的树.Tab页等标签 流程控制标签(属于非UI标签):主要包含用于实现分支.循环等流程控制的标签 数据访问标签(属于非UI标签):主要包含用于操作值栈和完成国际化功能的标签. OGNL表达式语言 (Object-Graph N

Struts2中使用OGNL表达式语言访问静态方法和静态属性以及我遇到的问题和解决方法

1.上一篇文章,我介绍了OGNL表达式语言,本来想在那篇文章上加上一个使用OGNL访问静态方法和静态属性的例子,但是昨天晚上我写代码时,报了一个警告,获取得到静态属性的值,却获取不到静态方法的返回值,所以今天特别的写篇文章来介绍一下. 2.这里我先附上这个例子,来了解如何使用OGNL表达式访问静态方法和属性. (1).其中访问静态方法或者静态属性的语法分别为:@类的路径@方法名,@类的路径@属性名,语法中类的路径,即包名+类名. (2).对于OGNL来说,java.lang.Math是其默认的类

Struts2中OGNL表达式的用法

OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,能通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能. 一.为什么要使用OGNL 视图层的表达式语言通常是用来简化数据的访问操作,取代Java脚本代码,提供更清晰的视图层实现.比如,要获取user对象的age属性,利用OGNL表达式可以写成: <s:property value="user.age&

OGNL表达式语言网上转来的

1.概念:OGNL是ObjectGraphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目. Struts 2框架使用OGNL作为默认的表达式语言. 2.功能: (1)支持对象方法调用,如xxx.sayHello(): (2)支持类静态方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@[email protected]('foo%s', 'bar')或@[email protected]_NAME: (3)操作集合对象

struts2 与 OGNL 表达式,jsp中 利用ognl 在valuestack中取值

在Struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是CompoundRoot中的一个元素.看下面的代码: public class UserAction { private String username; private Integer age; private boolean valid; //查看用户的详细信息 public String de

Struts2之OGNL表达式

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目.Struts2框架使用OGNL作为默认 的表达式语言. 相对于EL表达式,它提供了平时我们需要的一些功能,如: 支持对象方法调用,如xxx.sayHello(); 支持类静态方法调用和常量值访问,表达式的格式为@[类全名(包括包路径)]@[方法名|值名],例如:@[email protected]('foo%s','bar')或@[email protected]_NAME;

OGNL表达式语言

OGNL:Object Graphic Navigation Language(对象图导航图语言) 1.上下文------>ActionContext------>Map集合 OGNL有一个上下文概念,在Struts2中上下文的实现为ActionContext,它就是一个Map结构,它实现了java.utils.Map 接口. OGNL COntext: ValueStack(值栈,它是根对象) parameters request session application attr Actio

Struts2:OGNL表达式详解

OGNL用于操作ValueStack中的数据.它负责两件事.第一是在接收HTTP请求时将请求中的字符串转换成Java中的类型,比如int.String等,并赋值给ValueStack上的JavaBean,第二是在页面渲染的时候,从ValueStack中获取属性,并将Java类型转换成字符串进行输出.整个过程如下图: (侵权可删) 在HTTP的请求参数中,可以包含OGNL表达式(这就是当初Struts2爆重大漏洞的原因了). user.name=xxx表示给user属性中的name属性进行赋值.