Spring Bootによるウェブアプリ開発: コレクション(2)

辞書を作る: Mapの利用

Mapとは

  • 「キー」と「値」をペアで扱うコレクション(Listは値だけを扱う)
  • キーはユニーク(unique、唯一の)になる。同じキーで違う値は登録できない。
  • キーと値を保存するにはputメソッドを使う。
  • キーで検索して値を取り出すにはgetメソッドを使う。
  • Mapはインターフェース。Mapを実装したクラスとしてはHashMapがよく使われる。
  • 教科書P.215〜227

Mapを利用する例として、次の機能を持つ辞書アプリを作ってみよう。

  • 英語をキー、日本語を値として登録できる。
  • 英語から日本語を検索できる。
  • 登録されたデータ一覧を見ることができる。

登録

  • コントローラ、22行目: 辞書の情報を格納するHashSetをフィールドとして定義する。
  • コントローラ、37行目: putメソッドでMapに登録する。

検索

  • コントローラ、55行目: getメソッドでキーから値を得る。登録されていない場合はnullが返ってくる。

一覧

  • テンプレート、24行目: keySetメソッドでキーのSetを取得する。Setについては教科書P.205〜214を参照。
  • テンプレート、26行目: getメソッドでキーから値を得る。

資料

ソースコード
オンラインドキュメント
教科書

  • Map: P.215〜227
  • Set: P.205〜214

再評価のための復習: コンストラクタ

コンストラクタとは

インスタンス化の時(new演算子を使う時)に実行されるメソッド。

コンストラクタの定義

  • コンストラクタはメソッドの一種なのでメソッドの定義の仕方とあまり変わらない。下記の点がコンストラクタに特有であることに注意する。
    • メソッド名は自由につけられない。コンストラクタはクラス名と同じにする。
    • 戻り値(返り値)の型は記述しない。

コンストラクタが定義されているクラスの例

インスタンス化

ポイント

  • コンストラクタの名前はクラス名と同じでなければならないため、複数のコンストラクタを定義するには(メソッド名で区別できないので)、引数の形(個数、型の並び順)が違っていなければならない。つまりコンストラクタのオーバーロード。(教科書P.72等)
  • コンストラクタを定義しないクラスには、デフォルトコンストラクタが自動的に生成される(定義したことになる)。デフォルトコンストラクタは、引数なしで何の処理もしない。
  • ハマりやすいポイント: 引数ありのコンストラクタを定義しただけだと、引数なしでインスタンス化することができない(1つもコンストラクタを定義しない場合にしかデフォルトコンストラクタが生成されないから)。

教科書

  • P.74〜77: コンストラクタ
  • P.72: オーバーロード

Spring Bootによるウェブアプリ開発: コレクション(1)

Formの基礎(前回)のまとめ

前回のプログラム(おみくじ及び例1〜3)の動作を、下記の観点で確認しよう(記述の意味を理解すること)。

  • @RequestMappingアノテーション
  • @RequestParamアノテーション
  • ModelMap型のaddAttributeメソッド
  • postとgetの違い
  • @GetMappingアノテーションと@PostMappingアノテーション
  • th:text属性
  • th:each属性
  • th:if属性
  • @RequestParamアノテーションのrequiredオプション
  • メソッドのオーバーロード

掲示板の改良: 名前や日付も保存するList

第4回で作った掲示板はコメントだけを保存・表示するものであった。より実用的にするために、投稿者の名前と投稿時間も保存・表示するようにしてみよう。

まず第4回の掲示板を第5回で実行できるようにコピーする(テンプレートのパス等を修正しなければいけないことに注意する)。

どこをどのように変更するか?

  1. テンプレート: フォームに名前の入力欄を加える。
  2. コントローラ: 名前を受け取れるようにする。
  3. コメントを表すBbsCommentクラスを作成: 本文と名前と投稿日時のフィールドを作る。
  4. コントローラ: BbsComment型のインスタンスを作成
  5. コントローラ: コメントを保存するリストの型をList<BbsComment>にする。
  6. コントローラ: BbsComment型のインスタンスを作成し、リストに追加する。
  7. テンプレート: コメントの表示部分を修正する。

資料

ソースコード
オンラインドキュメント
教科書

  • Map: P.215〜227
  • Set: P.205〜214

再評価のための復習: メソッド

メソッドの概念

Method concept

  • メソッドを呼ぶと定義された処理が実行される
  • メソッドを呼ぶ時に引数を渡す場合がある。
  • メソッドを呼ぶと戻り値が返ってくる場合がある。

メソッドの定義

例: int型の数値を2つ足した合計を返すメソッドの定義

メソッド

引数

  • メソッド名の後ろのカッコの中に、型と引数名を書く。
  • 複数の場合はカンマで区切る
  • 引数がない場合は書かない(カッコは必要)

戻り値(返り値)

  • 戻り値の肩をメソッド名の前に書く。
  • 戻り値はreturn文で指定する。
  • 戻り値がない場合は、戻り値の型として「void」を指定する。return文はなくても良い(あっても良いがreturnの後ろに何も書かない)。

