Spring MVC についてまとめてみるよ！！！

#注意
これは自分用のメモです。未熟な雑魚Springユーザーが書いたものなので、きっと間違いもあります。ご容赦ください
#Spring MVC
MVCパターンはwebアプリケーションの開発に使われるパターンで、初めてreilsでポートフォリオを作ろうとしたときに僕は初めて知りました。ただ、SpringMVCは厳密にはフロントコントローラーパターンと呼ばれるアーキテクチャパターンで、僕も十分に理解できていないが、**全てのリクエストを一旦受け取るフロントコントローラーとと呼ばれるコントローラーを実装したパターン**らしい。
一方、SpringMVCの特徴は以下の通りです。

１. POJOで実装されてる
POJOってのはシンプルなJAVAのオブジェクトって意味。フレームワーク独自のインターフェースを実装する必要がない！
２. アノテーションを使って開発
リクエストマッピング（ここにアクセスしたらこのメソッドを実行するとか）などをアノテーションを使って記述するのでスッキリ簡単にかける。
３. メソッドシグネチャの定義を柔軟にできる
Controllerクラスのメソッドの引数には様々な型を指定できる。引数に関しても多くの型に対応している。
４. ServletAPIの抽象化
ServletAPIが抽象化できると、Controllerクラスの実装からServletAPIを使うコードを排除できるとのこと。これがどのくらいいいことなのかわかってはいないが、とりあえずコードの記述量が減るっぽい。
５. viewの実装技術の抽象化
viewの実装技術を意識しなくても、view名さえ指定してあげればviewを返却できる。
６. SpringのDIコンテナとの連携
SpringのDIやAOPを活用することができる。

##SpringMVCのアーキテクチャパターンを知ろう
<img width="746" alt="スクリーンショット 2020-06-10 9.26.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565905/9ed5573a-997e-8197-22f6-6ddd02b34cad.png">


SpringMVCではフロントコントローラーパターンと言うアーキテクチャパターンを持っていて、全てのリクエストを一旦フロントコントローラーが受け取り、その後適切なControllerを探しまっせ。と言う感じらしい。
さらにフロントコントローラーの中身を見てきましょ。

フロントコントローラーには以下の５つの部品が存在してます！

- DispatcherServlet
- HandlerMapping
- HandlerAdapter
- ViewResolver
- view

以下それぞれの説明さ！

**DispatcherServlet**
フロントコントローラーのエンドポイントとなるサーブレットクラス。司令塔的な役割を持つ。
図以外のインターフェイスを使用して他にも機能があるが、そこはひとまず割愛。

**HandlerMapping**
リクエストに対するcontrollerを選択する役割を持つ！
`@RequestMapping`アノテーションのついている元に、適切なcontrollerを探すよ。
今時は`@GetMapping`とかを使うかもだけど、どっちでも見つけてくれるよ！

**HandlerAdapter**
controllerのメソッドを呼び出す役割を持つ。
さらにメソッドの引数に値を渡す処理とかも実装されている。
さらにさらに、リクエストをjavaオブジェクトにする処理や、バリデーションとかもやっていくれる。
手広く処理してくれる頼れるやつ。

**ViewResolver**
controllerから返されたview名から、どのviewインターフェースの実装クラスを使うのかを決めてくれる。

**view**
Viewインターフェースはクライアントに返すデータを完成させるよ。

###リクエストを受けてからレスポンスを返すまでの流れ
例として、リクエストがあってからレスポンスを返すまでを図で見ていくよ！
<img width="881" alt="スクリーンショット 2020-06-13 15.47.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565905/4b73bb4a-6fcf-aef7-aa80-b21cd358a901.png">
DispatcherServlet：「あ、リクエスト来た！HandlerMapping君、コントローラーをおくれ！」
HandlerMapping：「仕方ねーな。お前がそう言うなら。必殺！getHandlerメソッド！」
HandlerMapping：「そのリクエストに対するControllerだよ。どうぞ。」
DispatcherServlet：「あんがと」
<img width="856" alt="スクリーンショット 2020-06-13 15.47.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565905/3b04d056-6d30-0b55-a8eb-991bc19c5652.png">
DispatcherServlet：「次はcontrollerのメソッドを実行したいから、、、HandlerMapping君！！！」
HandlerMapping：「おけ。必殺！handleメソッド！」
HandlerMapping：「実行したらview名帰ってきたから、渡しとくね」
DispatcherServlet：「あざまる」
<img width="898" alt="スクリーンショット 2020-06-13 15.47.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565905/b8dd5a1c-bf8a-8c32-9347-51bcd3734e73.png">
DispatcherServlet：「このview名のviewが欲しいのだが、知ってる？ViewResolver君」
ViewResolver：「知っとるよ。このviewでしょ。はい。」
DispatcherServlet：「ありがとー。じゃあこいつをレンダリングしてもらって良いですかな？Viewインターフェース君」
View：「任してくれよな。動けレンダリングエンジン！！これでレンダリングできたよ〜」
DispatcherServlet：「ありがと〜。じゃあこいつをレスポンスとして渡す〜。はいよ。」
クライアント：「ありがとね〜」

