Tutorial: Using Thymeleaf (ja)



Similar documents
<4D F736F F D20819C486F70658F6F93588ED297708AC7979D89E696CA837D836A B E A2E646F63>

2016 年 度 情 報 リテラシー 変 更 された 状 態 同 様 に 価 格 のセルを 書 式 設 定 する 場 合 は 金 額 のセルをすべて 選 択 し [ 書 式 ]のプルダウンメニューか ら[ 会 計 ]を 選 択 する すると が 追 加 され 金 額 としての 書 式 が 設 定 さ

計算式の取り扱い

CSI情報管理システム

Microsoft Word - 第3章.doc

GRIDY SFA カスタム 項 目 操 作 ガイド 用 本 書 はに 必 要 な 操 作 を 解 説 しております は GRIDY SFA ののことです GRIDY SFA へ 申 し 込 み 最 初 に 登 録 を 行 った 方 がそのままとなります カスタム 項 目 はの 方 のみ 操 作 可

Office 10 パッケージ版「リンク集」

1. 目 次 1. 目 次 2.はじめに 2-1.メールテンプレート 編 集 機 能 とは? 2-2. 対 象 読 者 3. 用 語 一 覧 4. 利 用 の 流 れ 4-1.メールテンプレート 編 集 の 流 れ 5. 機 能 説 明 利 用 方 法 5-1.テキストメール 編 集 開 封 率 を

SXF 仕 様 実 装 規 約 版 ( 幾 何 検 定 編 ) 新 旧 対 照 表 2013/3/26 文 言 変 更 p.12(1. 基 本 事 項 ) (5)SXF 入 出 力 バージョン Ver.2 形 式 と Ver.3.0 形 式 および Ver.3.1 形 式 の 入 出 力 機 能 を

<4D F736F F D F B B838082F090DD927582B782E995FB96405F E646F6378>

研究者情報データベース

1 書 誌 作 成 機 能 (NACSIS-CAT)の 軽 量 化 合 理 化 電 子 情 報 資 源 への 適 切 な 対 応 のための 資 源 ( 人 的 資 源,システム 資 源, 経 費 を 含 む) の 確 保 のために, 書 誌 作 成 と 書 誌 管 理 作 業 の 軽 量 化 を 図

KINGSOFT Office 2016 動 作 環 境 対 応 日 本 語 版 版 共 通 利 用 上 記 動 作 以 上 以 上 空 容 量 以 上 他 接 続 環 境 推 奨 必 要 2

SPARQL Finder設置方法

Microsoft Word - Jimdo基礎編(8版)

Ver 改 訂 日 付 改 訂 内 容 1

Microsoft Word - 311Tools_END

1/2

■デザイン

PowerPoint プレゼンテーション

Microsoft Word - xls_SW2_01_C.doc

PowerPoint プレゼンテーション

