ognl表达式

基本概念

        OGNLObject Graph Navigation Language),是一种表达式语言。使用这种表达式语言,你可以通过某种表达式语法,存取Java对象树中的任意属性、调用Java对象树的方法、同时能够自动实现必要的类型转化。如果我们把表达式看做是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。既然OGNL那么强大,那么让我们一起来研究一下他的API,看看如何使用OGNL.

OGNLAPI看起来就是两个简单的静态方法:

  public static Object getValue( Object tree, Map context, Object root ) throws OgnlException;
public static void setValue( Object tree, Map context, Object root, Object value ) throws OgnlException


 我们可以看到,简单的API,就已经能够完成对各种对象树的读取和设值工作了。这也体现出OGNL学习成本非常低。需要特别强调进行区分的,是在针对不同内容进行取值或者设值时,OGNL表达式的不同。Struts2 Reference 写道:


The Framework uses standard naming context to evaluate OGNL expressions. The top level object dealing with OGNL is Map (usually referred as context map or context). OGNL has notion of there being root (or default) object within the context. In expression, the properties of the root object can be referenced without any special "marker" notion. References to other objects are marked with pound sign (#).

针对上面的话,我们可以简单的理解为下面两点:

A) 针对根对象(Root Object)的操作,表达式是自根对象到被访问对象的某个链式操作的字符串表示。

B) 针对上下文环境(Context)的操作,表达式是自上下文环境(Context)到被访问对象的某个链式操作的字符串表示,但是必须在这个字符串的前面加上#符号,以表示与访问根对象的区别。


OGNL三要素:

     很多人习惯上把传入OGNLAPI的三个参数,称之为OGNL的三要素。OGNL的操作实际上就是围绕着这三个参数而进行的。

看下面一段测试代码:

 Ognl.setValue("department.name", user2, "dev");

 System.out.println(user2.getDepartment().getName());

 Ognl.setValue(Ognl.parseexpression_r("department.name"), context, user2, "otherDev");

 System.out.println(user2.getDepartment().getName());


