Struts2的值栈和OGNL表达式

1、值栈

值栈: ValueStack

当浏览器访问action的时候,会被前端控制器(StrutsPrepareAndExecuteFilter)拦截住,在filter中创建值栈(ValueStack)对象(特点:访问一次,创建一次)

创建完以后,会将访问的整个action对象放在ValueStack中,还会将request,session,servletContext对象的底层用来存储数据的map数据集合放在ValueStack中,还会将当前页面提交的所有数据以map的方式也存放在ValueStack中(ps:存放的都是地址引用)

当整个action执行完毕,action对象会被销毁,ValueStack对象也会被销毁下次访问又是一个新的aciton对象和新的ValueStack对象,也就是说:aciton的生命周期和ValueStack是同步的,ValueStack会伴随action一生

ValueStack: 是struts2提供了一个接口 真正的实现类是:OgnlValueStack

值栈的内存区域由两部分组成,root区和context区,大致描述图如下:

 从应用角度出发,值栈的主要作用是供Struts2的使用者通过值栈来存取数据。

那么,如何操作值栈中的数据,又如何获取值栈中的数据?

首先,如何操作值栈中的数据,我们可以通过ActionContext的对象来获取值栈对象,这是因为在Action的实例被创建时,会创建值栈对象,并将值栈对象存入ActionContext中。主要源码如下:

  public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
        ActionContext ctx;
        Integer counter = 1;
        Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
        if (oldCounter != null) {
            counter = oldCounter + 1;
        }
        
        ActionContext oldContext = ActionContext.getContext();
        if (oldContext != null) {
            // detected existing context, so we are probably in a forward
            ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));
        } else {
            ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
            stack.getContext().putAll(dispatcher.createContextMap(request, response, null));
            ctx = new ActionContext(stack.getContext());
        }
        request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);
        ActionContext.setContext(ctx);
        return ctx;
    }

因此,要获取ValueStack对象,只需要通过ActionContext来获取:

ValueStack valueStack = ActionContext.getContext().getValueStack();

操作值栈中的数据分为两部分,一部分为操作root中的数据,一部分为操作context区中的数据

操作root区数据,可以在获取值栈对象后,调用set或者push方法,其中push会将数据存储在栈顶

public class ValueStack3Action extends ActionSupport{

	@Override
	public String execute() throws Exception {
		// 获得值栈:
		ValueStack valueStack = ActionContext.getContext().getValueStack();
		/**
		 * ValueStack中的方法:
		 * 	* void set(String key,Object value);  -- 创建一个Map集合,将Map集合存入到值栈(root)中。
		 * 	* void push(Object obj);			  -- 将对象存入到值栈(root)中。
		 * * 栈的特点:先进后出.
		 */
		valueStack.set("name", "王强勇");// 一般list集合使用set
		
		User user = new User();
		user.setUsername("aaa");
		valueStack.push(user); // 一般Object使用push
		
		return SUCCESS;
	}
}

也可以通过想action类提供成员属性的方式来放入数据,上一篇说过,Struts2中的action为多实例,也就是其可以创建成员属性,而action对象会默认存储在root区的栈顶,只要对action加入成员属性,这个成员属性也会出现在栈中。

public class ValueStack3Action extends ActionSupport{

	private Integer age;
	
	public Integer getAge() {
		return age;
	}
..
}

操作context区的数据,主要是使用ActionContext的对象来调用get方法,获取context区中的Map,如Session,操作如下:

ActionContext act = ActionContext.getContext();
Map<String,Object> sessionMap = act.getSession();
sessionMap.put();

在往值栈中放入数据后,需要从页面获取到,实际上整个值栈中的数据都可以在页面获取到,可以用<s:debug></s:debug>来进行测试,但是要获取值栈中的数据,必须使用OGNL表达式,而在Struts2中,OGNL表达式必须在Struts2标签中使用,Struts2将OGNL表达式作为了自己的默认页面表达式语言。

要使用Struts2标签,必须首先在jsp页面中进行导入:<%@taglib prefix="s" uri="/struts-tags"%>,示例:

