(八)Struts2進(jìn)階之值棧詳解

1.什么是值棧

在Servlet中蛉腌,我們都是把數(shù)據(jù)放在域?qū)ο笾校缓笤趈sp頁面中進(jìn)行讀取。那么在Struts2中烙丛,提供了另外一種存儲(chǔ)機(jī)制舅巷,就是值棧,在action中把值放入值棧河咽,在頁面中進(jìn)行讀取钠右。

2.action和servlet的區(qū)別

action:每次訪問的時(shí)候都會(huì)創(chuàng)建一次。
servlet:默認(rèn)在第一次訪問的時(shí)候創(chuàng)建忘蟹,在生命周期里只會(huì)創(chuàng)建一次飒房。

我們創(chuàng)建一個(gè)LifeAction來看看

@SuppressWarnings("serial")
public class LifeAction extends ActionSupport {
    
    public LifeAction() {
        System.out.println("action創(chuàng)建了。媚值。狠毯。。");
    }
    @Override
    public String execute() throws Exception {
        // 沒有操作
        return NONE;
    }
}

在該類中有一個(gè)構(gòu)造方法杂腰,每次創(chuàng)建action的時(shí)候都會(huì)打印信息垃你。
在struts.xml中配置action

<action name="life" class="com.codeliu.action.LifeAction"></action>

訪問后,每次刷新頁面喂很,都會(huì)創(chuàng)建一個(gè)action對(duì)象惜颇。

3.值棧的存儲(chǔ)位置

每次創(chuàng)建一個(gè)action對(duì)象,都會(huì)跟隨著一個(gè)值棧對(duì)象少辣,也就是說每個(gè)action里面都有一個(gè)值棧凌摄。

4.獲取值棧對(duì)象

// 獲取ActionContext實(shí)例對(duì)象
ActionContext context = ActionContext.getContext();
// 獲取值棧對(duì)象
ValueStack stack1 = context.getValueStack();
ValueStack stack2 = context.getValueStack();
// true 說明每個(gè)action只有一個(gè)值棧對(duì)象
System.out.println(stack1 == stack2);

上述代碼通過ActionContext類獲取一個(gè)ValueStack(值棧),同時(shí)說明了一個(gè)action里面只有一個(gè)值棧漓帅。

5.值棧的內(nèi)部結(jié)構(gòu)

值棧分為兩部分锨亏。第一部分是root,第二部分是context忙干,通過給成程序加斷點(diǎn)器予,我們可以看到如下的結(jié)果

27.png

context是OgnlContext的實(shí)例對(duì)象,root是CompoundRoot的實(shí)例對(duì)象捐迫,我們看看這兩個(gè)類的定義

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

這說明root其實(shí)本質(zhì)是一個(gè)ArrayList乾翔,而context本質(zhì)是一個(gè)Map。

root中一般存放數(shù)值施戴,而context一般存放對(duì)象的引用反浓。

下面是context的存儲(chǔ)示意圖


28.png

