Struts2学习笔记三(OGNL表达式与值栈)

  • 这是学习过程中的一些记录,可能有出错的地方,仅供参考

值栈的简介

在Servlet中,servlet在与前端页面之间的数据传输是通过域对象来做中转的,那么在Struts2中也有他自己做定义的一个数据中转站,这个中转站就是值栈ValueStack。

  • 值栈的生命周期

值栈是Struts2的一个接口,当有页面请求时Struts2就会为我们创建好一个值栈的实现类OgnlValueStack对象,同时Struts2也会创建一个ActionContext对象和Action对象,然后将值栈封装在ActionCOntext对象中,值栈的生命周期是与Action息息相关的,Action存在则值栈存在,Action消亡则值栈也消亡。

  • 值栈的内部结构

总体来看,值栈的数据结构就是一个栈,底层实现是list,在值栈中主要看两个存贮数据的区域,一个是root区,一个是context区。
root区底层又是用ArrayList实现的,而context区是用Map实现的。

  1. root区

当有请求访问时,Struts2会创建一个Action实例,还会把action对象放到值栈的root区,注意所有放入值栈的都是放入对象的地址引用。在root区中,当放入的是一个对象,也会把对象内的成员属性也一并放入root区,因此Action对象中定义的成员属性也会被放入root区。

  1. context区

在context区中存放着request、session、application等对象,注意这个的request、session等都只是map集合的key,而value这是request等key所对应的request对象中的数据。

  • 值栈的查看

在Struts2中,我们可以通过使用Struts2的标签库来查看值栈的root区和context区。
注意要导入struts2的标签库。<%@taglib prefix=“s” uri="/struts-tags" %>
在jsp页面写入标签<s:debug></s:debug>,这样我们就可以在浏览器查看到值栈的内部结构。

  1. root区:
    root区
  2. context区:
    context区
  • 往值栈的root区存值
package com.wzm.action;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.ValueStack;
import com.wzm.entity.User;

public class ActionDemo6 extends ActionSupport{
	/*
	 * 向值栈的root区存储数据有两种方式,
	 * 一种是属性存值,因为struts2会吧action对象存在值栈的root区,
	 * 因此action对象里边的成员属性也会一并存在root区,
	 * 注意是存在值栈root区的Property Name+Property Value
	 * 另一种方式则是通过ActionContext获取值栈对象ValueStack,然后通过值栈获取root区CompoundRoot对象
	 * 调用push(user),底层是调用add(0, user)方法就可以往root区存值,
	 * 注意这里是存在list下标为0的区域,相当存在root区的栈顶,同时如果是对象,会把对象内的属性存在Property Name+Property Value
	 */
	
	//在action中直接定义一个成员属性,struts2会把这个属性存在root区
	//注意有个条件就是要有这个属性的getter方法
	private User user;
	public User getUser() {
		return user;
	}
	private String jsp;
	
	public String getJsp() {
		return jsp;
	}

	@Override
	public String execute() throws Exception {
		/*
		 * 通过获取root区的对象来往栈顶存值,其实不用获取root区对象也能实现功能
		 * valueStack.push(user);同样是往root区存值,底层调用的还是add(0, user)
		 */
		//获取actioncontext对象
		ActionContext context = ActionContext.getContext();
		//获取值栈对象
		ValueStack valueStack = context.getValueStack();
		//获取root区对象
		CompoundRoot root = valueStack.getRoot();
		user = new User();
		user.setAge(18);
		jsp = "/ognl.jsp";
		//往root区存值
		root.push(user);
		return "success";
	}
}

  • 往值栈的context区存值
package com.wzm.action;

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.ValueStack;
import com.wzm.entity.User;

public class ActionDemo7 extends ActionSupport{

	@Override
	public String execute() throws Exception {
		ActionContext context = ActionContext.getContext();
		/*
		 * 这里是向值栈中的context区存值
		 * 能够通过el表达式获取到${context区中的key}
		 * 之前说这个有点类似往request域对象中存值,但是实际上不是,
		 * 这是在context区中单独再创一个键值对出来,而不是在request中创建键值对
		 */
		context.put("msg", "context");
		//这里获取session,往session存值,也是通过值栈存值
		//session的引用存在值栈的context区中
		Map<String, Object> session = context.getSession();
		session.put("a", "a");
		return "success";
	}
}

