Action Element的結構都是 <jsp:{elements} {attribute key} = {attribute value} />。
從上面看起來,就像是普通的html,只不過有特別的prefix在前面。其實,在上一篇我們提到Directive 的taglib,其實就是這種概念。
因此,Action Element就像名字一樣,都是帶有一個特別目的的Element。最終目的是達到Code Reuse。
(和我部落格同時發佈:http://www.dotblogs.com.tw/alantsai/archive/2013/10/07/jsp-action_elements.aspx)
前言
這一篇我們來看看JSP裡面的Action Elements的運用。
JSP Action Element 概觀
Action Element的結構都是 <jsp:{elements} {attribute key} = {attribute value} />。
從上面看起來,就像是普通的html,只不過有特別的prefix在前面。其實,在上一篇我們提到Directive 的taglib,其實就是這種概念。
因此,Action Element就像名字一樣,都是帶有一個特別目的的Element。最終目的是達到Code Reuse。
Include action Element
我們在上一篇提到過jsp action也有一個include的element。差別在於,Directive的include是先把兩個並在一起在編譯,而action的include element則是兩個分開編譯,include進來的只是執行過後的內容。
範例:
<jsp:include page="include.jsp" />
Java Bean
在介紹java bean相關的action element之前,我們先介紹一下什麽是Java Bean,同時它帶來的好處。
java bean其實就是一個普通的java class,或稱之為POJO(Plain Ordinary Java Object)。看到這邊,如果有寫過Entity Framework就會覺得有個名詞和它很像,那就是POCO (Plain Ordinary Class Object)。那其實他們兩個概念很想,只不過POCO是用property 來對應到 DB裡面的欄位,而Java沒有property的概念,因此它使用的是 private variable,搭配上getter和setter來對應。
講到這邊希望大家對於java bean有一點感覺了,那就是以Asp.net MVC來說,它就是專門來做model那一層的。一個純粹的model可以用來對應到我們畫面上面的form 讓我們在處理起來更容易。
一個POJO也是用Convention over configuration的概念。作為一個POJO,他一定是:
1.此Class必定是public
2.此Class必有一個constructor是不需要傳入任何參數
3.要使用variable對應則定義一個private 的 variable然後有對應的getXXX和setXXX。如果variable是boolean類別,通常是isXXX和getXXX。
下面是一個範例:
我們定義了一個Person的POJO有兩個參數,一個是name,一個是age。接下來我們就要製作一個頁面,裡面有表單,輸入完以後,我們會顯示輸入內容。
表單頁面
我們的表單非常簡單,就是兩個欄位,一個輸入名字(name),一個輸入年齡(age)。這個完全是一個普通的html內容:
那當表單送出的時候,會去到beanPage.jsp。這一個頁面也很簡單,只是把剛剛表單post過去的內容顯示出來而已:
首先,請先忽略那些紅色的線,這邊程式碼沒有問題,但是我不確定為甚麼eclipse有那些虛線。
可以看到我們完全沒有使用任何scriptlet就把form裡面的值取出來了,而我們這邊其實透過了java bean來做到。
useBean action element
這個主要是定義說,我們有一個java bean要使用,而他有三個attribute:
1.id - 在頁面裡面用來區分不同的java bean的數值。基本上在setProperty和getProperty裡面的name和這個id對應
2.class - 這個定義此java bean到底是用哪一個POJO。注意到這邊是Fully Qualified Name
3.scope - 這個是定義此java bean的範圍有效性。(其實jsp的參數都有scope的概念,我們會在介紹)。總共有4個level,依次是page < request < session < application
上面提到的4個scope,總共意思是:page代表只存在這個頁面,request代表存在一次傳遞(例如從A頁到B頁還會保存,和asp .net mvc的ViewBag一樣的scope), session則是此使用者的這段時間,而最後application則是此web container(例如Tomcat)啟動到結束的這段時間大家都碰到一樣(和Static一樣意思)。
設定scope除了能夠設定此java bean要活多久以外,當在自動assign property的時候,也會有差別。同等scope的會assign同等的java bean。
所以,以我們的例子,就是定義一個叫做person的java bean,是對應到我們剛剛定義的那個POJO,而此java bean只會存在於此頁。
接下來我們就需要給他assign內容。
setProperty action element
這邊是設定此java bean的數值,總共也有三個attribute:
1.name - 表示要assign哪一個java bean
2.property - 表示要assign java bean的哪一個variable。這邊的值就是我們variable的名字,而實際上他會呼叫setXXX。輸入*表示所有的欄位
3.value - 這個是要assign什麽值給此variable。如果沒有提供value,則是他會自動去request裡面找有沒有對應XXX的值,有就把它當做value
如果有寫過asp .net mvc,就會感覺和裡面的model binding概念是一樣的(雖然我覺的mvc更帥,因為它是在背後幫你做好了),但是這個是同樣的概念。
getProperty action element
這個應該不需要多說,呼叫getXXX把值取出來。參數有兩個:
1.name - 表示哪一個java bean
2.property - 呼叫哪一個getXXX
java bean的背後運作基本原理
還記得我們說過所有的jsp都會被編譯成為Servlet,所以如果從Servlet的角度來看useBean就是:
com.sample.jsp.bean.Person person = new com.sample.jsp.bean.Person()
scope則是此variable的位置。所以可能是global variable,也可能是local variable,或者static,或者在request裡面
然後setProperty和getProperty就只是在呼叫method而已。
你其實可以吧最後那個age的getProperty改成用Scriptlet來寫,也是沒有問題的:
Plugin action element
我們知道網頁上面可以跑像applet來運行一些比較複雜的東西。通常applet要embed在網頁裏面需要用 <object >來達到。而因為他還滿多東西設定,因此很煩。
程式設計師是很懶的一群人,因此有一個plugin action element專門幫忙產生對應的 <object >內容。
這個Action我就不介紹了,因為我基本上沒有embed過applet。
Forward action element
就像在Servlet我們可以用Request.Dispactcher()來forward頁面給其他地方做處理,jsp也可以辦到。而這個是透過forward的action。範例如下:
<jsp:forward page="forward.jsp">
<jsp:param name="param1" value="param value" />
</jsp:forward>
這邊應該直接看就懂在做什麽,基本上傳過去的參數可以透過request.getParameter()取得。
這邊需要注意的是,和在Servlet使用Forward一樣,一旦使用,就不能在輸出內容到response,要不然會出錯。
directive action element
結構是:<jsp:directive.{directive element} />。
directive action element其實和directive element在做的事情一樣,因此
<jsp:directive.page /> = = <%@ page %>。
不過,還是使用directive element來設定比較好。
結語
這一篇介紹了jsp裡面的action element。這裡面java bean的概念很重要,因為我們其實已經有了一個MVC的雛形。Servlet作為Controller,JSP作為View而Java bean就可以作為Model。
使用jsp action element我感覺view乾淨了很多,畢竟一堆scriptlet看起來真的很痛苦,感覺好像又回到了asp時期,使用action element可以讓我們把一些重複的邏輯分開來,更容易使用。