OGNL表達式
OGNL是Object Graphic Navigation Language(對象圖導航語言)的縮寫,他是一個開源項目。Struts框架使用OGNL做爲默認的表達式語言。
OGNL優點html
@[類全名(包括包路徑)]@[方法名 | 值名],例如:
@java.lang.String@format('foo %s', 'bar')
或@tutorial.MyConstant@APP_NAME;java
如price=100, discount=0.8,calculatePrice(),這個表達式會返回80;api
總結:OGNL 有一個上下文(Context)概念,說白了上下文就是一個MAP結構,它實現了java.utils.Map 的接口。數組
Struts框架默認就支持Ognl表達式語言。(從struts項目必須引入ognl.jar包能夠看出)服務器
Ognl表達式語言的做用:session
OgnlContext對象是ognl表達式語言的核心。
可是項目中不會要求寫OgnlContext的代碼,Ognl標籤實際上是調用了OgnlContext對象。因此只作瞭解便可。app
OgnlContext對象在源碼中實現了Map接口:
public class OgnlContext implements Map {……}
框架
Ognl表達式語言取值,也是用java代碼取值的,原理就是使用OgnlContext和Ognl這兩個類,只須要記住,Ognl取根元素不用#號,取非根元素要使用#號:jsp
OgnlContext類
硬編碼方式,瞭解OgnlContext對象,由於OgnlContext對象實現是Map接口,全部OgnlContext本質就是一個Map,可使用map方法:post
OgnlContext context = new OgnlContext();
context.put("uesr",user);
context.put("address",address);
context.setRoot(address);
Ognl類
Ognl類也是Ognl底層運行的代碼,經常使用的api以下:
Object obj1 = Ognl.parseExpression(「country」); 解析ognl表達式
Ognl.getValue(obj1, context, context.getRoot()); 獲取ognl的表達式值,obj1是上面一個api,其餘兩個分別是建立的上下文對象以及一個不用修改的參數
Object obj2 = Ognl.parseExpression(「language.toUpperCase()」); 方法調用
Object obj3 = Ognl.parseExpression("@java.lang.Integer@toBinaryString(10)");等同於上面
Object obj4 = Ognl.parseExpression(「@@min(10,4)」); Math類的方法直接調用,靜態方法的調用
代碼示例以下:
package o_ognl; import ognl.Ognl; import ognl.OgnlContext; import ognl.OgnlException; import org.junit.Test; /** * OgnlContext用法 * 1.使用Ognl表達式語言取值,若是取非根元素的值,必須用#號 * 2.使用Ognl表達式語言取值,若是取根元素的值,不用#號 * 3.Ognl能夠調用靜態方法 */ public class OgnlDemo { //非根元素 @Test public void testOgnl1() throws OgnlException { //建立一個Ognl上下文對象 OgnlContext context = new OgnlContext(); /** * 1.OgnlContext放入基本變量數據 */ //放入數據 context.put("cn","China"); //獲取數據(map) String value = (String)context.get("cn"); System.out.println(value); /** * 2.OgnlContext放入對象數據 */ //建立對象,設置對象屬性 User user = new User(); user.setId(100); user.setName("Jack"); //【往非根元素放入數據,取值的時候表達式要用「#」】 context.put("user",user); //獲取對象屬性 //使用這種方式也能夠獲取 Object s = context.get("user"); System.out.println(s); //使用Ognl表達式來獲取 //舉例:例如標籤<s:a value="#user.id">取值,實際上就是運行了下面的代碼獲取的 //先構建一個Ognl表達式,再解析表達式 Object ognl = Ognl.parseExpression("#user.id");//構建Ognl表達式 Object value1 = Ognl.getValue(ognl, context, context.getRoot());//解析表達式 System.out.println(value1); User user1 = new User(); user1.setId(100); user1.setName("Jack"); context.setRoot(user1); Object ognl1 = Ognl.parseExpression("id");//構建Ognl表達式 Object value2 = Ognl.getValue(ognl1, context, context.getRoot());//解析表達式 System.out.println(value2); } //根元素, @Test public void testOgnl2() throws OgnlException { OgnlContext context = new OgnlContext(); User user1 = new User(); user1.setId(100); user1.setName("Jack"); context.setRoot(user1); //根元素直接使用id,不須要加#號 Object ognl1 = Ognl.parseExpression("id");//構建Ognl表達式 Object value2 = Ognl.getValue(ognl1, context, context.getRoot());//解析表達式 System.out.println(value2); } //ognl對靜態方法調用的支持 @Test public void testOgnl3() throws Exception{ //建立一個Ognl上下文對象 OgnlContext context = new OgnlContext(); //Ognl表達式語言,調用類的靜態方法 // Object ognl = Ognl.parseExpression("@Math@floor(10.9)"); //因爲Math類在開發中比較經常使用,全部也能夠這樣寫 Object ognl = Ognl.parseExpression("@@floor(10.9)"); Object value = Ognl.getValue(ognl, context, context.getRoot()); System.out.println(value); } }
1.ValueStack即值棧對象
ValueStack實際是一個接口,在Struts2中利用Ognl時,實際上使用的是實現了該接口的OgnlValueStack類,這個類是Struts2利用Ognl的基礎
2.ValueStack特色
ValueStack貫穿整個Action的生命週期(每一個Action類的對象實例都擁有一個ValueStack對象),即用戶每次訪問struts的action,都會建立一個Action對象、值棧對象、ActionContext對象,而後把Action對象放入值棧中;最後再把值棧對象放入request中,傳入jsp頁面。至關於一個數據的中轉站,在其中保存當前Action對象和其餘相關對象。Struts2框架把ValueStack對象保存在名爲「struts。valueStack」的request請求屬性中。
3.ValueStack存儲對象
代碼調試的時候,發現有一個root是compundRoot類,繼承ArrayList,保存的是action對象;還有一個OgnlContext是繼承Map,保存數據。
因此ValueStack存儲對象時是分兩個地方來存的,也即ValueStack對象的組成是由List棧和Map棧構成的:
ObjectStack
:Struts把根元素,即action對象及全局屬性存入ObjectStack中---List
list棧主要存儲:action對象,Map對象(經過vs.set()設置),經過push方法設置的對象,以及其餘代理對象
根元素的存儲示例:
//存儲值棧對象 ActionContext ac = ActionContext.getContext(); ValueStack vs = ac.getValueStack(); vs.set("user1",new User(100,"Jack1"));//Map vs.push(new User(100,"Jack2"));//棧頂
ContextMap
:Struts把各類各樣的映射關係(域數據)存入ContextMap中
Struts會把下面這些映射存入ContextMap中:
//存儲值棧對象 ActionContext ac = ActionContext.getContext(); //映射數據 ac.getContextMap().put("request_data", "request_data"); ac.getSession().put("session_data", "session_data"); ac.getApplication().put("application_data","application_data");
從棧中取值的兩種方式:
//1、獲取值棧對象的兩種方式,是等價的 public 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 }
在jsp頁面中,對不一樣ValueStack中的不一樣類型取值方法不一樣,
若是是根元素取值,直接寫表達式;
非根元素(request,Session,application,att,parmeters)必須用#號,例#request.cn
<%@taglib prefix="s" uri="/struts-tags" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>jsp頁面取值</title> </head> <body> index頁面 <%--頁面,必需要拿到ValueStack--%> <%--struts的調試標籤,能夠觀測值棧數據--%> <s:debug/> <br/>1.取根元素的值<br/> <s:property value="user.id"/> <s:property value="user.name"/> <br/>2.取非根元素<br/> <s:property value="#request.cn"/> <s:property value="#request.request_data"/> <s:property value="#session.session_data"/> <s:property value="#application.application_data"/><br/> <%--attr按順序自動找request/session/application,找到後馬上返回--%> <s:property value="#attr.application_data"/> <%--獲取請求參數數據--%> <s:property value="#parameters.userName"/> </body> </html>
struts標籤取值,就使用到ognl表達式語言。
1.4.中使用的就是Ognl表達式取值。使用方式是:
1.引入<%@taglib prefix="s" uri="/struts-tags" %>
2.使用 <s:property value="user.name"/>
標籤獲取取值,取值的時候要注意根元素(全局變量)不用#號,其餘的都用#號
還有一些標籤須要學習:
Iterator:標籤用於對集合進行迭代,這裏的集合包含List,Set和數組
int getCount(),返回當前迭代了幾個元素
int getIndex(),返回當前迭代元素的索引
boolean isEven(),返回當前迭代元素的索引是不是偶數
boolean isOdd(),返回當前迭代元素的索引是不是奇數
boolean isFirst(),返回當前迭代元素是不是第一個元素
boolean isLast(),返回當前迭代元素是不是最後一個元素
代碼示例:
<br/>1.list迭代<br/> <s:iterator var="user" value="#request.list" status="st"> <s:property value="#user.id"/> <s:property value="#user.name"/> <s:property value="#st.even"/><br/> </s:iterator> <br/>2.map迭代<br/> <s:iterator var="en" value="#request.map" status="st"> <s:property value="#en.key"/> <s:property value="#en.value.name"/> </s:iterator>
<%--Ognl表達式能夠取值,也能夠構建動態集合--%> <br/>1.構建list集合<br/> <s:iterator var="str" value="{'a','b','c'}"> <s:property value="#str"/> </s:iterator> <br/>2.構建map集合<br/> <s:iterator var="en" value="#{'cn':'China','usa':'America'}"> <s:property value="en.key"/> <s:property value="en.value"/><br/> </s:iterator>
<%@taglib prefix="s" uri="/struts-tags" %> <%--服務器標籤:最終被解析爲html標籤--%> <s:form action="/user_login" method="POST" name="frmLogin"> <s:textfield name="user.userName" label="用戶名"/> <s:textfield name="user.pwd" label="密碼"/> <s:submit value="登陸"/> </s:form>
也能夠給form指定主題,方法以下:
<!-- 服務器標籤 : 最終別解析爲html標籤--> <s:form action="/user_login" method="post" name="frmLogin" id="frmLogin" theme="simple"> 用戶名:<s:textfield name="user.name"></s:textfield> 密碼:<s:textfield name="user.pwd"></s:textfield> <s:submit value="登錄"></s:submit> </s:form>
注意:
給form指定主題,form下全部的表單元素都應用此主題
對Struts標籤默認的主題樣式:default.xml/struts.ui.theme=xhtml
能夠經過常量修改,改成簡單主題:
<!-- 修改主題 (當前項目全部的標籤都用此主題)--> <constant name="struts.ui.theme" value="simple"></constant>
$:配置文件取值
%:提供一個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>