SlideShare a Scribd company logo
1 of 13
Download to read offline
Mixer2 で作る 
カスタムテンプレートエンジン 
第八回#渋谷java 
Jun Futagawa (@jfut) 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 1
自己紹介 
 Jun Futagawa 
 有限会社インテグシステム 
 Twitter: @jfut 
 好きなこと: Linux サーバー・ネットワーク構築 
 今好きなフレームワーク: Cubby, S2JDBC, Mixer2 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 2
今日のお話 
 Mixer2 で作るカスタムテンプレートエンジン 
 素材: Mixer2 テンプレートエンジン 
 http://mixer2.org/ 
 作者: @nabedge さん 
 テンプレートファイルはHTML ファイル 
 HTML の構造をマッピングしたJava のクラスインスタンスに変換 
 HTML タグに対応する個別のJava クラス型を持つ 
 Java の世界でタグや値の合成操作 
 テンプレート記述言語を覚えなくて良い 
new Html(); 
new Body(); 
new Div(); new P() 
Html 
Head Body 
Div P 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 3
Mixer2: 利用例 
 HTML ファイルをMixer2 でインスタンス化、値を書き換えて出力 
<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
... <head /> 省略... 
<body> 
<article> 
<section> 
<h1>headline</h1> 
<p id="HERE.msg">here comes hello message</p> 
<span class="DEBUG">dummy span</span> 
<p class="DEBUG">dummy p</p> 
</section> 
</article> 
</body> 
<html> 
Mixer2Engine m2e = new Mixer2Engine(); 
Html html = m2e.loadHtmlTemplate(new File("hello.html")); 
H1 h1 = html.getDescendants(H1.class).get(0); 
h1.unsetContent(); 
h1.getContent().add("New Headline"); 
P p = html.getById("HERE.msg"); 
p.setId("msg"); 
p.unsetContent(); 
p.getContent().add("Hello World!"); 
// or html.removeDescendants("DEBUG"); 
List<AbstractJaxb> debugTagList = html.getDescendants("DEBUG"); 
for (AbstractJaxb abstractJaxb : debugTagList) { 
html.remove(abstractJaxb); 
} 
// タグで取得 
// コンテンツ削除 
// コンテンツ追加 
// id 属性で取得 
// id 属性の値を設定 
// コンテンツ削除 
// コンテンツ追加 
// ↓class 属性で取得 
// タグごと削除 
hello.html 
特別な記法のないHTML Java コードの例 
... 省略... 
<article> 
出力: m2e.saveToString(html); 
<section> 
<h1>New Headline</h1> 
<p id="msg">Hello World!</p> 
</section> 
</article> 
... 省略... 
DOM 操作ではないため 
判りやすい 
(ちょっと冗長ではある) 
* AbstractJaxb はMixer2 が持つHTML タグ用クラスのスーパークラス 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 4
カスタムテンプレートエンジン 
 なぜ? 
 Mixer2 はビューのHTML を全部Java で操作できる 
 でも、汎用部分を毎回Java で操作するのはさすがに手間 
 レイアウト・共通部品埋め込み 
 単なるリクエスト・セッションの値の出力 
 そこで 
 共通処理の記述はテンプレートファイルへ 
 <div id="機能名1">dummy div</div> 
 <p class="機能名2">dummy p</p> 
 Mixer2 でインスタンス化したhtml から機能名で該当タグを検索 
 AbstractJaxb tag = html.getById("機能名1"); 
 List<AbstractJaxb> tagList = html.getDescendants("機能名2"); 
 機能名に応じた処理を実行するヘルパークラスでタグや値を操作 
 ヘルパークラス群= カスタムテンプレートエンジン 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 5
Class ヘルパークラスの実装イメージ 
 テンプレートファイル 
<article> 
<section> 
<h1>headline</h1> 
<p id=" HERE.msg">here comes hello message</p> 
<span class="M_FUNC">dummy span</span> 
<p class=" M_FUNC ">dummy p</p> 
</section> 
</article> 
 ヘルパークラス実装 
