OGNL表达式

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。

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 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了java.utils.Map 的接口。
OgnlContext类【本质是一个Map】

分析:Struts框架默认就支持Ognl表达式语言。(struts必须引用的包:ognl.jar)


OgnlContext是Struts2的数据中心。

当Struts2接受一个请求时,会迅速创建ActionContext、ValueStack和Action对象。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。 示意图如下

可以打开OglnContext的源代码,如下:

public class OgnlContext extends Object implements Map
{
    public static final String          CONTEXT_CONTEXT_KEY = "context";
    public static final String          ROOT_CONTEXT_KEY = "root";
    public static final String          THIS_CONTEXT_KEY = "this";
    .......
}

有一个特点是继承自Map接口

现在可以写一写其测试类:

package com.gqx.ognl;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

import org.junit.Test;

public class OgnlTest {
	/**
	 * 使用Ognl表达式取值,取非根元素的值,必须要用"#"
	 */
	@Test
	public void test() {
		//创建一个OgnlContext上下文对象
		OgnlContext context=new OgnlContext();
		//存放数据,继承自map接口,所以map形式存放
		context.put("name", "gqxing");
		//获取数据
		String value=(String) context.get("name");
		System.out.println(value);
	}

	@Test
	public void test2() throws OgnlException {
		//创建一个OgnlContext上下文对象
		OgnlContext context=new OgnlContext();
		//存放数据,继承自map接口,所以map形式存放
		User user=new User();
		user.setId(101);
		user.setName("gqxing");
		context.put("user", user);
		//获取数据
		/*
		 * 第一种方式:
		User value=(User) context.get("user");
		System.out.println(user.getName()+":"+user.getId());
		*
		*第二种方式
		*先构建一个ognl表达式,在解析表达式
		*/
		//向非根元素取值是,要用"#"号
		Object ognl=Ognl.parseExpression("#user.id");
		Object value=Ognl.getValue(ognl, context, context.getRoot());
		System.out.println(value);
	}

	/**
	 * Ognl表达式语言语言取值,取根元素的值,不用带#号
	 * @throws OgnlException
	 */
	@Test
	public void test3() throws OgnlException {
		//创建一个OgnlContext上下文对象
		OgnlContext context=new OgnlContext();
		//存放数据,继承自map接口,所以map形式存放
		User user=new User();
		user.setId(101);
		user.setName("gqxing");
		context.put("user", user);
		//设置根元素,向根元素放数据
		context.setRoot(user);
		//获取数据(map)
		//向根元素取值是,直接写属性
		Object ognl=Ognl.parseExpression("id");
		Object value=Ognl.getValue(ognl, context, context.getRoot());
		System.out.println(value);
	}

	/**
	 * 获取属性之下的属性
	 * @throws OgnlException
	 */
	@Test
	public void test4() throws OgnlException {
		//创建一个OgnlContext上下文对象
		OgnlContext context=new OgnlContext();
		//存放数据,继承自map接口,所以map形式存放
		User user=new User();
		user.setId(101);
		user.setName("gqxing");
		context.put("user", user);
		//设置根元素,向根元素放数据
		context.setRoot(user);
		//获取数据(map)
		//向根元素取值是,直接写属性
		Object ognl=Ognl.parseExpression("address.province");
		Object value=Ognl.getValue(ognl, context, context.getRoot());
		System.out.println(value);
	}

	/**
	 * 静态方法调用
	 * @throws OgnlException
	 */
	@Test
	public void test5() throws OgnlException {
		OgnlContext context =new OgnlContext();
		//Ognl表达式语言,调用静态方法
		//Object ognl=Ognl.parseExpression("@Math@floor(5.6)");
		//由于Math类在开发中用的比较多,所以可以这样写
		Object ognl=Ognl.parseExpression("@@floor(5.6)");
		Object value=Ognl.getValue(ognl, context,context.getRoot());
		System.out.println(value);
	}

}

Struts2的值栈ValueStack

ValueStack即值栈对象,是整个数据存储的核心,或叫中转站。实现了该接口的OgnlValueStack类。
ValueStack特点
        ValueStack贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象. Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的request请求属性中,传入jsp页面。开发者只需通过ActionContext对象就可以直接去访问struts的其他关键对象,(ActionContext是专门给开发者使用的,便于学习和使用)

可以写一个Action来测试其中的关系

package com.gqx.ognl;

import javax.servlet.ServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

/**
 * struts的数据流转
 * @author GQXing
 *
 */
public class OgnlDemo  extends ActionSupport{
	@Override
	public String execute() throws Exception {
		//值栈对象存储数据的原理:
		ActionContext actionContext=ActionContext.getContext();
		ValueStack valueStack2=actionContext.getValueStack();
		System.out.println(valueStack2);
		return SUCCESS;
	}

	public String test(){
		//获取值栈对象。方式一:
		ServletRequest request=ServletActionContext.getRequest();
		ValueStack valueStack=(ValueStack) request.getAttribute("struts.valueStack");
		//获取值栈对象。方式二
		ActionContext actionContext=ActionContext.getContext();
		ValueStack valueStack2=actionContext.getValueStack();
		System.out.println(valueStack==valueStack2);  //true
		return SUCCESS;
	}
}

