当社の新人エンジニア研修のWebアプリケーションでは、MVCモデルを理解することを当面のゴールとしています。

なぜなら、皆さんが実務につくと使用するであろう各種フレームワークがMVCモデルを考慮して作られているからです。

フレームワークの例としては、JavaのSpring Framework、C#のASP.NET Core MVC、PythonのDjangoRuby on Railsなどが有名です。

この章では、 MVCモデル の概略を紹介して、この後の章のガイド的な役割を果たします。

1. MVCモデルとは?

WebアプリケーションにおけるMVCモデルとは

  • 通常のJavaクラス(やJavaBeans)であるModel
  • 入出力を担当するJSPで作るView
  • ユーザーからの入力を受けて処理をModelに振り分けたり出力のViewに返したりするController

からなる部品で構成するモデルです。

それぞれの頭文字を並べてMVCモデルと呼ばれています。

ややこしいのですが、Mのモデルと「MVCモデル」のモデルでは意味が違います。

そのためかMVCパターンともいいます。

MVCモデル はデザインパターンと呼ばれるものの一種で、過去のエンジニアが解決してきた設計のベストプラクティスがまとめられているのです。

あとでDAOパターンというものも学ぶ予定です。

  • ブラウザからのリクエストで送られたデータはServletが受け取ります。
    Servletはアプリケーションサーバー上で動くJavaプログラムです。
  • Servletは必要なJavaのクラスをインスタンス化し、処理を委ねます。
  • ServletはデータをJSPに送りJSPが出力画面を作ります。
    JSPは、【Java Server Pages】の略で、Servletと同じく アプリケーションサーバー上で動くJavaプログラムです。
    HTMLと組み合わさって出力画面を作ります。
  • 最後に、JSPがレスポンスとしてブラウザに返されて画面に表示されます。

MVCモデルの概念を下図1にまとめます。

図2.1 MVCモデルとは

2. なぜMVCモデルなのか?

MVCモデルが考案された理由を一言で説明すると、画面とロジックを別々に開発するためです。

皆さんが目にするWebアプリケーションも画面はとてもオシャレで洗練されていると思います。

それもそのはず、それらの画面はプロのデザイナーが作っているからです。

一方、皆さんが使っているWebアプリケーションは機能が豊富だと思います。

その機能を支えるロジックは皆さんと同じプロのITエンジニアが作っています。

デザインと機能、この両方を一人の人間が担当するのは困難です。

また、画面(View)と処理(ModelとController)を分けることで不具合時に原因を特定することが容易になったりシステムの更新がやりやすくなるのです。

そのような理由から、Webアプリケーションの主流はMVCモデルになっている訳です。

3. MVCモデルの簡単な例

ここからは、最も単純な例を使ってMVCモデルを紹介しましょう。

下図2のようなプロジェクト構成を元に解説します。

必要なデータは講師から受け取るか、解説のソースコードをコピーしてください。

この中のファイルではModelが①のKazuate.javaに、Viewが②のresult.jspに、Controllerが③のGameServlt.javaに対応しています。

図2.2 プロジェクトの構成

上記のプロジェクト構成を先のMVCモデルに当てはめると下図3のようになります。

図2.3 MVCモデルの例

※この図ではブラウザ側にindex.htmlが書かれているが、これは以前のレスポンスでサーバからブラウザに送られたファイルである

先のプロジェクトの構成のファイルがどこに書かれているか分かりますか?

JavaSEの卒業課題で作成したような数当てゲームのクラスがあるとします。

かなり簡略化して以下のようなクラスです。

MVCモデルでいえばModelです。

  • このクラス名はなんですか?
あなたの答え:
  • フィールドはいくつあって、型は何で、名前は何ですか?
あなたの答え:
  • コンストラクタでは何をしていますか?
あなたの答え:
  • メソッドはいくつありますか? それぞれのメソッドの引数、戻り値の型、処理の内容を答えてください。
あなたの答え:

これらの質問に答えられない場合、「新人エンジニア研修向けJava解説16テーマ」に戻って復習の必要があります。

以下のテストクラスを使って動作を確かめてみてください。

ここでは、このKazuateクラスを使ってWebアプリケーションとしても遊べるようにしてみましょう。

