文字化け対策: CharacterEncodingFilterの利用

文字化けは様々な原因が考えられますが、Springの環境ではCharacterEncodingFilterを使うことで文字化けをなくすことができる場合があります。

CharacterEncodingFilterはweb.xmlで設定します。

掲示板を作る: Viewの作成

最後にViewを作って完成です。

Controllerの返り値として「bbs/index」を指定しているので、templatesディレクトリの中にbbsフォルダを作ってその中にindex.htmlを作成します。

  • 10行目: th:eachを使うとリストから1つずつ取り出して、要素が生成される。この場合commentListから取り出した値はcommentとして参照できる。comment.nameでcomment.getName()が実行される。
  • 12行目: actionの代わりにth:actionを指定すると@{}を使ってURLを記述することができる。@{}を使うと、contextに応じたpathに書き換えてくれる。

実行例

BBS

H2コンソールで確認すると、idが自動的に割り当てられているのがわかります。

H2console2

掲示板を作る: Controllerの作成

掲示板のControllerを作成します。

今回はこれまで作ってきたTopContorollerではなくて、掲示板用のコントローラを作成します。掲示板では、コメントの表示とコメントの投稿の2つの機能が必要ですが、これを1つのページ(URL)で実現してみます。具体的にはたんなる表示の時はGETメソッドを用い、投稿時にはPOSTメソッドを使うようにします。

  • 18行目: ベースとなるURLを「/bbs」にする。
  • 20、21行目: @AutowiredアノテーションでCommentRepositoryをDI(dependency injection、依存性の注入)することを表す。これにより、システムがCommentRepositoryをインスタンス化してくれる。
  • 23〜28行目: GETメソッドによるアクセスを処理するメソッド。25行目でデータベースから全てのデータを取得する。26行目で取得したデータをビューに渡す設定をする。
  • 30〜37行目: POSTメソッドによるアクセスを処理するメソッド。32〜34行目で、Commentクラスのインスタンスを生成し受け取ったパラメータをそれぞれセットする。35行目でCommentRepositoryを使ってセーブする。これ以降の操作はGETメソッドの場合と同様なので、indexGetを呼んでそれを返り値とする。

掲示板を作る: EntityとRepositoryの作成

データベースの利用の例として、掲示板を作成してみましょう。

まずは、EntityとRepositoryを作成します。

Entity(JPA Entity)とは、データベースにおける表の個別の行に対応するオブジェクトです。JPAではPOJO(Plain Old Java Object、ごく普通のJavaオブジェクト)にアノテーションを加えるだけで作成できます。今回は単純に、名前と本文だけを保存するようにしてみます。DatabaseConfig.javaの44行目でEntityを示すパッケージを指定しているので、そこにCommentクラスを作成します。

  • 10行目: @EntityアノテーションでEntityであることを示す。
  • 12〜14行目: JPAでは主キーが必要となる。@Idアノテーションで主キーを示す。また@GeneratedValueで値を自動生成することを示す。
  • 15行目: 名前を格納するフィールド。
  • 16行目: 本文を格納するフィールド。
  • 18〜32行目: nameとtextのgetter/setter。getter/setterはメニューから[Code]→[Generate]→[Getter and Setter]で自動生成できる。

このCommentクラスのインスタンスをデータベースに格納するには、Repositoryとよばれる、データベースへの操作を行うためのオブジェクトが必要です。RepositoryはSpring Data JPAに含まれるJpaRepositoryインターフェースを使うと簡単に作成することができます。JpaRepositoryインターフェースを継承することにより、データベースの操作に関するメソッドが自動的に生成されます。

DatabaseConfig.javaの24行目でRepositoryを示すパッケージを指定しているので、そこにCommentRepositoryインターフェースを作成します。

  • 10行目: @RepositoryアノテーションでRepositoryであることを示す。
  • 11、12行目: JpaRepositoryを継承する。型変数はEntityの型とそのEntityの主キーの型を指定する。基本的な機能(メソッド)は自動的に生成されるので、いまのところメソッド等の記述は必要ない。

データベース接続の設定

今回はJPAを使います。実装としてHibernateを利用します。

まず、Spring Data JPAHibernateH2のライブラリをdependenciesに追加します。これまでと同様に、更新とArtifactの設定を行います。

次に、設定用のクラスを作成します。Thymeleafの設定と同様に、configパッケージ内にDatabaseConfigクラスを作成します。

  • 22行目: @Configurationアノテーションで設定用のクラスであることを示す。
  • 23行目: @EnableTransactionManagementアノテーションでトランザクションの管理を有効にする。
  • 23行目: @EnableJpaRepositoriesアノテーションでJPA Repositoriesを有効にする。Repositoryが格納されるパッケージを引数とする。
  • 27〜35行目: データソースをBean登録する。設定内容はH2の設定と同じにする。
  • 37〜54行目: EntityManagerFactoryをBean登録する。44行目で対象となるentityが含まれるパッケージを指定している。48行目でdialectを設定する。これによりHibernateがデータベースに適した動作をするようになる。49行目でテーブル等の自動生成について設定している。「create-drop」はdeply時に、テーブルを削除(drop)して作りなおす(create)という設定である。他に設定可能な値として、
    none
    何もしない
    create
    テーブルがない場合に作成する
    update
    テーブルの構造が変わった時に変更する
    validate
    テーブルの構造をチェックする

    等がある。開発時にはcreate-drop、create、updateを使い、運用時にvalidateにするといった使い分けをする。

  • 56〜61行目: トランザクションマネージャーをBean登録する。
  • 63〜66行目: 例外を変換するTranslatorをBean登録する。