String name = "M_FUNC"; 
... 
public <T extends AbstractJaxb> T replace(String path, String templatePath, T parent, HttpServletRequest request) { 
List<AbstractJaxb> abstractJaxbList = parent.getDescendants(name); 
for (AbstractJaxb abstractJaxb : abstractJaxbList) { 
... 機能に応じたインタスタンス操作... 
} 
return parent; 
} 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 6
ヘルパークラスのオプション値 
 機能によってはオプション値が必要 
 例: 値や条件式の指定 
 オプション値はHTML5 のdata-* 属性を利用すると便利 
 独自タグなし(独自data-* 属性は使う) 
 Class ヘルパーM_OUT 用のHTML テンプレート記述例: 
 .html: <span class="M_OUT" data-value="${ sessionScope.name }">dummy.name</span> 
 値の出力記述方法の比較 
 JSTL 例: 
 .jsp: <c:out value="${sessionScope.username }" /> 
 Thymeleaf の例 
 .html: <span th:text="${ session.username }">dummy.name</span> 
 Mayaa 例: 
 .html: <span id="name">dummy.name</span> 
 .mayaa: <m:writem:id="name" value="${ session.username }" /> 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 7
テンプレートエンジン実行例 
 Mixer2 を使用したView の処理時にまとめて実行 
 例: SpringWeb MVC: View クラス内 
 コントローラから対応するView 内で実行 
1. View に対応するテンプレートファイルからHtml インスタンス化(Mixer2) 
2. 事前処理ヘルパークラス群(カスタム) 
3. ページ固有のView 処理(Mixer2) 
4. 事後処理ヘルパークラス群(カスタム) 
処理イメージ 
Html html = m2e.loadHtmlTemplate(new File(templatePath)); 
/** 事前処理用共通ヘルパー群を適用します。*/ 
html = FunctionsHelper.getDefaultPreInstance().replaceAll(path, templatePath, html); 
...ページ固有のレンダリング処理をMixer2 のインスタンス操作で適用します。... 
/** 事後処理用共通ヘルパー群を適用します。*/ 
html = FunctionsHelper.getDefaultPostInstance().replaceAll(path, templatePath, html); 
ヘルパークラス群は事前に 
Map へ登録しておく 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 8
デモ実装 
 エンジン実装例: Spring Web MVC 依存 
 https://github.com/jfut/integ-web-spring-webmvc-mixer2 
 機能 
 M_ACTIVE_PATH 表示パスと同じ時にclass 属性へactive を追加 
 M_APP_NAME pom.xml の<name /> の値を出力 
 M_DEBUG デバッグモード時にデバッグ欄を作成して表示 
 M_DELETE レンダリング時に削除 
 M_EXPORT レイアウト機能 
 M_IF EL 式によるタグの表示・削除 
 M_IF_DEBUG バッグモード時のみ表示 
 M_INCLUDE 別のテンプレートファイルを埋め込む 
 M_LINK リンクアドレスの相対パスを解決 
 M_MESSAGE リソースファイルの値を出力 
 M_OUT リクエスト情報の値を出力、EL 式サポート 
 M_REQUEST_DEBUG リクエスト情報の値をすべて出力 
 M_VERSION pom.xml の<version /> の値を出力 
 利用例: Mixer2 のSpring Boot デモを修正 
 https://github.com/jfut/mixer2-sample/tree/custom-template 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 9
デモ実装利用例 
<span class="badge M_IF M_OUT" 
data-test="${ 0 != sessionScope.cart.getReadOnlyItemList().size() }" 
data-value="${ sessionScope.cart.totalAmount }"> 
dummy.10</span></a></li> 
<li class="M_ACTIVE_PATH" data-path="/"> 
<a class="M_LINK" data-href="../../" href="../../index.html"> 
ホーム</a></li> 
コンテンツファイル: /index.html (ここが起点) 
<div id="M_EXPORT" data-src="/component/layout/layout.html"> 
レイアウトファイル: /component/layout/layout.html 
<div id="M_EXPORT"></div> 
レイアウトファイル: /component/layout/layout.html 
<div class="M_INCLUDE" data-src="/component/layout/footer.html"> 
レイアウトファイル: /component/layout/layout.html 
<div class="M_INCLUDE" 
data-src="/component/layout/header.html"> 
z 
<a class="M_LINK" data-href="../../cart/view" href="../../cart.html">view cart</a> 
レイアウトファイル: /component/layout/layout.html 
<div class="M_INCLUDE" 
data-src="/component/layout/sidebar.html"> 
<span class="M_APP_NAME">dummy.appName</span> 
Version <span class="M_VERSION">x.y.z</span> 
<div class="M_REQUEST_DEBUG">dummy.M_REQUEST_DEBUG</div> 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 10
まとめ 
 Mixer2 
 HTML タグをすべてJava で操作可能 
 テンプレート記述言語を覚えなくて良い 
 レンダリング済みHTML のテストもJava で書ける= テスト簡単 
 参考: @nabedge さんのスライドたくさん: http://www.slideshare.net/nabedge 
 - さらばJSP - JAXBとテンプレートエンジンMixer2 など 
 Mixer2 の上にカスタムテンプレートエンジンが簡単に作れる 
 汎用部分の記述をテンプレートファイル側へ 
 独自のテンプレート記述言語(機能名、data-*属性)を覚えるデメリットはある 
 Mixer2 のインスタンス操作だけ、DOM 操作ツライがない 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 11
