【Struts2筆記整理七】值棧

版權聲明:本文爲 小異常 原創文章,非商用自由轉載-保持署名-註明出處,謝謝!
本文網址:https://blog.csdn.net/sun8112133/article/details/106677519







值棧(ValueStack)Struts2 中也是非常重要的知識,它其實類似於一個數據中轉站,Struts2 框架中的所有數據都保存到了 ValueStack 中。ValueStack 貫穿整個 Action 的生命週期,只要 Action 一創建,Struts2 就會創建一個 ValueStack 對象。

ValueStack 的實現類是 OgnlValueStack 對象,這個對象實現了 ValueStack 接口。

大家需要記住在 ValueStack 中存入的數據在任何地方都能把它取出來。


一、值棧的內部結構

ValueStack 的內部主要有兩個區域:root 區域context 區域

07值棧內部結構

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

我們一般所說的操作 ValueStack,通常指的是操作 ValueStack 中的 root 區域



二、值棧與 ActionContext 的關係

說起 ActionContext,大家肯定會想到 Servlet 中的 ServletContext

ServletContext 是 Servlet 的上下文。所謂的上下文其實就是它包含了全部,和上知五百年下知五百年道理一樣,包含了全部信息;

ActionContext 是 Action 的上下文。通過源碼得知:當請求過來的時候,執行過濾器中的 doFilter 方法,在這個方法中創建 ActionContext 對象,在創建 ActionContext 的過程中,就會創建 ValueStack 對象,並將 ValueStack 對象傳遞給 ActionContext 對象。所以我們 可以通過 ActionContext 獲取 ValueStack 對象 了。

ActionContext 對象之所以能夠訪問 Servlet 的 API (訪問的是域對象的數據)。因爲在其內部有值棧的引用。



三、操作值棧

1、獲得值棧

獲得 值棧 有兩種方式:

  1. 通過 ActionContext 對象獲取 值棧
  2. 通過 Request 對象獲取 值棧。在 Struts2 的內部,已經將 值棧 存入到了 Request 中。
@Override
public String execute() throws Exception {
	// 一種:通過 ActionContext 對象獲得
	ValueStack valueStack1 = ActionContext.getContext().getValueStack();
	
	// 二種:通過 request 對象獲得  "struts.valueStack"
	ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
	
	// 一個 Action 的實例,只會創建一個 ValueStack 的對象 
	System.out.println(valueStack1 == valueStack2);   // true
	return NONE;
}

2、向值棧中存入數據

值棧 中存入數據有兩種方式:

  1. Action 中提供屬性的 get 方法;
  2. 使用 ValueStack 中本身的方法(推薦)。

1)在 Action 中提供屬性的 get 方法

默認情況下,將 Action 對象放入到值棧中,而 Action 中的屬性也會存入,但是我們不推薦使用這種方式,因爲它存入的數據不在棧頂。

  • 編寫 JSP

    <body>
    	<h1>查看值棧的內部結構</h1>
    	<s:debug></s:debug>
    	<!-- 利用 Action 在值棧中的特性 -->
     	<s:property value="user.username" />
    	<s:property value="user.password" />
    </body>
    
  • 編寫 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;
    	}
    }
    

2)使用 ValueStack 中本身的方法(推薦)

  • 編寫 JSP

    <body>
    	<h1>查看值棧的內部結構</h1>
    	<s:debug></s:debug>
    	<!-- 調用 ValueStack 本身的方法,如果有兩個相同名字的,優先棧頂的 -->
    	<s:property value="username" />
    	<s:property value="password" />
    </body>
    
  • 編寫 Action

    /**
     * 操作 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);
    		// 一般保存對象用 push,保存集合用 set
    		User user = new User("李四", "333");
    		// 現在 user 在棧頂的位置
    		valueStack.push(user);
    		valueStack.set("name", "王五");    // 創建一個 Map 集合,將 Map 壓入到棧中
    		return SUCCESS;
    	}
    }
    

3、獲取值棧數據

獲取值棧中的數據就是在頁面中使用 OGNL 表達式即可。

  • 獲取 root 的數據時不需要加 # 號;
  • 獲取 context 數據需要加 # 號。
<body>
	<h3>獲取 root 的數據</h3>
	<s:property value="username" />
    
	<h3>獲取 context 的數據</h3>
	<s:property value="#name" />
</body>

4、EL 爲何能訪問到值棧的數據

因爲 Struts2 框架的底層對 request.getAttribute(String name); 進行了增強,首先從 request 中獲取值,如果找到了就返回,如果沒找到就從值棧中獲取。



博客中若有不恰當的地方,請您一定要告訴我。前路崎嶇,望我們可以互相幫助,並肩前行!



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