2 県 公 立 高 校 の 合 格 者 は このように 決 まる (1) 選 抜 の 仕 組 み 選 抜 の 資 料 選 抜 の 資 料 は 主 に 下 記 の3つがあり 全 高 校 で 使 用 する 共 通 の ものと 高 校 ごとに 決 めるものとがあります 1 学 力 検 査 ( 国 語 数

2016 年 度 情 報 リテラシー 次 に Excel のメニューから[ 挿 入 ]タブをクリックし 表 示 されたメニュー 内 の[グラフ]にある[ 折 れ 線 グラフ]のボタンをクリックする するとサブメニューが 表 示 されるので 左 上 の[ 折 れ 線 ]を 選 択 する [ 挿 入 ]

PowerPoint プレゼンテーション

R4財務対応障害一覧

養 老 保 険 の 減 額 払 済 保 険 への 変 更 1. 設 例 会 社 が 役 員 を 被 保 険 者 とし 死 亡 保 険 金 及 び 満 期 保 険 金 のいずれも 会 社 を 受 取 人 とする 養 老 保 険 に 加 入 してい る 場 合 を 解 説 します 資 金 繰 りの 都

t検定

治 験 実 施 管 理 システム NMGCP 向 け Excel 形 式 プロトコール 作 成 手 順 書 V4.0.3 対 応 版 第 1 版 株 式 会 社 富 士 通 アドバンストエンジニアリング All Rights Reserved,Copyright 株 式 会 社 富 士 通 アドバン

XML形式の電子報告書作成に当たっての留意事項

Microsoft Word - FrontMatter.doc

2016 年 度 情 報 リテラシー 三 科 目 合 計 の 算 出 関 数 を 用 いて 各 教 科 の 平 均 点 と 最 高 点 を 求 めることにする この2つの 計 算 は [ホーム]タブのコマ ンドにも 用 意 されているが 今 回 は 関 数 として 作 成 する まず 表 に 三 科

工事記録写真チェックシステム 操作説明書

返還同意書作成支援 操作説明書

< 目 次 > 8. 雇 用 保 険 高 年 齢 雇 用 継 続 給 付 27 ( 育 児 休 業 給 付 介 護 休 業 給 付 ) 8.1 高 年 齢 雇 用 継 続 給 付 画 面 のマイナンバー 設 定 高 年 齢 雇 用 継 続 給 付 の 電 子 申 請 高

1

目 次 1. 大 学 情 報 データベースシステムの 使 用 方 法 について EXCEL 一 括 登 録 EXCEL ダウンロード 検 索 条 件 の 指 定 プレビュー EXCEL ダウンロード(データ 抽 出 あ

TIPS - 棚 割 りを 開 始 するまで Liteを 起 動 し 企 業 情 報 の 追 加 を 行 い 棚 割 を 行 う 企 業 の 追 加 をして 下 さい 企 業 情 報 の 追 加 時 に エラーメッセージが 表 示 された 場 合 別 途 TIPS トラブルが 発 生 した 場 合

付 録 B Wiki を 閲 覧 編 集 する B.1 Wiki を 閲 覧 する Web ブラウザのアドレス 欄 に 公 開 されている 個 人 用 Wiki の URL またはメーリ ングリストの Wiki の URL を 入 力 すると その Wiki を 閲 覧 編 集 することができ ます

■ディレクトリ

1. 表 から 値 を 抽 出 する 説 明 1.1. 表 から 値 を 抽 出 するための 関 数 について 説 明 します LOOKUP VLOOKUP HLOOKUP 関 数 は 検 索 値 に 対 応 する 値 を 検 索 値 を 含 む 一 覧 表 から 抽 出 し てくれる 関 数 です

富士山チェックリスト

2.4 箇 条 書 のスタイルを 変 更 する 右 クリックして 箇 条 書 と 番 号 付 け を 選 択 する. あとは 少 し 遊 べば, このようなことをやりたい 人 は 理 解 できると 思 います 3 いろいろな 入 力 ワープロを 使 う 上 で 肝 心 な 点 は, 空 白 調 整

■ユーザ

目 次 1. 積 算 内 訳 書 に 関 する 留 意 事 項 1 ページ 2. 積 算 内 訳 書 のダウンロード 3 ページ 3. 積 算 内 訳 書 の 作 成 (Excel 2003の 場 合 ) 6 ページ 4. 積 算 内 訳 書 の 作 成 (Excel 2007の 場 合 ) 13

POWER EGG V2.01 ユーザーズマニュアル ファイル管理編

している 5. これに 対 して 親 会 社 の 持 分 変 動 による 差 額 を 資 本 剰 余 金 として 処 理 した 結 果 資 本 剰 余 金 残 高 が 負 の 値 となるような 場 合 の 取 扱 いの 明 確 化 を 求 めるコメントが 複 数 寄 せられた 6. コメントでは 親

ez_meishi.ppt

(Microsoft Word - Excel\211\236\227p2\217\315.docx)

MetaMoJi ClassRoom/ゼミナール 授業実施ガイド

メール 受 信 画 面 のレイアウトを 変 更 することができます ここでは 初 期 設 定 のレイアウトで 表 示 されているボタ ンやマークについて 解 説 します メール 一 覧 画 面 には 受 信 したメールが 一 覧 表 示 されます メール 受 信 タブをクリックすると 受 信 箱 フ

(1)1オールゼロ 記 録 ケース 厚 生 年 金 期 間 A B 及 びCに 係 る 旧 厚 生 年 金 保 険 法 の 老 齢 年 金 ( 以 下 旧 厚 老 という )の 受 給 者 に 時 効 特 例 法 施 行 後 厚 生 年 金 期 間 Dが 判 明 した Bは 事 業 所 記 号 が

PowerPoint プレゼンテーション

Microsoft Office Excel2007(NO.2エクセル初級後編)

Microsoft Word - TechSmith Deployment Tool Documentation.docx

ことばを覚える

税金読本(8-5)特定口座と確定申告

Microsoft Word - 生物学技研報告ONLINE ガイドブック.doc

変 更 履 歴 版 日 付 区 分 変 更 内 容 変 更 個 所 /11/30 新 規 初 版 作 成 /12/10 修 正 資 料 カバー 画 像 設 定 の 操 作 内 容 を 追 加 資 料 カバー 画 像 設 定 i

WEB版「新・相続対策マスター」(ご利用の手引き)

Microsoft Word - tutorial5-teammodeling.docx

PowerPoint プレゼンテーション

目 次 1. 本 マニュアルについて D-Case ステンシルの 導 入 概 要 インストール D-Case 編 集 D-Case メニュー ノード リンク..

注 雇 促 進 税 制 と 本 制 度 のどちらかを 利 する 可 能 性 があるが あらかじめどちらの 制 度 を 利 するか 判 断 できない という 場 合 雇 促 進 税 制 の 事 前 届 出 ( 雇 促 進 計 画 の 提 出 )をした 上 で 申 告 の 際 にどちらを 利 するかご

SchITコモンズ【活用編】

以 下 に 手 順 の 流 れを 記 載 します 3ページ 以 降 で 各 項 目 の 手 順 を 説 明 します ( をクリックすると 該 当 ページにジャンプします ) また 4ページに 汎 用 データ 受 入 に 関 するよくあるお 問 い 合 わせをご 紹 介 しています Step (3ペー

1. アクセスする 2. 簡 易 検 索 画 面 (fig. 1) アクセスすると 最 初 に 出 る 画 面 です 検 索 語 入 力 ボックスにキーワードを 入 力 して 論 文 検 索 ボタンをクリックし ます 3. ボックス 下 部 のチェック 項

01_07_01 データのインポート_エクスポート_1

GMO MobileHomePage

Taro-2220(修正).jtd

データベースS 演習資料

目 次 1.はじめに 書 式 の 説 明 表 紙 スケジュール 組 入 れ 基 準 併 用 禁 止 薬 併 用 注 意 薬 同 種 同 効 薬 医 師 モニタリング..

目 次 1. ログイン ユーザー 登 録 TOP 職 員...8 (1) 職 員 の 名 刺 表 示...8 (2) 職 員 の 名 刺 一 括 ダウンロード...8 (3) 職 員 の 名 刺 帳 から 検 索 検 索...9 (1) 氏 名

AdobeReader(pdf)の 場 合 1) AdobeReader で 文 書 を 開 き [ ファイル ] > [ プロパティ ]を 選 択 します 2) [ ページサイズ ]の 値 を 確 認 します 3. 定 格 サイズかを 確 認 する 下 にある A 列 B 列 の 寸 法 一 覧

Microsoft Word - サンプル _データベースアクセス_.doc

Microsoft Word - ML_ListManager_10j.doc

PowerPoint プレゼンテーション

<4D F736F F D C97F195CF8AB DEC90E096BE8F912091E6312E313294C52E646F63>

2. 研 究 者 / 評 価 者 情 報 修 正 この 画 面 では 研 究 者 が 自 分 自 身 の 情 報 の 修 正 を 行 います (A) 研 究 者 / 評 価 者 情 報 の 修 正 () 研 究 者 / 評 価 者 情 報 修 正 画 面 を 開 く HOME 画 面 メニューの 研

2 Wee とは Wee はホームページの 更 新 ツールです Wee は サイトの 枠 組 みをWeb 製 作 業 者 が 作 成 し 更 新 は お 客 様 に 自 由 にしていただこうというコンセプトの 製 品 です インターネットに 繋 がる 場 所 ならどこからでも ブラウザでホームページ

<4D F736F F D2090C389AA8CA72D92F18F6F2D D F ED28CFC82AF91808DEC837D836A B E838B A815B816A2E646F6378>

以 下 に 手 順 の 流 れを 記 載 します 3ページ 以 降 で 各 項 目 の 手 順 を 説 明 します ( をクリックすると 該 当 ページにジャンプします ) また 15ページに 汎 用 データ 受 入 に 関 する よくあるお 問 い 合 わせをご 紹 介 しています Step1 (

目 次 機 能 概 要 配 信 管 理 1. メールの 配 信 履 歴 と 予 約 を 確 認 する

特別徴収封入送付作業について

年齢別人数計算ツールマニュアル

EC-OrangePOS 簡易マニュアル

Microsݯft Word - 91 forܠ2009November.docx

目 次 1. 論 理 関 数 IF IF の 概 要 論 理 式 の 種 類 等 号 不 等 号 具 体 的 な 使 い 方 ネスト 複 数 の 条 件 を 記 述...

(Microsoft Word - Easy\203y\201[\203W\221\200\215\354\203K\203C\203h.doc)

22 第 1 章 資 本 金 等 利 益 積 立 金 貴 見 のとおり 資 本 等 取 引 は 本 来 は 増 資 とか 減 資 と か さらには 旧 資 本 積 立 金 額 の 増 加 または 減 少 をいうこと になる ただ 利 益 の 配 当 はいわゆる 資 本 金 等 取 引 である か 損

機 能 概 要 概 要 平 成 24 年 度 シームレスな 地 域 連 携 医 療 の 実 現 実 証 事 業 に 対 応 するため 地 域 連 携 システム( 能 登 北 部 版 )を 構 築 する 機 能 < 機 能 追 加 変 更 一 覧 > 1. 画 像 連 携 機 能 院 内 で 撮 影

情報処理技能検定試験 表計算2級 手順書

Microsoft Word - CiNii看護大

Tutorial: Using Thymeleaf (ja)

入 札 参 加 資 格 申 請 システム 操 作 マニュアル 入 札 参 加 資 格 の 資 格 有 効 ( 変 更 ) 日 を 迎 えると 追 加 届 の 登 録 ができるようになります ( 入 札 参 加 資 格 申 請 の 定 時 受 付 では いずれかの 申 請 先 団 体 から 入 札 参

(Microsoft PowerPoint -

<4D F736F F D F4390B3208A948C E7189BB8CE F F8C668DDA97702E646F63>

(Microsoft PowerPoint - Ver12\203o\201[\203W\203\207\203\223\203A\203b\203v\216\221\227\277.ppt)

もくじ はじめに 本 書 はスマートフォンやタブレットのアプリ LINE の 設 定 を 行 うためのマニュアルとなります 詳 しい 操 作 方 法 については メーカーホームページ 上 の 基 本 的 な 使 い 方 を 参 照 ください LINE 基 本 的 な 使 い 方

スライド 1

Transcription:

Thymeleaf Tutorial: Using Thymeleaf (ja) Japanese translation by: Mitsuyuki Shiiba (@bufferings) Document version: 20141222-22 December 2014 Project version: 2.1.4.RELEASE Project web site: http://www.thymeleaf.org Page 1 of 84

1 Thymeleafの の 紹 介 1.1 Thymeleafって 何? ThymeleafはJavaのテンプレートエンジンライブラリです XML/XHTML/HTML5で 書 かれたテンプレートを 変 換 して アプリ ケーションのデータやテキストを 表 示 することができます ウェブアプリケーション 内 のXHTML/HTML5を 扱 う 方 が 得 意 ですが どんなXMLファイルでも 処 理 できますし ウェブアプリ ケーションでもスタンドアローンアプリケーションでも 使 用 可 能 です Thymeleafのメインゴールは テンプレート 作 成 のための 優 雅 で 整 形 式 の 方 法 を 提 供 することです そのため テンプレート 内 にロジックを 記 述 する 方 法 ではなく 事 前 定 義 されたロジックの 実 行 を DOM(Document Object Model) 上 でXMLタグ 属 性 によって 指 定 する 方 法 を 基 本 としています このアーキテクチャのおかげで パースしたファイルを 賢 くキャッシュして 実 行 時 のI/O 処 理 を 最 小 限 に 抑 えることができるの で テンプレートを 高 速 に 処 理 することが 可 能 となっています さらに Thymeleafは 最 初 からXMLとウェブ 標 準 を 念 頭 に 置 いてデザインされているので 必 要 に 応 じて 完 全 にバリデーショ ンされた 状 態 のテンプレートを 作 成 することもできます 1.2 Thymeleafはどんな 種 類 のテンプレートを 処 理 できるの? Thymeleafは6 種 類 のテンプレートを 処 理 することができます これをテンプレートモードと 呼 びます: XML Valid XML XHTML Valid XHTML HTML5 Legacy HTML5 Legacy HTML5 以 外 は 整 形 式 XMLです Legacy HTML5 モードでは 閉 じていないタグ 値 がない 属 性 引 用 符 で 囲 まれていな い 属 性 が 許 容 されていますが Thymeleafはこのモードのファイルを 最 初 に 整 形 式 XMLに 変 換 します それでもHTML5として は 正 しい 状 態 です(そして 実 際 こちらがHTML5を 書 くのに 推 奨 されている 方 法 です) また バリデーションはXMLとXHTMLのみで 使 用 可 能 なことに 注 意 してください ただ Thymeleafが 処 理 できるテンプレートのタイプはこれだけではありません テンプレートを パースする 方 法 と 結 果 を 書 き 込 む 方 法 を 指 定 することで ユーザーは 独 自 のモードを 定 義 することができます Thymeleafは DOMツリーとし て 表 現 することができるものであれば 何 でも(XMLかどうかに 関 係 なく)テンプレートとして 効 率 よく 処 理 することができま す 1 1.3 ダイアレクト: スタンダードダイアレクト Thymeleafは 非 常 に 拡 張 性 の 高 いテンプレートエンジンです( 実 際 テンプレートエンジンフレームワーク と 呼 んだほうがい いかもしれません) Thymeleafでは 処 理 対 象 のDOMノードと そのDOMノードをどのように 処 理 するかを 完 全 に 定 義 する ことができます DOMノードにロジックを 適 用 するものを プロセッサ と 呼 びます そして プロセッサ 一 式 と いくつかの 特 別 な 生 成 物 のことをダイアレクトと 呼 びます Thymeleafでは スタンダードダイアレクト というそのまますぐに 使 えるコアライ ブラリを 提 供 していて 大 半 のユーザーにとってはこれで 十 分 です Page 2 of 84

このチュートリアルでカバーしているのはスタンダードダイアレクトです 以 降 のページで 学 ぶ 全 ての 属 性 や 文 法 は 特 に 明 記 していなくても このダイアレクトに 定 義 してあります もちろん ライブラリの 拡 張 機 能 を 利 用 して 独 自 の 処 理 ロジックを 定 義 したい など(スタンダードダイアレクトを 拡 張 するこ とも 含 めて) 独 自 のダイアレクトを 作 りたい 場 合 があるかもしれません テンプレートエンジンは 複 数 のダイアレクトを 同 時 に 使 用 できます 公 式 の thymeleaf-spring3 と thymeleaf-spring4 連 携 パッケージはどちらも Springスタンダードダイアレクト と 呼 ばれるダイアレクトを 定 義 しています これは ほぼスタンダードダイアレクトと 同 じで そこにSpring Framework 用 の 便 利 機 能 を 少 しだけ 適 用 しています( 例 えば Thymeleaf 標 準 のOGNLの 代 わりにSpring 式 言 語 を 使 用 するなど) です ので Spring MVCを 使 用 するような 場 合 でも 時 間 の 無 駄 にはなりません ここで 学 ぶことは 全 て Springアプリケー ションを 作 成 する 際 にも 役 立 つでしょう Thymeleafのスタンダードダイアレクトはどのテンプレートモードでも 使 用 できますが 特 にウェブ 向 けのテンプレートモー ドに 適 しています(XHTMLとHTML5モード) HTML5の 他 に 具 体 的 には 以 下 のXHTML 仕 様 をサポート 動 作 確 認 しています: XHTML 1.0 Transitional XHTML 1.0 Strict XHTML 1.0 Frameset そして XHTML 1.1 です スタンダードダイアレクトの 大 半 のプロセッサは 属 性 プロセッサ です 属 性 プロセッサを 使 用 すると XHTML/HTML5テ ンプレートファイルは 処 理 前 であってもブラウザで 正 しく 表 示 することができます 単 純 にその 属 性 が 無 視 されるからです 例 えば タグライブラリを 使 用 したJSPだとブラウザで 直 接 表 示 できない 場 合 がありますが: <form:inputtext name="username" value="${user.name}" /> Thymeleafスタンダードダイアレクトでは 同 様 の 機 能 をこのように 実 現 します: <input type="text" name="username" value="james Carrot" th:value="${user.name}" /> ブラウザで 正 しく 表 示 できるだけでなく ( 任 意 ですが)value 属 性 を 指 定 することもできます(この 場 合 の James Carrot の 部 分 です) プロトタイプを 静 的 にブラウザで 開 いた 場 合 にはこの 値 が 表 示 され Thymeleafでテンプレートを 処 理 した 場 合 には ${user.name} の 評 価 結 果 値 で 置 き 換 えられます 必 要 な 場 合 には 全 く 同 じファイルをデザイナーとデベロッパーが 触 ることができるので 静 的 なプロトタイプをテンプレー トに 変 換 する 労 力 を 減 らすことができます この 機 能 のことを ナチュラルテンプレーティング と 呼 びます 1.4 全 体 のアーキテクチャ ThymeleafのコアはDOM 処 理 エンジンです 具 体 的 にいうと 標 準 のDOM APIではなく 高 性 能 の 独 自 DOM 実 装 によってテ ンプレートのインメモリツリー 表 現 を 生 成 します その 後 そのインメモリツリー 上 でノードを 走 査 してプロセッサを 実 行 し DOMを 変 更 します DOMの 変 更 は 現 在 の 設 定 や テンプレートに 渡 されるコンテキストと 呼 ばれるデータセットに 従 いま す ウェブドキュメントはオブジェクトツリーとして 表 現 されることが 本 当 によくあるので DOMテンプレート 表 現 の 使 用 はウェ ブアプリケーションにとても 適 しています( 実 際 にブラウザはDOMツリーによってメモリ 上 でウェブページを 表 現 します) ま た 多 くのウェブアプリケーションで 使 用 するテンプレート 数 は 数 十 個 程 度 である そのテンプレートが 大 きなサイズでは ない アプリケーションの 実 行 中 に 通 常 は 変 更 されない という 考 えに 基 づいてThymeleafはテンプレートのDOMツリーのイ ンメモリキャッシュを 利 用 しています これによって 多 くのテンプレート 処 理 で( 必 要 だとしても)ほんの 少 しのI/Oしか 必 要 な くなるので 本 番 環 境 での 実 行 を 速 くすることができます このチュートリアルの 後 ろの 方 にキャッシュについてと 高 速 な 処 理 のためにThymeleafがどのようにメモリとリソー スを 最 適 化 しているかについて 説 明 した 章 がありますので 詳 細 はそちらを 参 照 してください Page 3 of 84

しかし 制 約 もあります: このアーキテクチャではテンプレート 処 理 に 他 のアプローチよりも 多 くのメモリスペースが 必 要 にな ります つまり (ウェブドキュメントとは 対 照 的 な) 大 きなサイズのデータXMLの 作 成 には 使 わない 方 が 良 いということで す 大 まかには(といってもJVMのメモリサイズによりますが)1テンプレートを 処 理 するのに 数 十 メガバイトが 必 要 になるXML ファイルを 処 理 する 場 合 は おそらくThymeleafを 使 わない 方 が 良 いでしょう ここで データXMLに 対 してだけこの 制 約 について 考 えているのは ウェブのXHTML/HTML5に 関 しては そんなに 大 きなサイズのドキュメントは 作 成 しないからです ブラウザもDOMツリーを 生 成 するので そんなことをすると 固 まっ てしまいますもんね 1.5 次 に 進 む 前 に 読 むことをお 勧 めします Thymeleafは 特 にウェブアプリケーションに 適 しています そしてウェブアプリケーションには 標 準 というものがあります みんながこの 標 準 についてよく 知 っているべきなのですが ほとんどの 人 が 知 りません たとえウェブアプリケーションの 仕 事 を 何 年 もやっている 人 であってもです HTML5の 出 現 によって 今 日 のウェブ 標 準 はかつてないほどに 混 乱 しています XHTMLからHTMLに 戻 るの? XMLシ ンタックスはなくなるの? XHTML2.0はどこにいったの? ということでこのチュートリアルでは 先 に 進 む 前 に Thymeleafのウェブサイトの 次 の 記 事 を 読 むことを 強 くお 勧 めします: From HTML to HTML (via HTML) http://www.thymeleaf.org/doc/articles/fromhtmltohtmlviahtml.html Page 4 of 84

2 The Good Thymes Virtual Grocery(グッドタイムス 仮 想 食 料 品 店 ) 2.1 食 料 品 店 用 のウェブサイト Thymeleafのテンプレート 処 理 のコンセプトを 分 かりやすく 説 明 するために このチュートリアルではデモアプリケーション を 使 用 します デモアプリケーションはプロジェクトのウェブサイトからダウンロードできます このアプリケーションは 架 空 の 仮 想 食 料 品 店 のウェブサイトで 様 々なThymeleafの 機 能 の 例 をお 見 せするのに 十 分 なシナリ オが 用 意 されています アプリケーションにはとてもシンプルなモデルエンティティが 必 要 でしょう: Products は Orders を 作 成 することによって Customers に 販 売 されます さらにこの Products について Comments も 管 理 しましょう: Example application model とてもシンプルなサービスレイヤも 作 りましょう 次 のようなメソッドを 持 つ Service オブジェクトです: Page 5 of 84

public class ProductService { } public List<Product> findall() { return ProductRepository.getInstance().findAll(); } public Product findbyid(integer id) { return ProductRepository.getInstance().findById(id); } 最 後 に リクエストURLに 応 じてThymeleafに 処 理 を 委 譲 するフィルタをウェブレイヤに 作 成 しましょう: private boolean process(httpservletrequest request, HttpServletResponse response) throws ServletException { } try { * Query controller/url mapping and obtain the controller * that will process the request. If no controller is available, * return false and let other filters/servlets process the request. IGTVGController controller = GTVGApplication.resolveControllerForRequest(request); if (controller == null) { return false; } * Obtain the TemplateEngine instance. TemplateEngine templateengine = GTVGApplication.getTemplateEngine(); * Write the response headers response.setcontenttype("text/html;charset=utf-8"); response.setheader("pragma", "no-cache"); response.setheader("cache-control", "no-cache"); response.setdateheader("expires", 0); * Execute the controller and process view template, * writing the results to the response writer. controller.process( request, response, this.servletcontext, templateengine); return true; } catch (Exception e) { throw new ServletException(e); } IGTVGController インターフェイスは 次 のようになります: Page 6 of 84

public interface IGTVGController { } public void process( HttpServletRequest request, HttpServletResponse response, ServletContext servletcontext, TemplateEngine templateengine); これで IGTVGController の 実 装 を 作 成 すれば 良 いだけです データをサービスから 受 け 取 って TemplateEngine オブジェクト を 使 用 してテンプレートを 処 理 します 最 終 的 にはこのようになりますが: Example application home page まずはテンプレートエンジンの 初 期 化 について 見 てみましょう 2.2 テンプレートエンジンの 作 成 と 設 定 フィルタの process( ) メソッドの 中 に 次 のような 文 があります: TemplateEngine templateengine = GTVGApplication.getTemplateEngine(); これは Thymeleafを 使 用 するアプリケーションにおいて 最 も 重 要 なオブジェクトの 中 の 一 つである TemplateEngine インス タンスの 作 成 と 設 定 を GTVGApplication クラスが 担 っているということです ここでは org.thymeleaf.templateengine を 次 のように 初 期 化 しています: Page 7 of 84

public class GTVGApplication { private static TemplateEngine templateengine; static { initializetemplateengine(); } } private static void initializetemplateengine() { } ServletContextTemplateResolver templateresolver = new ServletContextTemplateResolver(); // XHTML is the default mode, but we set it anyway for better understanding of code templateresolver.settemplatemode("xhtml"); // This will convert "home" to "/WEB-INF/templates/home.html" templateresolver.setprefix("/web-inf/templates/"); templateresolver.setsuffix(".html"); // Template cache TTL=1h. If not set, entries would be cached until expelled by LRU templateresolver.setcachettlms(3600000l); templateengine = new TemplateEngine(); templateengine.settemplateresolver(templateresolver); もちろん TemplateEngine オブジェクトを 初 期 化 するのには 様 々な 方 法 がありますが 今 はこの 数 行 のコードで 十 分 です テンプレートリゾルバー テンプレートリゾルバーからスタートしましょう: ServletContextTemplateResolver templateresolver = new ServletContextTemplateResolver(); テンプレートリゾルバーはThymeleafのAPIである org.thymeleaf.templateresolver.itemplateresolver を 実 装 しています: public interface ITemplateResolver { } * 文 字 列 名 (templateprocessingparameters.gettemplatename())によってテンプレートを 解 決 します * このテンプレートリゾルバーで 解 決 できない 場 合 は null を 返 します public TemplateResolution resolvetemplate( TemplateProcessingParameters templateprocessingparameters); テンプレートリゾルバーは どうやってテンプレートにアクセスするかを 決 定 する 役 割 を 担 っています GTVGアプリケー Page 8 of 84

ションの 場 合 は org.thymeleaf.templateresolver.servletcontexttemplateresolver 実 装 を 使 用 して Servlet Context からテ ンプレートファイルを 取 得 します: Javaの 全 てのウェブアプリケーションにはアプリケーションレベルの javax.servlet.servletcontext というオブジェクトが 存 在 し それによってウェブアプリケーションのルートをリソースパ スのルートとしてリソースを 解 決 することができます テンプレートリゾルバーにはいくつかのパラメータを 設 定 することができます まず 標 準 的 なものとして テンプレート モードがあります: templateresolver.settemplatemode("xhtml"); XHTMLは ServletContextTemplateResolver のデフォルトテンプレートモードですが 意 図 を 明 らかにするために 書 いておくの は 良 い 習 慣 ですね templateresolver.setprefix("/web-inf/templates/"); templateresolver.setsuffix(".html"); prefix と suffix は 文 字 通 り テンプレート 名 から 実 際 のリソース 名 を 作 り 出 すために 使 用 されます この 設 定 を 使 用 すると product/list というテンプレート 名 は 次 の 内 容 と 同 じになります: servletcontext.getresourceasstream("/web-inf/templates/product/list.html") 任 意 ですが cachettlms でテンプレートキャッシュの 生 存 期 間 を 指 定 することもできます: templateresolver.setcachettlms(3600000l); もちろんTTL 以 内 であってもキャッシュのサイズが 最 大 値 に 達 した 場 合 は 古 いエントリーから 削 除 されます キャッシュの 振 る 舞 いやサイズは ICacheManager インターフェイスの 実 装 によって 定 義 されます または 単 純 にデ フォルトで 設 定 されている StandardCacheManager を 修 正 しても 良 いです テンプレートリゾルバーについてのより 詳 細 な 説 明 は 後 ほど 行 います 今 はテンプレートエンジンオブジェクトの 生 成 につい て 見 てみましょう テンプレートエンジン テンプレートエンジンオブジェクトとは org.thymeleaf.templateengine のことです 現 在 の 例 ではこのようにエンジンを 作 成 しています: templateengine = new TemplateEngine(); templateengine.settemplateresolver(templateresolver); かなりシンプルですよね インスタンスを 作 成 してテンプレートリゾルバーをセットするだけです TemplateEngine に 必 須 のパラメータはテンプレートリゾルバーだけです もちろん 他 にも 色 々な 設 定 があります(メッセージ リゾルバーやキャッシュサイズなど)が それについては 後 ほど 説 明 します 今 はこれだけで 十 分 です これでテンプレートエンジンの 準 備 ができました では Thymeleafを 使 用 したページの 作 成 に 進 みましょう Page 9 of 84

3 テキストを 使 う 3.1 複 数 言 語 でウェルカム 私 たちの 食 料 品 店 用 の 最 初 のタスクはホームページ 作 成 です 最 初 のバージョンは 非 常 にシンプルです: タイトルとウェルカムメッセージだけです /WEB-INF/templates/home.html は 以 下 のようになります: <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>good Thymes Virtual Grocery</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" media="all" href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" /> </head> <body> <p th:text="#{home.welcome}">welcome to our grocery store!</p> </body> </html> 最 初 に 見 て 欲 しいのは このファイルがどんなブラウザでも 正 しく 表 示 できるXHTMLであるということです 理 由 は XHTMLにあるタグしか 使 っていないからです(そしてブラウザは th:text のような 知 らない 属 性 は 無 視 します) また 整 形 式 の DOCTYPE 宣 言 を 持 っているので 互 換 モードではなくスタンダードモードで 表 示 されます 次 に このファイルは th:text のような 属 性 を 定 義 したThymeleafのDTDを 指 定 しているので 妥 当 な XHTMLでもありま 2 す さらに テンプレートが 処 理 されると( 全 ての th:* 属 性 が 取 り 除 かれますが) Thymeleafは 自 動 的 に DOCTYPE 内 の DTD 定 義 を 標 準 的 な XHTML 1.0 Strict のものに 置 き 換 えます(このDTD 変 換 機 能 に 関 しては 後 の 章 で 説 明 します) thymeleaf 名 前 空 間 も th:* として 定 義 されています <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> もしテンプレートの 妥 当 性 や 整 形 式 であるかどうかを 全 く 気 にしないのであれば 単 純 に 標 準 の XHTML 1.0 Strict DOCTYPE を 指 定 すればよく xmlns 名 前 空 間 の 定 義 も 不 要 であることに 気 をつけてください: Page 10 of 84

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd"> <html> <head> <title>good Thymes Virtual Grocery</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" media="all" href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" /> </head> <body> <p th:text="#{home.welcome}">welcome to our grocery store!</p> </body> </html> こう 書 いてもXHTMLモードのThymeleafは 問 題 なく 処 理 することができます(IDEの 警 告 で 残 念 な 感 じになると 思 いますけ ど) バリデーションに 関 してはOKですね ではテンプレートに 関 する 本 当 に 面 白 い 部 分 に 進 みましょう: th:text 属 性 を 見 て 行 き ましょう th:text とテキストの 外 部 化 テキストの 外 部 化 とは テンプレートコードのフラグメント( 断 片 )をテンプレートファイルの 外 に 取 り 出 すことです それに よって テンプレートから 切 り 離 された 別 のファイル( 通 常 は.properties ファイル)の 中 でフラグメントを 管 理 することがで き また 簡 単 に 他 の 言 語 で 書 かれた 文 字 列 に 置 き 換 えることができます(このことを 多 言 語 対 応 または i18n と 呼 びます) 外 部 化 されたテキストのフラグメントのことを 通 常 は メッセージ と 呼 びます メッセージは そのメッセージを 特 定 するためのキーを 持 っており Thymeleafは #{} という 構 文 を 使 用 してテキストと メッセージの 紐 付 けを 行 います: <p th:text="#{home.welcome}">welcome to our grocery store!</p> ここでは 実 際 Thymeleafスタンダードダイアレクトの2つの 異 なる 機 能 を 使 用 しています: th:text 属 性 : この 属 性 は 値 の 式 を 評 価 した 結 果 をタグのボディに 設 定 します ここでは コード 内 の Welcome to our grocery store! というテキストを 置 換 します #{home.welcome} 式 : スタンダード 式 構 文 に 規 定 されています ここでは テンプレートを 処 理 する 全 てのロケールで home.welcome キーに 対 応 するメッセージを 取 得 して th:text 属 性 で 使 用 するということを 意 味 します ふむ では 外 部 化 されたテキストはどこにあるのでしょうか? Thymeleafでは 外 部 化 テキストの 場 所 は org.thymeleaf.messageresolver.imessageresolver を 実 装 することで 自 由 に 設 定 で きます 通 常 は.properties ファイルを 使 用 する 実 装 になっていますが 独 自 実 装 を 作 成 することも 可 能 です 例 えばメッ セージをDBから 取 得 することも 可 能 です ところで 私 たちのテンプレートエンジンには 初 期 化 の 時 にメッセージリゾルバーを 指 定 していません これは org.thymeleaf.messageresolver.standardmessageresolver クラスによって 実 装 された スタンダードメッセージリゾル バー を 使 用 していますよ ということです スタンダードメッセージリゾルバーは /WEB-INF/templates/home.html というテンプレートに 対 してテンプレートと 同 じフォ ルダ 内 で 同 じ 名 前 のファイルで 拡 張 子 が.properties のファイルの 中 からメッセージを 探 します /WEB-INF/templates/home_en.properties が 英 語 用 Page 11 of 84

/WEB-INF/templates/home_es.properties がスペイン 語 用 /WEB-INF/templates/home_pt_BR.properties がポルトガル 語 (ブラジル) 用 /WEB-INF/templates/home.properties がデフォルト 用 (ロケールが 一 致 しない 場 合 ) home_es.properties ファイルを 見 てみましょう: home.welcome= Bienvenido a nuestra tienda de comestibles! これでThymeleafのテンプレート 処 理 に 必 要 なことは 全 て 終 わりました ではHomeコントローラーを 作 成 しましょう コンテキスト テンプレートを 処 理 するために HomeController クラスを 作 成 します 前 述 の IGTVGController インターフェイスを 実 装 しま す: public class HomeController implements IGTVGController { } public void process( HttpServletRequest request, HttpServletResponse response, ServletContext servletcontext, TemplateEngine templateengine) { } WebContext ctx = new WebContext(request, response, servletcontext, request.getlocale()); templateengine.process("home", ctx, response.getwriter()); まずはコンテキストの 作 成 について 見 てみましょう Thymeleafのコンテキストは org.thymeleaf.context.icontext イン ターフェイスを 実 装 したオブジェクトです コンテキストはテンプレートエンジンの 実 行 に 必 要 な 全 てのデータを 変 数 のマッ プとして 持 ち また 外 部 化 メッセージで 使 用 されるロケールへの 参 照 を 持 っています public interface IContext { } public VariablesMap<String,Object> getvariables(); public Locale getlocale(); このインターフェイスの 拡 張 として org.thymeleaf.context.iwebcontext というインターフェイスがあります: public interface IWebContext extends IContext { } public HttpSerlvetRequest gethttpservletrequest(); public HttpSession gethttpsession(); public ServletContext getservletcontext(); public VariablesMap<String,String[]> getrequestparameters(); public VariablesMap<String,Object> getrequestattributes(); public VariablesMap<String,Object> getsessionattributes(); public VariablesMap<String,Object> getapplicationattributes(); Thymeleafのコアライブラリはそれぞれの 実 装 を 提 供 しています: Page 12 of 84

org.thymeleaf.context.context implements IContext org.thymeleaf.context.webcontext implements IWebContext コントローラーのコードを 見 ていただければ 分 かるように ここでは WebContext を 使 用 しています というか そうしなけ ればなりません ServletContextTemplateResolver が IWebContext の 実 装 を 必 要 とするからです WebContext ctx = new WebContext(request, servletcontext, request.getlocale()); 3つの 引 数 のうち2つだけが 必 須 です ロケールに 何 も 指 定 しなかったらシステムのデフォルトロケールが 使 用 されます( 実 際 の アプリケーションでは 絶 対 に 指 定 した 方 がよいですが) インターフェイスの 定 義 から WebContext はリクエストパラメータ リクエスト 属 性 セッション 属 性 アプリケーション 属 性 を 取 得 するメソッドを 持 っていることが 分 かりますが 実 際 のところ WebContext はもう 少 し 色 々とやっています: 全 てのリクエスト 属 性 をコンテキスト 変 数 マップに 追 加 全 てのリクエストパラメータを 持 つ param というコンテキスト 変 数 を 追 加 全 てのセッション 変 数 を 持 つ session というコンテキスト 変 数 を 追 加 全 てのサーブレットコンテキスト 属 性 を 持 つ application というコンテキスト 変 数 を 追 加 実 行 直 前 に 全 てのコンテキストオブジェクト( IContext の 実 装 )に 対 して 特 別 な 変 数 が 設 定 されます Context と WebContext のどちらもその 対 象 です この 変 数 は 実 行 情 報 ( execinfo )と 呼 ばれます この 変 数 はテンプレートで 使 用 される2 つのデータを 持 っています テンプレート 名 ( ${execinfo.templatename} ): エンジンの 実 行 時 に 指 定 される 名 前 です これは 処 理 するテンプレート 名 と 一 致 します 現 在 日 時 ( ${execinfo.now} ): テンプレートエンジンが 現 在 のテンプレートの 処 理 を 開 始 した 日 時 を 示 す Calendar オブジェ クトです テンプレートエンジンの 実 行 コンテキストオブジェクトが 準 備 できたので あとはテンプレートエンジンを 実 行 するだけです テンプレート 名 とコンテキ ストとレスポンスライターを 渡 してレスポンスへの 書 き 込 みを 行 います: templateengine.process("home", ctx, response.getwriter()); ではスペイン 語 ロケールを 使 用 して 結 果 を 見 てみましょう: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>good Thymes Virtual Grocery</title> <meta content="text/html; charset=utf-8" http-equiv="content-type"/> <link rel="stylesheet" type="text/css" media="all" href="/gtvg/css/gtvg.css" /> </head> <body> <p> Bienvenido a nuestra tienda de comestibles!</p> </body> </html> Page 13 of 84

3.2 テキストと 変 数 に 関 するその 他 のこと エスケープなしのテキスト 私 たちのホームページの 最 もシンプルなバージョンは 準 備 できましたが もしメッセージが 次 のようなものだったらどうしま しょう home.welcome=welcome to our <b>fantastic</b> grocery store! 今 のままでテンプレートを 実 行 するとこのようになります: <p>welcome to our <b>fantastic</b> grocery store!</p> これは 本 当 に 欲 しい 結 果 ではありません <b> タグがエスケープされてブラウザに 表 示 されてしまっています これは th:text 属 性 のデフォルトの 振 る 舞 いです ThymeleafでXHTMLタグをエスケープせずに 表 示 したいのであれば 違 う 属 性 を 使 用 しなければなりません: th:utext ( unescaped text 用 ): <p th:utext="#{home.welcome}">welcome to our grocery store!</p> This will output our message just like we wanted it: <p>welcome to our <b>fantastic</b> grocery store!</p> 変 数 の 使 用 と 表 示 さて 私 たちのホームページについてもう 少 し 見 てみましょう 例 えば ウェルカムメッセージに 次 のようなデータを 表 示 し たいかもしれません: Welcome to our fantastic grocery store! Today is: 12 july 2010 まずはじめに コントローラーを 修 正 してコンテキスト 変 数 に 日 付 を 追 加 します: public void process( HttpServletRequest request, HttpServletResponse response, ServletContext servletcontext, TemplateEngine templateengine) { } SimpleDateFormat dateformat = new SimpleDateFormat("dd MMMM yyyy"); Calendar cal = Calendar.getInstance(); WebContext ctx = new WebContext(request, response, servletcontext, request.getlocale()); ctx.setvariable("today", dateformat.format(cal.gettime())); templateengine.process("home", ctx, response.getwriter()); String 型 のtoday 変 数 をコンテキストに 追 加 したので テンプレートで 表 示 することができるようになりました: Page 14 of 84

<body> <p th:utext="#{home.welcome}">welcome to our grocery store!</p> <p>today is: <span th:text="${today}">13 February 2011</span></p> </body> 見 ての 通 りここでも th:text 属 性 を 使 用 しています(タグのボディを 置 換 したいので これで 問 題 ありません) ですが 構 文 が 少 し 違 いますね #{} 式 ではなく ${} 式 を 使 っています これが 変 数 用 の 式 です OGNL (Object-Graph Navigation Language) と 呼 ばれる 言 語 の 式 でコンテキスト 変 数 マップに 対 して 処 理 を 行 います この ${today} は 単 純 に todayという 名 前 の 変 数 を 取 得 する という 意 味 ですが もっと 複 雑 なこともできます( 例 えば ${user.name} は user 変 数 を 取 得 してその getname() メソッドを 呼 び 出 す という 意 味 になります) 属 性 には 様 々な 値 を 設 定 することができます: メッセージ 変 数 式 などなど 次 の 章 では どのようなものが 指 定 できるかを 全 て 見 ていきましょう Page 15 of 84

4 スタンダード 式 構 文 私 たちの 仮 想 食 料 品 店 の 開 発 は 少 し 休 憩 して Thymeleafスタンダードダイアレクトの 中 でもっとも 重 要 なものの 一 つについ て 学 んでいきましょう: Thymeleafスタンダード 式 構 文 です この 構 文 を 使 って 表 現 された2タイプの 属 性 値 を 既 に 見 てきました: メッセージ 式 と 変 数 式 です: <p th:utext="#{home.welcome}">welcome to our grocery store!</p> <p>today is: <span th:text="${today}">13 february 2011</span></p> ですが まだ 知 らないタイプがたくさんあります また 知 っているものにももっと 面 白 い 部 分 があります 初 めにスタン ダード 式 の 機 能 の 概 要 を 見 てみましょう 単 純 式 : 変 数 式 : ${} 選 択 変 数 式 : *{} メッセージ 式 : #{} リンクURL 式 : @{} リテラル テキストリテラル: 'one text', 'Another one!', 数 値 リテラル: 0, 34, 3.0, 12.3, 真 偽 値 リテラル: true, false Nullリテラル: null リテラルトークン: one, sometext, main, テキスト 演 算 子 : 文 字 列 結 合 : + リテラル 置 換 : The name is ${name} 算 術 演 算 子 : バイナリ 演 算 子 : +, -, *, /, % マイナス 符 号 ( 単 項 演 算 子 ): - 論 理 演 算 子 : 二 項 演 算 子 : and, or 論 理 否 定 演 算 子 ( 単 項 演 算 子 ):!, not 比 較 と 等 価 : 比 較 演 算 子 : >, <, >=, <= ( gt, lt, ge, le ) 等 価 演 算 子 : ==,!= ( eq, ne ) 条 件 演 算 子 : If-then: (if)? (then) If-then-else: (if)? (then) : (else) Default: (value)?: (defaultvalue) これら 全 ての 機 能 は 結 合 したりネストしたりすることができます: Page 16 of 84

'User is of type ' + (${user.isadmin()}? 'Administrator' : (${user.type}?: 'Unknown')) 4.1 メッセージ ご 存 知 の 通 り #{} メッセージ 式 は 次 のように 書 いて: <p th:utext="#{home.welcome}">welcome to our grocery store!</p> これとリンクすることができます: home.welcome= Bienvenido a nuestra tienda de comestibles! でも まだ 考 えていないことが 一 つあります: メッセージテキストが 完 全 に 静 的 ではない 場 合 はどうしましょうか? 例 えば ア プリケーションは 誰 がサイトに 訪 れているかをいつでも 知 っているとして その 人 の 名 前 を 呼 んで 挨 拶 文 を 出 したい 場 合 には どのようにすればいいのでしょうか? <p> Bienvenido a nuestra tienda de comestibles, John Apricot!</p> つまり メッセージにパラメータを 持 たせる 必 要 があるということです こんなふうに: home.welcome= Bienvenido a nuestra tienda de comestibles, {0}! パラメータは java.text.messageformat の 標 準 構 文 に 従 って 指 定 します つまり そのクラスのAPIドキュメントにあるよう に 数 値 や 日 付 にフォーマットを 指 定 することもできるということです HTTPセッションに 持 っている user という 属 性 をパラメータとして 指 定 するには 次 のように 記 述 します: <p th:utext="#{home.welcome(${session.user.name})}"> Welcome to our grocery store, Sebastian Pepper! </p> 必 要 に 応 じて 複 数 のパラメータをカンマ 区 切 りで 指 定 することも 可 能 です 実 際 のところ メッセージキー 自 体 も 変 数 から 取 得 することができます: <p th:utext="#{${welcomemsgkey}(${session.user.name})}"> Welcome to our grocery store, Sebastian Pepper! </p> 4.2 変 数 既 に 述 べたように ${} 式 は 実 際 にはコンテキスト 内 の 変 数 マップ 上 で 実 行 されるOGNL(Object-Graph Navigation Language) 式 です OGNL 構 文 や 機 能 についての 詳 細 はOGNL Language Guideを 参 照 してください: http://commons.apache.org/ognl/ OGNL 構 文 から 次 のようなことが 分 かります 以 下 の 内 容 は: Page 17 of 84

<p>today is: <span th:text="${today}">13 february 2011</span>.</p> 実 際 には 次 の 内 容 と 同 等 です: ctx.getvariables().get("today"); ただし OGNLではもっとパワフルな 表 現 が 可 能 です こんな 風 に: <p th:utext="#{home.welcome(${session.user.name})}"> Welcome to our grocery store, Sebastian Pepper! </p> これは 実 際 には 次 の 処 理 を 実 行 することでユーザー 名 を 取 得 します: ((User) ctx.getvariables().get("session").get("user")).getname(); ですが GetterメソッドのナビゲーションはOGNLの 機 能 の1つにすぎません もっと 見 てみましょう: * ポイント(.)を 使 用 したプロパティへのアクセス プロパティのGetterを 呼 び 出 すのと 同 じです ${person.father.name} * プロパティへのアクセスは 角 括 弧 ([])にプロパティ 名 を 指 定 することでも 可 能 です * プロパティ 名 の 指 定 は 変 数 でも シングルクォートで 囲 まれた 文 字 列 でも 可 能 です ${person['father']['name']} * オブジェクトがマップの 場 合 ドットも 括 弧 も 同 様 に get() メソッドを 呼 び 出 します ${countriesbycode.es} ${personsbyname['stephen Zucchini'].age} * 配 列 やコレクションに 対 するインデックスを 使 用 したアクセスも 同 様 に 角 括 弧 を 使 用 します * インデックスをクォートなしで 書 きます ${personsarray[0].name} * メソッド 呼 び 出 しが 可 能 です 引 数 ありでも 可 能 です ${person.createcompletename()} ${person.createcompletenamewithseparator('-')} 式 の 基 本 オブジェクト コンテキスト 変 数 に 対 してOGNL 式 で 評 価 をする 際 に より 柔 軟 に 記 述 できるようにいくつかのオブジェクトを 用 意 していま す これらのオブジェクトの 参 照 は(OGNL 標 準 に 従 って) # シンボルで 始 まります: #ctx : コンテキストオブジェクト #vars: コンテキスト 変 数 #locale : コンテキストロケール #httpservletrequest : (ウェブコンテキストのみ) HttpServletRequest オブジェクト #httpsession : (ウェブコンテキストのみ) HttpSession オブジェクト Page 18 of 84

次 のようなことができます: Established locale country: <span th:text="${#locale.country}">us</span>. 詳 細 は Appendix A を 参 照 して 下 さい 式 のユーティリティオブジェクト 基 本 オブジェクト 以 外 にも 式 の 中 の 共 通 のタスクを 手 助 けするためのユーティリティオブジェクトがあります #dates : java.util.date オブジェクト 用 のユーティリティメソッド: フォーマット コンポーネントの 抽 出 など #calendars : #dates に 似 ていますが java.util.calendar オブジェクト 用 です #numbers : 数 値 オブジェクト 用 のユーティリティメソッド #strings : String オブジェクト 用 のユーティリティメソッド: contains, startswith, prepending/appending, など #objects : オブジェクト 一 般 のユーティリティメソッド #bools : 真 偽 値 評 価 用 のユーティリティメソッド #arrays : 配 列 用 のユーティリティメソッド #lists : リスト 用 のユーティリティメソッド #sets : セット 用 のユーティリティメソッド #maps : マップ 用 のユーティリティメソッド #aggregates : 配 列 やコレクション 上 での 集 約 処 理 用 ユーティリティメソッド #messages : #{ } と 同 様 に 変 数 式 内 での 外 部 化 メッセージを 取 り 扱 うためのユーティリティメソッド #ids : ( 例 えば イテレーション 結 果 などの) 繰 り 返 し 処 理 内 でid 属 性 を 取 り 扱 うためのユーティリティメソッド それぞれのユーティリティオブジェクトの 詳 細 については Appendix B を 参 照 してください 私 たちのホームページ 内 の 日 付 を 再 フォーマット ユーティリティオブジェクトについて 学 んだので それを 使 って 私 たちのホームページ 内 の 日 付 表 示 を 変 えてみましょう 次 のように HomeController で 処 理 する 代 わりに: SimpleDateFormat dateformat = new SimpleDateFormat("dd MMMM yyyy"); Calendar cal = Calendar.getInstance(); WebContext ctx = new WebContext(request, servletcontext, request.getlocale()); ctx.setvariable("today", dateformat.format(cal.gettime())); templateengine.process("home", ctx, response.getwriter()); 次 のように 書 いて: WebContext ctx = new WebContext(request, servletcontext, request.getlocale()); ctx.setvariable("today", Calendar.getInstance()); templateengine.process("home", ctx, response.getwriter()); ビュー 側 でフォーマットすることができます: <p> Today is: <span th:text="${#calendars.format(today,'dd MMMM yyyy')}">13 May 2011</span> </p> Page 19 of 84

4.3 選 択 したものに 対 する 式 (アスタリスク 構 文 ) 変 数 式 は ${} だけでなく *{} でも 書 くことができます 重 要 な 違 いは アスタリスク 構 文 はコンテキスト 変 数 マップに 対 してではなく 選 択 されたオブジェクトに 対 して 評 価 をする 式 であるということです 選 択 されたオブジェクトがない 場 合 は ダラー 構 文 もアスタリスク 構 文 も 全 く 同 じになります オブジェクトの 選 択 とはどういうことでしょうか? th:object のことです では ユーザープロフィールページ ( userprofile.html ) で 使 ってみましょう: <div th:object="${session.user}"> <p>name: <span th:text="*{firstname}">sebastian</span>.</p> <p>surname: <span th:text="*{lastname}">pepper</span>.</p> <p>nationality: <span th:text="*{nationality}">saturn</span>.</p> </div> これは 次 と 全 く 同 じです: <div> <p>name: <span th:text="${session.user.firstname}">sebastian</span>.</p> <p>surname: <span th:text="${session.user.lastname}">pepper</span>.</p> <p>nationality: <span th:text="${session.user.nationality}">saturn</span>.</p> </div> もちろん ダラー 構 文 とアスタリスク 構 文 は 共 存 可 能 です: <div th:object="${session.user}"> <p>name: <span th:text="*{firstname}">sebastian</span>.</p> <p>surname: <span th:text="${session.user.lastname}">pepper</span>.</p> <p>nationality: <span th:text="*{nationality}">saturn</span>.</p> </div> ダラー 構 文 内 で #object 式 変 数 を 使 用 して 選 択 されているオブジェクトを 参 照 することもできます: <div th:object="${session.user}"> <p>name: <span th:text="${#object.firstname}">sebastian</span>.</p> <p>surname: <span th:text="${session.user.lastname}">pepper</span>.</p> <p>nationality: <span th:text="*{nationality}">saturn</span>.</p> </div> 繰 り 返 しになりますが オブジェクトが 選 択 されていない 場 合 はダラー 構 文 とアスタリスク 構 文 は 全 く 同 じ 意 味 になります <div> <p>name: <span th:text="*{session.user.name}">sebastian</span>.</p> <p>surname: <span th:text="*{session.user.surname}">pepper</span>.</p> <p>nationality: <span th:text="*{session.user.nationality}">saturn</span>.</p> </div> 4.4 リンクURL その 重 要 性 から URLはウェブアプリケーションテンプレートにおけるファーストクラスオブジェクトであり Thymeleafス タンダードダイアレクト にも 特 別 な 構 文 が 用 意 されています @ 構 文 です: @{} URLにはいくつかのタイプがあります: Page 20 of 84

絶 対 URL: http://www.thymeleaf.org 相 対 URL: ページ 相 対 URL: user/login.html コンテキスト 相 対 URL: /itemdetails?id=3 (サーバー 内 のコンテキスト 名 は 自 動 的 に 付 与 されます) サーバー 相 対 URL: ~/billing/processinvoice ( 同 じサーバー 内 の 異 なるコンテキスト(= application)のurlを 呼 び 出 すこ とができます ) プロトコル 相 対 URL: //code.jquery.com/jquery-2.0.3.min.js Thymeleafでは 絶 対 URLはどんな 場 合 でも 使 用 できますが 相 対 URLを 使 用 する 場 合 は IWebContext を 実 装 したコンテキスト オブジェクトが 必 要 です そのコンテキストオブジェクトを 使 用 して 相 対 リンクを 生 成 するための 情 報 をHTTPリクエスト 内 から 取 得 します ではこの 新 しい 構 文 を 使 ってみましょう th:href 属 性 で 使 用 します: <!-- Will produce 'http://localhost:8080/gtvg/order/details?orderid=3' (plus rewriting) --> <a href="details.html" th:href="@{http://localhost:8080/gtvg/order/details(orderid=${o.id})}">view</a> <!-- Will produce '/gtvg/order/details?orderid=3' (plus rewriting) --> <a href="details.html" th:href="@{/order/details(orderid=${o.id})}">view</a> <!-- Will produce '/gtvg/order/3/details' (plus rewriting) --> <a href="details.html" th:href="@{/order/{orderid}/details(orderid=${o.id})}">view</a> いくつか 注 意 点 : th:href は 属 性 変 更 用 の 属 性 です: リンクURLを 生 成 し <a> タグのhref 属 性 にセットします URLパラメータを 指 定 することができます( orderid=${o.id} の 部 分 です) 自 動 的 にURLエンコーディングされます 複 数 のパラメータを 指 定 する 場 合 はカンマ 区 切 りで 指 定 できます @{/order/process(execid=${execid},exectype='fast')} URLパス 内 でも 変 数 式 は 使 用 可 能 です @{/order/{orderid}/details(orderid=${orderid})} / で 始 まる 相 対 URL( /order/details )に 対 しては 自 動 的 にアプリケーションコンテキスト 名 を 前 に 付 けます クッキーが 使 用 できない 場 合 またはまだ 分 からない 場 合 は ";jsessionid=" を 相 対 URLの 最 後 につけてセッションを キープできるようにすることがあります これは URL Rewriting と 呼 ばれていますが Thymeleafでは 全 てのURLに 対 して サーブレットAPIの response.encodeurl() のメカニズムを 使 用 して 独 自 リライトフィルタを 追 加 することができます th:href タグを 使 用 する 場 合 ( 任 意 ですが) 静 的 な href 属 性 をテンプレートに 同 時 に 指 定 することができます そうする ことでプロトタイプ 用 途 などで 直 接 テンプレートをブラウザで 開 いた 場 合 でもリンクを 有 効 にすることができます メッセージ 構 文 ( #{} )のときと 同 様 に URL 構 文 でも 他 の 式 の 評 価 結 果 が 使 用 可 能 です <a th:href="@{${url}(orderid=${o.id})}">view</a> <a th:href="@{'/details/'+${user.login}(orderid=${o.id})}">view</a> 私 たちのホームページ 用 のメニュー リンクURLの 作 成 方 法 がわかったので ホームにサイト 内 の 他 のページへの 小 さなメニューを 加 えてみましょうか <p>please select an option</p> <ol> <li><a href="product/list.html" th:href="@{/product/list}">product List</a></li> <li><a href="order/list.html" th:href="@{/order/list}">order List</a></li> <li><a href="subscribe.html" th:href="@{/subscribe}">subscribe to our Newsletter</a></li> <li><a href="userprofile.html" th:href="@{/userprofile}">see User Profile</a></li> </ol> Page 21 of 84

サーバールート 相 対 URL 追 加 のシンタックスを 使 用 して (コンテキストルート 相 対 URLの 代 わりに)サーバールート 相 対 URLを 作 成 することができま す @{~/path/to/something} のように 指 定 することで 同 じサーバーの 異 なるコンテキストへのリンクを 作 成 することがで きます 4.5 リテラル テキストリテラル テキストリテラルはシングルクォートで 囲 まれた 文 字 列 です どんな 文 字 でも 大 丈 夫 ですが シングルクォート 自 体 は \' の ようにエスケープしてください <p> Now you are looking at a <span th:text="'working web application'">template file</span>. </p> 数 値 リテラル 数 値 リテラルは 数 字 そのままです <p>the year is <span th:text="2013">1492</span>.</p> <p>in two years, it will be <span th:text="2013 + 2">1494</span>.</p> 真 偽 値 リテラル 真 偽 値 リテラルは true と false です: <div th:if="${user.isadmin()} == false"> ここで 注 意 して 欲 しいのは == false が 括 弧 の 外 側 にあるということです この 場 合 はThymeleaf 自 身 が 処 理 します もし 括 弧 の 中 にある 場 合 は OGNL/SpringELのエンジンが 処 理 を 担 当 します <div th:if="${user.isadmin() == false}"> nullリテラル null リテラルも 使 用 可 能 です: <div th:if="${variable.something} == null"> リテラルトークン 数 値 真 偽 値 nullリテラルは 実 は リテラルトークン の 特 定 のケースなのです Page 22 of 84

このリテラルトークンはスタンダード 式 を 少 しだけシンプルにしてくれます テキストリテラル( '' )と 全 く 同 様 の 動 きを しますが 次 の 文 字 しか 使 用 できません: 文 字 ( A-Z and a-z ) 数 字 ( 0-9 ) 括 弧 ( [ と ] ), ドット (. ), ハイフン ( - ) アンダース コア ( _ ) ですので 空 白 文 字 やカンマ 等 は 使 用 できません この 利 点 は 何 でしょうか?それはトークンはクォートで 囲 む 必 要 がないという 点 です ですので 次 のように 書 く 代 わりに: <div th:class="'content'"></div> こう 書 くことができます: <div th:class="content"></div> 4.6 テキストの 追 加 テキストは + 演 算 子 で 追 加 できます 文 字 列 リテラルであっても 値 やメッセージ 式 の 評 価 結 果 であっても 大 丈 夫 です: th:text="'the name of the user is ' + ${user.name}" 4.7 リテラル 置 換 リテラル 置 換 を 使 用 すると 複 数 の 変 数 から 文 字 列 を 作 成 するフォーマットが 簡 単 になります '' + '' のようにリテラ ルを 追 加 する 必 要 がありません リテラル 置 換 を 使 用 する 場 合 は 縦 棒 ( )で 囲 みます: <span th:text=" Welcome to our application, ${user.name}! "> これは 以 下 の 内 容 と 同 じです: <span th:text="'welcome to our application, ' + ${user.name} + '!'"> リテラル 置 換 は 他 の 式 と 組 み 合 わせて 使 用 することができます: <span th:text="${onevar} + ' ' + ${twovar}, ${threevar} "> 注 意 点 : リテラル 置 換 ( ) 内 で 使 用 可 能 なのは 変 数 式 ( ${} )だけです 他 のリテラル( '' )や 真 偽 値 / 数 値 トークンや 条 件 式 などは 使 用 できません 4.8 算 術 演 算 子 いくつかの 算 術 演 算 子 が 使 用 可 能 です: +, -, *, /, % th:with="iseven=(${prodstat.count} % 2 == 0)" この 演 算 子 はOGNL 変 数 式 の 中 でも 使 用 可 能 なことに 注 意 して 下 さい(その 場 合 はThymeleafスタンダード 式 エンジンの 代 わり にOGNLによって 計 算 されます) Page 23 of 84

th:with="iseven=${prodstat.count % 2 == 0}" いくつかの 演 算 子 には 文 字 列 エイリアスもあります: div ( / ), mod ( % ) 4.9 比 較 演 算 子 と 等 価 演 算 子 式 の 中 の 値 は >, <, >=, <= シンボルで 比 較 できます また == と!= 演 算 子 で 等 価 性 を 確 認 できます ただし XMLの 属 性 値 には < と > を 使 用 すべきではないと 策 定 されていますので 代 わりに < と > を 使 用 すべきです th:if="${prodstat.count} > 1" th:text="'execution mode is ' + ( (${execmode} == 'dev')? 'Development' : 'Production')" 文 字 列 エイリアスもあります: gt ( > ), lt ( < ), ge ( >= ), le ( <= ), not (! ), eq ( == ), neq / ne (!= ) 4.10 条 件 式 条 件 式 は 条 件 (それ 自 体 が 別 の 式 です)を 評 価 した 結 果 によって 2つのうちのどちらかの 式 を 評 価 することを 意 味 します 例 を 見 てみましょう( 今 回 は th:class という 属 性 変 更 子 を 使 用 しますね): <tr th:class="${row.even}? 'even' : 'odd'"> 条 件 式 の3つのパーツ 全 て( condition, then and else )がそれぞれ 式 になっています つまり 変 数 ( ${}, *{} )やメッ セージ( #{} )や URL( @{} )やリテラル( '' )を 使 うことができるということです 条 件 式 は 括 弧 で 囲 むことでネスト 可 能 です: <tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'"> Else 式 は 省 略 可 能 です その 場 合 条 件 がfalseのときにはnull 値 が 返 されます <tr th:class="${row.even}? 'alt'"> 4.11 デフォルト 式 (エルビス 演 算 子 ) デフォルト 式 は then のない 特 別 な 条 件 式 です Groovyなどの エルビス 演 算 子 と 同 じです 2つの 式 を 指 定 して 最 初 の 式 がnullを 返 した 場 合 にのみ2 番 目 の 式 の 値 が 評 価 されます 実 際 にユーザープロフィールページを 見 てみましょう: Page 24 of 84

<div th:object="${session.user}"> <p>age: <span th:text="*{age}?: '(no age specified)'">27</span>.</p> </div> 演 算 子 は?: です 年 齢 ( *{age} )がnullの 場 合 にのみラベル( 今 回 はリテラル 値 )を 表 示 します つまり 以 下 の 内 容 と 同 じで す: <p>age: <span th:text="*{age!= null}? *{age} : '(no age specified)'">27</span>.</p> 括 弧 で 囲 むことでネスト 可 能 です: <p> Name: <span th:text="*{firstname}?: (*{admin}? 'Admin' : #{default.username})">sebastian</span> </p> 4.12 プリプロセッシング ここまで 見 てきた 式 に 加 えて Thymeleafは プリプロセッシング 式 を 提 供 します プリプロセッシングとはどういうことでしょうか?それは 通 常 の 式 よりも 先 に 評 価 されるということです それによって 最 終 的 に 実 行 される 実 際 の 式 の 変 更 をすることができます プリプロセッシング 式 は 普 通 の 式 と 全 く 同 じように 書 くことができますが 二 重 のアンダースコアで 囲 まれています ( ${expression} ) i18nの Messages_fr.properties のエントリに 言 語 特 有 のスタティックメソッドを 呼 び 出 すようなOGNL 式 が 含 まれていると しましょう: article.text=@myapp.translator.translator@translatetofrench({0}) Messages_es.properties の 対 応 する 部 分 : article.text=@myapp.translator.translator@translatetospanish({0}) ロケールに 応 じた 式 を 評 価 してマークアップを 作 成 する 必 要 があるので まずは(プリプロセッシングで) 式 を 選 択 して その 次 にThymeleafにそれを 実 行 させます: <p th:text="${ #{article.text('textvar')} }">Some text here</p> フランス 語 ロケールの 場 合 のプリプロセッシングは 次 と 同 等 になります: <p th:text="${@myapp.translator.translator@translatetofrench(textvar)}">some text here</p> プリプロセッシング 用 文 字 列 は 属 性 の 中 では \_\_ とエスケープします Page 25 of 84

5 属 性 値 を 設 定 する この 章 ではThymeleafでどのようにしてマークアップタグ 内 の 属 性 値 を 設 定 (または 変 更 )するかを 説 明 します タグのボディの 内 容 を 設 定 する 機 能 の 次 に 必 要 な 基 本 機 能 かもしれません 5.1 任 意 の 属 性 に 値 を 設 定 する 私 たちのウェブサイトでニュースレターを 発 行 するとしましょう ユーザーが 購 読 できるようにしたいので /WEB- INF/templates/subscribe.html テンプレートにフォームを 設 置 します: <form action="subscribe.html"> <fieldset> <input type="text" name="email" /> <input type="submit" value="subscribe me!" /> </fieldset> </form> これで 全 然 問 題 ないように 見 えます しかし 実 際 はこのファイルはウェブアプリケーションのテンプレートというよりは 静 的 なXHTMLに 見 えます まず action 属 性 がこのテンプレートファイル 自 身 への 静 的 リンクなので URLを 書 き 換 える 方 法 があ りません 次 に submitボタンのvalue 属 性 は 英 語 で 表 示 されますが 多 言 語 対 応 したいですよね ということで th:attr 属 性 を 使 いましょう これで タグの 中 の 属 性 値 を 変 更 することができます <form action="subscribe.html" th:attr="action=@{/subscribe}"> <fieldset> <input type="text" name="email" /> <input type="submit" value="subscribe me!" th:attr="value=#{subscribe.submit}"/> </fieldset> </form> コンセプトは 非 常 に 直 感 的 です: th:attr には 単 純 に 属 性 に 値 を 代 入 する 式 を 書 きます 対 応 するコントローラーやメッセー ジファイルを 作 成 することによって 想 定 通 りの 処 理 結 果 が 得 られます: <form action="/gtvg/subscribe"> <fieldset> <input type="text" name="email" /> <input type="submit" value=" Suscríbeme!"/> </fieldset> </form> 新 しい 属 性 の 値 が 使 用 されていることに 加 えて /gtvg/subscribe のURLには 既 に 説 明 したようにアプリケーションコンテキ スト 名 が 自 動 的 に 付 け 加 えられています 同 時 に 複 数 の 属 性 に 値 を 設 定 したい 場 合 はどうしたらよいでしょうか?XMLでは1つのタグの 中 に 同 じ 属 性 を2つ 以 上 書 くこと はできませんので th:attr にカンマ 区 切 りのリストを 指 定 します: <img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" /> メッセージファイルを 用 意 すれば このような 出 力 になります: Page 26 of 84

<img src="/gtgv/images/gtvglogo.png" title="logo de Good Thymes" alt="logo de Good Thymes" /> 5.2 特 定 の 属 性 に 値 を 設 定 する ここまでで 次 のような 書 き 方 はすごく 汚 いなぁと 思 っているかもしれませんね: <input type="submit" value="subscribe me!" th:attr="value=#{subscribe.submit}"/> 属 性 の 中 で 値 を 設 定 するというのはとても 実 用 的 ではありますが 常 にそうしないといけないというのはエレガントではあり ません ですよね なので 実 際 のところ th:attr 属 性 はテンプレート 内 ではほとんど 使 われません 通 常 は th:* 属 性 を 使 用 します この 属 性 を 使 用 すると( th:attr のような 任 意 の 属 性 ではなく) 特 定 のタグ 属 性 に 値 を 設 定 することができます ではスタンダードダイアレクトでボタンの value 属 性 に 値 を 設 定 するにはどのような 属 性 を 使 用 すればいいのでしょうか?こ れはかなり 分 かりやすいと 思 います th:value です では 見 てみましょう: <input type="submit" value="subscribe me!" th:value="#{subscribe.submit}"/> この 方 が 全 然 良 いですよね! 同 様 に form タグの action 属 性 も 見 てみましょう: <form action="subscribe.html" th:action="@{/subscribe}"> th:href 属 性 を home.html で 使 用 したのを 覚 えていますか?これも 同 じです: <li><a href="product/list.html" th:href="@{/product/list}">product List</a></li> このような 属 性 が 非 常 にたくさん 用 意 されていて それぞれが 特 定 のXHTMLやHTML5のタグを 対 象 にしています: + + th:abbr th:accept th:accept-charset th:accesskey th:action th:align th:alt th:archive th:audio th:autocomplete th:axis th:background th:bgcolor th:border th:cellpadding th:cellspacing th:challenge th:charset th:cite th:class th:classid th:codebase th:codetype th:cols th:colspan th:compact th:content th:contenteditable th:contextmenu th:data th:datetime th:dir th:draggable th:dropzone th:enctype th:for th:form th:formaction th:formenctype th:formmethod th:formtarget th:frame th:frameborder th:headers th:height th:high th:href th:hreflang th:hspace th:http-equiv th:icon th:id th:keytype th:kind th:label th:lang th:list th:longdesc th:low th:manifest th:marginheight th:marginwidth th:max th:maxlength th:media th:method th:min th:name th:optimum th:pattern th:placeholder th:poster th:preload th:radiogroup th:rel th:rev th:rows th:rowspan th:rules th:sandbox th:scheme th:scope th:scrolling th:size th:sizes th:span th:spellcheck th:src th:srclang th:standby th:start th:step th:style th:summary th:tabindex th:target th:title th:type th:usemap th:value th:valuetype th:vspace th:width th:wrap th:xmlbase th:xmllang th:xmlspace 5.3 複 数 の 値 を 同 時 に 設 定 する ここでは2つのちょっと 特 別 な 属 性 を 紹 介 します th:alt-title と th:lang-xmllang です 2つの 属 性 に 同 じ 値 を 同 時 に 指 定 することができます 具 体 的 には: Page 27 of 84

th:alt-title は alt と title を 設 定 します th:lang-xmllang は lang と xml:lang を 設 定 します 私 たちのGTVGホームページで 次 のように 書 いている 部 分 は: <img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" /> このように 書 くこともできますし: <img src="../../images/gtvglogo.png" th:src="@{/images/gtvglogo.png}" th:title="#{logo}" th:alt="#{logo}" /> このように 書 くこともできます: <img src="../../images/gtvglogo.png" th:src="@{/images/gtvglogo.png}" th:alt-title="#{logo}" /> 5.4 前 後 に 追 加 する th:attr と 同 じように 任 意 の 属 性 に 対 して 作 用 するものとして Thymeleafには th:attrappend と th:attrprepend 属 性 が あります 既 存 の 属 性 値 の 前 や 後 ろに 評 価 結 果 を 付 け 加 えるための 属 性 です 例 えばあるボタンに 対 して ユーザーが 何 をしたかによって 異 なるCSSクラスを 追 加 ( 設 定 ではなく 追 加 )したい 場 合 が 考 えられ ます これは 簡 単 です: <input type="button" value="do it!" class="btn" th:attrappend="class=${' ' + cssstyle}" /> cssstyle 変 数 に "warning" という 値 を 設 定 してテンプレートを 処 理 すると 次 の 結 果 が 得 られます: <input type="button" value="do it!" class="btn warning" /> スタンダードダイアレクトには2つの 特 別 な 属 性 追 加 用 の 属 性 があります: th:classappend と th:styleappend です CSSクラ スや style の 一 部 を 既 存 のものを 上 書 きせずに 追 加 します: <tr th:each="prod : ${prods}" class="row" th:classappend="${prodstat.odd}? 'odd'"> ( th:each 属 性 のことは 心 配 しないでください 繰 り 返 し 用 の 属 性 として 後 ほど 説 明 します ) 5.5 固 定 値 ブール 属 性 XHTML/HTML5 属 性 の 中 には 決 まった 値 を 持 つか その 属 性 自 体 が 存 在 しないかのどちらか という 特 別 な 属 性 がありま す 例 えば checked です: <input type="checkbox" name="option1" checked="checked" /> <input type="checkbox" name="option2" /> XHTML 標 準 では checked 属 性 には "checked" という 値 しか 設 定 できません(HTML5では 少 し 緩 いですが) disabled, Page 28 of 84

multiple, readonly と selected も 同 様 です これらの 属 性 に 対 して 条 件 の 結 果 によって 値 を 設 定 するための 属 性 を スタンダードダイアレクトでは 提 供 しています 条 件 の 評 価 結 果 がtrueの 場 合 はその 固 定 値 が 設 定 され falseの 場 合 は 属 性 自 体 が 設 定 されません: <input type="checkbox" name="active" th:checked="${user.active}" /> スタンダードダイアレクトには 次 のような 固 定 値 ブール 属 性 があります: -+ -+ - th:async th:autofocus th:autoplay th:checked th:controls th:declare th:default th:defer th:disabled th:formnovalidate th:hidden th:ismap th:loop th:multiple th:novalidate th:nowrap th:open th:pubdate th:readonly th:required th:reversed th:scoped th:seamless th:selected 5.6 HTML5フレンドリーな 属 性 や 要 素 名 のサポート よりHTML5フレンドリーな 書 き 方 もできます これは 全 く 異 なる 構 文 になります <table> <tr data-th-each="user : ${users}"> <td data-th-text="${user.login}"></td> <td data-th-text="${user.name}"></td> </table> data-{prefix}-{name} 構 文 は th:* などの 名 前 空 間 を 使 用 せずに 独 自 属 性 を 書 くためのHTML5での 標 準 的 な 方 法 です Thymeleafでは (スタンダードダイアレクトだけでなく) 全 てのダイアレクトでこの 構 文 を 使 用 することができます {prefix}-{name} という 形 式 で 独 自 タグを 指 定 するための 構 文 もあります これは W3C Custom Elements specification (より 大 きな W3C Web Components spec の 一 部 です)に 準 拠 しています 例 えば th:block 要 素 (または th-block )で 使 用 すること ができますが これについては 後 述 します 重 要 : この 構 文 は 名 前 空 間 を 使 用 した th:* に 追 加 された 機 能 であって 置 き 換 えるものではありません 将 来 的 に 名 前 空 間 構 文 を 非 推 奨 にする 意 図 は 全 くありません Page 29 of 84

6 繰 り 返 し 処 理 ここまでホームページとしてユーザープロフィールページと ニュースレター 購 読 ページを 作 ってきました ですが 商 品 に ついてはどうでしょう? 訪 問 者 に 私 たちの 商 品 を 知 ってもらうための 商 品 一 覧 ページを 作 るべきではないでしょうか? えぇ 明 らかにYesですね ではそうしましょう 6.1 繰 り 返 し 処 理 の 基 礎 /WEB-INF/templates/product/list.html ページに 商 品 一 覧 を 掲 載 するためにテーブルが 必 要 です 1 行 ( <tr> 要 素 )に1 商 品 ず つ 表 示 したいので テンプレートの 中 に テンプレート 行 ( 各 商 品 がどのように 表 示 されるかを 示 す 行 )を 作 って それを Thymeleafで 商 品 ごとに 繰 り 返 す 必 要 があります スタンダードダイアレクトにはそのための 属 性 があります th:each です th:each を 使 用 する 商 品 一 覧 ページのコントローラーはサービスレイヤから 商 品 一 覧 を 取 得 してテンプレートコンテキストにそれを 追 加 します: public void process( HttpServletRequest request, HttpServletResponse response, ServletContext servletcontext, TemplateEngine templateengine) { ProductService productservice = new ProductService(); List<Product> allproducts = productservice.findall(); WebContext ctx = new WebContext(request, servletcontext, request.getlocale()); ctx.setvariable("prods", allproducts); } templateengine.process("product/list", ctx, response.getwriter()); では 商 品 リストを 繰 り 返 し 処 理 するために th:each を 使 いましょう: Page 30 of 84

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>good Thymes Virtual Grocery</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" media="all" href="../../../css/gtvg.css" th:href="@{/css/gtvg.css}" /> </head> <body> <h1>product list</h1> <table> <tr> <th>name</th> <th>price</th> <th>in STOCK</th> <tr th:each="prod : ${prods}"> <td th:text="${prod.name}">onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.instock}? #{true} : #{false}">yes</td> </table> <p> <a href="../home.html" th:href="@{/}">return to home</a> </p> </body> </html> 上 記 の prod : ${prods} 属 性 値 は ${prods} の 評 価 結 果 の 各 要 素 に 対 して その 要 素 をprodという 変 数 に 詰 めて このテ ンプレートのフラグメントを 繰 り 返 し 処 理 する という 意 味 になります 呼 び 名 を 決 めておきましょう ここでは ${prods} のことを 被 繰 り 返 し 式 または 被 繰 り 返 し 変 数 と 呼 びます ここでは prod のことを 繰 り 返 し 変 数 と 呼 びます 繰 り 返 し 変 数 prod は <tr> 要 素 の 内 部 だけで 使 用 できることに 注 意 してください ( <td> のような 内 部 のタグでも 使 用 可 能 です) 3 繰 り 返 し 処 理 が 可 能 な 値 Thymeleafの 繰 り 返 し 処 理 で 使 用 可 能 なのは java.util.list だけではありません 実 際 に th:each ではオブジェクト 一 式 が 繰 り 返 し 可 能 だと 見 なされます java.util.iterable を 実 装 しているオブジェクト java.util.map を 実 装 しているオブジェクト マップを 繰 り 返 し 処 理 する 場 合 の 繰 り 返 し 変 数 は java.util.map.entry の クラスになります 配 列 その 他 のオブジェクトは そのオブジェクト 自 身 のみを 要 素 として 持 つ 1 要 素 だけのリストのように 扱 われます 6.2 繰 り 返 しステータスの 保 持 Page 31 of 84

th:each を 使 用 する 際 に 繰 り 返 し 処 理 中 のステータスを 知 るための 便 利 なメカニズムがThymeleafにはあります: ステータ ス 変 数 です ステータス 変 数 は th:each 属 性 の 中 で 定 義 され 次 の 内 容 を 保 持 しています: index プロパティ: 0 始 まりの 現 在 の 繰 り 返 しインデックス count プロパティ: 1 始 まりの 現 在 の 繰 り 返 しインデックス size プロパティ: 被 繰 り 返 し 変 数 の 全 要 素 数 current プロパティ: 繰 り 返 し 中 の 繰 り 返 し 変 数 even/odd 真 偽 値 プロパティ: 現 在 の 繰 り 返 し 処 理 が 偶 数 か 奇 数 か first 真 偽 値 プロパティ: 現 在 の 繰 り 返 し 処 理 が 最 初 かどうか last 真 偽 値 プロパティ: 現 在 の 繰 り 返 し 処 理 が 最 後 かどうか ではどのように 使 用 するのかを 前 回 の 例 で 見 てみましょう: <table> <tr> <th>name</th> <th>price</th> <th>in STOCK</th> <tr th:each="prod,iterstat : ${prods}" th:class="${iterstat.odd}? 'odd'"> <td th:text="${prod.name}">onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.instock}? #{true} : #{false}">yes</td> </table> ご 覧 のとおり th:each 属 性 の 中 で 繰 り 返 し 変 数 の 後 ろにカンマで 区 切 って 名 前 を 書 いてステータス 変 数 (この 例 では iterstat )を 定 義 します 繰 り 返 し 変 数 と 同 様 ステータス 変 数 も th:each 属 性 を 持 っているタグによって 定 義 されたフラグ メントの 内 部 でのみ 使 用 可 能 です それでは テンプレートの 処 理 結 果 を 見 てみましょう: Page 32 of 84

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>good Thymes Virtual Grocery</title> <meta content="text/html; charset=utf-8" http-equiv="content-type"/> <link rel="stylesheet" type="text/css" media="all" href="/gtvg/css/gtvg.css" /> </head> <body> <h1>product list</h1> <table> <tr> <th colspan="1" rowspan="1">name</th> <th colspan="1" rowspan="1">price</th> <th colspan="1" rowspan="1">in STOCK</th> <tr> <td colspan="1" rowspan="1">fresh Sweet Basil</td> <td colspan="1" rowspan="1">4.99</td> <td colspan="1" rowspan="1">yes</td> <tr class="odd"> <td colspan="1" rowspan="1">italian Tomato</td> <td colspan="1" rowspan="1">1.25</td> <td colspan="1" rowspan="1">no</td> <tr> <td colspan="1" rowspan="1">yellow Bell Pepper</td> <td colspan="1" rowspan="1">2.50</td> <td colspan="1" rowspan="1">yes</td> <tr class="odd"> <td colspan="1" rowspan="1">old Cheddar</td> <td colspan="1" rowspan="1">18.75</td> <td colspan="1" rowspan="1">yes</td> </table> <p> <a href="/gtvg/" shape="rect">return to home</a> </p> </body> </html> 繰 り 返 しステータス 変 数 は 完 璧 に 動 いていますね odd CSSクラスが 奇 数 行 のみに 適 用 されています( 行 番 号 は0から 始 まりま す) colspanとrowspan 属 性 が <td> タグに 追 加 されていますが これは <a> のshape 属 性 と 同 様 に 選 択 されている XHTML 1.0 Strict 標 準 のDTDに 従 ってThymeleafが 自 動 的 に 追 加 します XHTML 1.0 Strict 標 準 では これらの 値 が 属 性 のデフォルト 値 として 策 定 されています(テンプレートでは 値 を 設 定 していないことに 注 意 してください) ページの 表 示 には 影 響 はないので このことを 気 にする 必 要 は 全 然 ありません 例 えば HTML5(にはDTDがありませんが)を 使 用 していたら この 属 性 は 決 して 追 加 されません ステータス 変 数 を 明 示 的 に 指 定 しない 場 合 は 繰 り 返 し 変 数 の 後 ろに Stat をつけた 変 数 名 をThymeleafはいつでも 作 成 しま す: Page 33 of 84

<table> <tr> <th>name</th> <th>price</th> <th>in STOCK</th> <tr th:each="prod : ${prods}" th:class="${prodstat.odd}? 'odd'"> <td th:text="${prod.name}">onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.instock}? #{true} : #{false}">yes</td> </table> Page 34 of 84

7 条 件 の 評 価 7.1 単 純 な 条 件 : if と unless 特 定 の 条 件 が 満 たされる 場 合 にのみ フラグメントを 表 示 したい 場 合 があるでしょう 例 えば 商 品 テーブルの 各 商 品 に 対 してコメント 数 を 表 示 するカラムを 用 意 する 場 合 を 想 像 してみてください もしコメント があれば その 商 品 のコメント 詳 細 ページへのリンクを 貼 りたいです この 場 合 th:if 属 性 を 使 用 します: <table> <tr> <th>name</th> <th>price</th> <th>in STOCK</th> <th>comments</th> <tr th:each="prod : ${prods}" th:class="${prodstat.odd}? 'odd'"> <td th:text="${prod.name}">onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.instock}? #{true} : #{false}">yes</td> <td> <span th:text="${#lists.size(prod.comments)}">2</span> comment/s <a href="comments.html" th:href="@{/product/comments(prodid=${prod.id})}" th:if="${not #lists.isempty(prod.comments)}">view</a> </td> </table> 結 構 沢 山 のことをやっているので 重 要 な 行 にフォーカスしましょう: <a href="comments.html" th:href="@{/product/comments(prodid=${prod.id})}" th:if="${not #lists.isempty(prod.comments)}">view</a> 実 際 ほとんど 説 明 することはないですね: 商 品 の id を prodid パラメータに 設 定 してコメントページ( /product/comments ) へのリンクを 作 成 します でもそれは 商 品 にコメントがついている 場 合 だけです では 結 果 のマークアップを 見 てみましょう( 見 やすくするために デフォルト 属 性 の rowspan と colspan は 取 り 除 いていま す): Page 35 of 84

<table> <tr> <th>name</th> <th>price</th> <th>in STOCK</th> <th>comments</th> <tr> <td>fresh Sweet Basil</td> <td>4.99</td> <td>yes</td> <td> <span>0</span> comment/s </td> <tr class="odd"> <td>italian Tomato</td> <td>1.25</td> <td>no</td> <td> <span>2</span> comment/s <a href="/gtvg/product/comments?prodid=2">view</a> </td> <tr> <td>yellow Bell Pepper</td> <td>2.50</td> <td>yes</td> <td> <span>0</span> comment/s </td> <tr class="odd"> <td>old Cheddar</td> <td>18.75</td> <td>yes</td> <td> <span>1</span> comment/s <a href="/gtvg/product/comments?prodid=4">view</a> </td> </table> カンペキ!まさに 欲 しかったものです th:if 属 性 は boolean 条 件 のみを 評 価 するわけではないことに 注 意 して 下 さい もう 少 し 幅 広 いのです 次 のようなルールに 従 って 指 定 された 式 を true と 評 価 します: 値 が null ではない 場 合 : booleanの true 0 以 外 の 数 値 0 以 外 の 文 字 false でも off でも no でもない 文 字 列 真 偽 値 でも 数 値 でも 文 字 でも 文 字 列 でもない 場 合 ( 値 が null の 場 合 は th:if は false と 評 価 します). また th:if には 反 対 の 意 味 で 対 になるものがあります th:unless です 先 ほどの 例 で OGNL 式 の not を 使 用 する 代 わ りに これを 使 用 することもできます Page 36 of 84

<a href="comments.html" th:href="@{/comments(prodid=${prod.id})}" th:unless="${#lists.isempty(prod.comments)}">view</a> 7.2 スイッチ 文 Javaにおける switch 構 造 と 同 じように 使 用 して コンテンツを 条 件 毎 に 表 示 する 方 法 もあります: th:switch / th:case 属 性 のセットです ご 想 像 通 りの 動 きをします: <div th:switch="${user.role}"> <p th:case="'admin'">user is an administrator</p> <p th:case="#{roles.manager}">user is a manager</p> </div> 一 つの th:case 属 性 が true と 評 価 されるとすぐに 同 じスイッチコンテキスト 内 の 他 の 全 ての th:case 属 性 は false と 評 価 されることに 注 意 してください デフォルトオプションは th:case="*" で 指 定 します: <div th:switch="${user.role}"> <p th:case="'admin'">user is an administrator</p> <p th:case="#{roles.manager}">user is a manager</p> <p th:case="*">user is some other thing</p> </div> Page 37 of 84

8 テンプレートレイアウト 8.1 テンプレートフラグメントのインクルード フラグメントの 定 義 と 参 照 他 のテンプレートのフラグメントを 別 のテンプレートにインクルードしたいという 場 合 がよくあります よく 使 われるのは フッターやヘッダー メニューなどです そうするためにThymeleafではインクルード 可 能 なフラグメントを 定 義 する 必 要 があります 定 義 には th:fragment 属 性 を 使 用 します 私 たちの 食 料 品 店 の 全 てのページに 標 準 的 なコピーライトフッターを 追 加 したいとしましょう /WEB- INF/templates/footer.html ファイルにこのようなコードを 定 義 します: <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <body> <div th:fragment="copy"> 2011 The Good Thymes Virtual Grocery </div> </body> </html> このコードは copy と 呼 ばれるフラグメントを 定 義 しており 私 たちのホームページで th:include または th:replace 属 性 のどちらかを 使 用 して 簡 単 にインクルードすることができます: <body> <div th:include="footer :: copy"></div> </body> これらのインクルード 属 性 の 構 文 は 両 方 ともとても 直 感 的 です そのフォーマットには3 種 類 あります: "templatename::domselector" またはそれと 同 等 の templatename::[domselector] templatename という 名 前 のテンプレー ト 内 にある DOMセレクターで 指 定 されたフラグメントをインクルードします domselector はフラグメント 名 でも 大 丈 夫 なので 上 記 の 例 の footer :: copy のように 単 に templatename::fragmentname を 指 定 することもできることに 注 意 してください DOMセレクター 構 文 はXPath 表 現 やCSSセレクターと 似 ています 詳 しくは Appendix C を 参 照 してください "templatename" templatename という 名 前 のテンプレート 全 体 をインクルードします Page 38 of 84