Thank You for Your Attention! 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 12
Mixer2 + テスト 
 Spring MVC 連携時のテスト 
@Test 
public void showItem_exists() throws Exception { 
// Mock とRequestMappingHandlerAdapter を使用してリクエストを再現し、ModelAndView を取得 
... 省略... 
request.setMethod("GET"); 
request.setRequestURI("/item/10001"); 
Object handler = handlerMapping.getHandler(request).getHandler(); 
ModelAndView modelAndView = handlerAdapter.handle(request, response, handler); 
// ViewName をテスト 
String viewName = modelAndView.getViewName(); 
assertThat(viewName, is("item")); 
// ビューをレンダリング 
// レンダリング時にビュークラスでテンプレートHTML ファイルをMixer2 でインスタンス化し、タグの書き換え、レスポンスに書き出す 
AbstractMixer2XhtmlView view = 
(AbstractMixer2XhtmlView)mixer2XhtmlViewResolver.resolveViewName(viewName, Locale.getDefault()); 
view.render(modelAndView.getModelMap(), request, response); 
// レンダリングに使用したhtml インスタンスをダイレクトにテスト 
Html renderedHtml = view.getRenderedHtml(); // or view.getHtml(); 
H1 itemNameH1 = renderedHtml.getById("itemName"); // テンプレート: <h1 id="itenName">dummy.header</h1> 
assertThat(itemNameH1.getContent().get(0).toString(), is("Apple")); // レンダリング後: <h1 id="itemName">Apple</h1> 
Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 13 
} 
* https://github.com/jfut/mixer2-sample/blob/custom-template/mixer2-fruitshop-springboot

More Related Content

What's hot

10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
 10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1 10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1kenjis
 
FuelPHPをさわってみて
FuelPHPをさわってみてFuelPHPをさわってみて
FuelPHPをさわってみてSotaro Omura
 
はじめての FuelPHP
はじめての FuelPHPはじめての FuelPHP
はじめての FuelPHPSho A
 
Web技術勉強会23回目
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目龍一 田中
 
20091030cakephphandson 01
20091030cakephphandson 0120091030cakephphandson 01
20091030cakephphandson 01Yusuke Ando
 
EC-CUBEプラグイン講義
EC-CUBEプラグイン講義EC-CUBEプラグイン講義
EC-CUBEプラグイン講義ria1201
 
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4bitter_fox
 
XPagesDay2015 - 誰も教えてくれなかったデバッグ方法
XPagesDay2015 - 誰も教えてくれなかったデバッグ方法XPagesDay2015 - 誰も教えてくれなかったデバッグ方法
XPagesDay2015 - 誰も教えてくれなかったデバッグ方法Mitsuru Katoh
 
Djangoによるスマホアプリバックエンドの実装
Djangoによるスマホアプリバックエンドの実装Djangoによるスマホアプリバックエンドの実装
Djangoによるスマホアプリバックエンドの実装Nakazawa Yuichi
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!Shohei Okada
 
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るEWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るKiyoshi Sawada
 
今、最も勢いのあるWebフレームワーク「fuel php」
今、最も勢いのあるWebフレームワーク「fuel php」今、最も勢いのあるWebフレームワーク「fuel php」
今、最も勢いのあるWebフレームワーク「fuel php」Soudai Sone
 
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャーssuser070fa9
 