OGNL表达式

OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换。OGNL表达式不是Struts2专属的,Struts2只是对其进行了封装。

  • OGNL表达式的基本使用
    注:需要导入struts2的标签库
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!-- 要使用OGNL表达式,需要导入struts2的标签库 -->
<%@	taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<!-- 这是debug标签,通过这个可以看到值栈的内部结构 -->
	<s:debug></s:debug>


	<!-- property是struts2的标签,用来使用ognl表达式获取值 -->
	<!-- ognl表达式可以用来直接调用对象方法 -->
	<s:property value="'struts2'.length()"/><br>
	<!-- ognl表达式可以用来直接调用静态属性,注意格式@全限定名@静态属性 -->
	<s:property	value="@java.lang.Math@PI"/><br>
	<!-- ognl表达式可以用来直接调用静态方法,注意格式@全限定名@静态方法
			同时注意struts2默认不让调用静态方法,需要覆盖配置
			在struts.xml或者web.xml加都可以
		<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
	 -->
	<s:property value="@java.lang.Math@random()"/>
	<!-- ognl表达式可以用来获取值栈中的值 ,value中使用的值是值栈中root区的Property Name	
			如果存储的是一个对象,还可以通过对象.属性名来获取对象内的属性值
	-->
	<s:property value="user.username"/>
</body>
</html>
  • Struts2中el表达式

EL表达式原来的搜素顺序:
page Scope——>request Scope——>sessionScope——>application Scope
在struts2中,struts2框架通过使用装饰者模式对request对象进行了包装,并且对getAttribute方法进行了增强,使得el表达式的搜索顺序变为了:
page Scope—>request Scope—>root区—>context区- >sessionScope—>application Scope
因此当我们往context区中存数据时,我们可以使用el表达式得到存储的数据。

  • el表达式的三种特殊符号
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!-- 要使用OGNL表达式,需要导入struts2的标签库 -->
<%@	taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<!-- 这是debug标签,通过这个可以看到值栈的内部结构 -->
	<s:debug></s:debug>
	
	<!-- ognl表达式的几个特殊符号# % $ -->
	<!-- 当在ognl表达式中使用到#,代表是从值栈的context区中获取值
			value中使用的值的context区的key
	 -->
	 <s:property value="#request"/>
	 
	 <!-- #还可以用在遍历值栈中得到的集合 -->
	 <!-- 直接在value中创建一个list集合
	 		遍历出来的每一个值都存在var中,var是存在值栈的context区,因此取值需要加#
	 		每一次都会被覆盖
	  -->
	 <s:iterator value="{'aaa','bbb','ccc'}" var="l">
	 	<s:property value="#l"/>
	 </s:iterator>
	 
	  <!-- 直接在value中创建一个map集合,注意这里需要使用  #  来表明这是一个map集合
	 		遍历出来的每一个值都存在var中,map遍历出来的是键值对
	 		取值用#var.key或者key,#var.value获取值
	  -->
	 <s:iterator value="#{'1':'a','2':'b' }" var="m">
	 	<s:property value='#m.key'/>---》<s:property value='#m.value'/>
	 </s:iterator>
	 
	 <!-- %在ognl表达式的使用
	 	在struts2中不是所有的struts2标签都认识ognl表达式,
	 	因此当我们需要在其他struts2标签中使用ognl表达式就需要用到%
	  -->
	  <s:textfield name="username" value="%{user.username}"></s:textfield>
	  
	  
	  <!-- $在ognl表达式中是使用在struts.xml配置文件中的,注意与el表达式区分
	  		通过使用 $ 符号我们可以直接在struts.xml中使用ognl表达式获取值栈的值
	  		往值栈存储key为jsp的值,获取jsp的值“/ognl.jsp”直接跳转页面
	  		<package name="test6" extends="struts-default">
			  	<action name="demo6" class="com.wzm.action.ActionDemo6">
			  		<result>${jsp}</result>
			  	</action>
	  		</package>
	   -->
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值