JSF 2.0のテンプレート機能を使う
そういやテンプレートについてあんまり書かなかったなと思い書いてみる。
新規作成でNetBeansのウィザードを利用してはいるが、生成されたコードも全て載せてるので特にIDE依存は無いのでご安心を。
まずテンプレートファイルを作成する。新規作成ウィザードでfaceletsテンプレートを選ぶ。
できあがったテンプレートファイルは以下の通り。cssファイルが2つ作られているのがわかる。
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link href="./resources/css/default.css" rel="stylesheet" type="text/css" /> <link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" /> <title>Facelets Template</title> </h:head> <h:body> <div id="left"> <ui:insert name="left">Left</ui:insert> </div> <div id="content" class="left_content"> <ui:insert name="content">Content</ui:insert> </div> </h:body> </html>
出来上がったプロジェクトファイル一覧は現時点でこうなっている。
続いてテンプレートクライアントを作成する。
テンプレートクライアントとは実際に埋め込むべきデータとそのセットを現すもの。StrutsのTilesの設定ファイルと各種JSPのテンプレートが一緒になっている感じかな。
テンプレートクライアントウィザードで出来上がったコードは以下の通り。
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <body> <ui:composition template="./newTemplate.xhtml"> <ui:define name="left"> left </ui:define> <ui:define name="content"> content </ui:define> </ui:composition> </body> </html>
これを以下のように書き換える。
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <body> <ui:composition template="./newTemplate.xhtml"> ここは表示される? <ui:define name="left"> 左側のエリア </ui:define> ここは表示される? <ui:define name="content"> コンテンツエリア </ui:define> ここは表示される? </ui:composition> </body> </html>
予想通り、ui:defineタグの外側は一切表示されない。HTMLの部分抜きだしを自動でやってくれるということ。貧弱なテンプレート環境ではHTMLの部分的なものを意識して作成しないといけない。しかし、それではDreamWeaver等で作業が出来ないという問題点がある。このJSF2を利用するとfaceletsが標準のため、HTMLを作成するだけでよい。
URLを見ればわかるようにテンプレートクライアントをさすようにしている。
ここのleft部分を書き換えてpage2.xhtmlとして別名保存してみる。
<!-- <ui:define name="left"> 左側のエリア </ui:define> -->
実行結果は省略するが、左側のエリアには「Left」と表示される。テンプレートクライアントで定義されていない部分はテンプレートファイルの中身そのまま出るようだ。
動的に生成(といっても定数返すだけだが)するためにコードも入れてみる。
package managed; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class Page { public String getSide(){ return "サイドは共通とか"; } public String getPage1Content(){ return "Page1コンテンツ"; } public String getPage2Content(){ return "Page2コンテンツ"; } }
テンプレートは以下の部分をさしかえる。
page1.xhtml
<ui:define name="left"> #{page.side} </ui:define> <ui:define name="content"> #{page.page1Content} </ui:define>
page2.xhtml
<ui:define name="left"> #{page.side} </ui:define> <ui:define name="content"> #{page.page2Content} </ui:define>
実行。
これだけ楽ちんなテンプレートもないと思う。
faceletsといえばみんな思いつくのが標準採用しているJBOSS Seamだと思う。SeamがJSFを利用しつつ高効率で開発できる理由はfaceletsの恩恵が大きい。ちなみにJSF2でのfaceletsはJSF 1.2のころよりパワーアップしていて、ちゃんと思ったとおりの挙動をしてくれるはずだ。