FuelPHPで3種のprofilerを使ってみた
FuelPHPで3種のprofilerを使ってみたFuelPHPで3種のprofilerを使ってみた
FuelPHPで3種のprofilerを使ってみたKatsuhiro Miura
 
最近、僕がハマったFuelPHPの紹介
最近、僕がハマったFuelPHPの紹介最近、僕がハマったFuelPHPの紹介
最近、僕がハマったFuelPHPの紹介Naoto Mawatari
 
FuelPHP - フレームワーク4本勝負 @PHPカンファレンス関西2014
FuelPHP - フレームワーク4本勝負 @PHPカンファレンス関西2014 FuelPHP - フレームワーク4本勝負 @PHPカンファレンス関西2014
FuelPHP - フレームワーク4本勝負 @PHPカンファレンス関西2014 Mika Kane
 
Java SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にJava SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にTaku Miyakawa
 

What's hot (20)

HTML5最新動向
HTML5最新動向HTML5最新動向
HTML5最新動向
 
10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
 10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1 10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
 
FuelPHPをさわってみて
FuelPHPをさわってみてFuelPHPをさわってみて
FuelPHPをさわってみて
 
はじめての FuelPHP
はじめての FuelPHPはじめての FuelPHP
はじめての FuelPHP
 
Web技術勉強会23回目
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目
 
20091030cakephphandson 01
20091030cakephphandson 0120091030cakephphandson 01
20091030cakephphandson 01
 
HTML5&API総まくり
HTML5&API総まくりHTML5&API総まくり
HTML5&API総まくり
 
EC-CUBEプラグイン講義
EC-CUBEプラグイン講義EC-CUBEプラグイン講義
EC-CUBEプラグイン講義
 
PHP勉強会 #51
PHP勉強会 #51PHP勉強会 #51
PHP勉強会 #51
 
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
 
XPagesDay2015 - 誰も教えてくれなかったデバッグ方法
XPagesDay2015 - 誰も教えてくれなかったデバッグ方法XPagesDay2015 - 誰も教えてくれなかったデバッグ方法
XPagesDay2015 - 誰も教えてくれなかったデバッグ方法
 
Djangoによるスマホアプリバックエンドの実装
Djangoによるスマホアプリバックエンドの実装Djangoによるスマホアプリバックエンドの実装
Djangoによるスマホアプリバックエンドの実装
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!
 
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るEWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
 
今、最も勢いのあるWebフレームワーク「fuel php」
今、最も勢いのあるWebフレームワーク「fuel php」今、最も勢いのあるWebフレームワーク「fuel php」
今、最も勢いのあるWebフレームワーク「fuel php」
 
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
 
FuelPHPで3種のprofilerを使ってみた
FuelPHPで3種のprofilerを使ってみたFuelPHPで3種のprofilerを使ってみた
FuelPHPで3種のprofilerを使ってみた
 
最近、僕がハマったFuelPHPの紹介
最近、僕がハマったFuelPHPの紹介最近、僕がハマったFuelPHPの紹介
最近、僕がハマったFuelPHPの紹介
 
FuelPHP - フレームワーク4本勝負 @PHPカンファレンス関西2014
FuelPHP - フレームワーク4本勝負 @PHPカンファレンス関西2014 FuelPHP - フレームワーク4本勝負 @PHPカンファレンス関西2014
FuelPHP - フレームワーク4本勝負 @PHPカンファレンス関西2014
 
Java SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にJava SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心に
 

Viewers also liked

日本語によるJUnitの拡張について
日本語によるJUnitの拡張について日本語によるJUnitの拡張について
日本語によるJUnitの拡張についてKazuro Fukuhara
 
201311 webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園
201311 webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園201311 webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園
201311 webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園Y Watanabe
 
Javaでやってみる The Twelve Factor App JJUG-CCC 2014 Fall 講演資料
Javaでやってみる The Twelve Factor App JJUG-CCC 2014 Fall 講演資料Javaでやってみる The Twelve Factor App JJUG-CCC 2014 Fall 講演資料
Javaでやってみる The Twelve Factor App JJUG-CCC 2014 Fall 講演資料Y Watanabe
 
