1. 程式人生 > >Struts2【OGNL、valueStack】就是這麼簡單

Struts2【OGNL、valueStack】就是這麼簡單

什麼是OGNL表示式?

OGNL是Object Graphic Navigation Language 是操作物件屬性的開源表示式。 Struts2框架使用OGNL作為預設的表示式語言。

為什麼我們學習OGNL

在學習JSP的時候,我們已經學習過了EL表示式。EL表示式用起來也十分簡單…我們在Struts2框架中也是可以使用EL表示式的…那麼OGNL表示式好在哪裡呢??

  • 支援物件方法呼叫,如xxx.doSomeSpecial()
  • 支援類靜態的方法呼叫和值訪問,表示式的格式【例如:”@@floor(10.9)”就是呼叫Math.floor()的方法了】
  • 支援賦值操作和表示式串聯【這個其實EL表示式也能做】
  • 訪問OGNL上下文(OGNL context)和ActionContext
  • 操作集合物件【EL只能遍歷集合,OGNL可以建立集合】

OGNL是Struts2的預設表示式語言,OGNL是配搭Strut2的標籤使用的..我們學習了OGNL表示式,就可以更好地理解Struts2標籤的執行以及Struts2內部的儲存結構.

valueStack物件

在講解OGNL表示式之前,我們先來看看valueStack物件…valueStack是Struts2資料儲存的核心…我們首先要知道資料是怎麼存的,存到哪裡,然後才講解OGNL表示式是怎麼取出資料的

valueStack也被稱作值棧物件..

  • 當用戶訪問Action,都會建立一個Action物件,ActionContext物件、valueStack物件..
  • Struts2把Action物件放進valueStack物件之中
  • 將valueStack放進request域中,傳入JSP頁面(key: struts.valueStack)
  • JSP頁面就可以使用OGNL表示式獲取值棧中的資料了

這裡寫圖片描述

