JSP-サーブレットのMVCモデルとリダイレクト・フォワード、スコープについて

#MVCモデル
　Model,View,Controllerモデルの略で、それぞれ「処理」「結果表示」「統括」を担当する。
　ユーザ側のリクエストをコントローラが受け、コントローラはモデルにデータ処理を依頼し、モデルは処理したデータをコントローラに返し、そのデータはビューに渡され、ビューは成形してユーザにレスポンスとして返す、といった形になる。

　サーブレット・JSP環境では、コントローラをサーブレットクラスが、ビューをJSPが、モデルを通常のJavaのクラスが行うことが多い。
　こうする利点の一つに、複数分野にまたがる知識がなくても分担して開発することができる、という利点がある。

<img width="532" alt="01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562235/59eb4f7b-1328-4fe1-75bd-6a97e8d8f01f.png">

#フォワードとリダイレクト
　サーブレットクラスからJSPやほかのサーブレットクラスにページを遷移する方法として、フォワードとリダイレクトの2つがあげられる。
　フォワードは同一のアプリケーション内でしか移動できない代わりに早く、またブラウザのアドレスバーには最初のリクエスト先の情報が残るといった特徴がある。
　対してリダイレクトはファイルや別アプリケーション（別サイト）にもアクセスできる代わりに遅く、ブラウザのアドレスバーにある情報も変更されるといった特徴がある。

<img width="532" alt="02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562235/d55d0657-46c6-8e02-29fc-15d4b9fdd8e9.png">

##処理用のメソッド
###フォワード
*ServletRequest#getRequestDispatcher(String)*  … String で指定した先にデータを転送するためのオブジェクトを生成する。
*RequestDispatcher#forward(ServletRequest,ServletResponse)*　… Dispatcher のもつ転送先が代わりにレスポンスを行うフォワードを行う。このメソッドは通常の Response が返る前に行われる必要がある。
###リダイレクト
*HttpServletResponse#sendRedirect(String)*　… String で指定したURLに転送する指示をResponceとしてクライアントに出す。

##jspファイルの置き場所
　Webcontent/WEB-INF/下に保存したjspファイルは、ブラウザからの指示を受けて開くことはできないので、直接リンクされたくない場合に利用できる。
　また、ブラウザから直接開けないという性質から、フォワードからの表示は可能だがリダイレクトはできなくなっている。

#スコープ
フォワードやリダイレクトを使っても、そのままではデータを保存・送信することはできない。
スコープと呼ばれる領域にデータを保存することで、サーブレットやJSPの間でデータを共有することができる。

##共有のための条件
保存できるデータはインスタンスのみで、
　・java.io.Serializableを実装して直列化可能であること
　・クラスはパッケージに属していること
　・デフォルトコンストラクタ（引数なしのコンストラクタ）をpublicで持つこと
　・フィールドはカプセル化され、かわりに命名規則に従ったgetter/setterを持つこと
が共有するためのルールとして設定してある。

##共有する範囲
　スコープは保存範囲で４つに分けられ、それぞれ「ページスコープ」「リクエストスコープ」「セッションスコープ」「アプリケーションスコープ」と呼ばれている。
###ページスコープ
　範囲はそのページ内のみ。今回は割愛する。
###リクエストスコープ
　範囲はリクエストをされてからレスポンスが返るまで。
　入力されたデータをもとに計算結果を表示、といったWebアプリケーションに使える。
###セッションスコープ
　範囲はセッションの間。
　登録フォームなどで一時的に入れた値を何度か使うときに必要。
###アプリケーションスコープ
　投票ボタンなど、ユーザ全体で共有・参照するデータを扱うときに使う。
　アプリケーション終了時に破棄される。

##保存・取り出し方法
　スコープごとに異なるクラスの、名称と引数が共通したメソッドで保存・取り出しができる。

　**保存メソッド**
　*setAttribute(String,Object)* … String で指定した名前で認識されるObjectインスタンスを保存する。同じ名前のものを入れると上書き、 Object が null ならその名前のものの削除になる。

　**取得メソッド**
　*getAttribute(String)*　… String で指定した名前で認識されるインスタンスを取り出す。その名前のデータがない場合、 null が返ってくる。その中からデータをさらに取り出す場合はキャストを行う必要がある。

###リクエストスコープの場合

　利用するクラス：***ServletRequest***クラス

　JSPには暗黙オブジェクトという**明示的に宣言しなくても変数として利用できる変数**がいくつかあり、*ServletRequest*型で参照される「現在のリクエスト」は***request***で暗黙的に扱うことができる。


###セッションスコープの場合
　利用するクラス：***HttpSession***クラス

　データを保存する場合も取り出す場合も「使用しているセッション」のインスタンスを取り出す必要がある。
　*HttpServletRequest#getSession()*　で取り出すことができ、それを *HttpSession* 型の参照変数に入れて扱う。
　こちらも暗黙オブジェクトがあり、「現在利用中のセッション」を***session***で暗黙的に扱うことができる。

####セッションスコープ利用時の注意点
　複数人のセッションスコープを同時に管理するために、クライアント側とサーバ側でセッションIDを共有し、サーバ側でスコープとセッションIDを紐付けておく必要がある。
　そうすると、クライアントの数だけスコープを用意することになり、メモリのパンクが考えられるため、適宜スコープの中身やセッションの破棄を行う必要がある。一定時間利用されていないセッションをガベージコレクションの対象として破棄する、セッションタイムアウトがその一例である。

また、短時間のリクエスト集中に耐えやすいようにするために、それらの破棄を自主的に行うメソッドが用意されていて、開発者が適切に利用する必要がある。

###アプリケーションスコープの場合
　利用するクラス：***ServletContext***クラス

　こちらもセッションスコープと同様に、「使用しているアプリケーション」をのインスタンス取得する必要がある。
　これの暗黙オブジェクトは***application***の変数名で扱われる。メソッドとして取得する場合は *HttpServlet#getServletContext()* で取り出すことができる。

####アプリケーションスコープ利用時の注意点
　アプリケーションスコープには全クライアント共通の領域としてデータを保存できる。ただし、サーバ側にデータが残るのは一時的なものでしかないので、サーバの終了と同時に終了したアプリケーションの持つスコープは破棄される。
　再起動後にもそのデータを扱いたい場合は、ファイルなどの形にして残す必要がある。

###　
|スコープの種類|リクエストスコープ|セッションスコープ|アプリケーションスコープ|
|:--|:--|:--|:--|
|スコープ範囲|リクエストがレスポンスされるまで|セッションが破棄されるまで|アプリケーションが終了するまで|
|利用クラス|*ServletRequest*|*HttpSession*|*ServletContext*
|クラスの暗黙オブジェクト|***request***|***session***|***application***
|主な用途|入力フォーム|ログイン情報|共通データ|
|その他注意|リダイレクトでは一度レスポンスを返すため利用できない|データが溜まるとサーバに負荷がかかるので適宜破棄する|データを再利用したい場合はファイルなどに出力する