通過debug標(biāo)簽,可以查看值棧的內(nèi)部結(jié)構(gòu)赞哗。(要使用Struts2的標(biāo)簽雷则,必須在jsp開頭引入標(biāo)簽庫

創(chuàng)建一個(gè)ValueStackAction.java

@SuppressWarnings("serial")
public class ValueStackAction extends ActionSupport {
    @Override
    public String execute() throws Exception {
        
        return SUCCESS;
    }
}

在struts.xml中配置Action

<action name="valueStack" class="com.codeliu.action.ValueStackAction">
    <result name="success">/valueStack.jsp</result>
</action>

然后創(chuàng)建一個(gè)valueStack.jsp

<body>
    <!-- 通過這個(gè)標(biāo)簽獲取值棧的信息 -->
    <s:debug></s:debug>
</body>

運(yùn)行這個(gè)action之后就能看到一個(gè)鏈接,點(diǎn)進(jìn)去就能看到值棧的狀態(tài)


root的內(nèi)部

可以看到root內(nèi)部的棧頂是一個(gè)action實(shí)例肪笋。

action對(duì)象里有一個(gè)值棧對(duì)象月劈,值棧對(duì)象里有action引用度迂。

6.向棧中放數(shù)據(jù)

向值棧中放數(shù)據(jù)有三種方法,分別是使用set方法艺栈,push方法和使用action的變量英岭,下面來看一下。

(1)使用set方法

public class ValueStackAction extends ActionSupport {
    @Override
    public String execute() throws Exception {
        /**
         * 往值棧中放數(shù)據(jù)的三種方法
         */
        // 第一種 使用set方法
        ActionContext context = ActionContext.getContext();
        ValueStack stack = context.getValueStack();
        stack.set("url", "www.codeliu.com");
        return SUCCESS;
    }
}

同樣使用debug標(biāo)簽查看值棧的狀態(tài)湿右,發(fā)現(xiàn)棧頂元素變成了我們插入的數(shù)據(jù)Map


棧頂元素已經(jīng)改變了

(2)使用push方法

@SuppressWarnings("serial")
public class ValueStackAction extends ActionSupport {
    @Override
    public String execute() throws Exception {
        /**
         * 往值棧中放數(shù)據(jù)的三種方法
         */
        ActionContext context = ActionContext.getContext();
        ValueStack stack = context.getValueStack();
        // 第二種 使用push方法
        stack.push("codeliu");
        return SUCCESS;
    }
}

再次查看诅妹,發(fā)現(xiàn)棧頂元素變成了一個(gè)String


棧頂元素又變了

(3)使用Action類的變量來放數(shù)據(jù)

@SuppressWarnings("serial")
public class ValueStackAction extends ActionSupport {
    // 1. 定義變量
    private String url;
    // 2. 記得要get方法
    public String getUrl() {
        return url;
    }
    @Override
    public String execute() throws Exception {
        /**
         * 往值棧中放數(shù)據(jù)的三種方法
         */
        // 3.設(shè)置值
        url = "www.codeliu.com";
        return SUCCESS;
    }
}

刷新查看值棧,結(jié)果如下


棧頂沒變毅人,但action中的元素多了

我們發(fā)現(xiàn)棧頂元素沒有變吭狡,但action實(shí)例中多了一行。

一般我們使用第三種方法更多丈莺,因?yàn)檫@樣更節(jié)省空間划煮,同時(shí)使用第三種方法,記得提供get方法缔俄,不然無法插入弛秋。

7.從棧中讀數(shù)據(jù)

現(xiàn)在我們看看使用OGNL+Struts2的標(biāo)簽從值棧中讀取使用上面第三種方法放入的數(shù)據(jù)。
(1)讀字符串的值

@SuppressWarnings("serial")
/**
 * 從值棧中獲取字符串俐载、對(duì)象和List集合
 * @author liu
 */
public class GetValueFromValueStackAction extends ActionSupport {
    private String url;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
    public GetValueFromValueStackAction() {}
    
    @Override
    public String execute() throws Exception {
        url = "www.codeliu.com";
        return SUCCESS;
    }
}

在struts.xml中增加一條記錄

<action name="getValue" class="com.codeliu.action.GetValueFromValueStackAction">
    <result>/getvalue.jsp</result>
</action>

創(chuàng)建getvalue.jsp

<body>
    <!-- OGNL集合Struts2的標(biāo)簽獲取值棧中的值 -->
    <s:property value="url"/>
</body>

啟動(dòng)tomcat后蟹略,進(jìn)入網(wǎng)頁就能看到輸出了url的值。

(2)讀對(duì)象的值
還記得我們上篇文章中有一個(gè)User類遏佣,里面有username和password屬性挖炬,現(xiàn)在我們修改GetValueFromValueStackAction類

@SuppressWarnings("serial")
/**
 * 從值棧中獲取字符串、對(duì)象和List集合
 * @author liu
 */
public class GetValueFromValueStackAction extends ActionSupport {
    private User user = new User();
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public GetValueFromValueStackAction() {}
    @Override
    public String execute() throws Exception {
        user.setUsername("CodeTiger");
        user.setPassword("123456");
        return SUCCESS;
    }
}

在getvalue.jsp中添加如下代碼

<!-- 通過ognl獲取user對(duì)象的值 -->
<s:property value="user.username"/>
<s:property value="user.password"/>

運(yùn)行后状婶,輸出我們?cè)O(shè)置的值意敛。