(このようにあるシステムを別の環境でも動くようにすることを「移植」するといいます)

Webアプリケーション特有の詳細な文法の説明は後の章に譲り、大きな流れに着目して解説します。

皆さんはHTMLを学びましたね。

まずは、下図2.4のような入力画面を作ります。

図2.4 ここでは例として5を入れている

ソースコードは以下のようになります。

  • このフォームのメソッドはなんですか? また、このメソッドの特徴はなんでしたか?
あなたの答え:
  • このフォームの部品には何が使われていますか? また、リクエストパラメータは送信先で何という名前で扱えますか?
あなたの答え:
  • 送信ボタンを押した後のアドレスバーの表記はどうなりますか?
あなたの答え:http://localhost:8080

9行目でmethod = "get" とありますからhttpプロトコルのgetリクエストを使って/03_JavaWebText/GameServletにフォーム入力したデータを送っています。

10行目でname ="guess"とありますからリクエストパラメータにはguess(推測)という名前を付けてデータを送っています。

したがって「送信」ボタンを押した後のURLは下図2.5のようになります。

図2.5

先のテストクラスとの対比でいえば、この入力の部分は下表2.1のような対応関係になります。(ポイントは太字にしています。以下同様)

JavaSEの場合の記述JavaWebアプリの場合の記述

Scanner sc = new Scanner(System.in);
int guess = sc.nextInt();
<form method=“get” action=“/03_JavaWebText/GameServlet”>
<input type =“text” size =“10” name =“guess”>
<button type="submit">送信</button>
</form>
表2.1 入力部分のソースコード比較

次に、 以下のGameServlet.javaを見てみます。

サーブレットは拡張子が「.java」となっていることからも明らかなように通常のJavaプログラムです。

ただし、Webアプリケーションでの役割としてはHTML(やJSP)から受け取ったデータを処理して他のサーブレット(やJSP)に返す役割に限定されています。

MVCモデルでいえばControllerですね。

サーブレット特有の文法は無視して、JavaSEの知識でこのサーブレットを読み解いてみましょう。

  • このクラスの名前は何ですか?
あなたの答え:
  • このクラスのスーパークラスの名前は何ですか?
あなたの答え:

全てのサーブレットは HttpServlet クラスを継承したクラスです。

  • このクラスにフィールドとメソッドはそれぞれいくつありますか?
あなたの答え:
  • このクラスのメソッド名、仮引数、戻り値を答えなさい。
あなたの答え:
  • このクラスのメソッドの後ろについているthrowsキーワードは何のためにありますか?
あなたの答え:

これらの質問に答えられない場合も「新人エンジニア研修向けJava解説16テーマ」に戻って復習の必要があります。

ここからはサーブレット特有の文法の説明です。

  • 10行目のurlPatternsというのは、このJavaクラス(サーブレットという特殊なクラスです)がどのようなurlで呼び出せるかということを表しています。
    今回は、「 GameServlet 」という名前で呼ばれることを表しています。
  • 14行目のdoGetというのは、getリクエストでデータが送られた場合は、このメソッドが働くということを意味しています。
    他にdoPostメソッドがありますが詳しくは後述します。
  • 16行目のrequest.getParameter("guess")という記述は、この一文でHTMLフォームから送られた guess という名前のついたデータという意味になります。
    上記のサーブレットではこの後に"5"という文字列として受け取ったデータを数値に変換しています。
    この処理を忘れるとIDEが注意してくれます。
    無視して実行しても500エラーが出ます。(試してみましょう)
  • 21行目のrequest.setAttribute("message", kazuate.checkTheAnswer(num))という記述は、同一リクエスト間で有効な request 属性という記憶領域に kazuate.checkTheAnswer(num) の返り値の文字列をmessage という名前で保存することを意味しています。
    MVCモデルでは関係するJSPとサーブレットの間で情報を共有するためにはリクエスト属性を利用するのが一般的です。
    リクエスト属性にデータを保存することで他のページでデータ(今回はmessageの内容)を取り出すことができるようになるのです。
  • 23行目の部分はresult.jsp に出力を依頼するための記述になります。

この部分を先のJavaSEのテストクラスと対比すると下表2のようになります。

MVCモデルでいえばModelがKazuateクラスでしたね。

