1. 程式人生 > >OGNL表達式

OGNL表達式

pre list 引用 lin method inspur 類方法 uname filter

Struts2的一個關鍵特性就是它可以對Action攜帶的數據進行讀寫訪問,例如在前面我們在表單中使用username指定數據傳遞給Action的username屬性,在<s:property>元素中使用username來獲取用戶的名字,這是通過表達式語言(Expression Language,EL)來實現的,這種表達式語言就是OGNL。

OGNL的全稱是Object Graph Navigation Language(對象圖導航語言),它是一種強大的表達式語言,讓你通過簡單一致的表達式語法來讀取和設置Java對象的屬性值,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉換等功能。

一、為什麽要使用OGNL

視圖層的表達式語言通常是用來簡化數據的訪問操作,取代Java腳本代碼,提供更清晰的視圖層實現。例如,在JSP頁面中使用JSP2.0內置的表達式語言獲取user對象的username屬性,可以簡寫為${user.username},如果換作Java腳本代碼,則需要寫為:

<%@ page language="java" import="java.util.*,com.bim.pojo.User" pageEncoding="gbk"%>

<%

User user = (User)request.getAttribute("user");

String username = user.getUsername();

out.print(username);

%>

哪一種方法更為簡捷,相信大家已經一目了然了。

既然JSP2.0已經內置了一種表達式語言,那麽為什麽還要使用OGNL呢?

相對於其它的表達式語言而言,OGNL的功能更為強大,它提供了很多高級而必須的特性,例如強大的類型轉換功能,靜態或實例方法的執行,跨集合投影(projection),以及動態lambda表達式定義等。

二、 OGNL的原理--ActionContext

ActionContext是Struts的核心數據區,是Action和頁面進行數據交換的“共享數據區”,也叫做Action的OGNL上下文

補充:上下文是一種非常泛化的概念,大致意思就是“與現在這個工作相關的周圍環境”。一般存儲了該環境的一些屬性值。 )

ActionContext的結構:包含值棧和非值棧。當Action被請求時會被創建Action對象,且會把該對象放到值棧中。

值棧的概念:值棧是OGNL表達式的根對象; Struts總是將當前訪問的Action對象存放在棧頂;OGNL表達式對值棧中的任何對象直接訪問,而不需要使用“#”標記 (Struts提供了一個特殊的OGNL PropertyAccessor接口,此接口可以自動查找值棧內的、從棧頂到棧底的所有對象,直到找到對象為止 )

怎麽訪問值棧中的值:根對象可以缺省#。OGNL直接訪問屬性:user.userName

怎麽訪問非值棧區的中的值: #key,如#request.loginID

根對象的屬性直接訪問案例

userInert.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<[email protected] prefix="s" uri="/struts-tags"%>

<%

String path = request.getContextPath();%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title>My JSP ‘MyJsp.jsp‘ starting page</title>

</head>

<body>

<form action="userAction" method="post">

<table>

<tr>

<td>

用戶名:

</td>

<td>

<input type="text" name="user.userName">

</td>

</tr>

<tr>

<td>

用戶所在組名:

</td>

<td>

<input type="text" name="user.group.groupName">

</td>

</tr>

<tr>

<td>

用戶所在組的機構編號:

</td>

<td>

<input type="text" name="user.group.org.orgId">

</td>

</tr>

<tr>

<td>

用戶所在組的機構名字:

</td>

<td>

<input type="text" name="user.group.org.orgName">

</td>

</tr>

<tr>

<td>

<input type="submit" name="submit" value="添加">

</td>

<td>

<input type="reset" name="reset" value="取消">

</td>

</tr>

</table>

</form>

</body>

</html>

userShow.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<[email protected] prefix="s" uri="/struts-tags"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title>My JSP ‘userShow.jsp‘ starting page</title>

</head>

<body>

<s:debug></s:debug>

<form action="userAction" method="post">

<table>

<tr>

<td>

用戶名:

</td>

<td>

<s:property value="user.userName" />

</td>

</tr>

<tr>

<td>

用戶所在組名:

</td>

<td>

<s:property value="user.group.groupName" />

</td>

</tr>

<tr>

<td>

用戶所在組的機構編號:

</td>

<td>

<s:property value="user.group.org.orgId" />

</td>

</tr>

<tr>

<td>

用戶所在組的機構名字:

</td>

<td>

<s:property value="user.group.org.orgName" />

</td>

</tr>

<tr>

<td>

<input type="submit" name="submit" value="確認">

</td>

<td>

<input type="reset" name="reset" value="取消">

</td>

</tr>

</table>

</form>

<br>

</body>

</html>

Struts.xml

<action name="userAction" class="com.inspur.actions.UserAction">

<result name="show">/user/userShow.jsp</result>

</action>

Web.xml

<filter>

<filter-name>struts2</filter-name>

<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

userAction.java

package com.inspur.actions;

import com.inspur.pojo.User;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{

private User user;

public User getUser() {

return user;

}

public void setUser(User user) {

this.user = user;

}

@Override

public String execute() throws Exception{

return "show";

}

}

User.java

package com.inspur.pojo;

public class User {

private String userName;

private Group group;

get/set……

}

Ogr.java

package com.inspur.pojo;

public class Org {

private String orgId;

private String orgName;

get/set……

}