獲取valueStack物件

  • 在Action中我們可以手動獲取值棧物件,有兩種方式獲取
    //獲取值棧物件的2種方式
    private void getVs() {
        // 獲取值棧物件,方式1:
        HttpServletRequest request = ServletActionContext.getRequest();
        ValueStack vs1 = (ValueStack) request.getAttribute("struts.valueStack"
); // 獲取值棧物件,方式2: ActionContext ac = ActionContext.getContext(); ValueStack vs2 = ac.getValueStack(); System.out.println(vs1 == vs2);//true }

valueStack內部儲存結構

上面已經說了,使用者訪問Action時,會建立Action物件,valueStack物件。Struts2內部會將Action物件存到valueStack物件之中…那麼valueStack的儲存結構是什麼樣的呢???我們來看看

這裡寫圖片描述

CompoundRoot

Action物件和Action的成員屬性等值都是存到CompoundRoot下的.該CompoundRoot繼承著ArrayList,因此它是List結構的

    public class CompoundRoot extends ArrayList {}

OgnlContext

OgnlContext物件儲存著相關的域物件:request、response、session等資料,實現Map集合,是Map結構..

為了讓request、response等域物件可以儲存多個值,值也是使用Map結構

public class OgnlContext implements Map {}

小總結

這裡寫圖片描述

CompoundRoot儲存著這樣的資料:

  • Action物件以及Action物件的成員屬性資料
  • 使用ValueStack物件.push()進去的資料
  • 使用ValueStack物件.set()進去的資料
  • 其他代理物件的資料

OgnlContext儲存著這樣的資料:

  • 維護了CompoundRoot中所有的資料
  • request、response等域物件所有的資料

OGNL表示式取值

  • Struts2會將valueStack物件封裝進request物件域中,傳入JSP頁面。
  • valueStack儲存著OgnlContext物件。
  • OgnlContext物件維護了CompoundRoot物件的資料
  • CompoundRoot儲存著Action等資料

也就是說通過OgnlContext物件可以獲取大部分我們需要的資料了。

那麼OGNL表示式是怎麼取出OgnlContext物件中資料的呢??下面我們通過硬編碼的方式來講解

    /**
     * 1. Ognl表示式語言語言取值,取非根元素的值,必須用#號
     * @throws Exception
     */
    @Test
    public void testOgnl() throws Exception {
        // 建立一個Ognl上下文物件
        OgnlContext context = new OgnlContext();
        // 放入資料
        User user = new User();
        user.setId(100);
        user.setName("Jack");
        // 【往非根元素放入資料, 取值的時候表示式要用"#"】
        context.put("user", user);

        // 獲取資料(map)
        // 先構建一個Ognl表示式, 再解析表示式
        Object ognl = Ognl.parseExpression("#user.name");
        Object value = Ognl.getValue(ognl, context, context.getRoot());

        System.out.println(value);
    }

    /**
     * 2. Ognl表示式語言語言取值,取根元素的值,不用帶#號
     * @throws Exception
     */
    @Test
    public void testOgn2() throws Exception {
        // 建立一個Ognl上下文物件
        OgnlContext context = new OgnlContext();
        // 放入資料
        User user = new User();
        user.setId(100);
        user.setName("Jack");
        // 【往根元素放入資料】
        context.setRoot(user);

        // 獲取資料(map)
        // 先構建一個Ognl表示式, 再解析表示式
        Object ognl = Ognl.parseExpression("address.province");
        Object value = Ognl.getValue(ognl, context, context.getRoot());

        System.out.println(value);
    }

也就是說,JSP頁面中取出資料的時候,它會先構建一個OGNL表示式,再解析表示式

  • 如果是CompoundRoot類的資料,表示式不需要帶#號
  • 如果不是CompoundRoot類的資料,表示式需要帶#號

這裡寫圖片描述

例子:



    <!-- 頁面: 必須要拿到ValueStack -->
     <br/>1. 取根元素的值<br/>
     <s:property value="user.id"/> 
     <s:property value="user.name"/> 
     <s:property value="user.address"/> 
     <s:property value="user.address.city"/> 
     <s:property value="user.address.province"/> 

      <br/>2. 取非根元素的值<br/>
      <s:property value="#request.cn"/>
      <s:property value="#session.Session_data"/>
      <s:property value="#application.Application_data"/>    <br/>

      <!-- 自動找request/session/application,找到後立刻返回 -->
      <s:property value="#request_data"/>
      <s:property value="#attr.Session_data"/>
      <s:property value="#attr.Application_data"/>  <br/>

      <!-- 獲取請求的引數資料 -->
      <s:property value="#parameters.userName"/>

     <!-- struts的除錯標籤:可以觀測值棧資料 -->
     <s:debug></s:debug>

OGNL對靜態方法的呼叫


    /**
     * 3.Ognl對 靜態方法呼叫的支援
     * @throws Exception
     */
    @Test
    public void testOgn3() throws Exception {
        // 建立一個Ognl上下文物件
        OgnlContext context = new OgnlContext();

        // Ognl表單式語言,呼叫類的靜態方法
        //Object ognl = Ognl.parseExpression("@[email protected](10.9)");
        // 由於Math類在開發中比較常用,所以也可以這樣寫
        Object ognl = Ognl.parseExpression("@@floor(10.9)");
        Object value = Ognl.getValue(ognl, context, context.getRoot());
        System.out.println(value);
    }

OGNL建立集合


    <br/>一、.構建 list集合</br>
    <s:iterator var="str" value="{'a','b'}">
        <s:property value="#str"/>
    </s:iterator>

     <br/>一、.構建 map集合</br>
     <s:iterator var="en" value="#{'cn':'China','usa':'America'}">
        <s:property value="#en.key"/>
        <s:property value="#en.value"/>  <br/>
     </s:iterator>

構建Map集合的時候,需要使用#號

OGNL 幾個特殊的符號

#獲取非根元素值 、 動態都建map集合
$ 在配置檔案取值
% 提供一個ognl表示式執行環境


<body>
     <br/>獲取request域資料<br/>
     <!-- property 標籤是物件型別的標籤,預設支援ognl表示式, 會從根元素去China名稱對應的值 -->
     <s:property value="China"/>        <br/>
     <!-- 如果直接賦值,需要用單引號 -->
     <s:property value="'China'"/>      <br/>
     <s:property value="%{#request.cn}"/>       <br/>

     <!-- 值型別的標籤,value值預設就是值型別,不支援ognl表示式 -->
     國家:<s:textfield name="txtCountry" value="%{#request.cn}"></s:textfield>
  </body>

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y

相關推薦

Struts2OGNLvalueStack就是這麼簡單

什麼是OGNL表示式? OGNL是Object Graphic Navigation Language 是操作物件屬性的開源表示式。 Struts2框架使用OGNL作為預設的表示式語言。 為什麼我們學習OGNL 在學習JSP的時候,我們已經學習過了EL

JavaEE筆記Struts2 (三) ognl值棧操作等

一. ognl概述 1. 在web階段,學習過EL表示式,EL表示式在JSP中獲取域物件裡面的值 2. ognl是一種表示式,這個表示式功能更加強大 i.在struts2裡面操作值棧資料 ii.

教程一鍵挖礦這麼簡單-ITGC

最近有很多朋友請教我如何挖礦,而挖礦這個事,三言兩語又很難說清楚,目前主流幣過高的挖礦投入、技術門檻都讓小白們“望幣興嘆”。對於新朋友而言,再生派(ITGC)是一個很好的切入點。 再生派(貨幣代號ITGC),一個基於區塊鏈的跨平臺、多落地應用的資源再流通生

BZOJ37812038莫隊算法2水題

bsp space har 情況 ros clu while 給定 print 【BZOJ3781】小B的詢問 題意:有一個序列,包含N個1~K之間的整數。他一共有M個詢問,每個詢問給定一個區間[L..R],求Sigma(c(i)^2)的值,其中i的值從1到K,其中c(i

python16_day17Django_sessionajax

cookies span ajax 失效 lte obj code keys def 一、Session   1.settings.py  SESSION_ENGINE = ‘django.contrib.sessions.backends.db‘ # 引擎(默認)

字節輸入流寫文本文件OutputStreamFileOutputStream

byte[] 方法名 cell end borde 方法 oid 所有 寫入文件 字節輸入流寫文本文件 1.OutputStream基類 作用:把內存中的數據輸出到文件中。 ※OutputStream類的常用方法 方法名稱 說明

001-docker安裝nginxmysql

瀏覽器 配置 操作 nbsp emctl mct lac 這就是 systemctl 一、 1、系統配置要求   操作系統:64位操作系統和3.10或者更高版本的內核:uname -r   Docker-v1.12 及更高版本   Docker Compose-v1

MySQL開發——介紹安裝

dbms tab 數據結構 個數 關系模型 集合 base 存儲 模型 什麽是數據庫?   數據庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫,       每個數據庫都有一個或多個不同的API用於創建,訪問,管理,搜索和復制所保存的數據。 數據庫的分類?

智能家居入門DIY——組合

vat -- cond 一點 ros 但是 comm end 上電 前面幾篇介紹了一些傳感器和代碼,這篇介紹一下把它們組合起來。之所以單獨列出這部分,原因在於組合更多功能的時候發現使用軟串口庫驅動ESP8266時由於內存過小導致發送失敗甚至整個系統無法工作的

EFCore SqliteMysql資料庫遷移 並使用資料庫,CodeFirstDBFirst

通過alt+v+e+o組合鍵來喚醒程式包管理器 通過在程式包管理器控制檯中輸入指令: get-help about_entityframeworkcore 檢視EFCore的幫助文件。 EFCore CodeFirst EFCore 使用Sqlite資料庫遷移的步驟: 第一步

JavaScript_12設計模式(單體模式)惰性單體和分支單體

<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>New Web Project</title>

Java第一階段(12) 異常集合 11.21

第一階段 異常 集合 練習 異常 異常大家族 Throwable 錯誤 :Error ,不能處理的,只能去修改程式碼 異常 :Exception, 可以處理,程式碼不用改,使用異常處理的方案來繞過異常

nginx + tomcat 8.5 優化配置,安裝nginxcentos67

第一步安裝 軟體 1.1 依賴包 # yum -y install gcc # yum install expat-devel # sudo yum install  zlib-devel 到http://apr.apache.org/download.cgi#apr1這

STL原始碼剖析(五)hash_sethash_map

hash_set 與set區別及聯絡 與set大同小異,set以RB-tree作為其底層,而hash_set以hash table作為其底層 兩者都是藉由其底層操作完成我們所看到的那些操作 二者最大的不同在於set的底層RB-tree有自動排序功能,所以反映在se

亞馬遜產品定價其實這麼簡單,一個公式解決

目錄 海貓跨境作者:海貓跨境 2016-11-24 16:33:51 如果產品銷量不好,很多賣家首先想到的是圖片、listing是不是做的不夠好,很少賣家會想想是不是自己的定價有問題,定價對銷量的影響也是至關重要的,定價是一門高深的學問,如果產品

NOJ15961597貪心演算法之最小生成樹最少修建多長的公路能把所有村莊連起來(圖示Prim與Kruskal演算法)

1596.最少修建多長的公路能把所有村莊連起來(一) 時限:1000ms 記憶體限制:10000K  總時限:3000ms 描述 一個地區有n個村莊,有一些村子之間可以修路,已知每條路的長度,問最少修建多長的公路可以把所有的村子連線起來。 輸入 先輸入兩個正整數n,

一次心驚肉跳的伺服器誤刪檔案的恢復過程轉載收藏 一次心驚肉跳的伺服器誤刪檔案的恢復過程

一次心驚肉跳的伺服器誤刪檔案的恢復過程 經歷了兩天不懈努力,終於恢復了一次誤操作刪除的生產伺服器資料。對本次事故過程和解決辦法記錄在此,警醒自己,也提示別人莫犯此錯。也希望遇到問題的朋友能找到一絲靈感解決問題。 事故背景 安排一個妹子在一臺生產伺服器上安裝Oracle,妹子

4《SSO CAS單點系列》之 實操!輕鬆玩轉SSO CAS這麼簡單(相遇篇)

CAS是中央認證服務Central Authentication Service的簡稱。最初由耶魯大學的Shawn Bayern 開發,後由Jasig社群維護,經過十多年發展,目前已成為影響最大、廣泛使用的、基於Java實現的、開源SSO解決方案。2012年,Jasig和另一

CentOS7下三步安裝單點OpenStackKVMVMwareOK

失敗7次後成功。 注意:1、必須CENTOS7,主要是python要2.7,yum要能用 2、關閉NetworkManager 3、多次安裝,千萬別修改IP,否則,必然失敗 4、安裝過程中,失敗多次,處理各不同:【不知道是否與我的網路情況有關,導致失敗多次】 使用配置參

jetbrains系列啟用\註冊碼\破解碼WebstormDataGrip

【有效】https://s.tuzhihao.com:666/【失效】http://hb5.s.osidea.cc:1017【有效】codeK03CHKJCFT-eyJsaWNlbnNlSWQiOiJLMDNDSEtKQ0ZUIiwibGljZW5zZWVOYW1lIjoib