Struts2的值棧(ValueStack),詳解+圖解

值棧的概述

1、什麼是值棧

Struts2將XWork對Ognl的擴展這一套機制封裝起來,這個對象叫ValueStack。
ValueStack實際上就是一個容器。
它由Struts框架創建,當前端頁面如jsp發送一個請求時,Struts的默認攔截器會將請求中的數據進行封裝,併入ValueStack的棧頂。

ValueStack是Struts的一一個接口,字面意義爲值棧,OgnIValueStack 是ValueStack 的實現類,客
戶端發起一個請求struts2 架構會創建一個action 實例同時創建-一個OgnIValueStack 值棧實例,OgnlValueStack貫穿整個Action 的生命週期,struts2 中使用OGNL將請求Action的參數封裝爲對象存儲到值棧中,並通過OGNL表達式讀取值棧中的對象屬性值。

簡化理解ValueStack其實類似一個數據的中轉棧(Strust2框架當中的數據就都保存到了ValueStack中)
ValueStack接口,實現類OgnlValueStack的對象。
ValueSatck貫穿整個Action的生命週期。(Action一旦創建了,框架就會創建一個ValueStack對象)
放入值棧的數據可以在任何位置取出來(JSP、Servlet、Action、配置文件,在Struts2的任何地方都可以取到)

2、值棧的內部結構

ValueStack當中有兩個主要的區域:

在這裏插入圖片描述

root區域: 其實就是一個ArrayList。裏面一般放置的對象。獲取root的數據是不需要加#
context區域:其實就是一個Map。裏面放置的是Web開發的一些常用的對象數據的引用。獲取的是context當中的數據是需要加#

requets:
session:
application:
parameters:
attr:
所說的操作值棧,通常指的是操作的是ValueStack當中的root區域。
創建一個類繼承ActionSupport

public class ValueStackDemo1 extends ActionSupport {
	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		//獲得值棧的對象
		ValueStack valueStack = ActionContext.getContext().getValueStack();
		return SUCCESS;
	}
}

設置跳轉頁面
在這裏插入圖片描述

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>查看值棧的內部結構</h1>
	<s:debug></s:debug>
</body>
</html>

結果頁面的數據
在這裏插入圖片描述

3、值棧與ActionContext的關係

ServletContext:Servlet的上下文。(貫穿整個應用的對象)

ActionContext:Action的上下文。(貫穿整個應用的對象)

通過源碼查看到:當請求過來的時候,執行過濾器當中的doFilter方法,在這個方法當中創建ActionContext,
在創建ActionContext的過程當中,創建ValueStack對象,將ValueStack對象傳遞給ActionContext對象。
所以我們可以通過ActionContext來獲取值棧的對象
ActionContext這個對象之所以能夠訪問到Servlet的API(訪問的是域對象當中的數據)。因爲在其內部有值棧的引用

//獲得值棧的對象
ValueStack valueStack = ActionContext.getContext().getValueStack();

4、獲得值棧

(1)第一種:通過ActionContext對象來獲取值棧對象。

在Struts2內部,將值棧存入到request中一份。

// 第一種:通過ActionContext獲得:
ValueStack valueStack = ActionContext.getContext().getValueStack();
(2) 第二種:通過request對象來獲得
// 第二種:通過request對象來獲得
ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
(3) 測試兩個對象是不是同一個對象

一個Action的實例,只會創建一個ValueStack的對象(一個ValueStack只會爲一個Action服務)

public class ValueStackDemo2 extends ActionSupport {
	@Override
	public String execute() throws Exception {
		// 第一種:通過ActionContext獲得:
		ValueStack valueStack1 = ActionContext.getContext().getValueStack();
		// 第二種:通過request對象來獲得
		ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest()
				.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
		System.out.println(valueStack1 == valueStack2);
		return NONE;
	}
}

瀏覽器訪問
在這裏插入圖片描述
表示兩個方式獲取的Action是同一個值棧對象
在這裏插入圖片描述

5、操作值棧-向值棧當中存入數據(Root當中)

(1)第一種:在Action當中提供屬性的get方法的方式。

默認的情況下,將Action對象壓入到值棧。Action都在值棧當中,那麼Action的屬性一定也在值棧當中。

/*
 * 操作ValueStack:方式一:利用Action本身在值棧當中本身的特性。
 */
public class ValueStackDemo3 extends ActionSupport {
	private User user;
	public User getUser() {
		return user;
	}
	@Override
	public String execute() throws Exception {
		// 向ValueStack中去存值
		user = new User("李峯", "222");
		return SUCCESS;
	}
}

配置文件
在這裏插入圖片描述
jsp頁面
在這裏插入圖片描述
可以在Root當中得到對應的user對象
在這裏插入圖片描述
在這裏插入圖片描述

(2)第二種:使用ValueStack當中本身的一些方法的方式。
import com.itzheng.struts2.domain.User;
import com.opensymphony.xwork2.ActionContext;
/*
 * 操作值棧:方式二:調用值棧當中的方法來進行實現。
 */
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class ValueStackDemo4 extends ActionSupport {
	@Override
	public String execute() throws Exception {
		//向值棧保存數據:
		//獲得值棧對象
		ValueStack valueStack = ActionContext.getContext().getValueStack();
		//一般會使用值棧當中的兩個對象
		//使用push(Object obj); set(String key,Object obj);
		User user = new User("李四","121212");
		//壓棧,user在棧頂的位置 
		valueStack.push(user);
		return super.execute();
	}
}

在這裏插入圖片描述
User在棧頂
在這裏插入圖片描述

注意:通過set的方式將輸入放入到棧當中
誰最後調用誰就在最上面,創建了一個MAP集合,將MAP集合壓入到棧當中
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

6、獲取值棧的是數據

(1)獲取root當中的數據:不需要加#

獲取值棧當中數據就是在頁面當使用OGNL表達式即可。
獲取對象的數據
在這裏插入圖片描述
在這裏插入圖片描述
瀏覽器頁面上
在這裏插入圖片描述
保存並獲取集合當中的數據

public class ValueStackDemo5 extends ActionSupport {
	@Override
	public String execute() throws Exception {
		// 向值棧當中保存對象
		User user = new User("aaa", "123");
		ActionContext.getContext().getValueStack().push(user);


		// 同值棧中保存一個集合
		List<User> list = new ArrayList<User>();
		list.add(new User("aaa", "111"));
		list.add(new User("bbb", "222"));
		list.add(new User("ccc", "333"));
		ActionContext.getContext().getValueStack().set("list", list);
		return super.execute();
	}
}

在這裏插入圖片描述
在這裏插入圖片描述

(2)獲取context當中的數據:不需要加#

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

(3)拓展內容

注意如果是arrt.name那麼獲取的是棧值當中的棧頂元素(也就是第一個元素)
在這裏插入圖片描述
parameters.id的作用是接收參加
在這裏插入圖片描述
在這裏插入圖片描述

7、EL爲什麼可以訪問值棧的數據

因爲Struts2的框架的底層對request.getAttribute(String name);

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章