首页 > WEB开发 > 后台开发 > OGNL表达式 & ValueStack
2014
09-15

OGNL表达式 & ValueStack

04. OGNL表达式 & ValueStack21

ValueStack是Struts2数据传输背后的机制,其基础是OGNL。想了解ValueStack的工作机制,必须先理解OGNL。

一、OGNL

1、简介

OGNL(Object Graphic Navigation Language),对象图导航语言。下面解释何为对象图导航:

对象图导航,即以任意一个对象为根,可以访问这个对象关联的其他对象。如下面三个类:以一个User对象为根,可以导航到Group对象,进而导航到Organization对象。导航的目的,是为了获取、设置某个对象的值或调用某个对象的方法!

04. OGNL表达式 & ValueStack281

① 通过Java代码从User对象导航到Organization的orgId属性:

String orgId = user.getGroup().getOrg().getOrgId();

② 通过OGNL进行导航:String orgId = (String)Ognl.getValue(“group.org.orgId”,user);

Ognl.getValue方法的第一个参数就是一条OGNL表达式,第二个参数是指定在表达式中需要用到的root对象。

也许通过这个例子,你会觉得OGNL显得更复杂点,但OGNL的目的并不在于此。OGNL表达式的真正目的,是为了在那些不能写JAVA代码的地方、或者不方便写Java代码的地方执行JAVA代码。如在Struts2工程中,可以在strtus.xml和JSP页面使用OGNL表达式,同Action交换数据,所以,非常有必要理解OGNL的基本机制。

2、OGNL入门

下面以代码说明了OGNL表达式的用法,下面的代码完全可以在Java工程中模拟,只需导入ognl.jar和javassist.jar即可。这两个包可以在Struts2的lib库中找到。

Ognl.getValue(String expression, Object root)

public class OGNLDemo1 {
	@Test
	public void testOGNL1() throws Exception{
		User user = new User();
		user.setUsername("张三");

		String value= (String) Ognl.getValue("username", user);
		System.out.println(value);
	}

	@Test
	public void testOGNL2() throws Exception{
		User user = new User();
		Group g = new Group();
		Organization o = new Organization();
		o.setOrgId("Y11");
		g.setOrg(o);
		user.setGroup(g);

		//java代码导航
		System.out.println(user.getGroup().getOrg().getOrgId());

		//OGNL代码导航
		String value= (String) Ognl.getValue("group.org.orgId", user);

		System.out.println(value);
	}

	@Test
	public void testOGNL3() throws Exception{
		User user = new User();
		Group g = new Group();
		Organization o = new Organization();
		o.setOrgId("Y11");
		g.setOrg(o);
		user.setGroup(g);

		//java代码导航
		System.out.println(user.getGroup().getOrg().getOrgId());

		//OGNL代码导航(使用#root代表root对象)
		String value= (String) Ognl.getValue("#root.group.org.orgId", user);

		System.out.println(value);
	}
}

Ognl.getValue(String expression, Map context, Object root)

context:在OGNL的表达式中,有可能需要访问到多个毫不相干的对象,这时候,我们需要给OGNL传递一个Map类型的对象,把表达式中需要用到的对象放到Map中即可!这个Map对象,称为context。

要在表达式中访问到context中的对象,需要使用“#对象名称”的语法规则。

public class OGNLDemo2 {
	@Test
	public void testOGNL1() throws Exception{
		User user = new User();
		user.setUsername("张三");

		User user2 = new User();
		user2.setUsername("李四");

		Map<String, User> context = new HashMap();
		context.put("u1", user);
		context.put("u2", user2);

		//#对象名称:去访问context中的对象
		//如果表达式中没有用到root对象,那么可以用任意一个对象代表root对象!
		String value = (String) Ognl.getValue("#u1.username+','+#u2.username", context, new Object());
		System.out.println(value);
	}
	@Test
	public void testOGNL2() throws Exception{
		User user = new User();
		user.setUsername("张三");
		Group g = new Group();
		Organization o = new Organization();
		o.setOrgId("Y11");
		g.setOrg(o);
		user.setGroup(g);

		User user2 = new User();
		user2.setUsername("李四");

		User user3 = new User();
		user3.setUsername("王五");

		Map<String, User> context = new HashMap<String, User>();
		context.put("u1", user);
		context.put("u2", user2);

		//#对象名称:去访问context中的对象
		String value = (String) Ognl.getValue("#u1.username+','+#u2.username", context, user3);
		System.out.println(value);
	}
}

③ 赋值:setValue方法和 = 运算符

public class OGNLDemo3 {
	//测试赋值
	@Test
	public void testOGNL1() throws Exception{
		User user = new User();

		Ognl.setValue("username", user, "张三");
		System.out.println(user.getUsername());
	}

	@Test
	public void testOGNL2() throws Exception{
		User user = new User();

		Map context = new HashMap();
		context.put("u1", user);

		Ognl.setValue("#u1.username", context, new Object(), "张三");
		System.out.println(user.getUsername());
	}

	@Test
	public void testOGNL3() throws Exception{
		User user = new User();

		Map context = new HashMap();
		context.put("u1", user);

		//getValue也可以赋值:利用"="进行赋值
		String value = (String) Ognl.getValue("#u1.username='李四'", context, new Object());
		System.out.println(user.getUsername());
		System.out.println(value);
	}

	@Test
	public void testOGNL4() throws Exception{
		User user = new User();
		User user2 = new User();

		Map context = new HashMap();
		context.put("u1", user);
		context.put("u2", user2);

		//用逗号分隔,同时执行多个表达式
		String value = (String) Ognl.getValue("#u1.username='李四',#u2.username='王五'", context, new Object());
		System.out.println(user.getUsername());
		System.out.println(value);
	}
}

④ 使用OGNL调用对象中的方法

public class OGNLDemo4 {
	//使用OGNL调用对象的方法
	@Test
	public void testOGNL1() throws Exception{
		//如果是调用root对象的方法,可以直接使用方法的名称来调用方法
		User user = new User();

		Ognl.getValue("setUsername('汪')", user);
		String value = (String) Ognl.getValue("getUsername()", user);
		System.out.println(value);
	}

	@Test
	public void testOGNL2() throws Exception{
		User user = new User();
		user.setUsername("汪");
		//调用静态变量,需要在类名和变量名前面加上@来调用,对于实例方法,用"."来调用
		String value = (String)Ognl.getValue("@System@out.println(username)", user);
		System.out.println(value);
	}

	@Test
	public void testOGNL3() throws Exception{
		//调用静态方法,注意使用全路径类名
		String value = (String)Ognl.getValue("@java.util.UUID@randomUUID().toString()", new Object());
		System.out.println(value);
	}
}

OGNL表达式 & ValueStack》有 4 条评论

  1. 玉慕瑕 说:

    我见过的最简洁明了的讲解!

  2. 最励志网 说:

    无意溜达到了你的网站 留下足迹

留下一个回复

你的email不会被公开。