Struts2之OGNL表达式与值栈对象及常用标签的使用

一,概述

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有一个上下文(OgnlContext)概念,其实它的上下文就是map结构,它实现了java.utils.Map接口.

public class OgnlContext extends Object implements Map{...}

二,OGNL的API类和方法

OgnlContext类(本质上是一个Map)

硬编码方式了解OgnlContext对象

1)Ognl表达式语言取值,取非根元素的值,必须用#号

/**
	 * Ognl表达式语言取值,取非根元素的值,必须用#号
	 * @throws Exception
	 */
	@Test
	public void testOgnl() throws Exception {
		OgnlContext context=new OgnlContext();
		
		User user=new User();
		user.setId(111);
		user.setName("张国荣");
		
		//存
		context.put("Leslie", "哥哥");
		//往非根元素放入数据,取值的时候要用#
		context.put("user", user);
		
		//拿数据:通过map
		//通过Ognl表达式取数据
		Object ognl = Ognl.parseExpression("#Leslie");
		//Object ognl = Ognl.parseExpression("#user.name");
		Object value = Ognl.getValue(ognl, context, context.getRoot());
		System.out.println(value);
	}

2)Ognl表达式语言取值,取根元素的值,不用#号

@Test
	public void testOgnl2() throws Exception {
		OgnlContext context=new OgnlContext();
		
		User user=new User();
		user.setId(111);
		user.setName("张国荣--哥哥");
		
		//往非根元素放入数据,取值的时候要用#
		context.setRoot(user);//往根元素中放入数据,取值时直接用属性即可
		
		//拿数据:通过map
		//先构建一个ognl表达式,再解析表达式,通过Ognl表达式取数据
		Object ognl = Ognl.parseExpression("name");
		Object value = Ognl.getValue(ognl, context, context.getRoot());
		System.out.println(value);
	}
	

3)Ognl对静态方法调用的支持

@Test
	public void testOgnl3() throws Exception {
		OgnlContext context=new OgnlContext();
		
		//Object ognl = Ognl.parseExpression("@Math@floor(11.5)");
		//由于Math类比较常用,设计的比较特殊,所以可以这样写
		Object ognl = Ognl.parseExpression("@@floor(18.5)");
		Object value = Ognl.getValue(ognl, context, context.getRoot());
		System.out.println(value);
	}

三,ValueStack对象

1) ValueStack实际是一个接口,在Struts2中使用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2使用OGNL的基础.

public interface ValueStack {...}
2)ValueStack特点:ValueStack贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的request请求属性中,传入到jsp页面.
3)开发者只需要通过ActionContext对象就可以访问struts的其他的关键对象.(ActionContext是给开发者用的,便于学习与使用)

4) ObjectStack: Struts  把动作和相关对象压入 ObjectStack 中--List
    ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
    Struts 会把下面这些映射压入 ContextMap 中
    parameters: 该 Map 中包含当前请求的请求参数
    request: 该 Map 中包含当前 request 对象中的所有属性
    session: 该 Map 中包含当前 session 对象中的所有属性
    application:该 Map 中包含当前 application  对象中的所有属性
    attr: 该 Map 按如下顺序来检索某个属性: request, session, application

ValueStack数据:



root=CompoundRoot表示的根元素数据,里面存放当前Action对象,成员变量(要提供相应的setter与getter方法才能通过<s:debug></s:debug>标签看到成员变量信息)等等.

context=OgnlContext主要就是存储一些域数据.

5)获取值栈ValueStack的两种方式,在同一个Action中不同方式拿到的值栈对象是相同的.

private void vs() throws Exception {
		//获取值栈对象:方式一
		HttpServletRequest request = ServletActionContext.getRequest();
		ValueStack vs1 = (ValueStack) request.getAttribute("struts.valueStack");
		
		//获得值栈对象:方式二
		ActionContext ac = ActionContext.getContext();
		ValueStack vs2 = ac.getValueStack();
		
		System.out.println(vs1 == vs2);//輸出:true
	}
}

四,struts标签(使用了OGNL表达式语言)

1)存数据

package cn.bighuan.b_ognl;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
/**
 * struts的数据流转
 * @author bighuan
 *
 */
public class OgnlAction extends ActionSupport{
	