Group.java

package com.inspur.pojo;

public class Group {

private String groupName;

private Org org;

get/set……

}

非根對象的屬性使用“#”訪問 案例(只寫出了部分代碼)

Login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<[email protected] prefix="s" uri="/struts-tags" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title>login page</title>

</head>

<body>

<form action="loginAction">

<font color="red"><s:property value="#request.msg"/></font>

<table align="center">

<tr><td>用戶名:<input type="text" name="uname"></td></tr>

<tr><td>密&nbsp;&nbsp;碼:<input type="password" name="upass"></td></tr>

<tr><td><input type="submit" value="登錄"></td></tr>

</table>

</form>

</body>

</html>

LoginAction.java

public String login(){

//第一種方式:actioncontext

ActionContext context = ActionContext.getContext();

Map<String, String> requestMap = (Map<String, String>) context.get("request");

Map<String, Object> sessionMap = (Map<String, Object>) context.getSession();

if("ross".equals(this.uname) && "111".equals(this.upass)){

sessionMap.put("uname", uname);

return SUCCESS;

}else{

requestMap.put("msg", "登錄名或密碼錯誤");

return ERROR;

}

}

Index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<[email protected] prefix="s" uri="/struts-tags" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title>用戶登錄成功界面</title>

</head>

<body>

<p>

歡迎您,<s:property value="#session.uname"/>,用戶登錄成功!

</p>

</body>

</html>

Struts.xml

<!-- 配置請求和Action組件的映射關系 -->

<action name="loginAction" class="com.inspur.actions.LoginAction" method="login">

<result name="success">/index.jsp</result>

<result name="error">/login.jsp</result>

<result name="input">/login.jsp</result>

</action>

三、OGNL訪問數組、list、map、set

訪問數組元素:array[0]

訪問List元素:{‘name1‘,‘name2‘}[0]

訪問map元素:mymap[‘key’]或者mymap.key

訪問set中元素:userSet

案例代碼:

頁面生成數組和list:

<tr>

<td>用戶的愛好: </td>

<td>

籃球<input type="checkbox" name="likes" value="籃球">

足球<input type="checkbox" name="likes" value="足球">

羽毛球<input type="checkbox" name="likes" value="羽毛球">

</td>

</tr>

<tr>

<td>用戶熟悉的計算機語言: </td>

<td>

Java<input type="checkbox" name="language" value="java">

c<input type="checkbox" name="language" value="c">

c#<input type="checkbox" name="language" value="c#">

</td>

</tr>

Action裏:

private String likes[];

private List<String> language;

private Map<String,String> books = new HashMap<String,String>();

private Set<String> set = new HashSet<String>();

get/set……

public String execute() throws Exception{

books.put("1","紅樓夢");

books.put("2","三國演義");

set.add("tom");

set.add("joy");

return "show";

}

頁面顯示

數組:

取所有元素<s:property value="likes" />

取第一個元素<s:property value="likes[0]" />

List:

取所有元素<s:property value="language" />

取第一個元素<s:property value="language[0]" />

Map:

取所有元素<s:property value=" books" />

取第一個元素<s:property value=" books[‘1‘]" />

<p><s:property value="books.1" /></p>

取所有key值<p><s:property value="books.keys" /></p>

取所有value值<p><s:property value="books.values" /></p>

Set:

取所有set值<p><s:property value="set" /></p>

取set大小<p><s:property value="set.size" /></p>

四、投影和選擇

投影:OGNL提供了一種簡單的方式在一個集合中對每一個元素調用相同的方法,或者抽取相同的屬性,並將結果保存為一個新的集合,稱為投影。例如,users是一個包含了user對象的列表,那麽#users.{name}將返回所有人的名字和列表。在投影期間,使用#this變量來引用叠代中的當前元素

選擇:OGNL提供了一種簡單的方式來使用表達式從集合中選擇某些元素,並將結果保存到新的集合中,稱為選擇。如#users.{?#this.salary>3000}將返回薪水大於3000 的所有人的列表。#users.{^#this.salary>3000}將返回第一個薪水大於3000人。#users.{$#this.salary>3000}將返回最後一個薪水大於3000的人。

案例

//Action裏面定義一個list放入user對象:

private List<User> userList = new ArrayList();

//給user對象添加一個年齡屬性,並書寫對應構造方法
userList.add(new User("ross",31));

userList.add(new User("rechel",28));

userList.add(new User("joy",32));

頁面顯示:

<h4>訪問類方法</h4>

<s:property value="new com.inspur.actions.UserAction().showString()"/>

<h4>選擇所有用戶的名字</h4>

<s:property value="userList.{userName}"/>

<!-- 驗證-->

<hr>

<h4>選擇年齡>30的用戶信息</h4>

<s:property value="userList.{?#this.age>30}"/>

<h4>選擇年齡>30的用戶信息中用戶名</h4>

<s:property value="userList.{?#this.age>30}.{userName}"/>

<h4>選擇第一個年齡>30的用戶信息中用戶名</h4>

<s:property value="userList.{^#this.age>30}.{userName}"/>

<h4>選擇最後一個年齡>30的用戶信息中用戶名</h4>

<s:property value="userList.{$#this.age>30}.{userName}"/>

OGNL表達式