Spring Bootによるウェブアプリ開発の基礎(5)


永続化(永続性を保つ事)について。

計算機科学における永続性(英: Persistence)は、データを生成したプログラムが終了してもそのデータが存続する特性を指す。この特性がない場合、データはメモリ上にのみ存在し、コンピュータのシャットダウン時など、メモリの電源が切られた時点で消失する。(Wikipedia: 永続性より引用)

Javaアプリケーションにおける永続化の方法

  • ファイル操作を行うAPI(クラス)を用いる。[教科書6章]
  • JSONで保存: Jackson
  • リレーショナルデータベースに保存
    • JDBC: Javaプログラム内でSQLを構成・実行する
    • JPA (Java Persistence API): JavaにおけるO/Rマッパーの標準的な仕様
  • リレーショナルデータベース以外のデータベースに保存
  • etc…

Spring Bootではデータの永続化のために、JdbcTemplate(JDBCを簡単に使える機能)やSpring Dataが利用できるようになっている。

テキストファイルの読み書き

PersistenceSampleController.javaのloadTextメソッドとappendTextメソッド

JPA

  • build.gradleに追加
  • Memo.java: エンティティーを作成する。
  • MemoRepository.java: JpaRepositoryを継承してリポジトリを作成する。
  • PersistenceSampleController.java
    • @AutowiredでDIする
    • findAllで取り出す
    • saveで保存

Spring Bootによるウェブアプリ開発の基礎(4)


ここまでのまとめ。

コントローラ

  • @Controllerアノテーションが付加されたクラスがコントローラになる。
  • @RequestMappingアノテーションで対応するパス(URLのホスト部分より後)を指定する。クラスとメソッドにそれぞれに付加することができる。「クラスに付加された値」+「メソッドに付加された値」が対応するパスとなる。例えばクラスに「@RequestMapping(“/form”)」、メソッドに「@RequestMapping(“text”)」と付加されていた場合、そのメソッドが対応するパスは「/form/text」となる。
  • 各メソッドの返り値はString型とし、テンプレートのルートパス(src/main/resources/templates)からの相対パス(ファイル名)を返すようにする。「.html」は省略する。例えば、「return “form/text”」とした場合、「src/main/resources/templates/form/text.html」がテンプレートとして使われるようになる。
  • テンプレートに値を渡したい場合、ModelMap型のインスタンスにaddAttributeメソッドを使って値を保存する(とテンプレートで取り出すことができる)。
    キーと値のペアで保存する。ModelMap型のインスタンスは、メソッドの引数として指定することで取得することができる。
  • フォームからパラメータを受け取りたい場合は、メソッドの引数として指定し@RequestParamアノテーションを付加する。カッコ内はname属性で指定された値を指定する。

ビューテンプレート

  • テンプレートはThymeleafで記述する。
  • テキストノード(タグで囲まれた部分)にコントローラから受けとった値を埋め込むには、th:text属性をにキーを指定すれば良い。例: <タグ th:text=”${キー}”>埋め込まれる場所</タグ>
  • フォームで値を送りたい場合は、formタグを用いる。action属性で、送信先のURL(パス)を指定する。コントローラにおける区別のためにname属性を指定する。

フォームのサンプル

Spring Bootによるウェブアプリ開発の基礎(2)


HTMLフォームでデータを入力しよう!

後で書き直す。

  • formタグ、action属性、method属性
  • inputタグ、name属性
  • buttonタグ、type属性

他のトピックス。

  • selectを使うには?
  • radio、checkboxを使うには?
  • hiddenの使いどころ。
  • デフォルト値は?
  • ファイルのアップロードは?
  • GETとPOSTの違い
  • etc…

Spring Bootによるウェブアプリ開発の基礎(1)


本当はきっちり解説したいけど時間が足りないので、とりあえず動かすための最低限なポイント解説。

Gradle

Gradleはビルドツールの1つで、Androidアプリの開発でも使われるなど、メジャーになりつつある(すでにメジャーである)。

ポイント: Gradle以外にも色々あるけど、Gradle使っとけば多分大丈夫。

処理の流れ

Mvc