JavaSEの場合の記述JavaWebアプリの場合の記述

Kazuate kazuate = new Kazuate();
String message = kazuate.checkTheAnswer(guess);
int answer = kazuate.getTheAnswer();
String str = request.getParameter("guess");
int guess = Integer.parseInt(str);
Kazuate kazuate = new Kazuate();
request.setAttribute("message", kazuate.checkTheAnswer(guess));
request.setAttribute("answer", kazuate.getTheAnswer());
request.getRequestDispatcher("02MVC/result.jsp").forward(request, response);
表2.2 処理部分のソースコード比較

実験1

doGetメソッドの修飾子がprotectedであるのはどういう理由によるものでしょうか?

例えば、publicにしても動作するでしょうか?

privateではどうでしょうか?

パッケージプライベート(修飾子なし)ではどうでしょうか?

調べてみましょう

サーブレットはフィールドを持たないことが一般的です。

なぜ、サーブレットにフィールドを持たせないのでしょうか?

どのような問題があるのか調べてみましょう。

出力のイメージは下図2.6のとおりです。

<アウトプットイメージ>

図2.6 入力値の5に対してコンピュータの値が2の場合の表示例

この画面のソースコードであるresult.jspというファイルを見てみましょう。

MVCモデルでいえばViewでしたね。

ここでのポイントは10行目、11行目の${}という書き方です。

この記述をEL【Expression Language】といいます。

先のサーブレットで以下のようにメッセージにmessage、答えにanswerという名前を付けていました。

request.setAttribute("message", kazuate.checkTheAnswer(guess));
request.setAttribute("answer", kazuate.getTheAnswer());

そのため同じ名前でJSP側でも呼び出すことが可能なのです。

ここまでの結果を一覧表にすると下表3のようになります。

JavaSEの場合の記述JavaWebアプリの場合の記述

Scanner sc = new Scanner(System.in);
int guess = sc.nextInt();
<form method=“get” action=“/03_JavaWebText/GameServlet”>
<input type =“text” size =“10” name =“guess”>
<input type =“submit” value =“送信">
</form>

Kazuate kazuate = new Kazuate();
String message = kazuate.checkTheAnswer(guess);
int answer = kazuate.getTheAnswer();
String str = request.getParameter("guess");
int guess = Integer.parseInt(str);
Kazuate kazuate = new Kazuate();
request.setAttribute("message", kazuate.checkTheAnswer(guess)); request.setAttribute("answer", kazuate.getTheAnswer()); request.getRequestDispatcher("02MVC/result.jsp").forward(request, response);

System.out.println(message);
System.out.println("答えは" + answer);
${message}<br>
 答えは${answer}
表2.3 JavaSEとの比較

細かい記述を無視すれば概ね同じと言えるのではないでしょうか?

下図2.7に数当てゲームのJavaWebアプリを図示しておきますので本章の振り返りに使ってください。

kazuate1
図2.7 数当てゲームのイメージ

研修内容がWebアプリケーションに入ると急速に難しくなったと感じて脱落してしまう新人エンジニアの方がいらっしゃいます。

本当は多少ややこしくなっただけで、本質は今までやってきたInput,Process,Outputなのですが。。。

ただ、Webアプリケーションの方が一般的にファイル数が増える点、ファイルの場所がフォルダとJavaパッケージに分かれる点も慣れるまでは大変かと思います。

したがってこれまでのJavaSEとこれからのMVCモデルを使ったJavaWebアプリは何が同じで何が違うのか?

その点に気をつけて学んでいただければと思います。

今回はMVCモデルについて学びました。

次回は、サーブレットからJSPにデータを渡して表示する方法を学んでいきます。

<まとめ:隣の人に正しく説明できたらチェックを付けましょう>

□MVCモデルを理解することが本研修のゴール

□ MVCモデルとは、通常のJavaクラスであるModel、入出力を担当するJSPで作るView、ユーザーからの入力を受けて処理をModelに振り分けたり出力のViewに返したりするControllerからなる3つの部品で構成するモデルである

□ MVCモデルが考案された理由は画面とロジックを別々に開発するためである

□ JavaSEで利用・作成してきたクラスもおおむねModelとして使用できる

JavaWebアプリケーション目次に戻る