20140405 mavenセントラルリポジトリへの登録のコツ 第5回渋谷java
20140405 mavenセントラルリポジトリへの登録のコツ 第5回渋谷java20140405 mavenセントラルリポジトリへの登録のコツ 第5回渋谷java
20140405 mavenセントラルリポジトリへの登録のコツ 第5回渋谷javaY Watanabe
 
渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと
渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと
渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なことY Watanabe
 
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)sogdice
 

Viewers also liked (6)

日本語によるJUnitの拡張について
日本語によるJUnitの拡張について日本語によるJUnitの拡張について
日本語によるJUnitの拡張について
 
201311 webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園
201311 webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園201311 webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園
201311 webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園
 
Javaでやってみる The Twelve Factor App JJUG-CCC 2014 Fall 講演資料
Javaでやってみる The Twelve Factor App JJUG-CCC 2014 Fall 講演資料Javaでやってみる The Twelve Factor App JJUG-CCC 2014 Fall 講演資料
Javaでやってみる The Twelve Factor App JJUG-CCC 2014 Fall 講演資料
 
20140405 mavenセントラルリポジトリへの登録のコツ 第5回渋谷java
20140405 mavenセントラルリポジトリへの登録のコツ 第5回渋谷java20140405 mavenセントラルリポジトリへの登録のコツ 第5回渋谷java
20140405 mavenセントラルリポジトリへの登録のコツ 第5回渋谷java
 
渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと
渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと
渋谷java−あなたのプロジェクトで気軽にjavaをバージョンアップするために必要なこと
 
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)
 

Similar to Mixer2 で作るカスタムテンプレートエンジン #渋谷java

WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~hokori matu
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略takezoe
 
エンタープライズ分野での実践AngularJS
エンタープライズ分野での実践AngularJSエンタープライズ分野での実践AngularJS
エンタープライズ分野での実践AngularJSAyumi Goto
 
Ruby on Rails Tutorial
Ruby on Rails TutorialRuby on Rails Tutorial
Ruby on Rails TutorialKen Iiboshi
 
C#で作成するfacebookアプリ mvp community camp
C#で作成するfacebookアプリ mvp community campC#で作成するfacebookアプリ mvp community camp
C#で作成するfacebookアプリ mvp community campShinichi Hirauchi
 
jQuery と MVC で実践する標準志向 Web 開発
jQuery と MVC で実践する標準志向 Web 開発jQuery と MVC で実践する標準志向 Web 開発
jQuery と MVC で実践する標準志向 Web 開発Akira Inoue
 
ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~Yoshitaka Seo
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!Shinpei Ohtani
 
symfonyで汎用設定値を読み書きするモデル等をプラグインにした話
symfonyで汎用設定値を読み書きするモデル等をプラグインにした話symfonyで汎用設定値を読み書きするモデル等をプラグインにした話
symfonyで汎用設定値を読み書きするモデル等をプラグインにした話Hidenori Goto
 
ゼロからつくるWord pressテーマ第6回
ゼロからつくるWord pressテーマ第6回ゼロからつくるWord pressテーマ第6回
ゼロからつくるWord pressテーマ第6回Hitsuji
 
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例Yoshifumi Kawai
 
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)Hiroaki KOBAYASHI
 
Elasticsearchプラグインの作り方
Elasticsearchプラグインの作り方Elasticsearchプラグインの作り方
Elasticsearchプラグインの作り方Shinsuke Sugaya
 
Spring Framework ふりかえりと4.3新機能
Spring Framework ふりかえりと4.3新機能Spring Framework ふりかえりと4.3新機能
Spring Framework ふりかえりと4.3新機能kimulla
 
Geeklog2.1新機能紹介 20140723
Geeklog2.1新機能紹介 20140723Geeklog2.1新機能紹介 20140723
Geeklog2.1新機能紹介 20140723Tetsuko Komma
 
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
jvmlang.daitokai 1.0.0 MinCamlJを作ってみたjvmlang.daitokai 1.0.0 MinCamlJを作ってみた
jvmlang.daitokai 1.0.0 MinCamlJを作ってみたKazuyoshi Kamitsukasa
 

Similar to Mixer2 で作るカスタムテンプレートエンジン #渋谷java (20)

WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略
 