1. 表达式(Expression


  表达式是整个OGNL的核心,所有的OGNL操作都是针对表达式的解析后进行的。表达式会规定此次OGNL操作到底要干什么。我们可以看到,在上面的测试中,namedepartment.name等都是表达式,表示取name或者department中的name的值。OGNL支持很多类型的表达式,之后我们会看到更多。

2. 根对象(Root Object

  根对象可以理解为OGNL的操作对象。在表达式规定了干什么以后,你还需要指定到底对谁干

  在上面的测试代码中,user就是根对象。这就意味着,我们需要对user这个对象去取name这个属性的值(对user这个对象去设置其中的department中的name属性值)。

3. 上下文环境(Context

  有了表达式和根对象,我们实际上已经可以使用OGNL的基本功能。例如,根据表达式对根对象进行取值或者设值工作。不过实际上,在OGNL的内部,所有的操作都会在一个特定的环境中运行,这个环境就是OGNL的上下文环境(Context)。说得再明白一些,就是这个上下文环境(Context),将规定OGNL的操作在哪里干

  OGNL的上下文环境是一个Map结构,称之为OgnlContext。上面我们提到的根对象(Root Object),事实上也会被加入到上下文环境中去,并且这将作为一个特殊的变量进行处理,具体就表现为针对根对象(Root Object)的存取操作的表达式是不需要增加#符号进行区分的。

       OgnlContext不仅提供了OGNL的运行环境。在这其中,我们还能设置一些自定义的parameterContext中,以便我们在进行OGNL操作的时候能够方便的使用这些parameter。不过正如我们上面反复强调的,我们在访问这些parameter时,需要使用#作为前缀才能进行。

OGNL表达式实现原理

    Struts 2中的OGNL Context实现者为ActionContext,它结构示意图如下:



ognl概念和原理详解
  当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。访问上下文(Context)中的对象需要使用#符号标注命名空间,如#application、#session,另外OGNL会设定一个根对象(root对象),在Struts2中根对象就是ValueStack(值栈) 。如果要访问根对象(即ValueStack)中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。

       在struts2中,根对象ValueStack的实现类为OgnlValueStack,该对象不是我们想像的只存放单个值,而是存放一组对象。在OgnlValueStack类里有一个List类型的root变量,就是使用他存放一组对象 |--request |--application context ------|--OgnlValueStack root变量[action, OgnlUtil, ... ] |--session |--attr |--parameters,在root变量中处于第一位的对象叫栈顶对象。通常我们在OGNL表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。 大家注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:<s:property value="name"/>

       由于ValueStack(值栈)是Struts 2中OGNL的根对象,如果用户需要访问值栈中的对象,在JSP页面可以直接通过下面的EL表达式访问ValueStack(值栈)中对象的属性: ${foo} //获得值栈中某个对象的foo属性。如果访问其他Context中的对象,由于他们不是根对象,所以在访问时,需要添加#前缀。

application对象:用于访问ServletContext,例如#application.userName或者#application['userName'],相当于调用ServletContext的getAttribute("username")。
session对象:用来访问HttpSession,例如#session.userName或者#session['userName'],相当于调用session.getAttribute("userName")。
request对象:用来访问HttpServletRequest属性(attribute)的Map,例如#request.userName或者#request['userName'],相当于调用request.getAttribute("userName")。

parameters对象:
用于访问HTTP的请求参数,例如#parameters.userName或者#parameters['userName'],相当于调用request.getParameter("username")。
attr对象:用于按page->request->session->application顺序访问其属性。


----------------------------http://blog.sina.com.cn/s/blog_7ffb8dd5010149u2.html-------------------


Struts2学习笔记(OGNL表达式)

Struts 2支持以下几种表达式语言:

  1. OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;
  2. JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言;
  3. Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些起特性;
  4. Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。

Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:

  1. 支持对象方法调用,如xxx.doSomeSpecial();
  2. 支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 |  值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
  3. 支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;
  4. 访问OGNL上下文(OGNL context)和ActionContext;
  5. 操作集合对象

OGNL是通常要结合Struts 2的标志一起使用,如<s:property value="xx" />等。大家经常遇到的问题是#、%和$这三个符号的使用。

  1. 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性: image
  2. 用于过滤和投影(projecting)集合,如books.{?#this.price<100}。
  3. 构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。

个人觉得OGNL真的很简单,即使有的表达方式忘了也没关系,一查就搞定了,尚学堂的教学中有个例子不错,基本上常用的都包括了。

下面是OGNL表达式的使用例子。

OGNL表达式示例代码<?xml version="1.0" encoding="GB18030" ?>
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030" />
<title>OGNL表达式语言学习</title>
</head>
<body>
	<ol>
		<li>访问值栈中的action的普通属性: username = <s:property value="username"/> </li>
		<li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age"/> | <s:property value="user['age']"/> | <s:property value="user[\"age\"]"/> | wrong: <%--<s:property value="user[age]"/>--%></li>
		<li>访问值栈中对象的普通属性(get set方法): <s:property value="cat.friend.name"/></li>
		<li>访问值栈中对象的普通方法:<s:property value="password.length()"/></li>
		<li>访问值栈中对象的普通方法:<s:property value="cat.miaomiao()" /></li>
		<li>访问值栈中action的普通方法:<s:property value="m()" /></li>
		<hr />
		<li>访问静态方法:<s:property value="@com.bjsxt.struts2.ognl.S@s()"/></li>
		<li>访问静态属性:<s:property value="@com.bjsxt.struts2.ognl.S@STR"/></li>
		<li>访问Math类的静态方法:<s:property value="@@max(2,3)" /></li>
		<hr />
		<li>访问普通类的构造方法:<s:property value="new com.bjsxt.struts2.ognl.User(8)"/></li>
		<hr />
		<li>访问List:<s:property value="users"/></li>
		<li>访问List中某个元素:<s:property value="users[1]"/></li>
		<li>访问List中元素某个属性的集合:<s:property value="users.{age}"/></li>
		<li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/></li>
		<li>访问Set:<s:property value="dogs"/></li>
		<li>访问Set中某个元素:<s:property value="dogs[1]"/></li>
		<li>访问Map:<s:property value="dogMap"/></li>
		<li>访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[\"dog101\"]"/></li>
		<li>访问Map中所有的key:<s:property value="dogMap.keys"/></li>
		<li>访问Map中所有的value:<s:property value="dogMap.values"/></li>
		<li>访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li>
		<hr />
		<li>投影(过滤):<s:property value="users.{?#this.age==1}[0]"/></li>
		<li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li>
		<li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li>
		<li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li>
		<hr />
		<li>[]:<s:property value="[0].username"/></li>
	</ol>
	<s:debug></s:debug>
</body>
</html>

下面是对应的java,都是最简单的class

OgnlAction.java

OgnlAction.javapackage com.bjsxt.struts2.ognl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.opensymphony.xwork2.ActionSupport;

public class OgnlAction extends ActionSupport {
	private Cat cat;
	private Map<String, Dog> dogMap = new HashMap<String, Dog>();
	private Set<Dog> dogs = new HashSet<Dog>();

	private String username;
    private String password;

    private User user;
    private List<User> users = new ArrayList<User>();

	public OgnlAction() {
		users.add(new User(1));
		users.add(new User(2));
		users.add(new User(3));

		dogs.add(new Dog("dog1"));
		dogs.add(new Dog("dog2"));
		dogs.add(new Dog("dog3"));

		dogMap.put("dog100", new Dog("dog100"));
		dogMap.put("dog101", new Dog("dog101"));
		dogMap.put("dog102", new Dog("dog102"));
	}

	public String execute() {
		return SUCCESS;
	}

    public String m() {
        return "hello";
    }

    public User getUser() {
        return user;
    }

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

    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 Cat getCat() {
        return cat;
    }

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

    public Map<String, Dog> getDogMap() {
        return dogMap;
    }

    public void setDogMap(Map<String, Dog> dogMap) {
        this.dogMap = dogMap;
    }

    public Set<Dog> getDogs() {
        return dogs;
    }

    public void setDogs(Set<Dog> dogs) {
        this.dogs = dogs;
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

Dog.java

Dog.javapackage com.bjsxt.struts2.ognl;

public class Dog {
	
	private String name;
	
	public Dog() {
		
	}

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

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

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

 

Cat.java

Cat.javapackage com.bjsxt.struts2.ognl;

public class Cat {
	
	private Dog friend;
	
	public Dog getFriend() {
		return friend;
	}

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

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

User.java

User.javapackage com.bjsxt.struts2.ognl;

public class User {
	private int age = 8;
	
	public User() {
		
	}
	
	public User(int age) {
		super();
		this.age = age;
	}


	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "user" + age;
	}
}

S.java

User.javapackage com.bjsxt.struts2.ognl;

public class S {
	public static String STR = "STATIC STRING";
	
	public static String s() {
		return "static method";
	}
}
-----------------http://www.cnblogs.com/Cratical/archive/2012/09/09/2677909.html--------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OGNL(Object-Graph Navigation Language,对象图导航语言)是一个强大的表达式语言,可以用于Java的各种应用程序中,包括Struts、JavaServer Faces、JavaServer Pages等。在Mybatis中,OGNL表达式可以用于Mapper XML文件中的各种标签中,例如`<if>`、`<where>`、`<set>`、`<foreach>`等标签中。 OGNL表达式可以用于获取Java对象的属性值、调用Java对象的方法、进行算术运算、比较运算、逻辑运算等。例如: ```xml <select id="selectByCondition" resultType="com.example.User"> select * from user where name like #{keyword} and age >= #{minAge} <if test="maxAge != null"> and age <= #{maxAge} </if> </select> ``` 在这个例子中,`#{keyword}`、`#{minAge}`、`#{maxAge}`都是OGNL表达式,表示获取Java对象中的属性值。例如,如果传入的参数对象是一个`User`对象,那么`#{keyword}`可以表示`user.getKeyword()`方法的返回值,`#{minAge}`可以表示`user.getMinAge()`方法的返回值。 在OGNL表达式中,还可以进行算术运算、比较运算、逻辑运算等。例如,`age >= #{minAge}`表示将`age`和`#{minAge}`进行比较,判断`age`是否大于等于`#{minAge}`;`age <= #{maxAge}`表示将`age`和`#{maxAge}`进行比较,判断`age`是否小于等于`#{maxAge}`。 除了基本的运算符和表达式OGNL还提供了丰富的函数和操作符,例如`in`操作符、`not`操作符、`contains`函数、`size`函数等。这些函数和操作符可以方便地进行集合操作、字符串操作等。在使用OGNL表达式时,需要注意语法的正确性和安全性,以避免可能的安全漏洞。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值