More Related Content
Similar to SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
Similar to SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug (20)
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
- 1. SpringMVCとmixer2で作る
Webアプリのキホン
Basic Web Application
with SpringMVC & mixer2
Spring勉強会 by #JSUG at VMWare-Japan
2013-01-24
- 8. 自己紹介
• わたなべ
• SI屋の技術屋さん
• @nabedge
• nabedge@gmail.com
• http://nabedge.blogspot.jp/
8
- 9. 目次
1. SpringMVC
2. テンプレートエンジン
3. Mixer2をHelloWorldで解説
4. Why mixer2 ?
5. SpringMVCとmixer2の組み合わせの勘所
6. コントローラとビューに対するテスト
7. Webアプリの分割開発
8. まとめ
9. FAQ
9
- 11. SpringMVC
• JavaでWebアプリをつくりためのMVCフレー
ムワーク。
• 生のサーブレット&JSPで作るより100倍作り
やすい。
• 大昔のStrutsより10倍は学習しやすい
• ライバルとしてはSeasarのSAStrutsとか。
• Spring3.Xになって以降はSAStrutsよりもさら
に使いやすくなった!
• 詳しくは「Spring3入門」を読みましょう。
11
- 18. 補足:タグとJava型
HTMLタグとJavaオブジェクトを相互マッピング
<html>…</html> ⇔ org.mixer2.jaxb.xhtml.Html
<div>…</div> ⇔ org.mixer2.jaxb.xhtml.Div
(ほか全120種類くらいのタグすべてを実装済み)
タグの属性はJavaオブジェクトのプロパティにマッピング。
setter/getterメソッドでアクセス
<div id=“foo”>…</div>
をテンプレートとしてロードすると
String id = div.getId(); // これでidに”foo”が入る
(html4/5のすべての属性を実装済み)
18
- 19. 補足:複数要素はListになる
template.html listの中身
<html> index 型
<body>
0 P
<p>Hello World</p>
foo 1 String
<span>bar</span>
</body> 2 Span
</html>
Html html = mixer2Engine java.util.List<Object> list
.loadHtmlTemplate( = html.getBody()
“template.html”); .getContent();
19
- 20. ちょっと一息
•水分補給
•時間を確認
10分か15分くらい?
20
- 23. デモ
(フルーツショップサンプルアプリ編)
https://github.com/nabedge/mixer2-
sample/tree/master/mixer2-fruitshop-springmvc
「github mixer2-fruitshop-springmvc」
でググるとすぐ見つかります。
23
- 27. ふつうのコントローラとJSP
商品情報を表示するコントローラクラス
@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);
}
JSP
<%@page pageEncoding="UTF-8"%>
<html>
<body>
<span>商品名:${item.name}</span>
</body>
</html> 27
- 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());
// 価格、説明、その他もろもろも...
28
- 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行で済む
29
- 30. コントローラの肥大化を防ぐ
ヘルパーはごく単純なstaticメソッドでよい
public class ItemHelper {
テンプレのhtml DBから取得した商品情報
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());
30
- 36. Java/Webアプリでの静的ファイルの配置
src
└─main
├─java
├─resources
│ │ applicationContext.xml
│ │
│ └─m2mockup テンプレートhtmlと画像
│ ├─m2static
│ │ └─img やCSSをまとめて
│ │ logo.png resources配下に置く。
│ │ クラスパス上に置くほう
│ └─m2template が、Javaコードから扱い
│ index.html やすいから!
│ item.html
│
└─webapp
36
- 39. ただし、注意しないと、、、!
1. こういうディレクトリ構造で 2. こういう設定をしてしまうと
src <mvc:resources
└─main mapping=
├─java
├─resources
"/m2mockup/**"
│ └─m2mockup location=
│ ├─img "classpath:/m2mockup/"/>
│ │ logo.png
│ └─item.html
└─webapp
3. 画像やCSSだけでなく、テンプレートhtmlにもそのままアクセス
できてしまう!(もちろんまずい)
http://…/[ContextPath]/m2mockup/img/logo.png
http://…/[ContextPath]/m2mockup/item.html
39
- 40. だから、これがオススメ構造
src
└─main
├─java m2mockup配下にモック
├─resources アップhtmlを作る
│ │ applicationContext.xml
│ │
│ └─m2mockup 画像やCSSはm2static配下に
│ ├─m2static 置いて、 <mvc:resources />
│ │ └─img
│ │ logo.png
の設定での出力対象にする
│ │
│ └─m2template
│ index.html
│ item.html
│
└─webapp htmlテンプレートは
m2template配下に
40
- 41. これでデザイナとプログラマが仲良く仕事できる!
プログラマとデザイナの取り決め事項
1. htmlモックアップは
src/main/resources/m2mockup の下に作
ろうぜ。
2. ただし*.htmlはm2template,それ以外は
m2staticの配下でたのむ。
3. 商品情報のdivタグはid=“itemBox”にしよう。
4. 商品名はspanタグでid=“itemName”
5. …..その他の情報も同様にclass属性やid属性を決
めておけばよい。
41
- 44. ざっくりした流れ
1. JunitコードのランナーとしてSpringJUnit4ClassRunner を
使えば、DIコンテナが勝手にいい感じで起動してくれる。
2. HttpServletRequest, HttpServletResponseのモックをイン
スタンス化する
3. モックのrequestにテスト対象のURIやパラメータをセット
4. そのrequestオブジェクトをリクエストハンドラに渡すと疑似
リクエストが発生し、コントローラクラスに渡される。
5. コントローラの該当メソッドが戻り値として返す
ModelAndViewオブジェクトにhtmlStringが入っている。
6. このhtmlStringの中をMixer2Engineで再度Htmlオブジェク
ト化する
7. Htmlオブジェクトの中をAssertすればよい。
44
- 46. 最後の給水
•水分補給
•時間を確認
40分くらい?
46
- 49. 普通のWebアプリを分割開発するときのカベ
1. Javaクラスや、その設定ファイル
(*.properties,*.xml,*.sql)は別プロジェクト化
してjar化してWebアプリ側から依存関係を
つくればいい。
– つまり、Javaライブラリは分割開発可能
2. しかし、src/main/webapp 配下に置くような
JSP,静的リソース、設定ファイル類(MVCで
言うとViewの周辺)は、プロジェクト分割&
別パッケージ化が難しい。
49
- 55. 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