エンタープライズ分野での実践AngularJS
エンタープライズ分野での実践AngularJSエンタープライズ分野での実践AngularJS
エンタープライズ分野での実践AngularJS
 
Ruby on Rails Tutorial
Ruby on Rails TutorialRuby on Rails Tutorial
Ruby on Rails Tutorial
 
C#で作成するfacebookアプリ mvp community camp
C#で作成するfacebookアプリ mvp community campC#で作成するfacebookアプリ mvp community camp
C#で作成するfacebookアプリ mvp community camp
 
jQuery と MVC で実践する標準志向 Web 開発
jQuery と MVC で実践する標準志向 Web 開発jQuery と MVC で実践する標準志向 Web 開発
jQuery と MVC で実践する標準志向 Web 開発
 
ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~
 
WordPress と Bootstrap
WordPress と BootstrapWordPress と Bootstrap
WordPress と Bootstrap
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!
 
symfonyで汎用設定値を読み書きするモデル等をプラグインにした話
symfonyで汎用設定値を読み書きするモデル等をプラグインにした話symfonyで汎用設定値を読み書きするモデル等をプラグインにした話
symfonyで汎用設定値を読み書きするモデル等をプラグインにした話
 
Ext.direct
Ext.directExt.direct
Ext.direct
 
Vue入門
Vue入門Vue入門
Vue入門
 
ゼロからつくるWord pressテーマ第6回
ゼロからつくるWord pressテーマ第6回ゼロからつくるWord pressテーマ第6回
ゼロからつくるWord pressテーマ第6回
 
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
 
Inside Movable Type
Inside Movable TypeInside Movable Type
Inside Movable Type
 
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
 
Elasticsearchプラグインの作り方
Elasticsearchプラグインの作り方Elasticsearchプラグインの作り方
Elasticsearchプラグインの作り方
 
Spring Framework ふりかえりと4.3新機能
Spring Framework ふりかえりと4.3新機能Spring Framework ふりかえりと4.3新機能
Spring Framework ふりかえりと4.3新機能
 
Geeklog2.1新機能紹介 20140723
Geeklog2.1新機能紹介 20140723Geeklog2.1新機能紹介 20140723
Geeklog2.1新機能紹介 20140723
 
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
jvmlang.daitokai 1.0.0 MinCamlJを作ってみたjvmlang.daitokai 1.0.0 MinCamlJを作ってみた
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
 

Recently uploaded

TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成Hiroshi Tomioka
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 

Recently uploaded (9)

TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 