	//Action全局成员都是根元素的值
	private User user=new User(11,"Leslie");
	public void setUser(User user) {
		this.user = user;
	}
	public User getUser() {
		return user;
	}

	@Override
	public String execute() throws Exception {
		ActionContext ac = ActionContext.getContext();
		//这两种存数据的方式有点不一样
		Map<String, Object> request = ac.getContextMap();
		request.put("request_data","request_data");
		
		Map<String ,Object> request1 = (Map<String, Object>) ac.get("request");
		request1.put("request_data111","request_data111");
		
		
		Map<String, Object> session = ac.getSession();
		Map<String, Object> application = ac.getApplication();
		
		request.put("request_data","request_data");
		session.put("session_data", "session_data");
		application.put("application_data", "application_data");
		
		
		ValueStack vs = ac.getValueStack();
		
		System.out.println(vs);
		return SUCCESS;
	}

2)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">    
    <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>
    <%--页面必须要拿到ValueStack --%>
    <h3>取根元素的值 </h3>
    <s:property value="user.name"/><br/>
    <s:property value="user.id"/><br/>
    
    <hr/>
    <h3>取非根元素的值  </h3>
    <s:property value="#request.request_data"/><br/>
      <s:property value="#session.session_data"/><br/>
       <s:property value="#application.application_data"/><br/>
       
       <%--自动找request-->session-->application --%>
        <h5>取非根元素的值 :通过attr取数据 </h5>
       <s:property value="#attr.request_data"/><br/>
        <s:property value="#attr.session_data"/><br/>
         <s:property value="#attr.application_data"/><br/>
       
       <hr/>
        <h3>直接通过key取值  </h3>
       ********Map<String, Object> request = ac.getContextMap();两种方式取值******************<br/>
       <s:property value="#request_data"/><br/>
        <s:property value="#request.request_data"/><br/>
       ***Map<String ,Object> request1 = (Map<String, Object>) ac.get("request");只有一种方式****<br/>
       <%--  <s:property value="#request_data111"/><br/>错误 --%>
       <s:property value="#request.request_data111"/><br/>
         <s:property value="user.name"/><br/><br/>
         
      <br/>*******************重要点**********************   
         <hr>通过get("request")得到map对象得到的数据,这种方式只能通过#+域+key取值</hr><br/>
         <s:property value="#request.request_data111"/>
    
    
    <%--调试标签 --%>
    <s:debug></s:debug>
  </body>
</html>

3_存List数据或Map数据

package cn.bighuan.b_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;
import com.opensymphony.xwork2.util.ValueStack;

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<10; i++) {
			User user = new User(i,"Leslie" + i);
			
			list.add(user);
			map.put(user.getId(), user);
		}
		
		// 保存 
		ActionContext.getContext().getContextMap().put("list", list);
		ActionContext.getContext().getContextMap().put("map", map);
		
		
		return super.execute();
	}
}

4)迭代器标签

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

</head>

<body>
	<br />一、. 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 />二、迭代map
	</br>
	<table border="1">
		<tr>
			<td>编号</td>
			<td>名称</td>
		</tr>
		<s:iterator var="en" value="#request.map" status="st">
			<tr>
				<td><s:property value="#en.key" />
				</td>
				<td><s:property value="#en.value.name" />
				</td>
			</tr>
		</s:iterator>
	</table>


	<!-- Ognl表达式可以取值,也可以动态构建集合 -->
</body>
</html>

五,ValueStack总结

1)值栈以struts.valueStack的名字存储在request请求中,值栈主要包含两个栈:对象栈和Map栈.
        对象栈存储的是用户的基本数据和对象数据 ; Map栈主要存储的是域对象属性。
        用户每次一个请求就一个Action实例,对应一个值栈对象。
2)思考:
       放在request中的值栈中可以存储session和servletContext域数据,显然request的作用有没有那么大?直接使用拷贝的方式以key=value的方式拷贝到Map栈对应的Map中.
Map栈中的_root
       debug可见该属性中引用的是对象栈数据。如果在Map栈中不存储_root对于对象栈的引用,那么开发者需要访问数据时候首先要区分是访问对象栈还是Map栈,比较繁琐。因此以后操作数据直接操作Map栈即可。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值