加入断点调试,可以看到相应的变量值

可以先写这个程序来测试

package com.gqx.ognl;

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class OgnlDemo2 extends ActionSupport{

	private User user=new User(101,"gqxing");

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		ActionContext ac=ActionContext.getContext();
		Map<String, Object> map=(Map<String, Object>) ac.get("request");
		//映射数据
		map.put("request_data", "request_data");
		map.put("cn", "China");
		//ac.getContextMap().put("request_data", "request_data");
		ac.getSession().put("Session_data", "Session_data");
		ac.getApplication().put("Application_data", "Application_data");
		ValueStack vs=ac.getValueStack();
		/*********操作根元素的几种方法*********/
//		vs.push(new User(111,"hehe")); 	//入栈顶
//		vs.pop();	//栈顶元素出来

		//map结构存储
//		vs.set("user1", new User(102,"Code"));
//		vs.set("user2", new User(103,"Hello"));

		System.out.println(vs);
		return super.execute();
	}
}

当用户在访问这个action的时候,action参数产生的临时数据都保存在ValueStack中,jsp页面要做出响应的反应,都是从这个ValueStack中取数据的。

ValueStack中相应的数据如下

有上面可以得到值栈对象的案例可以得到

创建一个action以及对应的实体配置

package com.gqx.ognl;

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class OgnlDemo2 extends ActionSupport{

	private User user=new User(101,"gqxing");
	public void setUser(User user) {
		this.user = user;
	}
	public User getUser() {
		return user;
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		ActionContext ac=ActionContext.getContext();
//		Map<String, Object> map=(Map<String, Object>) ac.get("request");
		//映射数据
//		map.put("request_data", "request_data");
//		map.put("cn", "China");
		ac.getContextMap().put("request_data", "request_data");
		ac.getSession().put("Session_data", "Session_data");
		ac.getApplication().put("Application_data", "Application_data");
		ValueStack vs=ac.getValueStack();
		/*********操作根元素的几种方法*********/
//		vs.push(new User(111,"hehe")); 	//入栈顶
//		vs.pop();	//栈顶元素出来

		//map结构存储
//		vs.set("user1", new User(102,"Code"));
//		vs.set("user2", new User(103,"Hello"));

		System.out.println(vs);
		return super.execute();
	}
}

在xml中配置:

<action name="ognl2" class="com.gqx.ognl.OgnlDemo2">
    		<result name="success">/ognl.jsp?name=${user.name}</result>
</action>

jsp页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags"  prefix="s"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>

    <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">    

  </head>

  <body>

	  <!-- 页面:必须要拿到ValueStack -->
	 <br> 取根元素的值<br>
   		<s:property value="user.id"/>
   		<s:property value="user.name"/>
   		<s:property value="user.address.province"/>
   		<s:property value="user.address.city"/>

   	<br> 取非根元素的值<br>
   	<s:property value="#request.cn"/>
   	<s:property value="#request.request_data"/>
   	<s:property value="#session.Session_data"/>
   	<s:property value="#application.Application_data"/>
   	<br> 通过attr来取非根元素的值<br>
   	<!-- 自动查找request/session/application,找到后立即自动返回 -->
   	<s:property value="#attr.cn"/>
   	<s:property value="#attr.request_data"/>
   	<s:property value="#attr.Session_data"/>
   	<s:property value="#attr.Application_data"/>
   	<br> 2、取非根元素的值<br>
	<!-- 这种方式只有在Request中可以用 -->
   	<s:property value="#request_data"/>

   	<br>
   	<!-- 获取请求的参数 -->
   	<s:property value="#parameters.name"/>
	<!--struts的调试标签 ,可以观测值栈数据-->
	<s:debug></s:debug>
  </body>
</html>

效果如图:

现在利用struts的list和map迭代学习:

先创建一个Action类

package com.gqx.ognl;

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

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class OgnlDemo3 extends ActionSupport{
	@Override
	public String execute() throws Exception {
		List<User> list =new ArrayList<User>();
		Map<Integer, User> map=new HashMap<Integer, User>();
		//初始化
		for (int i = 0; i < 11; i++) {
			User user=new User(i,"gqxing"+i);
			list.add(user);
			map.put(user.getId(), user);
		}
		//保存在request
		ActionContext.getContext().getContextMap().put("list", list);
		ActionContext.getContext().getContextMap().put("map", map);
		/*不加警号
		ActionContext.getContext().getValueStack().push(arg0);
		*/

		return super.execute();
	}
}

以及与其对应的jsp页面:

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
	<%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
	<html>
<head>

<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">
<style type="text/css">
	.odd{
		background-color: red;'
	}
	.even{
		background: blue;
	}

</style>
</head>

