プロジェクトの雛形を作成
- ブラウザで「http://start.spring.io」にアクセスする。
- 「Cradle Project」を選択する。
- グループIDとして、パッケージ名を入力する。ここでは「ユーザ名.webapp」とする。
- アーティファクトIDとしてプロジェクト名を入力する。ここでは「webapp」とする。
- 利用する依存ライブラリを入力する。名前の一部を入力すると選択肢が現れるのでクリックして選択する。ここでは「Web」と「Thymeleaf」を選択する。
- 選択されたものが表示されているので「Web」と「Thymeleaf」が選択されていることを確認する。
- クリックするとプロジェクトのファイル(ZIPファイル)のダウンロードが始まる。
NetBeansでインポート
メニューから[ファイル]→[プロジェクトをインポート]→[ZIPから]を選択し、ダウンロードしたファイル(webapp.zip)を指定してインポートする。
Spring Bootアプリケーションの実行
アプリケーションを実行するためのタスクが定義されているため、それを使う。
プロジェクトを右クリックして、[Task]→[boot]→[bootRun]を選択する。
アプリケーションが立ち上がると、出力ウィンドウの最後に「Started WebappApplication」と表示される。
その1行前に「Tomcat started on port(s): 8080 (http)」と出力されているということは、8080番ポートにアクセスすれば何らかの反応があるはずである。http://localhost:8080/にアクセスしてみよう。
エラーメッセージが表示されたが、これは、まだコンテンツを返すプログラムを作っていないために表示されるもので、正常な動作である。アプリケーションを終了するには、出力ウィンドウの左側にあるStopボタンをクリックする。
Spring Web MVC frameworkの基礎中の基礎
処理の流れ
これから作るウェブアプリケーションはSpringのWeb MVCフレームワークを利用している。このフレームワークにおける処理の流れを次の図に示す(http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-servletより引用)。
フロントコントローラがリクエストを適切なコントローラに渡し、コントローラが出力するデータをビュー(テンプレート)が表示するという仕組み。このうち、自分で作るのは、「コントローラ」と「ビューテンプレート」である。
まずは、単純に「こんにちは」と表示するようにコントローラとテンプレートを作ってみよう。
テンプレートを作る
テンプレートとは雛形のことであり、そこに流し込まれるデータとともに使うことが一般的な使い方であるが、まずはデータの流し込みを想定しないテンプレートを作成してみよう。
まず、テンプレートを格納するディレクトリを作成しよう。Resourcesのtemplatesにlecture03というディレクトリ(パッケージ)を作る。NetBeansのパッケージの表示の仕方によっては、作業が難しい。プロジェクトウィンドウの背景部分を右クリックし、「Javaパッケージの表示方法」を「ツリー」にすると階層構造がわかりやすい。
lecture03を右クリックして新規から「HTMLファイル」を選択する。ファイル名を「hello」と入力する。拡張子は自動でつくので入力しない。作成したら、次のように書き換えよう。
1 2 3 4 5 6 7 8 9 10 |
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>こんにちは</title> </head> <body> <p>こんにちは</p> </body> </html> |
今の所、次の2点が注意する点で、これ以外は普通のHTMLファイルである。
- 2行目: xmlns属性はXML名前空間の宣言である。テンプレートエンジンであるThymeleafはHTMLへの埋め込みをXMLによって行うことが大きな特徴である。名前宣言によってThymeleafによる操作をthというプレフィックスで行うことができる。
- 4行目: 単独で使われるタグ(brやhr等)は後ろに/をつける(XMLのルール)。
コントローラを作る
コントローラは、リクエストに対してどのテンプレートを使うか(そしてテンプレートにどのような値を埋め込むか)ということを決定するためのものである。
具体的には@Controllerアノテーションをつけたクラスで、リクエストに対応してメソッドを定義する。メソッドの返り値としてテンプレートを指定する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
package net.teachingprogramming.webapp; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import java.time.LocalTime; /** * 第3回で使うコントローラ */ @Controller @RequestMapping("/lecture03") public class Lecture03Controller { @RequestMapping("/hello") public String hello() { return "lecture03/hello"; // テンプレートのファイル名を返す } @RequestMapping("/dice") public String dice(ModelMap modelMap) { int pips = (int)Math.floor(Math.random()*6) + 1; modelMap.addAttribute("pips", pips); return "lecture03/dice"; } @RequestMapping("/greeting") public String greeting(ModelMap modelMap) { LocalTime localTime = LocalTime.now(); int hour = localTime.getHour(); String message; if (4 <= hour && hour < 11) { message = "おはよう"; } else if (11 <= hour && hour < 16){ message = "こんにちは"; } else { message = "こんばんは"; } modelMap.addAttribute("message", message); return "lecture03/greeting"; } } |
- 12行目: コントローラを表すアノテーション
- 13行目: このコントローラが、「/lecture03」のURLを担当することを表す。
- 16〜19行目: /hello(つまりhttp://localhost:8080/lecture03/hello)に対応するメソッド
- 16行目: /helloに対応すること表す
- 17行目: 戻り値の型はStringにする。メソッド名はなんでも良い。
- 18行目: テンプレートのルート(resources/templates)から利用するテンプレートの相対パス(拡張子は除く)
20行目以降は次節以降で解説する。
動作を確認
http://localhost:8080/lecture03/helloにブラウザでアクセスしよう。
テンプレートに値を渡す
- メソッドにModelMap型の引数を加える。
- そのaddAttributeメソッドで名前と値を登録する。
- テンプレートでth:text属性を使う。
例1: サイコロ
アクセスするたびに表示される数が変化する。乱数については教科書P.108を参照。
21 22 23 24 25 26 |
@RequestMapping("/dice") public String dice(ModelMap modelMap) { int pips = (int)Math.floor(Math.random()*6) + 1; modelMap.addAttribute("pips", pips); return "lecture03/dice"; } |
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>ダイス</title> </head> <body> <p> <span th:text="${pips}">サイコロの目</span> </p> </body> </html> |
例2: 挨拶
現在時刻によって表示されれる挨拶が変化する。時刻の扱いについては、教科書P.257を参照。
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
@RequestMapping("/greeting") public String greeting(ModelMap modelMap) { LocalTime localTime = LocalTime.now(); int hour = localTime.getHour(); String message; if (4 <= hour && hour < 11) { message = "おはよう"; } else if (11 <= hour && hour < 16){ message = "こんにちは"; } else { message = "こんばんは"; } modelMap.addAttribute("message", message); return "lecture03/greeting"; } |
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>挨拶</title> </head> <body> <p> <span th:text="${message}">ここがmessageで置き換わる</span> </p> </body> </html> |