Spring3のSpring MVCでなるべく最小単位のHello world


# 目的
Spring MVCをちょっとかじってみようと思ったときに、webや書籍のサンプルだと大きすぎて取っ付きにくくてちょうど良いものがなかったので、なるべく最小単位の構成で"Hello world"するサンプルを作ってみました。
最小単位なので、DIやAOPはほとんどでてきませんし、DBなんかもでてきません。

# 前提
- STSは使わない（自分の環境制約でインストールできなかったので）
- quick-start的なものは使わない（取っ付きやすいかもしれないが、どこに関連があるか分かりにくいので）
- ServerにはTomcat_7.0.50を使用
- ビルドツールはmavenを使用
- Viewにはjspを使用
- Controllerを使って"Hello world"するところをゴールとする

# フォルダ・ファイル構成

Spring3入門を参考にして以下のような構成にしました。
基本的にはmavenの構成で、設定ファイルはクラスパスで参照できるようにsrc/main/resources配下に置いています。

ここで登場するファイルは以下の5つです。
以下でそれぞれについて見ていきます。

- pom.xml
- web.xml
- beans-webmvc.xml
- HelloWorldController.java
- helloworld.jsp


```
SpringTodo
 |-pom.xml
 |-src
    |-main
    |  |-java
    |  |  |-controller
    |  |     |-HelloWorldController.java -- Controllerクラス
    |  |-resources 
    |  |  |-META-INF　-- Spring周りの設定ファイルおよびリソースファイルを配置するフォルダ
    |  |     |-spring
    |  |        |-beans-webmvc.xml -- Spring MVCのBean定義ファイル
    |  |-webapp -- Web Application周りのファイルを配置するフォルダ
    |     |-WEB-INF
    |        |-web.xml
    |        |-resources -- 静的リソースを配置するフォルダ
    |        |-views -- jspなどのviewを配置するフォルダ
    |           |-helloworld.jsp
    |-test

```

# pom.xml

とにかく最小限ということで、依存関係は以下の2つに絞っています。
あとは、web applicationなのでpackagingをwarに設定しておきます。

|groupId            |artifactId    |version      |scope  |説明       |
|-------------------|--------------|-------------|-------|-----------|
|org.springframework|spring-webmvc |3.1.1.RELEASE|compile|Spring MVC |
|javax.servlet      |servlet-api   |2.5          |compile|Servlet API|


# web.xml

Spring MVCの中心はDispatherServletです。
DispatcherServletは全てのHTTPリクエストを受け付け、その他のオブジェクト同士の流れを制御します。
基本的には用意されているDispatcherServletクラスをそのまま使用すればよいので、(1)で設定しています。
このとき、Spring MVCのBean定義ファイルをパラメータで渡します。
今回はBean定義ファイルをクラスパスで参照できる場所に置いているので、"classpath:"で指定することができます。

(2)ではDispatcherServletに対応するパスを設定しています。
ここでも設定してある通り、通常はコンテキストルートに設定します。

```xml:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
        http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
        ">
    <display-name>spring-todo</display-name>
    <!-- (1) -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath:/META-INF/spring/beans-webmvc.xml
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

	<!-- (2) -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
```

# beans-webmvc.xml

これはSpring MVCのBean定義ファイル(SpringでDIするための設定ファイル)です。
ここでは、Spring MVCのためのカスタムスキーマmvcを定義して使用します。

(1)ではControllerクラスをDIコンテナに登録するための設定を行っています。
base-packageにcontrollerを指定すると、controllerパッケージ配下にある@Controllerアノテーションが設定されたクラスをControllerとして読み込むことができます。

(2)ではSpring MVCのアノテーションを使用するための設定です。これにより@Controllerなどのアノテーションが有効になります。

(3)ではhtmlやcssなどの静的リソースファイルにアクセスするための設定です。
これにより、"WEB-INF/resources"配下にあるファイルを"コンテキストパス/resources/"というURLで読み込むことができるようになります。

(4)ではViewResolverの設定を行っています。
ViewResolverはView名からViewオブジェクトを生成する役割を持っています。
これによりControllerとViewを疎結合にすることができます。
ここでは、jspを読み込むためにInternalResourceViewResolverというクラスを使用し、prefixとsuffixを指定しています。

```xml:beans-webmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
	<!-- (1) -->
    <context:component-scan base-package="controller" />

	<!-- (2) -->
    <mvc:annotation-driven />

	<!-- (3) -->
    <mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />

	<!-- (4) -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>
```

# Controllerクラス(HelloWorldController)

Controllerクラスはクライアントからのリクエストに応じて処理を実行するためのクラスです。
そのため、どの処理をどのURLにマッピングさせるかという設定と、表示するView名を返す処理が必要になります。

(1)は、このクラスがControllerであることを示すためのアノテーションです。

(2)は、どの処理をどのURLにマッピングさせるかという設定を記述しています。
@RequestMappingというアノテーションを使用して、valueにマッピングさせるURL、methodに対応するHTTPメソッドを指定します。
このケースでは、homeメソッドをコンテキストルートにGETメソッドでアクセスした場合に対応させるという意味になります。

(3)は、実際に実行する処理を記述しています。今回のケースでは、単純に表示するView名を返すだけの処理になっています。

```java:HelloWorldController.java
package controller;

import static org.springframework.web.bind.annotation.RequestMethod.GET;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

// (1)
@Controller
public class HelloWorldController {
    // (2)
    @RequestMapping(value = "/", method = GET)
    public String home() {
		// (3)
        return "helloworld";
    }
}
```

# hellowolrd.jsp

単に"hello world"を表示するだけのjspです。

```jsp:helloworld.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<h1>hello world</h1>
```


# 処理の流れ

今回のアプリケーションでの処理の流れを整理しておきます。


1. "コンテキストパス/"にリクエストがくると、DispatcherServletがリクエストを受け付ける
1. DispatcherServletはリクエストされたURLから対応するControllerを指定のパッケージ配下から探し、URLに対応するメソッド(HelloWorldControllerクラスのhomeメソッド)を実行する
1. HelloWorldControllerクラスのhomeメソッドはView名として"helloworld"を返す
1. DispatcherServletは返されたView名を指定のViewResolverに渡し、ViewResolverは”/WEB-INF/views/helloworld.jsp"というjspに対応するViewオブジェクトを返す
1. DispatcherServletはViewオブジェクトに画面の描画を依頼する
1. Viewオブジェクトは該当するjspを呼び出して画面表示を依頼する
1. jspが画面表示処理を実行し、画面が表示される


# 参考

[Spring 3 入門](http://www.amazon.co.jp/Spring3%E5%85%A5%E9%96%80-%E2%80%95%E2%80%95Java%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%BB%E3%82%88%E3%82%8A%E8%89%AF%E3%81%84%E8%A8%AD%E8%A8%88%E3%81%A8%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3-%E9%95%B7%E8%B0%B7%E5%B7%9D-%E8%A3%95%E4%B8%80/dp/477415380X)