Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
SpringMVCとmixer2で作るWebアプリのキホン
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Yu Watanabe
January 24, 2013
Technology
130
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
SpringMVCとmixer2で作る Webアプリのキホン
WebデザイナーフレンドリーなJavaテンプレートエンジン"Mixer2"と、SpringMVCフレームワークを組み合わせての開発
Yu Watanabe
January 24, 2013
More Decks by Yu Watanabe
See All by Yu Watanabe
JUnitテストをCI環境で並列で実行する方法とその速度, スケーラビリティ
nabedge
6
3k
クラウド時代だからSpring-Retryフレームワーク
nabedge
0
330
ツール比較しながら語るO/RマッパーとDBマイグレーション
nabedge
0
190
JavaでWebサービスを作り続けるための戦略と戦術
nabedge
0
120
サーバーサイドな人がフロントエンド技術と仲良くするはじめの一歩
nabedge
0
90
Selenium再入門
nabedge
0
82
Webエンジニアがスタートダッシュをキメるためのローカル開発環境の勘所
nabedge
0
97
テストゼロからイチに進むための戦略と戦術
nabedge
0
110
jOOQってなんて読むの?から始めるSpringBootとO/Rマッパーの世界
nabedge
0
180
Other Decks in Technology
See All in Technology
M5Stackで作る BLEマウス GPSログの世界
tomokusaba
0
420
エンタメ企業のM&Aを支えるデータ基盤 ― 統合から店舗のリアルタイム分析まで / Data Engineering Summit 2026
genda
0
180
『SAR衛星データ解析入門』のご紹介とその応用
syuchimu
0
120
フロントエンドカンファレンス関西2026 - 速すぎるUIに、待ち時間を
teamlab
PRO
0
130
「事実」を「計測」して、「解釈」する 〜AWS Lambdaのメモリ最適解の見つけ方〜
maimyyym
0
170
宣言型部分更新は何を解決しどこへ向かうのか
shuta13
1
460
大型犬好きによるPugの紹介
yamanoku
1
160
触りたくないデータに、どう触るか AI時代のRBACアクセスガバナンス
ivry_presentationmaterials
0
260
TinyGoでオブザーバビリティ?OpenTelemetryはTinyGoで使えるのか / Is OpenTelemetry available in TinyGo environment?
ymotongpoo
2
140
DWH の限界突破! AI エージェント向け爆速リアルタイムデータ基盤 ClickHouse
jozono
1
470
AI × アーキテクト 第1・2章|生成AIの課題とアーキテクトの素養
daidaidai
0
170
QA4AI 2026-Oct 生成AI時代の品質保証
tokuty
1
860
Featured
See All Featured
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
410
Why Our Code Smells
bkeepers
PRO
340
58k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
460
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
800
Faster Mobile Websites
deanohume
310
32k
Unsuck your backbone
ammeep
672
58k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
7k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
1
280
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
710
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
750
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
930
Transcript
SpringMVCとmixer2で作る Webアプリのキホン Basic Web Application with SpringMVC & mixer2 Spring勉強会
by #JSUG at VMWare-Japan 2013-01-24
プロローグ PROLOGUE 2
クリスマスイブのとあるツイート 3
MacBookじゃなくてスイマセン... 4
SpringMVCとmixer2で作る Webアプリのキホン なんかこのタイトルもダサく 思えてきた...
とりあえずタイトル変えてみる!
Webデザイナーさんと 仲良く仕事するための SpringMVCとmixer2 2013-01-24 Spring勉強会
自己紹介 • わたなべ • SI屋の技術屋さん • @nabedge •
[email protected]
•
http://nabedge.blogspot.jp/ 8
目次 1. SpringMVC 2. テンプレートエンジン 3. Mixer2をHelloWorldで解説 4. Why mixer2
? 5. SpringMVCとmixer2の組み合わせの勘所 6. コントローラとビューに対するテスト 7. Webアプリの分割開発 8. まとめ 9. FAQ 9
10 1. Spring MVC
SpringMVC • JavaでWebアプリをつくりためのMVCフレー ムワーク。 • 生のサーブレット&JSPで作るより100倍作り やすい。 • 大昔のStrutsより10倍は学習しやすい •
ライバルとしてはSeasarのSAStrutsとか。 • Spring3.Xになって以降はSAStrutsよりもさら に使いやすくなった! • 詳しくは「Spring3入門」を読みましょう。 11
12 2. テンプレートエンジン
テンプレートエンジン 13 JSP:一番身近なテンプレートエンジン こんにちは <% if (name == null) {
%> ゲストさん <% } else { %> <%= name %>さん <% } %> 通常のJava言語、EL式、カスタムタグで書く
テンプレートエンジン 14 Velocity:Javaでは老舗のテンプレートエンジン こんにちは #if (name == null) { ゲストさん
#else ${name}さん #end VTL = Velocity Template Languageで書く
テンプレートエンジン 15 FreeMarker:最近人気のテンプレートエンジン こんにちは <#if name?has_content> ${name}さん <#else> ゲストさん </#if>
FTL = Freemarker Template Languageで書く
テンプレートエンジン 16 Mixer2:Webデザイナーと仲良く仕事するため のテンプレートエンジン こんにちは <span id=“name”>ななし</span>さん String name =
“ヤマダ”; Span span = html.getById(“name”, Span.class); span.getContent.clear(); span.getContent.add(name); // これで <span id=“name”>ヤマダ</span>さん // になる テンプレートファイル(*.html)は純粋なXHTMLとCSS 値の埋め込みやロジックは普通のJavaで書く(*.java)
17 3. mixer2を HelloWorld(SpringMVC編) で解説 http://mixer2.org/site/springmvcsample.html
補足:タグとJava型 18 <html>…</html> ⇔ org.mixer2.jaxb.xhtml.Html <div>…</div> ⇔ org.mixer2.jaxb.xhtml.Div (ほか全120種類くらいのタグすべてを実装済み) HTMLタグとJavaオブジェクトを相互マッピング
タグの属性はJavaオブジェクトのプロパティにマッピング。 setter/getterメソッドでアクセス <div id=“foo”>…</div> をテンプレートとしてロードすると String id = div.getId(); // これでidに”foo”が入る (html4/5のすべての属性を実装済み)
補足:複数要素はListになる 19 <html> <body> <p>Hello World</p> foo <span>bar</span> </body> </html>
index 型 0 P 1 String 2 Span Html html = mixer2Engine .loadHtmlTemplate( “template.html”); java.util.List<Object> list = html.getBody() .getContent(); listの中身 template.html
ちょっと一息 20 •水分補給 •時間を確認 10分か15分くらい?
21 4. Why mixer2 ?
最大のメリット 22 htmlモックアップを JSPに書き変えずに そのまま使える
23 デモ (フルーツショップサンプルアプリ編) https://github.com/nabedge/mixer2- sample/tree/master/mixer2-fruitshop-springmvc 「github mixer2-fruitshop-springmvc」 でググるとすぐ見つかります。
24 5. Mixer2とSpringMVCを 組み合わせる場合の勘所
勘所 1. コントローラクラスの肥大化を防ぐ 2. aタグやimgタグの相対パスの書き換え 3. <mvc:resources />で静的リソースを出 力 4.
上の2,3を生かすためのおススメディレ クトリ構造 25
26 コントローラクラスの肥大化を防ぐ
ふつうのコントローラとJSP 27 @Controller public class ItemController { @RequestMapping(value = "/item/{itemId}")
public ModelAndView showItem(@PathVariable long itemId) { // DBから商品情報を取得 Item item = itemService.getItem(itemId); // modelAndViewにitemを詰めて返す retern new ModelAndView(“item.jsp”, “item”, item); } <%@page pageEncoding="UTF-8"%> <html> <body> <span>商品名:${item.name}</span> </body> </html> 商品情報を表示するコントローラクラス JSP
コントローラの肥大化を防ぐ 28 @RequestMapping(value = "/item/{itemId}") public ModelAndView showItem(@PathVariable long itemId)
{ // DBから商品情報を取得 Item item = itemService.getItem(itemId); // テンプレートのロード String mainTemplate = "classpath:m2mockup/m2template/item.html" File file = ResourceUtils.getFile(mainTemplate); Html html = mixer2Engine.loadHtmlTemplate(file); // 商品情報のdivタグ Div itemBox = html.getBody().getById("itemBox", Div.class); // 商品名を書き込む itemBox.getById("itemName", H1.class).getContent().clear(); itemBox.getById("itemName", H1.class).getContent().add(item.getName()); // 価格、説明、その他もろもろも... このへんが肥大化 してしまう
コントローラの肥大化を防ぐ 29 @RequestMapping(value = "/item/{itemId}") public ModelAndView showItem(@PathVariable long itemId)
{ // DBから商品情報を取得 Item item = itemService.getItem(itemId); // テンプレートのロード String mainTemplate = "classpath:m2mockup/m2template/item.html" File file = ResourceUtils.getFile(mainTemplate); Html html = mixer2Engine.loadHtmlTemplate(file); // 商品情報を埋め込む ItemHelper.replaceItemBox(html, item); …… ヘルパークラスに切り 出せば1行で済む
コントローラの肥大化を防ぐ 30 public class ItemHelper { public static void replaceItemBox(Html
html, Item item) { // 商品情報を入れるdivタグを取得 Div itemBox = html.getBody().getById("itemBox", Div.class); // divの中のH1やSpanの中にDBから取得した値を入れる itemBox.getById("itemName", H1.class).getContent().clear(); itemBox.getById("itemName", H1.class).getContent().add(item.getName()); itemBox.getById("itemPrice", Span.class).getContent().clear(); itemBox.getById("itemPrice", Span.class).getContent().add( item.getPrice().toString()); itemBox.getById("itemDescription", Div.class).getContent().clear(); itemBox.getById("itemDescription", Div.class).getContent().add( item.getDescription()); ヘルパーはごく単純なstaticメソッドでよい テンプレのhtml DBから取得した商品情報
相対パスの書き換え 31 <a class=“topPageAnchor” href="../m2template/index.html"> <img src="../m2static/img/fruitshop-logo.png" /> </a> 左上のロゴはトップページへ
のリンク テンプレートファイルではこうなってるけど <a class=“topPageAnchor” href=“/[contextPath]/"> <img src="/[contextPath]/m2static/img/fruitshop-logo.png" /> </a> 実際の出力ではこうしなきゃならない
相対パスの書き換え 32 String ctx = "xxx"; // コンテキストパスを取得しておく for (A
a : html.getDescendants("topPageAnchor", A.class)) { a.setHref(ctx + "/"); } “topPageAnchor”というclass属性を持つすべてのaタグのhref属 性を書き変える Mixer2ではすべてのタグ型が下記のメソッドを持っている • getDescendants()メソッド:該当するすべての子孫タグをList で取得 • getById()メソッド:id属性でタグを1個だけ取得 • 他にもreplace系とかremove系のメソッドもあります。
相対パスの書き換え 33 // <img src="" /> for (Img img :
tagObj.getDescendants(Img.class)) { if (img.isSetSrc()) { String src = img.getSrc(); img.setSrc(convertPath(src)); } } Imgタグのsrc属性、styleタグのhref属性なども同様 convertPathメソッドは、 ../m2static/ のような文字列を /[contextPath]/m2static/ に置換している
34 <mvc:resources />で 静的リソースを出力
Java/Webアプリでの静的ファイルの配置 35 http://localhost:8080/[contextPath]/foo/bar.png src └─main ├─java ├─resources └─webapp └─foo └─bar.png
※maven標準ディレクトリ構造です 普通ならdocroot配下に置く。 さもないとブラウザからアク セス不可能
Java/Webアプリでの静的ファイルの配置 36 src └─main ├─java ├─resources │ │ applicationContext.xml │
│ │ └─m2mockup │ ├─m2static │ │ └─img │ │ logo.png │ │ │ └─m2template │ index.html │ item.html │ └─webapp テンプレートhtmlと画像 やCSSをまとめて resources配下に置く。 クラスパス上に置くほう が、Javaコードから扱い やすいから!
DispatcherServletのstatic resource機能 • Spring3.X以降、DispatcherServletは、http リクエストをコントローラクラスに中継する機 能だけでなく、静的リソースを直接レスポンス する機能がある 37
Java/Webアプリでの静的ファイルの配置 38 <mvc:resources mapping="/m2static/**" location="classpath:/m2mockup/m2static/" cache-period="60" /> src/main/resources/mvc-dispatcher-servlet.xml の抜粋 1.
http://.../contextPath/m2static/** というURLへの アクセスに対して 2. クラスパスから /m2mockup/m2static/** というリ ソースを探してそれを返す 3. そのとき Cache-Control: max-age=60 のような httpレスポンスヘッダつきで返す
ただし、注意しないと、、、! 39 src └─main ├─java ├─resources │ └─m2mockup │ ├─img
│ │ logo.png │ └─item.html └─webapp 1. こういうディレクトリ構造で <mvc:resources mapping= "/m2mockup/**" location= "classpath:/m2mockup/"/> 2. こういう設定をしてしまうと 3. 画像やCSSだけでなく、テンプレートhtmlにもそのままアクセス できてしまう!(もちろんまずい) http://…/[ContextPath]/m2mockup/img/logo.png http://…/[ContextPath]/m2mockup/item.html
だから、これがオススメ構造 40 src └─main ├─java ├─resources │ │ applicationContext.xml │
│ │ └─m2mockup │ ├─m2static │ │ └─img │ │ logo.png │ │ │ └─m2template │ index.html │ item.html │ └─webapp m2mockup配下にモック アップhtmlを作る 画像やCSSはm2static配下に 置いて、 <mvc:resources /> の設定での出力対象にする htmlテンプレートは m2template配下に
これでデザイナとプログラマが仲良く仕事できる! 41 プログラマとデザイナの取り決め事項 1. htmlモックアップは src/main/resources/m2mockup の下に作 ろうぜ。 2. ただし*.htmlはm2template,それ以外は
m2staticの配下でたのむ。 3. 商品情報のdivタグはid=“itemBox”にしよう。 4. 商品名はspanタグでid=“itemName” 5. …..その他の情報も同様にclass属性やid属性を決 めておけばよい。
42 もちろん 「htmlをjspに書き変える」 という退屈な作業は不要
43 6. コントローラとビューに対するテスト
ざっくりした流れ 1. JunitコードのランナーとしてSpringJUnit4ClassRunner を 使えば、DIコンテナが勝手にいい感じで起動してくれる。 2. HttpServletRequest, HttpServletResponseのモックをイン スタンス化する 3.
モックのrequestにテスト対象のURIやパラメータをセット 4. そのrequestオブジェクトをリクエストハンドラに渡すと疑似 リクエストが発生し、コントローラクラスに渡される。 5. コントローラの該当メソッドが戻り値として返す ModelAndViewオブジェクトにhtmlStringが入っている。 6. このhtmlStringの中をMixer2Engineで再度Htmlオブジェク ト化する 7. Htmlオブジェクトの中をAssertすればよい。 44
45 実際のテストコードで説明します https://github.com/nabedge/mixer2- sample/blob/master/mixer2-fruitshop- springmvc/src/test/java/org/mixer2/samp le/web/controller/ItemControllerTest.java
最後の給水 46 •水分補給 •時間を確認 40分くらい?
47 Webアプリの分割開発
普通のWebアプリプロジェクト(maven形式) 48 Javaクラスとか このへん Javaクラス以外は src/main/webapp 静的ファイル このへん JSPとか このへん
普通のWebアプリを分割開発するときのカベ 1. Javaクラスや、その設定ファイル (*.properties,*.xml,*.sql)は別プロジェクト化 してjar化してWebアプリ側から依存関係を つくればいい。 – つまり、Javaライブラリは分割開発可能 2. しかし、src/main/webapp
配下に置くような JSP,静的リソース、設定ファイル類(MVCで 言うとViewの周辺)は、プロジェクト分割& 別パッケージ化が難しい。 49
Mixer2を使うと 1. Mixer2は、Viewを普通のjavaコードで取 扱う。 2. そのテンプレートもJavaコードから見ると ただのリソースファイルとして扱える。 3. よって、普通のJavaライブラリ同様に分割 が可能。
50
デモ • デモでお見せします。 プロジェクト間依存関係はこんな感 じ m2flowershop-web(.war) m2flowershop-front(.jar) m2flowershop-cart(.jar) m2flowershop-resource(.jar) 51
後日談 • ※結局、当日までにサンプルのコーディング が間に合わなかったのでこのデモはやってま せん。(^^; 52
53 7. まとめ
まとめ • SpringMVCはシンプルで使いやすいフレームワーク • mixer2とSpringMVCは良いコンビ • ディレクトリ構造を考えたうえでSpringMVCの静的リ ソース出力機能と組み合わせれば、htmlモックアップ をjspに書き変える作業は不要 •
jspでは難しい、ビューに対するテストの自動化も可 能 • htmlテンプレートファイルと静的ファイル(ex.画像)と Javaクラスをjarパッケージ化できるので、Webアプリ の分割開発すら可能。 54
FAQ • Q. モックアップHTMLはクラスパス上に置かなきゃダメですか? – A. Mixer2EngineのloadHtmlTemplateメソッドはjava.io.File, String, StringBufferのいずれかでテンプレートhtmlを読めます。したがってOSのファイ ルシステム上でもDB上でもどこでもOKです。
– ※後日談:ver1.1.14 以降、InputStreamからも読めるようになりました。 • Q. WEB-INF/view/mixer2view.jsp を通じて結局jspを使っているのはダ サくないですか? – A. 実はその通りです。本来は、コントローラのメソッドの戻り値としてHtmlオブ ジェクトを返すだけで済むようなViewResolverを実装するべきです。誰か作っ て!(Pull Request熱烈歓迎!) • Q. mixer2を使う場合はJSPは完全に排除しなきゃだめですか?既存の taglibも使いたいのですが? – A. 可能です。たとえば、 *.htmlで用意したテンプレートを読み込んで、その一部 のタグだけを部分マーシャルし、jsp上に埋め込むことも可能です。 55
56 ご静聴ありがとうございました