1. 程式人生 > >Struts2_ValueStack,OGNL詳解

Struts2_ValueStack,OGNL詳解

一、ValueStack
    1
.ValueStack是一個介面,在struts2中使用OGNL(Object-Graph Navigation Language)表示式實際上是使用
        實現了ValueStack介面的類OgnlValueStack.它是ValueStack的預設實現類.
    2.ValueStack貫穿整個action的生命週期,每一個action例項都擁有一個ValueStack物件,其中儲存了當前action物件和其他相關物件.

    3.struts2把ValueStack物件儲存在名為:struts.valueStack的request域中.即ValueStack作用域為request.當action建立的時候,ValueStack就建立了,action被銷燬的時候,ValueStack就銷燬了

    4.ValueStack中的資料分兩部分存放:root(棧結構,CompoundRoot)和context(map形式,OgnlContext)
         (1)    * 其中的root物件是CompoundRoot,CompoundRoot繼承了ArrayList,提供了額外的方法:push(),和pop()方法,
                 用來對root物件中所包含的資料進行存取.正是由於這兩個方法,CompoundRoot變成了一個棧結構.
            * struts2中,一個請求在最終到達Action的方法之前,Action物件本身會被壓入ValueStack(實際上就是放到ValueStack
                的CompoundRoot中),所以action物件是CompoundRoot中的一個元素.
        (2)* 其中的context物件是OgnlContext,它實現了map介面,在valuestack的預設實現類中,即OgnlValueStack類中,
                呼叫ongl中的方法:Ognl.createDefaultContext(..)給context賦值,檢視原始碼可知,
                此方法返回的是一個OgnlContext物件.
    5
.獲取ValueStack的三種方式
        (1)ValueStack valueStack = ActionContext.getContext().getValueStack();    
                ActionContext為Action的上下文,其中有重要的6大物件
                    * valueStack,parameters,request,session,application,attr
                    * 而ognl表示式必須選擇AcitonContext中的一個物件作為根物件(root),預設為valueStack,因此訪問valueStack中的資料不加#
                        而如果要使用另外5個物件作為根物件,需要加#字首.
        (2)ValueStack valueStack = ServletActionContext.getValueStack(ServletActionContext.getRequest());        
                ServletActionContext繼承了ActionContext,它與web容器耦合,可以獲取web容器的一些資訊.

        (3)ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");

    6.ValueStack記憶體結構圖

    7.常用的儲存資料的方法
        (1)向map棧中存資料,即ValueStack中的context(OgnlContext)
            * 通過request,session等向map中儲存資料
                ServletActionContext.getRequest().setAttribute("username","joey");
                ServletActionContext.getSession().put("pwd","123");
            * 直接向map棧中放資料
                ActionContext.getContext().put("msg","how you doing");    
        (2)向物件棧中存資料,即ValueStack中的root(CompoundRoot)物件
            * 先得到root,再把資料壓入到root中,這中方式是放入到棧底.
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.getRoot().add(new Person());
            * 先得到root,利用add(index,Object)把一個物件壓入到root中指定位置.
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.getRoot().add(0,new Person());//這裡0,表示壓入棧頂.
            * 存放一個map到物件棧中
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.set("msg","dude"); //先封裝成Map,在把Map放入到物件棧中,且放入棧頂.
            * 利用valueStack的push方法把一個物件直接壓入棧頂
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.push(new Person());

    8.利用OGNL表示式取ValueStack中的資料
        (1)<s:property />:取棧頂的元素.
        (2)<s:iterator />:取棧頂的元素.
            注意:此標籤的value屬性值無論來自物件棧還是Map棧,都可以不加#字首(<s:select/>標籤也適用).
                因為此標籤在迭代的時候,總是把當前正在迭代的元素放入到棧頂.

二、ognl
    1
.ognl是struts2中使用的一種表示式語言,可用於jsp的標籤庫中,以方便訪問各種物件的屬性.
        它用於把介面的引數傳遞到Action中(並進行型別轉換),它還可以用於struts2的配置檔案中.
    2.Root物件
        OGNL稱為物件圖導航語言,所謂物件圖,即以任意一個物件為根,通過OGNL可以訪問與這個物件關聯的其它物件.
        例如:

	public class User{
		private String username;
		private Group group;
		//省略setter,getter方法
	}
	public class Group{
		private String name;
		private Organization org;
		//省略setter,getter方法
	}
	public class Organization{
		private String orgId;
		//省略setter,getter方法
	}

        以上三個類,描述了通過一個User物件,同過User物件可以導航到Group物件,進而導航到Organization物件.
            以User為根,通過基本的getters方法,可以訪問到此根物件的其它關聯物件.【物件圖的導航,必須通過getters方法導航】
        注意:    * 導航的目的,就是為了獲取某個物件的值或設定某個物件的值或呼叫某個物件的方法.
            * OGNL表示式語言的真正目的,是為了在那些不能寫java程式碼的地方執行java程式碼,或者是為了更方便的執行java程式碼.
    3.Context物件
        * 在OGNL表示式中,有可能需要訪問到多個毫不相干的物件,這時候,我們需要給OGNL傳遞一個Map型別的物件,把表示式中需要用到的物件放到
            Map中即可.而這個Map物件稱為Context
        * 要在表示式訪問到context中的物件,需要使用"#物件名稱"的語法規則.
        * 存在context的主要原因就是在OGNL中,不支援多個root物件,而如果需要在表示式中訪問多個毫不相關的物件時,
            只能通過一個Map來把這些物件統一傳遞給OGNL.