アクセス修飾子

  • フィールドと同様にアクセス修飾子をつけることで、そのメソッドを呼び出すことのできる呼び出し元を制限することができる。
  • アクセス修飾子は戻り値の型の前に書く。

処理で使える変数

  • 引数
  • フィールド
  • その場で定義した変数

教科書

  • P.66: メソッドの定義
  • P.68: メソッドの呼び出し(1)
  • P.70: メソッドの呼び出し(2)

Spring Bootによるウェブアプリ開発: Formの基礎

前回の要点

  • http://start.spring.ioでプロジェクトを作成する。
  • 処理の流れ
  • テンプレートとコントローラを作る。
  • テンプレート
    • HTMLで記述する。ただし単独で現れるタグは後ろに「/」をつける。
    • コントローラから送られてきた値を表示するところで、th:text属性を使う。
  • コントローラ
    • クラスに@Controllerアノテーションをつける。
    • クラスとメソッドにつける@RequestMappingアノテーションで担当するURLを指定する。
    • メソッドの返り値で利用するテンプレートを指定する。
    • テンプレートに値を送り込みたい場合は、メソッドにModelMap型の引数を加え、そのaddAttributeメソッドで名前と値を指定する。
  • その他
    • ポート番号を変える: resourcesにあるapplication.propertiesに「server.port = 18080」などと記述する。

ドキュメント

Formの作成と表示

おみくじアプリを作ってみよう。

処理のシーケンスは次のようになる。

おみくじのシーケンス

名前を入力する(フォームの利用)

  • formタグ: どこからどこまでがフォームかを表す。action属性でどこに送るか指定する。method属性でどのような形で送るかを指定する。
  • inputタグ: name属性で区別のための名前をつける。この例ではその名前にnameとつけて紛らわしいので注意すること。
  • buttonタグ: type属性をsubmitとすることで、formの送信ボタンにすることができる。

コントローラ

  • 18〜21行目:「/lecture04/omikuji_input」にアクセスがあると、「lecture04/omikuji_input」がブラウザに送られる。
  • 26〜34行目:「/lecture04/omikuji_output」にアクセスがあると、「lecture04/omikuji_output」がブラウザに送られる。
    • 27行目:「フォームから送られてくるパラメータを受け取るための引数」を指定する為に@RequestParamアノテーションをつける。
    • 28〜31行目: String型の変数を乱数によって「吉」か「大吉」にする。
    • 32行目: 「result」という名前で変数resultをテンプレートに送る。
    • 32行目: 「name」という名前で変数nameをテンプレートに送る。

結果の表示

  • コントローラからは「name」と「result」という名前で値が送られてきている。それぞれ、th:text属性で表示する。

例1: 掲示板

テンプレート

  • 最初の表示(get)とコメントを書き込む時(post)の両方でこのテンプレートを使う。
  • formのaction属性は省略すると、同じURLにアクセスすることになる。
  • リストから一つづつ取り出すのは、th:each属性を使う。コロンの左側でつけた名前でアクセスできる(スコープは、属性をつけた要素の内側)。注意しなければならないのは、繰り返し出力されるのは、th:each属性がついた要素(タグ)だということ。例えば、commentListに3つの文字列が入っていたとしたら、li要素が3つ出力される。
  • タグ無しで値を出力するのはth:blockタグを使う。

コントローラ

  • @RequestMappingはgetとpostの両方で実行されるが、@GetMappingと@PostMappingを使うことで、同じURLでgetとpostの処理を別のメソッドに分けて書くことができる。
  • コントローラ全体

例2: じゃんけん

テンプレート

  • 最初の表示(get)とじゃんけんをした時(post)の両方でこのテンプレートを使う。
  • th:ifで条件が真(true)の時だけ要素を表示させることができる。ここでは、コントローラからresultが送られてきた時(つまりresultがnullでない)にそれを表示している。
  • input要素のtype属性は「radio」。checked=”checked”をつけた要素がデフォルトで選択される。
  • name属性は全て同じにする(nameを同じにすると同一グループとなり排他的選択ができる)。
  • 選択されたボタンのvalue属性がコントローラに送られる。

コントローラ

  • getとpostで同じメソッド名となっているが、これをオーバーロードという(教科書P.132)。
  • StringBuilderは文字列を繋げる時に使える(教科書P.82)。
  • 律儀にコンピュータの手を決定して結果を出力してもいいが、ここでは選択した手に関わらずランダムで結果を出力している。
  • コントローラ全体

例3: アンケート

テンプレート

  • チェックボックスはname属性で区別する。

コントローラ

  • チェックボックスは、チェックをしたときにしかパラメータが送信されない。そのため、デフォルトの@RequestParamではエラーになる。
  • パラメータが送信されなくてもエラーにならないようにするには、「required = false」とする。
  • チェックされているときはtrue、チェックされてない時(パラメータが無い時)は、falseになる。
  • コントローラ全体

教科書

再評価のための復習: フィールド

最もシンプルなフィールドの定義

型名 フィールド名;

これにアクセス修飾子や初期化がつく。

フィールド定義の例

外部からのアクセス(アクセス修飾子の違い)

教科書