イントロダクション
前回はSpringframeworkを使用してMVCモデルのうち「C(Controller)」と「V(View)」を実装しました。Controllerから、View(HTML)に値を渡すところまで実装しました。
Controllerでは、次の2つの方法でレスポンスを返すことができることを学習しました。
-
文字列を返却する方法は下のように、返却値が文字列になっています。
@RequestMapping("/") public String index(ModelAndView mav) { return "<html>" + "<title>Hello World</title>" + "<body><h1>こんにちは</h1>" + "<p>~PGボックスより~</p>" + "</body>" + "</html>"; }
-
HTMLを返却する方法は下のように、ModelAndViewクラスを返却します。
@RequestMapping("/") public ModelAndView index(ModelAndView mav) { mav.setViewName("book"); return mav; }
HTMLの場合は、Timeleafを使用しているので「resources/templates」の下に配置します。そして、例のコードでは「book.html」を返却します。
Modelを実装する
今まで、MVCモデルの「V」と「C」を学習してきました。ここら辺は、下の図で見ると簡単です。
全体の動きをイメージする
ブラウザで自分が運用しているウェブサイトの画面を開くことをイメージしてください。サーバーの設定ではJavaアプリケーションなので「WAR」ファイルとか「EAR]ファイルをアップロードすることになります。
PHPやHTMLをアップロードするようなサーバーを使ったときは、ドキュメントルート「/」のフォルダにPHPとかHTMLファイルを配置します。
Javaの場合は、リソース(画像ファイルやテキストファイルなど)を圧縮して先ほどの「WAR」や「EAR」にするのでドキュメントルートとかを意識しずらいですが、Javaでもやはりルートからディレクトリ構造ができています。
自分で作成したアプリをテストするときに「localhost:8080/」とブラウザのURLを入力して初期画面表示を行うと思いますが、「/」がルートを示します。
Javaコードでは「@RequestMapping("/")」のように実装しました。つまり、実際にファイルは配置していないけどURLでディレクトリ構造を作ることができます。HTMLファイルをここで指定するように配置するとURLとファイルの配置が結びついてわかりやすくなります。
この部分も自由に実装することができます。
Modelとは?
話をModelに戻します。上記の全体像を踏まえたところで、MVCの「V」と「C」はイメージがついていると思います。
今度は、MVCの「M」について学習します。
<例としてECサイトを見ます。>
よくあるECサイトを思い出してください。実際に存在する店舗の情報や、商品の情報をブラウザで見てクレジット決済を使用して購入できます。
この時に、「ウェブサーバー」と「商品」、「運送方法」に関して考えてみましょう。
1.ブラウザで商品を選択する
ブラウザで商品を選択して、購入します。この時に購入した商品は、元々どこにあったのでしょうか?商品だから「在庫」があることを確認する必要があります。
つまり、在庫にあった商品をブラウザで表示しているということです。この「在庫」を管理しているのはまた別のシステムになりますが、これはシステム同士で情報をやり取りする形で連携をしています。
具体的には、「在庫管理システム」と「商品受注システム」の連携が生じるということです。
2.商品をあなたに届ける
受注を受けたので、在庫が一つ減ります。しかし数字だけ減らしてもそれでは「商売」になりません。
受けた注文に対して「商品を届ける」というミッションが発生します。
これをどのように行うかは各社で方法がありますが、AMAZON社は配送するための仕組み=システムを構築しているようです。
ウェブシステムをメインで作成、管理しているところは「AWS」という会社で行っているらしいですが。。。
このような形で「ウェブシステム」→「アナログシステム(仕組み)」と連携して商品が手元に届きます。
Modelの存在
システム間で連携して、一連の作業を行っていることが多いのですが、ウェブシステムでも似たようなことが起こっています。
それは、MVCモデルでも同様です。
MVCの「V」でユーザーの操作を受け取ります。具体的には「商品を選択する」という操作を「リクエスト」という形でブラウザからサーバーへ通知を受け取ります。そして、サーバーサイドで何かしらの処理を行うのですが、これをちょっと分解してみてみましょう。
ウェブ画面の商品
ブラウザ(ウェブ画面)上の商品は明確に言うならば「イメージファイル」です。拡張子が「gif」とか「jpg」になっているファイルです。
これを、ユーザー(あなた)がクリックしたときに、サーバーへ「リクエスト(Request)」が送信されます。送信するのはユーザー(あなた)が使用しているPCです。もっと具体的に言うならば、ブラウザ(ChromeやEdge)です。
送信された「リクエスト」はサーバーへ届きます。言葉を変えるなら「V(View)」から送信されたリクエストを「C(Controller)」で受け取ります。
※HTML(View)にはクリックしたときにどこへ送信するか指定するタグやリンクを設定してあります。
この時に、どのコントローラーで受け取るのかはHTML側で決められているので、動きとしてはHTML→Javaソースとなります。これは今まで学習してきた「V」から「C」へリクエストが送信される部分に当たります。
本題のModelについて
「V」から「C」へリクエストが送信されるのはわかったけれど、「商品」の扱いが全然出てきませんね。
そうなんです。「商品」はDBや、サーバーに配置されているファイルを参照する必要があるので「C(Controller)」は、触らないことになっているのです。
なぜならば、それは「M(Model)」の役目だからです。コントローラーから受けたリクエストに応じて「何かしらの処理」を行うのが「M(Model)」の役目です。なので「ロジック(Logic)」とか呼ばれていることも多いです。
まとめると、下のように役割を分担した形が「MVCモデル」ということなのです。
- M: ModelはDBやファイル(リソース)にアクセスして何かしらの処理を行う
- V: Viewはユーザーの操作、入力を受け取りそれ(Request)をControllerに送る
- C: ControllerはViewからのRequestを受け取りModelを呼び出しその処理結果をViewに返す
順番がごっちゃになっていますが、「MVCモデル」は上記のような分担を行った実装方法ということです。
Mmodelを作る
今までの解説のように、Modelは「何かしらの処理」を行うので、「1+1」の計算結果を返しましょう。
ちなみに「デフォルトコンストラクタ」はインジェクション(newしないでインスタンスを取得する)時に必要になるので作製しています。
public class SamplModel {
/** デフォルトコンストラクタ */
public SamplModel() {
}
public int sampleLogic() {
return 1 + 1;
}
}
MVCの「M」を呼ぶ
MVCモデルの「V」「C」に関しては割愛しますが、「C」から「M」を呼び出してやる必要があります。
図にすると下のようになります。
ControllerからViewを呼び出すのには、「ModelAndView」クラスを使用します。このクラスはSpringframeworkの部品です。
そして、ControllerからModelを呼び出すのには、直接プログラムを書きます。
今回は、簡単に「new」してModelを呼び出しました。
このModelを呼び出す方法に関しては、依存性の注入という言葉があり、カタカナでは「インジェクション」といいます。
早い話が、Springframeworkであれば「@Service」アノテーションを使用してModelを呼び出す方法です。
ちなみに、JavaEEというテクノロジー(仕様)では「@Inject」で呼び出すことができます。「CDI」という言い方をしていますが結局は「インジェクト」です。
インジェクション
「インジェクト」を行うことを、このように言います。もう日本語も英語も区別がつきませんね(笑)
「@Inject」「@Service」などのアノテーションをつけてクラスのインスタンスを取得する方法です。
よくあるのはControllerクラスのフィールドにインスタンスを注入(インジェクト)する方法です。
具体的なコードは下のような形です。Serviceインターフェースを実装(implements)して実行することもあります。
ちなみに、ServiceインタフェースはSpringframeworkの部品です。
public MyControler /** implements Service */{
/** サービス */
@Service // Springの場合
MyService service1;
public void execute() {
// サービスの処理を呼び出す。
service1.somethingTodo();
}
}
アノテーションについて
アノテーションはフィールドにつけたり、クラスやメソッドにつけたりできます。まとめた言い方をすると「自身を含めた、クラスの要素(プロパティ)につけることができるインターフェース」のことです。
具体的にはアノテーションを作るときは下のように書きます。インターフェースなんですね。
@Target(ElementType.TYPE)
public @inteface MyAnnotation {
}
細かい作り方は、参考にしたサイトを参照ください。
<<< 前回