LoginSignup
39
46

More than 1 year has passed since last update.

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

Last updated at Posted at 2020-06-25

注意

これは自分用のメモです。未熟な雑魚Springユーザーが書いたものなので、きっと間違いもあります。ご容赦ください

Spring MVC

MVCパターンはwebアプリケーションの開発に使われるパターンで、初めてreilsでポートフォリオを作ろうとしたときに僕は初めて知りました。ただ、SpringMVCは厳密にはフロントコントローラーパターンと呼ばれるアーキテクチャパターンで、僕も十分に理解できていないが、全てのリクエストを一旦受け取るフロントコントローラーとと呼ばれるコントローラーを実装したパターンらしい。
一方、SpringMVCの特徴は以下の通りです。

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

SpringMVCのアーキテクチャパターンを知ろう

スクリーンショット 2020-06-10 9.26.06.png

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

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

  • DispatcherServlet
  • HandlerMapping
  • HandlerAdapter
  • ViewResolver
  • view

以下それぞれの説明さ!

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

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

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

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

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

リクエストを受けてからレスポンスを返すまでの流れ

例として、リクエストがあってからレスポンスを返すまでを図で見ていくよ!
スクリーンショット 2020-06-13 15.47.03.png
DispatcherServlet:「あ、リクエスト来た!HandlerMapping君、コントローラーをおくれ!」
HandlerMapping:「仕方ねーな。お前がそう言うなら。必殺!getHandlerメソッド!」
HandlerMapping:「そのリクエストに対するControllerだよ。どうぞ。」
DispatcherServlet:「あんがと」
スクリーンショット 2020-06-13 15.47.22.png
DispatcherServlet:「次はcontrollerのメソッドを実行したいから、、、HandlerMapping君!!!」
HandlerMapping:「おけ。必殺!handleメソッド!」
HandlerMapping:「実行したらview名帰ってきたから、渡しとくね」
DispatcherServlet:「あざまる」
スクリーンショット 2020-06-13 15.47.41.png
DispatcherServlet:「このview名のviewが欲しいのだが、知ってる?ViewResolver君」
ViewResolver:「知っとるよ。このviewでしょ。はい。」
DispatcherServlet:「ありがとー。じゃあこいつをレンダリングしてもらって良いですかな?Viewインターフェース君」
View:「任してくれよな。動けレンダリングエンジン!!これでレンダリングできたよ〜」
DispatcherServlet:「ありがと〜。じゃあこいつをレスポンスとして渡す〜。はいよ。」
クライアント:「ありがとね〜」

FormオブジェクトとかEntityオブジェクトとの連携!

スクリーンショット 2020-06-14 10.18.25.png
EntityとかFormオブジェクトがどうやってviewに反映されてるんだい!って思うのでそれをこの図で紹介。フロントコントーラーが作るModelってのが。一時的な倉庫の役割をやってくれていて、そこにControllerがFormやEntityをぶち込むことによってviewはその倉庫から必要な材料を取り出しているって感じ。

DIコンテナとの繋がり

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

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

DispatchServletクラスを複数持つことってあるの?って思ったけど『API用』と『UI用(webページ用)』とかのように分けて実装することがあるとのこと。なるほどなるほど。
スクリーンショット 2020-06-13 18.02.05.png

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

サーブレットコンテナとservlet、DIコンテナの繋がり

スクリーンショット 2020-06-14 10.45.15.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についてはこちらがわかりやすかった。

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クラスを作ります!

@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クラスをアプリケーションコンテナを作る時に利用します!っていう設定とのこと。参考
③:ハンドリングするURLのパターンを指定し、ハンドリングしたリクエストをどのサーブレットクラスで捌いてもらうかを<servlet-name>タグで指定。ここではwebアプリに対する全てのリクエストをappと言う名前のクラスで捌くように指示している。appの名前がついているのは①のDispatcherServletなので、こいつに渡すことになる。

ViewResolverのセットアップ

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

@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のアプリケーションのこと。ここがわかりやすい。
  • プレゼンテーションロジック:ユーザーが向き合う画面のロジック
  • ビジネスロジック:データ処理を行うところ
  • WARファイル:http://e-words.jp/w/WAR%E5%BD%A2%E5%BC%8F.html
  • Handler:controllerのこと。
39
46
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
46