Mixer2 で作るカスタムテンプレートエンジン #渋谷java

  • 1. Mixer2 で作る カスタムテンプレートエンジン 第八回#渋谷java Jun Futagawa (@jfut) Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 1
  • 2. 自己紹介  Jun Futagawa  有限会社インテグシステム  Twitter: @jfut  好きなこと: Linux サーバー・ネットワーク構築  今好きなフレームワーク: Cubby, S2JDBC, Mixer2 Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 2
  • 3. 今日のお話  Mixer2 で作るカスタムテンプレートエンジン  素材: Mixer2 テンプレートエンジン  http://mixer2.org/  作者: @nabedge さん  テンプレートファイルはHTML ファイル  HTML の構造をマッピングしたJava のクラスインスタンスに変換  HTML タグに対応する個別のJava クラス型を持つ  Java の世界でタグや値の合成操作  テンプレート記述言語を覚えなくて良い new Html(); new Body(); new Div(); new P() Html Head Body Div P Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 3
  • 4. Mixer2: 利用例  HTML ファイルをMixer2 でインスタンス化、値を書き換えて出力 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> ... <head /> 省略... <body> <article> <section> <h1>headline</h1> <p id="HERE.msg">here comes hello message</p> <span class="DEBUG">dummy span</span> <p class="DEBUG">dummy p</p> </section> </article> </body> <html> Mixer2Engine m2e = new Mixer2Engine(); Html html = m2e.loadHtmlTemplate(new File("hello.html")); H1 h1 = html.getDescendants(H1.class).get(0); h1.unsetContent(); h1.getContent().add("New Headline"); P p = html.getById("HERE.msg"); p.setId("msg"); p.unsetContent(); p.getContent().add("Hello World!"); // or html.removeDescendants("DEBUG"); List<AbstractJaxb> debugTagList = html.getDescendants("DEBUG"); for (AbstractJaxb abstractJaxb : debugTagList) { html.remove(abstractJaxb); } // タグで取得 // コンテンツ削除 // コンテンツ追加 // id 属性で取得 // id 属性の値を設定 // コンテンツ削除 // コンテンツ追加 // ↓class 属性で取得 // タグごと削除 hello.html 特別な記法のないHTML Java コードの例 ... 省略... <article> 出力: m2e.saveToString(html); <section> <h1>New Headline</h1> <p id="msg">Hello World!</p> </section> </article> ... 省略... DOM 操作ではないため 判りやすい (ちょっと冗長ではある) * AbstractJaxb はMixer2 が持つHTML タグ用クラスのスーパークラス Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 4
  • 5. カスタムテンプレートエンジン  なぜ?  Mixer2 はビューのHTML を全部Java で操作できる  でも、汎用部分を毎回Java で操作するのはさすがに手間  レイアウト・共通部品埋め込み  単なるリクエスト・セッションの値の出力  そこで  共通処理の記述はテンプレートファイルへ  <div id="機能名1">dummy div</div>  <p class="機能名2">dummy p</p>  Mixer2 でインスタンス化したhtml から機能名で該当タグを検索  AbstractJaxb tag = html.getById("機能名1");  List<AbstractJaxb> tagList = html.getDescendants("機能名2");  機能名に応じた処理を実行するヘルパークラスでタグや値を操作  ヘルパークラス群= カスタムテンプレートエンジン Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 5
  • 6. Class ヘルパークラスの実装イメージ  テンプレートファイル <article> <section> <h1>headline</h1> <p id=" HERE.msg">here comes hello message</p> <span class="M_FUNC">dummy span</span> <p class=" M_FUNC ">dummy p</p> </section> </article>  ヘルパークラス実装 String name = "M_FUNC"; ... public <T extends AbstractJaxb> T replace(String path, String templatePath, T parent, HttpServletRequest request) { List<AbstractJaxb> abstractJaxbList = parent.getDescendants(name); for (AbstractJaxb abstractJaxb : abstractJaxbList) { ... 機能に応じたインタスタンス操作... } return parent; } Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 6
  • 7. ヘルパークラスのオプション値  機能によってはオプション値が必要  例: 値や条件式の指定  オプション値はHTML5 のdata-* 属性を利用すると便利  独自タグなし(独自data-* 属性は使う)  Class ヘルパーM_OUT 用のHTML テンプレート記述例:  .html: <span class="M_OUT" data-value="${ sessionScope.name }">dummy.name</span>  値の出力記述方法の比較  JSTL 例:  .jsp: <c:out value="${sessionScope.username }" />  Thymeleaf の例  .html: <span th:text="${ session.username }">dummy.name</span>  Mayaa 例:  .html: <span id="name">dummy.name</span>  .mayaa: <m:writem:id="name" value="${ session.username }" /> Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 7
  • 8. テンプレートエンジン実行例  Mixer2 を使用したView の処理時にまとめて実行  例: SpringWeb MVC: View クラス内  コントローラから対応するView 内で実行 1. View に対応するテンプレートファイルからHtml インスタンス化(Mixer2) 2. 事前処理ヘルパークラス群(カスタム) 3. ページ固有のView 処理(Mixer2) 4. 事後処理ヘルパークラス群(カスタム) 処理イメージ Html html = m2e.loadHtmlTemplate(new File(templatePath)); /** 事前処理用共通ヘルパー群を適用します。*/ html = FunctionsHelper.getDefaultPreInstance().replaceAll(path, templatePath, html); ...ページ固有のレンダリング処理をMixer2 のインスタンス操作で適用します。... /** 事後処理用共通ヘルパー群を適用します。*/ html = FunctionsHelper.getDefaultPostInstance().replaceAll(path, templatePath, html); ヘルパークラス群は事前に Map へ登録しておく Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 8
  • 9. デモ実装  エンジン実装例: Spring Web MVC 依存  https://github.com/jfut/integ-web-spring-webmvc-mixer2  機能  M_ACTIVE_PATH 表示パスと同じ時にclass 属性へactive を追加  M_APP_NAME pom.xml の<name /> の値を出力  M_DEBUG デバッグモード時にデバッグ欄を作成して表示  M_DELETE レンダリング時に削除  M_EXPORT レイアウト機能  M_IF EL 式によるタグの表示・削除  M_IF_DEBUG バッグモード時のみ表示  M_INCLUDE 別のテンプレートファイルを埋め込む  M_LINK リンクアドレスの相対パスを解決  M_MESSAGE リソースファイルの値を出力  M_OUT リクエスト情報の値を出力、EL 式サポート  M_REQUEST_DEBUG リクエスト情報の値をすべて出力  M_VERSION pom.xml の<version /> の値を出力  利用例: Mixer2 のSpring Boot デモを修正  https://github.com/jfut/mixer2-sample/tree/custom-template Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 9
  • 10. デモ実装利用例 <span class="badge M_IF M_OUT" data-test="${ 0 != sessionScope.cart.getReadOnlyItemList().size() }" data-value="${ sessionScope.cart.totalAmount }"> dummy.10</span></a></li> <li class="M_ACTIVE_PATH" data-path="/"> <a class="M_LINK" data-href="../../" href="../../index.html"> ホーム</a></li> コンテンツファイル: /index.html (ここが起点) <div id="M_EXPORT" data-src="/component/layout/layout.html"> レイアウトファイル: /component/layout/layout.html <div id="M_EXPORT"></div> レイアウトファイル: /component/layout/layout.html <div class="M_INCLUDE" data-src="/component/layout/footer.html"> レイアウトファイル: /component/layout/layout.html <div class="M_INCLUDE" data-src="/component/layout/header.html"> z <a class="M_LINK" data-href="../../cart/view" href="../../cart.html">view cart</a> レイアウトファイル: /component/layout/layout.html <div class="M_INCLUDE" data-src="/component/layout/sidebar.html"> <span class="M_APP_NAME">dummy.appName</span> Version <span class="M_VERSION">x.y.z</span> <div class="M_REQUEST_DEBUG">dummy.M_REQUEST_DEBUG</div> Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 10
  • 11. まとめ  Mixer2  HTML タグをすべてJava で操作可能  テンプレート記述言語を覚えなくて良い  レンダリング済みHTML のテストもJava で書ける= テスト簡単  参考: @nabedge さんのスライドたくさん: http://www.slideshare.net/nabedge  - さらばJSP - JAXBとテンプレートエンジンMixer2 など  Mixer2 の上にカスタムテンプレートエンジンが簡単に作れる  汎用部分の記述をテンプレートファイル側へ  独自のテンプレート記述言語(機能名、data-*属性)を覚えるデメリットはある  Mixer2 のインスタンス操作だけ、DOM 操作ツライがない Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 11
  • 12. Thank You for Your Attention! Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 12
  • 13. Mixer2 + テスト  Spring MVC 連携時のテスト @Test public void showItem_exists() throws Exception { // Mock とRequestMappingHandlerAdapter を使用してリクエストを再現し、ModelAndView を取得 ... 省略... request.setMethod("GET"); request.setRequestURI("/item/10001"); Object handler = handlerMapping.getHandler(request).getHandler(); ModelAndView modelAndView = handlerAdapter.handle(request, response, handler); // ViewName をテスト String viewName = modelAndView.getViewName(); assertThat(viewName, is("item")); // ビューをレンダリング // レンダリング時にビュークラスでテンプレートHTML ファイルをMixer2 でインスタンス化し、タグの書き換え、レスポンスに書き出す AbstractMixer2XhtmlView view = (AbstractMixer2XhtmlView)mixer2XhtmlViewResolver.resolveViewName(viewName, Locale.getDefault()); view.render(modelAndView.getModelMap(), request, response); // レンダリングに使用したhtml インスタンスをダイレクトにテスト Html renderedHtml = view.getRenderedHtml(); // or view.getHtml(); H1 itemNameH1 = renderedHtml.getById("itemName"); // テンプレート: <h1 id="itenName">dummy.header</h1> assertThat(itemNameH1.getContent().get(0).toString(), is("Apple")); // レンダリング後: <h1 id="itemName">Apple</h1> Mixer2 で作るカスタムテンプレートエンジン, September 20, 2014 13 } * https://github.com/jfut/mixer2-sample/blob/custom-template/mixer2-fruitshop-springboot