<h1>获取root区数据</h1>
<h3>获取push的数据</h3>
<s:property value="username"/>
<s:property value="password"/>
<h3>获取set的数据</h3>
<s:property value="user.username"/>
<s:property value="user.password"/>
<h3>获取list集合中的数据</h3>
<s:property value="list[0].username"/>
<s:property value="list[0].password"/>
<s:property value="list[1].username"/>
<s:property value="list[1].password"/>
<s:property value="list[2].username"/>
<s:property value="list[2].password"/>
<br/>

<h1>获取context区数据</h1>
<s:property value="#request.name"/>
<s:property value="#session.name"/>
<s:property value="#application.name"/>
<s:property value="#parameters.id"/>
<s:property value="#attr.name"/>

最主要的需要记住,当获取root区中的数据时,不需要使用#,而context区的数据需要加#。

此外,也可以用el表达式获取值栈中的数据,11个常用的web操作对象都可以:

requestScope、sessionScope、pageScope、applicationScope、param、paramValues、header、headerValue、cookie、initparams、pageContext,举例如下:

${sessionScope.msg1 }
${applicationScope.msg2 }
${requestScope.msg }--->${msg}

 

2、OGNL表达式简介

OGNL表达式:对象图导航语言,是一门功能强大的表达式语言(功能比EL强大很多倍)。

ognl是单独的表达式语言,Struts2将OGNL引入到自身

所以:struts2的默认表达式语言就是ognl

OGNL的作用如下:

a、调用对象的方法(了解)

b、调用类的静态属性(了解)

条件:   @全限定名@静态属性

c、调用类的静态方法(了解)

条件:   @全限定名@静态方法

 配置常量允许调用类的静态方法

d、获取值栈的数据

其中a-c的用法举例如下:

<h1>OGNL在Struts2环境中使用</h1>
<h3>访问对象的方法</h3>
hello的长度是:<s:property value="'helloworld'.length()"/>
<h3>访问对象的静态属性</h3>
π的值是:<s:property value="@java.lang.Math@PI"/><br/>
<h3>访问对象的静态方法</h3>
随机数是:<s:property value="@java.lang.Math@random()"/>

OGNL中的三个符号:#,%,$

#:获取context区中的数据,遍历list集合、遍历Map集合、构建Map集合,举例如下:

#获取context中的数据
<s:property value="#request.name"/>
<s:property value="#session.name"/>
<s:property value="#application.name"/>
<s:property value="#parameters.id"/>
<s:property value="#attr.name"/>

<h3>遍历List集合</h3>
<s:iterator var="i" value="{'aa','bb','cc'}">
	<s:property value="#i"/><br/>
</s:iterator>
<h3>遍历Map集合</h3>
<s:iterator var="entry" value="#{'aa':'11','bb':'22','cc':'33'}">
	<s:property value="key"/>--<s:property value="value"/><br/>
	<s:property value="#entry.key"/>--<s:property value="#entry.value"/><br/>
</s:iterator>
<h3>使用Struts2UI标签构建Map集合的地方</h3>
传统方式:<br/>
性别:<input type="radio" name="sex" value="男"/>男<input type="radio" name="sex" value="女"/>女<br/>
性别:<input type="radio" name="sex" value="1"/>男<input type="radio" name="sex" value="2"/>女<br/>
Struts2UI标签的方式:<br/>
<s:radio list="{'男','女'}" name="sex" label="性别"/>
<s:radio list="#{'1':'男','2':'女' }" name="sex" label="性别"/>

%:用于强制解析OGNL表达式(?)

<%
	request.setAttribute("name", "王强勇");
%>
<input type="text" name="name" value="<s:property value="#request.name"/>"/>
<s:textfield name="name" value="%{#request.name}"/>

$符号:在Struts2的配置文件中使用,来进行取值

如:文件下载
<action name=”download” class=””>
	<result name=”” type=”stream”>${fileName}</result>
</action>

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值