(3)讀List集合的值
修改GetValueFromValueStackAction類的代碼如下

@SuppressWarnings("serial")
/**
 * 從值棧中獲取字符串、對(duì)象和List集合
 * @author liu
 */
public class GetValueFromValueStackAction extends ActionSupport {
    private User user = new User();
    private List<User> list = new ArrayList<User>();
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    
    public List<User> getList() {
        return list;
    }

    public void setList(List<User> list) {
        this.list = list;
    }

    public GetValueFromValueStackAction() {}
    
    @Override
    public String execute() throws Exception {
        user.setUsername("CodeTiger");
        user.setPassword("123456");
        list.add(user);
        return SUCCESS;
    }
}

讀取值棧中的List膛虫,一般有三種方法

<!-- 獲取List集合中的值 -->
    <!-- 第一種方式 -->
    <s:property value="list[0].username"/>
    <s:property value="list[0].password"/><br>
    <!-- 第二種方式 -->
    <s:iterator value="list">
        <s:property value="username"/>
        <s:property value="password"/>
    </s:iterator><br>
    <!-- 第三種方式 -->
    <s:iterator value="list" var="user">
        <!-- 每次遍歷出來的user對(duì)象草姻,都會(huì)放到context中去,使用OGNL取root中的數(shù)據(jù)稍刀,
            可以不用#碴倾,但取context中的數(shù)據(jù),則要加上# 
        -->
        <s:property value="#user.username"/>
        <s:property value="#user.password"/>
    </s:iterator>

注意第三種方式


下篇文章講OGNL掉丽,所以講OGNL之前得先熟悉了解一下值棧,才能更好的使用OGNL异雁。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末捶障,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纲刀,更是在濱河造成了極大的恐慌项炼,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锭部,居然都是意外死亡暂论,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門拌禾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來取胎,“玉大人,你說我怎么就攤上這事湃窍∥胖” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵您市,是天一觀的道長觉痛。 經(jīng)常有香客問我,道長茵休,這世上最難降的妖魔是什么薪棒? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮榕莺,結(jié)果婚禮上俐芯,老公的妹妹穿的比我還像新娘。我一直安慰自己帽撑,他們只是感情好泼各,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亏拉,像睡著了一般扣蜻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上及塘,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天莽使,我揣著相機(jī)與錄音,去河邊找鬼笙僚。 笑死芳肌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肋层。 我是一名探鬼主播亿笤,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼栋猖!你這毒婦竟也來了净薛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤蒲拉,失蹤者是張志新(化名)和其女友劉穎肃拜,沒想到半個(gè)月后痴腌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡燃领,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年士聪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猛蔽。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡剥悟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出枢舶,到底是詐尸還是另有隱情懦胞,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布凉泄,位于F島的核電站躏尉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏后众。R本人自食惡果不足惜胀糜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蒂誉。 院中可真熱鬧教藻,春花似錦、人聲如沸右锨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绍移。三九已至悄窃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蹂窖,已是汗流浹背轧抗。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞬测,地道東北人横媚。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像月趟,于是被迫代替她去往敵國和親灯蝴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 本文包括:1孝宗、OGNL 表達(dá)式概述(了解)2绽乔、值棧概述3、值棧的存值與取值4碳褒、EL 表達(dá)式也會(huì)獲取到值棧中的數(shù)據(jù)5...
    廖少少閱讀 1,246評(píng)論 0 14
  • 概述 什么是Struts2的框架Struts2是Struts1的下一代產(chǎn)品折砸,是在 struts1和WebWork的...
    inke閱讀 2,249評(píng)論 0 50
  • OGNL表示式使用 和 值棧OGNL是Object Graphic Navigation Language(對(duì)象圖...
    luweicheng24閱讀 357評(píng)論 1 1
  • 1.OGNL 1.1 OGNL 概述 OGNL,全稱是 Object-Graph Navigation Langu...
    Wizey閱讀 362評(píng)論 0 0
  • 流云入夢(mèng)枕驚寒沙峻, 無眠思涌盡闌珊睦授。 沉寂歲月彷徨路, 待有臥龍出蜀川摔寨。
    卷哥是流氓閱讀 168評(píng)論 0 3