SpringのWeb MVCにおける処理の流れ(http://docs.spring.io/spring/docs/4.0.5.RELEASE/spring-framework-reference/html/mvc.html#mvc-servletより引用)

フロントコントローラがリクエストを適切なコントローラに渡し、コントローラが出力するデータをビュー(テンプレート)が表示するという仕組み。

ポイント: コントローラとテンプレートを用意すれば、ブラウザにページを表示させることができる。

アノテーション

クラスやメソッド、パッケージに対してメタデータとして付加情報を記入する機能(Wikipedia: アノテーションより)

大抵は「付加情報を記入する」だけではなく、アノテーションプロセッサによって様々な処理がなされる。Spring Bootでは、コントローラを作る時にアノテーションを使う等、様々なところで利用する。

ポイント: Spring Bootによるウェブアプリ開発ではアノテーションを良く使う。

コントローラの作成

  • クラスに@Controllerアノテーションをつけることで、このクラスがコントローラとして扱われる。
  • @RequestMappingアノテーションで、どのURLを対象とするかを指定する。
  • メソッドの戻り値はString型で、テンプレートのファイル名(拡張子は除く)を指定する。
  • メソッドの引数にModelMap型を加えると、テンプレートにモデルを渡すためのオブジェクトを得ることができる。addAttributeメソッドでキーと値を指定する。

ポイント: コントローラでは、URLに対応したメソッドを作る。メソッドはテンプレートを指定する。

テンプレートの作成

テンプレートエンジンとして標準ではThymeleafが使われる。

# Spring Boot 1.3.6ではThymeleaf 2.1.4(最新版ではない)が使われることに注意。

src/main/resources/templatesに作成する。

  • (Thymeleaf 2.1.4では)well-formedなXML文書でなければならないので注意する。つまり「タグは開始タグと終了タグを記述する(省略できない)」と「空要素(単独で現れるタグ、例えばhrタグ)はスラッシュをつける(例:<hr/>)」を守ればよい。
  • xmlns属性でThymeleafで使うプレフィックスを指定する。
  • th:text属性で、その要素のテキストノードに値を設定できる。
  • th:text属性では「${key}」とする。keyにはコントローラで指定したModelMapのキーを指定する。

ポイント: テンプレートでは、コントローラから送られてきたモデルをどこに表示するかをHTMLで記述する。

NetBeansによるSpring Bootアプリケーションの開発


Gradleプラグイン

NetBeansで、[ツール]→[プラグイン]→[使用可能なプラグイン]を選択し、「Gradle Support」をインストールする。

プロジェクトの作成

http://start.spring.io にアクセスする。

1: 「Gradle Project」を選択する。

2: Groupを指定する。パッケージだと思えば良い。net.teachingprogramming.webapp

3: Artifactを指定する。アプリの名前だと思えば良い。webapp

4: 「web」と入力すると候補として「Web」が表示されるので、選択する。同様に「Thymeleaf」も選択する。

5: 「Web」と「Thymeleaf」が選択されていることを確認する。

5: クリックするとZIPファイルのダウンロードが始まる。

Spring Initializr

NetBeansで、[ファイル]→[プロジェクトをインポート]→[ZIPから]を選択し、ダウンロードしたZIPファイルを選択して[インポート]をクリックする。

NetBeans IDE 8 0 2

緑色のアイコンがついたプロジェクトが生成される。

アプリケーションの実行

webapp [root]を右クリックし、[Tasks]→[boot]→[bootRun]を選択すると、ビルド(コンパイル等)が開始され、ビルドが成功するとアプリケーションが起動する。
出力ウィンドウに次のように表示されれば起動完了。

Tomcatが8080ポートで起動しているのがわかるので、ブラウザでアクセスすると、エラーメッセージが表示される。これは、まだコンテンツを返すプログラムを作っていないために表示されるもので、正常な動作です。ブラウザのエラー(Chromeの場合は「このサイトにアクセスできません」と表示される)とは違うことを確認してください。

Localhost 8080

アプリケーションを終了するには、出力ウィンドウの左側にあるStopボタンをクリックする。

第6回: コレクション(2)


コレクションに関する Q and A

Q: プリミティブ型を格納できる?
A: できません。ラッパークラスを使いましょう。

Q: 自作クラスのインスタンスをHashSetに格納したいのだけど、「同じ」の判定がおかしい?
A: equalsメソッドとhashCodeメソッドを適切にオーバーライドしましょう。

Q: ArrayListの要素を取得するとき、範囲外のインデックスを指定して、エラーになるんだけど、エラーを出さないようにするには?
A: きちんと例外処理を行いましょう。

Q: HashSetで要素を取得するとき、格納されてないキーを指定してエラーになるんだけど、、エラーを出さないようにするには?
A: nullかどうか判定するか、例外処理を行いましょう。

Q: コレクションの要素をソートしたいんだけど?
A: 単純なソートならCollections.sortを使う。ソート順を細かく指定したいなら、Collections.sortにComparatorを渡す。常にソートした状態にする(addしたタイミングでソートする)なら、対象のクラスにComparableを実装しておく。

第5回: コレクション(1)


コレクション

コレクションとはデータの集合のこと。Javaにはコレクションを扱うライブラリが標準で含まれている。

よく使うコレクションとして、次の3つがある

java.util.ArrayList
順序の情報を保持するコレクション。同じ要素も格納できる。
java.util.HashSet
同じ要素格納できない。順序も保持できない。注: デメリットではない
java.util.HashMap
キーと値のペアで保持する。辞書のようなもの。

ArrayListの利用

ArrayListの後ろに中に格納するインスタンスの型を「<」と「>」で囲んで記述する。

addメソッドで追加する。

取り出すときはgetメソッドを使う。引数として0から始まるインデックスを指定する(配列の場合と同じ)。全てを取り出すときは、for文が使える。リストの要素数(サイズ)はsizeメソッドで取得することができる。

コレクションからデータを取り出すときには、「拡張for文」を使うと簡潔に記述できる。

自作のクラスのインスタンスを格納する場合も同様。

HashSetの利用

ArrayListと同様に利用出来るが、以下の違いがある。

  • 要素が順番に並んでるわけではないので、getメソッドが使えない。取り出すときは拡張for文で取り出す(他の方法としてIteratorを使う方法等があるが本講義では扱わない)。
  • 同じ要素は1つだけ格納される。下記のソースコードの場合、出力は3つになる。

格納する型(クラス)によっては、意図した通りにならない場合がある。例えば自作のPersonクラスの場合、「たろう」が2回、取り出されてしまう。これは、それぞれの「たろう」を表すインスタンスが「同じ」とみなされていないから、である。

「どうしたら意図したように動作するのか?」はまた後日解説するので、とりあえず、ここでは「HashSetが格納するのがStringのインスタンスなら大丈夫」と覚えておこう。

HashMapの利用

キー(key)と値(value)のペアで格納することができる。つまり辞書のようにデータを格納することができる。keyはSetで管理されるので、同じkeyを使って別の値を格納することはできないので注意。

インスンタンス化時、格納する型はkeyとvalueのそれぞれ指定する。

putメソッドで格納する。addメソッドではない点に注意。

取得はgetメソッドだが、インデックスではなく、keyを引数にする。

すでに格納されているkeyでputすると、上書きされる。

keyを取得したい場合は、keySetメソッドで、keyのSetを取得する。keyのSetから1つづつ取り出すのは、拡張for文を使う。

ソースコード全体

第4回: 復習3


クラスの基礎

コンストラクタ

インスタンス化するときに実行されるメソッドのこと[教科書P.137]。引数有りのコンストラクタを用意する(また、引数なしのコンストラクトを用意しない)ことによって、インスタンス化時にフィールドの値を設定する等の処理を行うことができる。

アクセス修飾子

メンバー(フィールド、メソッド)を、どこからアクセスできるか(読み書きできるか)を指定する[教科書P.137]。

クラスを拡張する

あるクラスを元に、新しくクラスを作る(継承する)ことができる。元になるクラスを「スーパークラス」、継承したクラスを「サブクラス」という。継承するにはextendsキーワードを使う[教科書P.126]。

オーバーライド

スーパークラスで定義されたメソッドを、サブクラスで書き換える(上書き)することができる。これをオーバーライドという[教科書P.131]。元のメソッドとオーバーライトしたメソッドを区別するにはsuperキーワードを使う[教科書P.127]。

第3回: 復習2


クラスの基礎

クラスを定義する

  • パッケージ宣言(1行目)で、クラスが所属するパッケージを指定する[教科書P.24]。
  • クラスには、メンバ(member)によって構成されている。メンバには値を保存するためのフィールド(field)と、処理をするためのメソッド(method)の2つがある[教科書P.114]。
  • メンバは、お互いに利用可能。上記の例では、メソッドbmiでフィールドwidthとheightを利用して計算している。

クラスを使う(インスタンスを作って使う)

  • クラスは「設計図」に位置づけられるので、そのままでは使えない。設計図から「実体」をつくってから利用する。実体のことをインスタンス(instance)という。クラスからインスタンスを作ることを「インスタンス化」という。
  • インスタンスの作成にはnew演算子を使う[教科書P.115]。
  • メンバを使うには、「.」を使う。
  • 同じパッケージのクラスあるいは、import宣言したクラスはパッケージを書かなくても使える(5行目と11行目を比較)。