###FormオブジェクトとかEntityオブジェクトとの連携！
<img width="640" alt="スクリーンショット 2020-06-14 10.18.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565905/4e3bc8b7-08da-385b-1c81-d0d0f3b45f2d.png">
EntityとかFormオブジェクトがどうやってviewに反映されてるんだい！って思うのでそれをこの図で紹介。フロントコントーラーが作るModelってのが。一時的な倉庫の役割をやってくれていて、そこにControllerがFormやEntityをぶち込むことによってviewはその倉庫から必要な材料を取り出しているって感じ。

###DIコンテナとの繋がり
上記の例ではDispatcherServletが他の部品と連携していたけど、その部品たちは全部DIコンテナに入っておるとのこと。SpringMVCでは以下の２つのDIコンテナ（アプリケーションコンテキストとも言う）を使う。

- WEBアプリケーション用DIコンテナ：WEBアプリに対して１つだけ作る
- DispatchServlet用のDIコンテナ：DispatchServletに対して１つ作る

DispatchServletクラスを複数持つことってあるの？って思ったけど『API用』と『UI用（webページ用）』とかのように分けて実装することがあるとのこと。なるほどなるほど。
<img width="797" alt="スクリーンショット 2020-06-13 18.02.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565905/28dc6707-93cd-0c42-6879-64764a026f25.png">

DispatcherServletはDispatcherServlet用のDIコンテナと繋がっておるんですな。
ちな、それぞれのDIコンテナを作るためにはConfigファイルの作成とweb.xmlに設定をする必要がある。

###サーブレットコンテナとservlet、DIコンテナの繋がり
<img width="681" alt="スクリーンショット 2020-06-14 10.45.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565905/aabfd2d0-cf11-c3cd-45cd-d3003f7a71ec.png">


##SpringMVCを始める前のセットアップ
SpringMVCを始めるにも、まずは準備から。やらなければいけないセットアップは以下の5つ。

1. ライブラリのセットアップ
2. ContextLoaderListenerのセットアップ
3. DispatcherServletのセットアップ
4. CharacterEncodingFilterのセットアップ
5. ViewResolverのセットアップ

###ライブラリのセットアップ
Marvenは以下のように。

```pom.xml
<dependency>
    <groundId>org.springframework</groundId>
    <artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
    <groundId>hibernate</groundId>
    <artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
    <groundId>org.slf4j</groundId>
    <artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
    <groundId>ch.qos.logback</groundId>
    <artifactId>logback-classic</artifactId>
</dependency>
```
gradleならこっちで。

```build.gradle
dependencies {
    compile group: 'org.springframework', name: 'spring-webmvc'
    compile group: 'hibernate', name: 'hibernate-validator<'
    compile group: 'org.slf4j', name: 'jcl-over-slf4j'
    compile group: 'ch.qos.logback', name 'logback-classic'
}
```

###ContextLoaderListenerのセットアップ（DIコンテナを作る）
**アプリケーションコンテキストを生成するために`ContextLoaderListener`クラスをサーブレットコンテナに登録する必要がある**とのこと。アプリケーションコンテキストとはDIコンテナのことだと思っておけば良さそうです・
また、サーブレットコンテナとはjavaのプログラムを動かすためにクライアントからの命令を中継してjavaプログラムを動かしてくれるやつってイメージ。
ContextLoaderListenerクラスをサーブレットコンテナに登録するにはまず、アプリケーションコンテキストにBeanを登録するためのBean定義が必要になる。Bean定義を行うためにはConfigクラス（設定用のクラスみたいな）を作ろう。