<body>
	<br>1、list迭代
	<br>
	<table border="1">
		<tr>
			<td>编号</td>
			<td>名称</td>
		</tr>
		<s:iterator var="user" value="#request.list" status="st">
			<tr class=<s:property value="#st.even?'even':'odd'"/>>
				<td><s:property value="#user.id" /></td>
				<td><s:property value="#user.name" /></td>
			</tr>
		</s:iterator>
	</table>
	<br>1、map迭代
	<br>
	<table border="1">
		<tr>
			<td>编号</td>
			<td>名称</td>
		</tr>
		<s:iterator var="entry" value="#request.map" status="st">
			<tr class=<s:property value="#st.even?'even':'odd'"/>>
				<td><s:property value="#entry.key" /></td>
				<td><s:property value="#entry.value.name" /></td>
			</tr>
		</s:iterator>
	</table>
	<!-- Ognl表达式 可以取值,也可以动态创建集合-->
	<br>一、构建List集合<br>
	<s:iterator var="str" value="{'a','b'}">
			<s:property value="#str"/>
			<br>
	</s:iterator>
	<br>一、构建Map集合<br>
	<s:iterator var="en" value="#{'cn':'China','name':'gqxing' }">
			<s:property value="#en.key"/>
			<s:property value="#en.value"/>
			<br>
	</s:iterator>

</body>
	</html>

效果如图:

Ognl表达式语言的更多相关文章

  1. Struts2的OGNL表达式语言

    一.OGNL的概念 OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者 ...

  2. OGNL表达式语言网上转来的

    1.概念:OGNL是ObjectGraphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目. Struts 2框架使用OGNL作为默认的表达式语言. 2.功能: ...

  3. Struts ognl表达式语言几个符号

    #  获取非根元素值  . 动态都建map集合 $  配置文件取值 %  提供一个ognl表达式运行环境 <%@ page language="java" import=&q ...

  4. Struts2中使用OGNL表达式语言访问静态方法和静态属性

    1.一定要在struts.xml配置文件中配置允许使用OGNL访问静态方法,否则不能使用OGNL访问静态方法 2.<s:property value="@com.gk.StaticTe ...

  5. Ognl表达式基本原理和使用方法

    Ognl表达式基本原理和使用方法 1.Ognl表达式语言 1.1.概述 OGNL表达式 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个 ...

  6. Spring表达式语言 之 5.1 概述 5.2 SpEL基础(拾叁)

    5.1  概述 5.1.1  概述 Spring表达式语言全称为"Spring Expression Language",缩写为"SpEL",类似于Struts ...

  7. 20160502-struts2入门--ognl表达式

    一.OGNL表达式语言 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目. Struts 2框架使用OGNL作为默认的表达式语言 ...

  8. ValueStack背后的OGNL表达式

    原文地址:http://blog.csdn.net/li_tengfei/archive/2010/12/25/6098134.aspx 前言: Strut2的Action类通过属性可以获得所有相关的 ...

  9. 开涛spring3(5.1&5.2) - Spring表达式语言 之 5.1 概述 5.2 SpEL基础

    5.1  概述 5.1.1  概述 Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行 ...

随机推荐

  1. Nginx+uWSGI或fastcgi部署Django项目

    nginx+uWSGI ubuntu下先安装下C编译器和Python环境: sudo apt-get install build-essential python-dev 使用pip安装uWSGI: ...

  2. cdev[典]

    linux-2.6.22/include/linux/cdev.hstruct cdev {   struct kobject kobj;          // 每个 cdev 都是一个 kobje ...

  3. ckeditor的配置及使用

    一.使用方法:1.在页面<head>中引入ckeditor核心文件ckeditor.js<script type="text/javascript" src=&q ...

  4. Eclipse中将classes文件删除之后显示:找不到或无法加载主类解决方案

    第一步: 将Eclipse自动编译打开 Project -> Build Automatically 第二步: Eclipse - Project - Clean

  5. poj1195Mobile phones(二维树状数组)

    http://poj.org/problem?id=1195 模版题 i写成k了 找了一个多小时没找出来.. #include <iostream> #include<cstring ...

  6. poj 1260 Pearls(dp)

    题目:http://poj.org/problem?id=1260 题意:给出几类珍珠,以及它们的单价,要求用最少的钱就可以买到相同数量的,相同(或更高)质量的珍珠. 珍珠的替代必须是连续的,不能跳跃 ...

  7. Java5 并发学习

    在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动.调度.管理线程的一大堆API了.在Java5以后,通过 Executor来启动线程比用Thread的start()更好.在新特征 ...

  8. POJ 1815 Friendship ★(字典序最小点割集)

    [题意]给出一个无向图,和图中的两个点s,t.求至少去掉几个点后才能使得s和t不连通,输出这样的点集并使其字典序最大. 不错的题,有助于更好的理解最小割和求解最小割的方法~ [思路] 问题模型很简单, ...

  9. GitHub进一步了解

    为什么要引入Git: 1)用简单一点的例子来讲: 一个公司有几个甚至十几个人共同合作开发一款项目的时候,公司对项目代码有明确规范,不可能再像学校做的小项目一样,你觉得哪个同学的代码写的不好,或者和你的 ...

  10. 上传文件出错:org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly

    最近做一个web项目中有上传文件的功能,已经写出并在本地和部署到服务器上测试了好几个文件上传都没问题(我用的是tomcat).后来又上传了一个700多K的文件(前边的都是不足600K的,并且这个wor ...