1.OGNL的用法詳解
Ognl表達式一般是結合struts2框架的標籤來使用的,最重要的作用,就是獲取值棧中存儲的數據。
在下面的示例,咱們將對ognl的各種用法進行測試,分析OGNL是如何使用的。
- 1.Java對象的直接訪問
例如:’itcast’ - 實例方法調用
語法:object.doSomething(),object是對象實例
例如:’itcast’.toUpperCase() - 靜態方法調用(類的靜態方法或靜態變量的訪問)–不常用
語法:@[類全名(包括包路徑)]@[方法名|值名]
例如:@java.lang.Math@max(10,20)
注意:必須通過配置struts2的常量來開啓靜態方法調用功能:
struts.ognl.allowStaticMethodAccess=true
- 賦值操作或表達式串聯。–可以運算
如計算1+2或者2*2 - 對集合對象的操作
<s:property value="#{‘上海’:‘浦東’,‘北京’:‘豐臺’}"/> Ognl對值棧的操作
示例:
搭建struts2的環境:導入jar、struts.xml、web.xml,引入struts標籤庫,編寫表達式代碼
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<!-- s:property標籤中的value可以用來解析ognl表達式獲取各類數據 -->
<!-- ognl表達式的用法 -->
<!-- s:property標籤中的value 可以解析ognl表達式 -->
<s:property value="'itcast'"/><br>
<!-- 可以操作對象的實例方法 -->
<s:property value="'itcast'.toUpperCase()"/><br>
<!-- 可以操作靜態方法 -->
<s:property value="@java.lang.Math@max(1,20)"/><br>
<!-- 操作集合 -->
<s:property value="{'上海','北京'}"/><br>
<!-- 操作map集合 -->
<s:property value="#{'上海':'浦東','北京':'豐臺' }"/><br>
<!-- 操作表達式 -->
<s:property value="10%3"/><br>
</body>
</html>
應用ognl 表達式調用對象方法或者靜態方法,需要結合struts2的\<s:property > 標籤,其中提供的value屬性支持ognl。
2.值棧概述
2.1 值棧(ValueStack)是什麼
值棧(ValueStack),是Struts2的數據中轉站(類似於超市)
他自動保存了當前Action對象和其他相關對象(包括常用的Web對象的引用,如request、application、session等),也可以手動保存自己的數據對象,同時也可以隨時隨地將對象從值棧取出或操作(通過OGNL表達式)
最核心的作用:存值
值棧(ValueStack)的接口是ValueStack類,實現類是OgnlValueStack類,該對象是Struts2利用OGNL的基礎。只要我們用到ognl,那麼就需要依賴值棧。
Struts2框架將ValueStack對象保存在名爲“struts.valueStack”的請求(request)
屬性中,即值棧是request中的一個對象,一個請求對應一個Action實例和一個值棧對象。
值棧的獲取方式:
request.getAttribute(“struts.valueStack”)- ActionContext.getContext().getValueStack()
該兩種方式獲取的值棧其實是同一個。
2.2 值棧的數據存儲結構的分析
【示例1】
目標:值棧對象的獲取,並證明兩種方式獲取的對象是同一個對象:
1)request.getAttribute(“struts.valueStack”)
2)ActionContext.getContext().getValueStack()
步驟一:編寫action
創建包和action
public class DemoAction extends ActionSupport{
@Override
public String demo(){
//獲取值棧的第一種方式
ValueStack valueStack1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
//獲取值棧的第二種方式
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
System.out.println(valueStack1);
System.out.println(valueStack2);
return SUCCESS;
}
}
<struts>
<!-- 配置開發者模式 -->
<constant name="struts.devMode" value="true"></constant>
<package name="p1" extends="struts-default">
<action name="demo" class="cn.itcast.valueStack.DemoAction" method="demo">
<result name="success">/demo.jsp</result>
</action>
</package>
</struts>
【值棧小結】:
值棧包括兩部分:root棧和map棧
1、root棧:繼承了List接口,又稱之爲對象棧
2、map棧:實現了Map接口,又可以稱之爲上下文棧(context)
3.值棧的操作(重點)
3.1 Root棧的存值和取值
Root棧的存值:
它按照先進後出
的原則存儲數據,即先進入的數據被壓入棧底
,最後進入的數據在棧頂
,需要讀取數據的時候,從棧頂開始彈出數據(即最後一個數據被第一個讀出來)。
棧也被成爲先進後出表,可進行插入和刪除操作,插入稱之爲進棧(壓棧)(push)
,刪除稱之爲退棧(pop)
。
【示例】
值棧數據的保存:向root棧存入數據,響應頁面根據不同的方式(通過ognl表達式)分別將值獲取出來。
1.Push方式壓入棧頂
push方法:將數據壓入root棧的棧頂。
public class DemoAction extends ActionSupport{
@Override
public String demo(){
//獲取值棧的第一種方式
ValueStack valueStack1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
//獲取值棧的第二種方式
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
System.out.println(valueStack1);
System.out.println(valueStack2);
//將數據存入root棧,以push方法壓入棧頂
valueStack2.push("zhangsan");
//繼續將一個數據壓入棧頂
valueStack2.push("lisi");
return SUCCESS;
}
}
Root棧分析:
步驟二:設置響應頁面利用ognl表達式從值棧取值
導入struts標籤:
<%@taglib uri="/struts-tags" prefix="s" %>
demo.jsp頁面內容:
<!--
通過s:property標籤獲取數據
value:是一個ognl表達式,通過valu值可以到值棧中去查詢對應的數據
[0].top:表示獲取root棧棧頂的數據
-->
獲取棧頂數據1:<s:property value="[0].top"/><br>
獲取棧頂數據2:<s:property/><br>
<s:debug></s:debug>
執行成功!
步驟三:測試
2.Set方式壓入棧頂
set方法:
將數據壓入棧頂:會先創建一個map集合,讓後將數據存入到集合中,最後將map集合壓入棧頂。
步驟一:修改DemoAction :
public class DemoAction extends ActionSupport{
public String demo(){
//第一種獲取值棧的方式
ValueStack valueStack1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
System.out.println(valueStack1);
//第二種獲取值棧的方式
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
System.out.println(valueStack2);
//將數據存入root棧棧頂
valueStack2.push("zhangsan");
valueStack2.push("lisi");
//set:創建一個map集合,將數據存入該集合中,最終將map集合壓入root棧棧頂
valueStack2.set("name","wangwu");
return SUCCESS;//相當於"none",表示不響應任何結果集視圖
}
}
<%--
如果棧頂是map集合:通過集合的key可以直接獲取value值
通過name到值棧中從上往下進行查找,找到的第一個進行返回
--%>
獲取棧頂map中的數據:<s:property value="name"/><br>
3.通過action的成員變量將數據存入值棧
頁面的<s :debug>標籤會通過getName()方法從值棧中獲取數據並顯示在root棧中
步驟一:修改ValueStackAction
在action中添加成員變量,並設置成員變量的的getter和setter方法
3.2 Map棧的存值和取值
1.通過put方法將數據存入map棧
put方法:
將數據存入map棧,map棧是一個map,因此需要通過key來獲取對應的value.
如果需要直接從map棧獲取數據,建議在ognl表達式中添加一個#,表示直接從map棧查找,而不是從root棧棧頂開始從上往下查找。
如:<s:property value="#name"/>
修改DemoAction
public class DemoAction extends ActionSupport{
private String name = "maliu";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String demo(){
//第一種獲取值棧的方式
ValueStack valueStack1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
System.out.println(valueStack1);
//第二種獲取值棧的方式
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
System.out.println(valueStack2);
//將數據存入root棧棧頂
valueStack2.push("zhangsan");
valueStack2.push("lisi");
//set:創建一個map集合,將數據存入該集合中,最終將map集合壓入root棧棧頂
valueStack2.set("name","wangwu");
//將數據存入map棧
//由於map棧本質就是一個集合,因此存儲方式和map一樣
ActionContext.getContext().put("name", "tianqi");
return SUCCESS;//相當於"none",表示不響應任何結果集視圖
}
}
頁面獲取map棧數據
<%--
從map棧獲取數據:在ognl表達式中使用#表示直接從map棧查找數據
--%>
獲取map棧中的數據:<s:property value="#name"/>
3.3 值棧的存取小結
值棧的主要作用就是數據的保存和獲取
使用值棧的時候要思考:用什麼代碼存進去,然後再用什麼代碼取出來