Springにおけるデータベースへのアクセス方法

一般に、Javaにおけるデータベース(RDBMS)へのアクセスには(代表的なものとして)下記の方法が使われます。

  • JDBC
  • HibernateやTopLink等のORMライブラリ
  • Java Persistence API (JPA)
  • Java Data Object (JDO)

JDBCはデータベースに接続し、SQLによるクエリを実行するためのAPIです。SQLは自分で書かなければいけません。

HibernaeやTopLink等のORMライブラリを利用すると、SQLを(あまり)意識することなくJavaのインスタンスをデータベースに保存できるようになります。ライブラリがSQLを自動生成・実行してくれるわけです。

JPAとJDOは「仕様」のため、様々な実装が存在します。JPAはRDBMSへの操作を抽象化するAPIです。HibernaeやTopLinkもJPAの実装として利用することができます。JDOは永続化そのものを抽象化するAPIで、RDMBS以外のデータベースも対象としています。

Springでは、これらを直接使うのではなく(直接使うこともできますが)、利用をサポートする仕組みが用意されています。例えば、JDBCの場合には、Spring Framework JDBCを使うことで、データベースの接続やトランザクション等を簡単に扱うことができます。
JPAを使う場合には、Spring Dataに含まれるプロジェクトであるSpring Data JPAを利用することで、ページング等を簡単に実現することができます。

H2の起動

データをデータベースに保存できるようにしましょう。

今回はデータベースとしてH2を利用します。

ちなみにGlassFishにはJava DB(中身はDerby)が付属しているので、こちらを利用することもできます。

zipをダウンロードしたら、適当な場所に展開し、次のようにして起動します。

% cd bin
% java -cp h2-1.4.180.jar org.h2.tools.Server &
TCP server running at tcp://XXX.XXX.XXX.XXX:9092 (only local connections)
PG server running at pg://XXX.XXX.XXX.XXX:5435 (only local connections)
Web Console server running at http://XXX.XXX.XXX.XXX:8082 (only local connections)

ブラウザが自動的に開いてH2コンソールが表示されます。各項目を入力して[保存]をクリックします。

設定名
MyFirstSpringApp (Server)
ドライバクラス
org.h2.Driver
JDBC URL
jdbc:h2:tcp://localhost/~/tmp/myfirstspringapp
ユーザ名
sa
パスワード
password

H2console

設定名はなんでもOKです。JDBC URLはアプリケーションからアクセスするときに使うURLです。この場合、起動したユーザのホームディレクトリ(~)のtmpディレクトリに、myfirstspringapp.mv.dbというファイルに保存されるということになります。ユーザ名・パスワードは任意に設定できます。

[接続]もしくは[接続テスト]をクリックして、接続できるか確かめておきます。

ライブラリのアップデート

Spring Framework 4.0.6がリリースされました。バグフィックスも行われているので、アップデートしておきましょう。

dependenciesの追加と同様に、build.gradleの「4.0.5」(2箇所)を「4.0.6」に書き換えて、更新ボタンをクリックします。

注意しなければならないのは、「Artifactの設定は自動的に変わらない」ということです。

Artifact2

赤く表示されている古いライブラリを削除して、Available Elementsにある新しいライブラリを追加します。

パラメータを受け取りコントローラで処理する

パラメータ(HTMLのformで送ることができる値)を受け取ってみましょう。

ここでは例として「足し算」を行います。2つの数値をフォームから送信し、その数値を足し算してページに表示します。

HTMLによるフォームは次のようになります。数値を入力して送信ボタンを押すと、actionで指定したURLにパラメータとともにリクエストされます。input要素のname属性で参照のための名前(ここでは「a」と「b」)を指定します。formのmethod属性では、getかpostが指定できます。getの場合はURLに「?a=1.2&b=3.4」といった形でパラメータが付加されます。

足し算した結果を表示するページは次のようにします。

コントローラは次のようにします。

受け取りたいパラメータは、@RequestParamアノテーションをつけてメソッドの仮引数として指定します。@RequestParamの後ろのカッコ内には、input要素のname属性と対応するように指定します。このようにすることで、パラメータを普通のメソッドの引数と同じように扱うことができます。

実行例
Sample3a

Sample3b

もちろん、仮引数の型がdoubleなので、doubleと解釈できない文字列の場合はエラーになります。ビュー側で数値以外が入力できないようにしたり、コントローラではStringで受け取って適切なエラー処理をする等といった処理を(必要に応じて)行うとよいでしょう。

コントローラからビューに値を渡す

コントローラからビューに値を渡す方法(の1つ)に、ModelMapを使う方法があります。

メソッドの仮引数に、ModelMapを指定することで使えるようになります。

ModelMapのaddAttributeメソッドで、名前と値を指定します。ここでは、messageという名前で「こんにちは」を、diceという名前で1〜6の範囲の乱数をビューに渡します。

ビューでは、要素の属性としてth:textを追加します。属性の値は${名前}で指定します。これにより、要素の子要素(タグで囲まれた部分)がコントローラーから渡された値で置き換わります。

Sample2