技術要點
本節代碼對OGNL一些經常使用特性進行分析,用演示代碼演示這些特性。
經常使用特性介紹。
OGNL在Struts2中頁面中的應用。
OGNL特殊符號介紹html
1.利用OGNL進行應用的頁面:java
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ page import="com.opensymphony.xwork2.util.ValueStack"%> <%@ taglib uri="/struts-tags" prefix="s"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title><s:text name="bookPageTitle"/></title> </head> <body> session 中的User:<s:property value="#session.user" /><br/> request中的第一本書的書名:<s:property value="#request.bookList[0].bookName"/><br/> <br/><br/> 篩選id>2的書:<br/> <s:iterator value="bookList.{?#this.id > 2}" id="book"> <s:property value="#book.bookName"/><br/> </s:iterator> <br/><br/> 篩選第一本id>2的書:<br/> <s:iterator value="bookList.{^#this.id > 2}" id="book"> <s:property value="#book.bookName"/><br/> </s:iterator> <br/><br/> 篩選最後一本id>2的書:<br/> <s:iterator value="bookList.{$#this.id > 2}" id="book"> <s:property value="#book.bookName"/><br/> </s:iterator> <br/> 取出bookList中的書名是「DDD」的id: <s:property value="bookList.{?#this.bookName=='DDD'}.{id}[0]"/> <br/> <br/> <!-- OGNL新建Map類型數據集合,顯示子元素值 --> <s:set name="newBook" value="#{'abcd':'efgh','bookName':'XXX','bookAuthor':'xxx'}"/><br/> OGNL新建Map類型數據集合,顯示子元素值 :<s:property value="#newBook.abcd"/> </body> </html>
2. struts.xml文件的配置:數據庫
<action name="getBooks" class="struts2.action.GetBooksAction"> <result name="error">/error.jsp</result> <result name="success">/showbook.jsp</result> <result name="login">/index.jsp</result> </action>
3.BookService類提供模擬數據庫讀出:session
package struts2.action; import struts2.biz.BookService; import struts2.entity.Book; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionContext; public class GetBooksAction implements Action { private Book[] bookList; public Book[] getBookList() { return bookList; } public void setBookList(Book[] bookList) { this.bookList = bookList; } public String execute() throws Exception { // TODO Auto-generated method stub String name = (String)ActionContext.getContext().getSession().get("user"); if(null != name && "123".equals(name)){ setBookList(BookService.getBooks()); return SUCCESS; }else{ return LOGIN; } } }
4.Book實體類:app
package struts2.entity; public class Book { private String bookName; private String bookAuthor; private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public Book(int id,String bookName,String bookAuthor){ this.id = id; this.bookAuthor = bookAuthor; this.bookName = bookName; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getBookAuthor() { return bookAuthor; } public void setBookAuthor(String bookAuthor) { this.bookAuthor = bookAuthor; } }
4.Action代碼:jsp
package struts2.action; import struts2.biz.BookService; import struts2.entity.Book; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionContext; public class GetBooksAction implements Action { private Book[] bookList; public Book[] getBookList() { return bookList; } public void setBookList(Book[] bookList) { this.bookList = bookList; } public String execute() throws Exception { // TODO Auto-generated method stub String name = (String)ActionContext.getContext().getSession().get("user"); if(null != name && "123".equals(name)){ setBookList(BookService.getBooks()); return SUCCESS; }else{ return LOGIN; } } }
代碼解釋
(1)Struts2中將應用範圍裏的數據以及Action處理的數據都存儲在一個區域裏。在Struts2中叫作「valueStack」,中文名爲「值棧」。而OGNL就是從「值棧」取出數據,並在某些條件下進行數據過濾和計算的表達式語言。在Struts2中值棧做爲OGNL的根對象,從值棧中取出本身須要的數據,並且值棧存取數據是按照先入後出的概念。所以查詢數據時候每每是值棧中最頂部的數據先被查詢出來。更加須要指出的是在值棧中也可使用索引,能夠在指定的索引位置開始搜索數據。this
在OGNL中若是搜索的數據不是值棧裏存儲的數據,並且其餘對象中,特別是Struts2的ActionContext中的對象,則在訪問這些對象時候,前面要加「#」。好比ognl.jsp中訪問session和request對象時候代碼中在request和session以前就有「#」。spa
對於數據集合類型,若是根據條件查詢該集合裏的數據,造成子集合的時候,經常使用的OGNL還有「?」、「^」、「$」。此三個符號中「?」是取得全部符合條件的數據時使用。「^」是取這些符合條件的數據中索引中第一個或第一條數據。而「$」則正好相反,是取得最後一個或最後一條數據。code
在OGNL中,還有lamuda表達式和不少計算公式的表達式,筆者認爲若是堅持鬆耦合理念的話,最好不要使用。畢竟OGNL更多使用在MVC模式中view和comtrol兩層,而計算公式等OGNL知識更多的和業務邏輯聯繫關聯比較大,因此本書就不作過多介紹。xml
(2)本示例中,首先建立了建築材料的模型對象。其中有材料名、材料價格、材料庫存量三個屬性。在OgnlExampleAction中作了兩件事情,一件事情是在request、session中各放入key爲「materialName」的值。另外一件事情是初始化三個材料對象,將這些對象放在 List類型的數據集合中。
而後在struts.xml中對OgnlExampleAction作定義,將其導航到ognl.jsp中。在該jsp中,讀者參看其代碼。首先將request、session中「materialName」的值用OGNL取出。由於request、session都不是值棧,因此在它們名字以前都以「#」開頭。在代碼中將以前List類型的數據集合中全部材料價格小於50的數據顯示出來。這裏用了「?」也就是以前所說去取符合條件的數據集時使用。
在取材料名爲「人造石臺面」的材料庫存量時候,OGNL先利用條件過濾獲得符合條件的材料對象集而後用「{}」去取庫存量屬性,再取該子集中第一個索引,這裏索引次序和Java中相同,也是從「0」開始代表集合中第一個元素。
在ognl.jsp中,OGNL也新建了一個Map對象,而後定義了該對象中的key和value。OGNL對於顯示Map對象中某個key的值採起ognl.jsp代碼中所示。「[]」中寫key的名字,並用‘’包含。
(3)OGNL中常常會有「#」、「%」、「$」三個符號。通常「#」都是像前文所述表明那些非值棧的對象。還有就是ognl.jsp中建立 Map對象時候用到。而「%」則是顯示對象中的值。至於「$」則是用來顯示屬性文件中定義的值。好比某屬性文件中定義了「kkk=10」則在 Struts2的struts.xml或者JSP文件中用「${kkk}」則系統會讀取「10」這個值做爲顯示值。
(4)Struts2還提供了一些命名對象,這些命名對象與根對象無關,它們只是存在於Stack Context中。因此,訪問這些對象時須要使用#前綴來指明。
1.parameters對象:用於訪問HTTP請求參數。例如#parameters['foo']或#parameters.foo,用於返回調用HttpServletRequest的getParameter("foo")方法的返回值。
2.request對象:用於訪問HttpServletRequest的屬性。例如# request ['foo']或# request.foo,用於返回調用HttpServletRequest的getAttribute("foo")方法的返回值。
3.session對象:用於訪問HttpSession的屬性。例如# session ['foo']或# session.foo,用於返回調用HttpSession的getAttribute("foo")方法的返回值。
4.application對象:用於訪問ServletContext的屬性。例如# application ['foo']或# application.foo,用於返回調用ervletContext的getAttribute("foo")方法的返回值。
5.attr對象:該對象將依次搜索以下對象:PageContext、HttpServletRequest、HttpSession、ServletContext中的屬性。
注意:當系統建立了Action實例後,該Action實例已經被保存到ValueStack中,故無需書寫#便可訪問Action屬性。