Unit 05 - 引入資源, 顯示圖片及部分頁面更新(Ajax)
目標
- 瞭解如何引入資源, 如 CSS, JS, 至 JSF 專案中
- 瞭解如何顯示圖片
- 動作後, 更新部分頁面
知識
JSF 專案中資源的目錄位置
JSF 專案中的 web 資源指 CSS, JavaScript, images 等. 這些 Web 資源必須放在 /resources
目錄之下.
此目錄又稱為 Library Root. 第二層的目錄為 Library Name.
在產生動態頁面時, 預設的 JSF Resource Handler 會讀取此目錄下的資源. 若不依照此慣例存放 Web 資源, 會導致 h:outputStylesheet
, h:outputScript
, h:graphImage
等 facelets 無法正常運作.
ResourceHandler
ResourceHandler
是一個執行期的 API, 用來取得 web 資源. UIComponent
或者 Renderer
實體皆會使用此 API 取得 JSF 專案中的資源. 某些的 Facelet 也會使用到 ResourceHandler
.
在處理請求時, JSF Runtime 會指示瀏覽器去做後續的資源請求(resource requests). 此時, JSF Runtime 會呼叫 ResourceHandler 的方法取得資源的 URI. 瀏覽器會使用此 URI 在向應用程式伺服器取得此 URI 的資源 [3].
瀏覽器在請求資源時, JSF Runtime 會呼叫 ResourceHandler 的方法, 將資源的內容以串流的方式回應給瀏覽器. 瀏覽器便可以顯示圖片或取得資源 [3].
Facelets
JSF 的 Command Components 相關的 facelet 標籤:
h:outputStylesheet
: 引入樣式表h:outputScript
: 引入 JSh:graphImage
: 載入圖片
Ajax
Facelet Ajax tag 為 f:ajax
, 用來更新部分頁面. 此標籤有數個重要的屬性, 決定 Ajax 的行為:
event
: 監聽的客戶端事件, 例如keyup
execute
: 要送回伺服器端處理的元件render
: 處理完成後, 要更新的頁面元件
event
屬性
要觸發 Ajax 請求(Ajax Request)的事件. 事件可以是 HTML 元件產生的 DOM event (瀏覽器上的事件) 或者是 JSF 元件的事件 (伺服器端事件).
支援的 DOM Event 有:
- Mouse events: click, dbclick, mousedown, mouseup, mouseover
- Keyboard events: keydown, keypress, keyup.
支援的 JSF 元件事件有:
action
: 按下h:commandButton
,h:commandlink
等元件所產生的事件valueChange
: 可編輯資料之元件, 如h:selectOneRadio
,h:inputText
等, 產生的資料內容異動事件.
在底下範例中, 當使用者選擇不同的圖片選項時, 因為 h:selectOneRadio
的值改變, 產生 valueChange
event. 此事件觸發 Ajax Request. 在此 Request 中, id 為 sor1
的元件被送到伺服器端處理, JSF Runtime 會更新 Managed Bean 的 property. 之後, 再更新 id 為 display
的頁面元素.
1
2
3
4
5
6
7
8
9
<h:form>
<f:ajax event="valueChange" execute="sor1" render="display">
<h:selectOneRadio id="sor1" value="#{handler.currentSelect}">
<f:selectItem itemLabel="Image01" itemValue="img01.jpg"/>
<f:selectItem itemLabel="Image02" itemValue="img02.jpg"/>
</h:selectOneRadio>
</f:ajax>
</h:form>
<h:graphicImage id="display" library="img" name="#{handler.currentSelect}"/>
execute
屬性
指定哪些 JSF 元件要放在 Ajax Request 中送到後端伺服器處理. execute
屬性內可以放多個元素的 ID, ID 間以空白分開. 也可以放以下的關鍵字, 指定提交元件範圍:
@none
: 沒有任何的元件.@this
: 內有f:ajax
的元件@form
: 表單內的元件@all
: 在頁面中的所有元件
render
屬性
指定要更新哪些元件, 在 Ajax Request 處理完成後.
屬性內可以放多個元素的 ID, ID 間以空白分開. 也可以放以下的關鍵字, 指定要更新的元件範圍[4]:
@none
: 沒有任何的元件.@this
: 內有f:ajax
的元件@form
: 表單內的元件@all
: 在頁面中的所有元件
User Story
User Story 1: Non-Ajac update
頁面上有兩個選項鈕, 供使用者選擇以顯示不同的圖片. 選擇完成後, 使用者按下 Show Image 按鈕, 在頁面下方顯示圖片內容.
User Story 2: Ajax update
頁面上有兩個選項鈕, 供使用者選擇以顯示不同的圖片. 選擇完成後, 系統馬上在下方顯示對應的圖片, 使用者不需要在按下 Show Image 按鈕.
實作程序
建立一個 Web Application 專案, 使用 JSF Framework. 依序完成以下步驟:
Step 在專案根目錄下, 建立 \resources\img
目錄.
Step 在 source package
下建立 jsfBeans
package.
Step 建立一個 Request Scoped Managed Bean:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package jsfBeans;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import java.util.logging.Logger;
@Named(value = "handler")
@RequestScoped
public class ImageHandler {
private String currentSelect;
public ImageHandler() {
currentSelect="img01.jpg";
}
@PostConstruct
public void init(){
Logger.getGlobal().info("Create ImageHandler");
}
public String getCurrentSelect() {
return currentSelect;
}
public void setCurrentSelect(String currentSelect) {
this.currentSelect = currentSelect;
}
public String showImage(){
return null;
}
}
Step 複製兩個 jpeg 檔案到 \resources\img
, 名稱分別為 img01.jpg
及 img01.jpg
.
Step 在 index.xhtml
頁面加入 h:form
標籤.
Step 在 h:form
標籤內,輸入以下的代碼:
1
2
3
4
5
6
7
<h2>Non-Ajax Update</h2> <br/>
<h:selectOneRadio value="#{handler.currentSelect}">
<f:selectItem itemLabel="Image01" itemValue="img01.jpg"/>
<f:selectItem itemLabel="Image02" itemValue="img02.jpg"/>
</h:selectOneRadio>
<br/>
<h:commandButton action="#{handler.showImage}" value="Show Image"/>
Step 接著, 再輸入以下的代碼:
1
2
3
4
5
6
7
<h2>Ajax Update</h2>
<f:ajax event="valueChange" execute="sor1" render="display">
<h:selectOneRadio id="sor1" value="#{handler.currentSelect}">
<f:selectItem itemLabel="Image01" itemValue="img01.jpg"/>
<f:selectItem itemLabel="Image02" itemValue="img02.jpg"/>
</h:selectOneRadio>
</f:ajax>
Step 在 h:form
的結尾標籤後方, 加入以下的程式碼, 顯示圖片:
1
<h:graphicImage id="display" library="img" name="#{handler.currentSelect}"/>
Step 測試你的程式.
複習問題
h:graphicImage
產生的資源 uri 的結構為何?h:graphicImage
的library
屬性內的值對應到哪一個專案目錄?- 有一個 JavaScript
/resources/js/main.js
. 要如何使用 facelet 引入到 JSF 專案中呢?
技術挑戰
請使用 JQuery 提供的 Tooltip 工具, 當滑鼠停留在選項時顯示提示文字.
JavaScript 請使用 h:outputScript
標籤引入專案.
參考資料
[1] Chapter 5 JSF Configurations Using XML Files and Annotation. In Mastering JavaServer Faces 2.2.
[2] Oracle, 2014. Chapter 3 Creating JSF Pages Using Facelets. In JAVA EE 6: Develop Web Applications with JSF: Student Guide, vol 1.
[3] ResourceHandler (Java(TM) EE 7 Specification APIs)
[4] ajax (JSF 2.1 View Declaration Language: Facelets Variant)