```JavaConfig.java
@Configration
public JavaConfig {
}
```
このConfigクラスを使ってアプリケーションコンテキストを作るように設定します。
その設定には`web.xml`という設定ファイルを作って書いていく必要があるとのこと。
web.xmlについては[こちら](https://eng-entrance.com/servlet-web-xml#:~:text=web.xml%E3%81%A8%E3%81%AF%E3%80%81Web,%E3%81%9F%E3%82%81%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82&text=url%2Dpattern%E3%81%8Cservlet%2Dname,%E3%81%B8%E3%81%A8%E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%81%95%E3%82%8C%E3%82%8B%E3%80%82)がわかりやすかった。

```web.xml
<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener　・・・①
    </listener-class>
</listener>
<context-param>
    <param-name>contextClass</param-name>
    <param-value>
        org.springframework.web.context.support.AnnotationConfigWebApplicationConfig　・・・②
    </param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>example.config.JavaConfig</param-value>　・・・③
</context-param>
```
①：サーブレットコンテナのリスナクラスとしてContextLoaderListenerを指定
②：サーブレットコンテナのcontext-paramというパラメータにAnnotationConfigWebApplicationConfigというクラスを指定する。
③：どのConfigクラスを使ってDIコンテナを作るのかをここで指定する。

###DispatcherServletのセットアップ
SpringMVCのフロントコントローラーパターン(MVCの弱点を改善したアーキテクチャパターン)を利用するために、DispatcherServletクラスというものをサーブレットコンテナに登録する必要があるとのこと。それにはwebアプリケーションコンテキストとは別にDispatcherServlet用のアプリケーションコンテキストを作成しなければならないらしい。
DispatcherServlet用のアプリケーションコンテキストが必要ということはそれ用のConfigクラスを作る必要があるということ。というわけでDispatcherServlet用のConfigクラスを作ります！

```java
@Configration
@EnableWebMvc　・・・①
@ComponentScan("example.app")
public class WebMvcConfig extends WebMvcConfigureAdapter {　・・・②
}
```
①：`@EnableWebMvc`を指定することでSpringMVCが提供するコンフィギュレーションクラスがインポートされ、SpringMVCを利用するのに必要となるコンポーネントのBean定義が自動で行われる。
②：WebMvcConfigureAdapterクラスを継承することで、デフォルトで提供されるBean定義を簡単にカスタマイズできるようになる。

続いて、DispatcherServletクラスをサーブレットコンテナに登録します。その際に、先ほど作成したDispatcherServlet用のConfigクラスを使ってアプリケーションコンテキスト（DIコンテナ）を生成するように定義します。

```web.xml
<servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet　・・・①
    </servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationCofigWebApplicationContect　・・・②
        </param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>example.config.WebConfig</param-value>　・・・③
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/</url-pattern>　・・・④
</servlet-mapping>
```
①：フロントコントローラー（全部の処理を一旦受け取るコントローラー）を設定するタブの`<servlet-class>`に`DispatcherServlet`クラスを登録する。こいつはspringが提供してくれているクラスで、とりあえずこいつを使っておけばいいらしい。このクラスに好きな名前をつけるのだが、今回は`app`にしよう（上の`<servlet-name>`に名前を入力）。
②：contextClassパラメータに`AnnotationCofigWebApplicationContect`を指定。こいつは何か調べてみると、`@Configration`アノテーションのついたConfigクラスをアプリケーションコンテナを作る時に利用します！っていう設定とのこと。[参考](https://www.ibm.com/developerworks/jp/webservices/library/ws-springjava/index.html)
③：ハンドリングするURLのパターンを指定し、ハンドリングしたリクエストをどのサーブレットクラスで捌いてもらうかを`<servlet-name>`タグで指定。ここではwebアプリに対する全てのリクエストを`app`と言う名前のクラスで捌くように指示している。`app`の名前がついているのは①の`DispatcherServlet`なので、こいつに渡すことになる。


###ViewResolverのセットアップ
SpringMVCではビュー名を解決して使用するViewを判別するために`ViewResolver`を使うらしい。
ここではviewにJSPを使うものとしてViewResolverの実装手順を書いていく。

```java
@Configuration
@EnableWebMvc
@ComponentScan("example.app")
public class WebConfig extends WebMvcConfigAdapter {
    @Override
    public void configureViewResolvers(viewResolverRegistry registry) {　・・・①
        registry.jsp();　・・・②
    }
}
```
①：configureViewResolversのメソッドをオーバーライド
②：viewResolverRegistryクラスのjspメソッドを呼び出しJSP用のviewResolverをセットアップする。

これでセットアップは終わりです！お疲れ様です！

##用語集
- メソッドシグネチャ：「メソッド名」「パラメータ数と順序、パラメータの型」「戻り値の型」をまとめた名称
- サーブレット：webサーバーで働くjavaのアプリケーションのこと。[ここ](https://wa3.i-3-i.info/word12836.html)がわかりやすい。
- プレゼンテーションロジック：ユーザーが向き合う画面のロジック
- ビジネスロジック：データ処理を行うところ
- WARファイル：http://e-words.jp/w/WAR%E5%BD%A2%E5%BC%8F.html
- Handler：controllerのこと。