チャートを生成・表示する
ソースコード
変更(追加)
- build.grade: jfreechartをdependenciesに追加
新規作成
- DateController: コントローラ
- テンプレート
実行例
ポイント
- チャート描画はJavaScriptで行うのが一般的だが、ここではJFreeChartを用いてサーバーサイドで生成している。
- 画像ファイルを生成するのではなく、data URIで画像データを表示している。
プログラミングを教える
Gmailを使う場合の例。
昨年度の資料はバージョンが古いので注意する必要があるが、参考になるはず。
前回は、掲示板のデータをデータベースに格納するように(永続化するように)改良した。そこでのポイントは以下の通り。
データベースを使った永続化の扱いの基本はCRUDと言われている。
今回はオンラインメモ帳の開発を通してCRUDを一通り実装してみよう。また、Spring Bootにおけるウェブアプリ開発で使われる基本を紹介する。
前回、テーブルの作成はH2のウェブインターフェースから行ったが、これもプログラムから実行できる。下記はテーブルを作成するプログラムであるが、「IF NOT EXISTS」をつけることによって、テーブルが存在している場合は実行されない(テーブルがない時だけ実行される)。これをコントローラのコンストラクタで実行している。(Lect11Controller.javaの34〜41行目)
レコードを更新するにはUPDATEを使う。更新するカラムを「カラム名 = 値」で指定する。WHEREで更新するレコードを限定する。(Lect11Controller.javaの103行目)
フォームのデフォルト値はほとんどの場合、value属性で設定することができる。これをTymeleafで設定するには「th:value=”${変数}”』をタグにつければ良い。ただし、textareaタグはタグによって挟まれたところ(textareaの子となるテキストノード)がデフォルト値となるので「th:text」を使う。
画面上に表示させないが、フォームで値を送信したい場合、type属性の値として「hidden」を指定する。(edit.htmlの14行目)
レコードを削除するにはDELETEを使う。WHEREで更新するレコードを限定する。(Lect11Controller.javaの112行目)
SELECTでレコードを取得するときには並び順を指定することができる。「ORDER BY カラム名 順番」を付加する。順番はASC(昇順)かDESC(降順)を指定する。(Lect11Controller.javaの50行目)
HTMLにおいて改行はスペースと同様の扱いになる(基本的には。例外はpreタグ等)。このため改行がある場合は、brタグを挿入する等の処理が必要である。色々な方法が考えられるが、今回のコードでは下記のような処理を行なっている。
index.htmlでは操作に関するリンクを動的に生成している。
マッピングの指定(@GetMapping、@PostMapping、@RequestMapping)で「{}」を使うと、その部分を変数として利用することができる。
Lect11Controller.javaの119行目を見てみよう。ここでは「/view/{id}」となっている。これは、/view/1や/view/2といったURLに対応する。
「{id}」の部分を取得するには、メソッドの引数に、カッコ内と同じ文字列(ここではid)を指定して@PathVariableアノテーションを付加する(Lect11Controller.javaの120行目)。
本日の内容: https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/html/boot-features-sql.html
これまで作ったウェブアプリは、起動し直すとそれまでに入力したデータ(例えば掲示板のコメント等)は消えてしまっていた。今回は、入力されたデータを保存することを考えよう。このように、プログラムの実行を終了してもデータが存続する特性を永続性(Persistence)といい、永続性を持たせることを永続化という。
色々な方法がある。
本講義はJavaに関する講義であるが、RDBMSは知っておいた方がいい。実際、ウェブアプリ開発ではRDBMSがめちゃくちゃ使われている。
RDBMSはSQLという言語を使う。様々なRDBMSが存在するが、どれもSQLを使うので、これを知っておけばどのRDBMSでも基本的な操作はできるようになる。
まずはRDBMSを選定しよう。今回は、組み込みで使える(アプリケーションの中に入れてしまうことができる)H2を使う。
次にJavaのプログラムからどのような方法を使ってデータベースにアクセスするかを決めよう。その方法は主に次の2つがある。
JDBCは、SQLをJavaプログラムの中で使ってデータベースを操作する方法で、JPAはO/Rマッパーというもので、Javaのインスタンスをデータベースに格納できる形に変換してデータベースにアクセスする方法(データベースにアクセスするSQLを自動生成する方法)である。
こう説明すると「JPAを使えばJavaだけでOK」と思えるかもしれないが、現状、JPAはSQLをよく知らないと使いこなすことはできない。
というわけで、本講義では、JDBCを使っていく。
build.gradleのdependenciesに下記の2行を追記して「Reload Project」を実行する。
1 2 |
compile('org.springframework.boot:spring-boot-starter-jdbc') compile('com.h2database:h2') |
これで、必要なファイル等が追加される。
H2には、ブラウザからデータベースを操作できるインターフェースが内蔵されている。これはSpring Bootアプリケーションに組み込んだ状態でも利用することができる。
ウェブインターフェースを利用可能にするため、下記の1行をapplication.propertiesに加えよう。
1 |
spring.h2.console.enabled = true |
bootRunで実行し、http://localhost:18080/h2-consoleにアクセスする。
次に各設定項目を入力しよう。
入力して、Connectボタンをクリックすると、SQLの入力画面となる。
掲示板のコメントを格納するためのテーブルを作成しよう。
次のSQL文を入力して、Runボタンをクリックするとテーブルが作成される。
1 2 3 4 5 6 |
CREATE TABLE bbs_comment ( id INT AUTO_INCREMENT PRIMARY KEY, comment TEXT, name TEXT, date TIMESTAMP ) |
「bbs_comment」はテーブル名。Javaのクラスに例えるとクラス名に相当する。
id、comment、name、dateはカラム名。Javaのクラスに例えるとフィールド名に相当する。
INT、TEXT、TIMESTAMPは型で、それぞれJavaのint、String、Dateに対応している(参考: Data Types)。
AUTO_INCREMENTは、自動的に番号をつけることを意味している。だから、保存するときにidには値を入れないで良い。保存されたときに自動的に番号がつく。PRIMARY KEYは、そのレコード(Javaでいうところのインスタンス)における「テーブルの中に保存されているデータのある1行を識別するために必要な情報」を表し、主キーという。Javaにはそういうものはないが(無理やりこじつけるとすればhashCodeかな?)、データベースではレコードを区別するためにあったほうが良い(ほとんどの場合設定するが、なくても大丈夫)。
左側に表のアイコンがついた「BBS_COMMENT」というのができれば作成成功。
登録するには、INSERT命令を使う。
1 |
INSERT INTO bbs_comment ( comment, name, date ) VALUES ('こんにちは', 'たろう', '2017-06-21 13:05:00') |
うまくいったら、「Update count: 1」と表示される。適当に値を変えて、さらにデータを入力してみよう。
データの検索・取得には、SELECTを使う。先ずは全件取得してみよう。
1 |
SELECT * FROM BBS_COMMENT |
「*」は全てのカラムの情報(ここでは、id、name、comment、date)を取得することを示す。
一部のデータを表示(検索)するには、WHERE節を追加する。
1 |
SELECT * FROM BBS_COMMENT WHERE NAME = 'たろう' |
これは、nameカラムの値が「たろう」であるレコードだけが表示される。
プログラムから扱うために、接続についての情報をapplication.propertiesに加えよう。ウェブインターフェースでデータベースに接続する時の情報と同じにする。
1 2 3 4 |
spring.datasource.driver-class-name = org.h2.Driver spring.datasource.url = jdbc:h2:~/webappdb/database spring.datasource.username = sa spring.datasource.password = sa |
コントローラは次のようになる: Lect10Controller.java)。
ベースとなっているLect05Controllerと比較しながらみていこう。
プログラムからJDBCを使いデータベースにアクセスするには、JdbcTemplateクラスを用いる。このクラスのインスタンスを用意し、データベースにアクセスするための各種メソッドを利用すれば良い。
この「JdbcTemplateクラスのインスタンス」をどのようにして用意すればいいだろうか?これまでと同様にnew演算子を使えばいいのだろうか?
Spring Bootの環境においては、一部のクラスは、自分でnew演算子を使ってインスタンス化するのではなくシステムにインスタンス化してもらって埋め込むという「依存性注入(dependency injection、DI)」によって行う。
JdbcTemplateクラスのインスタンスはDIで用意する。これを行なっているのが、コンストラクタである。コンストラクタに@Autowiredをつけると、引数はDIコンテナによってインスタンス化されたものが渡される。それをフィールドとして保持する。
postされたデータをデータベースに登録する。
データを登録するINSERT文を実行するには、updateメソッドを利用する。
第1引数にSQL文を指定する。SQL文の中に「?」をかくと、そこには変数を埋め込むことができる。この「?」をプレースホルダ(placeholder)という。
第2引数以降はプレースホルダに対応した変数を指定する。
最後に、同一サーバの「/lect10/bbs」にリダイレクトする。
データベースからデータを全件取り出して表示する。
データを取り出すSELECT文を実行するには、queryForListメソッドを利用する。このメソッドの戻り値は、レコードのListである。レコードは、カラム名がキーでデータが値となるMapの形となっている。よって、queryForListの戻り値の型は「List<Map<String, Object>>」となる。
取り出したデータからBbsCommentのインスタンスを生成し、表示用のリストに入れていく。
Spring Boot 2.0.2がリリースされた。
自分のプロジェクトもupdateしよう。build.gradleを書き換えればよい。
ポイント:
前回の「ポイント」を再掲
ポイント:
Javaのコレクション(特に下記)調べよう。
「BMIの計算」を例として、「ブラウザから何か入力して、サーバで処理を行い、結果をブラウザで表示する」ということを行ってみよう。サーバに何か送るにはフォーム(HTMLのformタグとその関連タグ)を使う。
処理の流れを次のシーケンス図に示す。
テンプレートとコントローラを作成しよう。
ポイント:
formt要素のaction属性を書かない場合は、同じURLにリクエストを送ることになる。action属性を使わない例は次のようになる。
ポイント:
Javaのコレクション(特に下記)調べよう。
Q: これまでクラスを作った(書いた、定義した)ら、new演算子でインスタンス化しないと使えなかったけど、コントローラのインスタンス化は?
A: フレームワークがインスタンス化してくれる。フレームワークとは「全体の処理・流れ定義(実装)されており、その中の一部に自分のコードを組み込んでいくシステム」のこと。わかりやすい解説としてSoftware framework、ソフトウエアのフレームワークとはなにか等。
前回は、文字をブラウザに表示したが、これでは表現力がなさすぎる。HTMLで表示するようにしてみよう。もちろん、コントローラからHTMLで出力するようにしてもいいが、ものすごく大変なので、テンプレートを用意しそこに文字をはめ込んで表示するようにしよう。
これから作るウェブアプリケーションはSpringのWeb MVCフレームワークを利用している。このフレームワークにおける処理の流れを次の図に示す(http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-servletより引用)。
フロントコントローラがリクエストを適切なコントローラに渡し、コントローラが出力するデータをビュー(テンプレート)が表示するという仕組みだ。このうち、自分で作るのは、「コントローラ」と「ビューテンプレート」である。コントローラからビューに「モデル(要するにデータ)」を渡すことによって表示内容を動的に(つまりメソッド実行時に)変えることができる。
テンプレートエンジン(テンプレートに関する処理を行うソフトウェア)は、前回、SPRING INITIALIZRでプロジェクト作成時に指定したThymeleafが使われる。
テンプレートを利用するコントローラを作成しよう。
前回との違い:
テンプレートを置く場所(基点)はResourcesのtemplatesだ。コントローラで「lect02/hello」とした場合、templatesの中にlect02というディレクトリを作り、その中にhello.htmlというファイルを作る。
NetBeansのパッケージの表示の仕方によっては、作業が難しい。プロジェクトウィンドウの背景部分を右クリックし、「Javaパッケージの表示方法」を「ツリー」にすると階層構造がわかりやすい。または、プロジェクト表示ではなく、ファイル表示にするとわかりやすい。
コントローラでは3つのテンプレートを指定している。それぞれ作成しよう。
ポイント
実行して、確認しよう。
どのようなHTMLが出力されているかはChromeのデベロッパーツール等を使うと良い。
HTMLのフォームについて(特に下記)調べよう。
例えば、BMIを計算するアプリケーションを作るとしたら(とりあえず見た目だけ)、どんなフォームを作ればいいか?