Spring4勉強会 第一回

# Spring4勉強会 第一回
* 概要
* 前提条件
* 環境構築
* サンプルPJの作成
* tcサーバの起動とサンプルの実行
* Mavenについて
* Springの構成について
* Springの基本
* Controllerから文字列を渡して表示してみよう

※[第二回](http://qiita.com/yu_eguchi/items/1f7e12d723cafaa7db0a)は以下
* Form連携

※[第三回](http://qiita.com/yu_eguchi/items/5a1b2ae46ff803b020bf)は以下
* 入力値検証

※[第四回](http://qiita.com/yu_eguchi/items/5bdda6f6ee7baf441870)は以下
* MyBatis連携

※[第五回](http://qiita.com/yu_eguchi/items/7de03903b43dcb445b52)は以下
* MyBatis x Spring x MySQLでトランザクション制御を扱ってみる

※[第六回](http://qiita.com/yu_eguchi/items/69d073292ccb94d5e19f)は以下
* RESTfulAPIの作成

# 概要

今回はJavaのFrameWork、SpringMVCについて取り扱います。
各Verは以下となります。
・4.1.6.RELEASE
・JSP 2.2
・Servlet 3.1.0
・Spring Mybatis 1.2.2
・Mybatis 3.3.0

最初は単純なテキスト表示から始め、最終的にはDBと連携するところまで学習を進める予定です。

# 前提条件

eclipse4.4(luna) x Windows 7 or 8の想定で進めます。
事前に環境構築を済ませておいて下さい。

# 環境構築
1. STSプラグインの導入

※STS(SpringToolSuite)…Spring純正開発ツール。Eclipseをベースにしているため、Eclipseを既に利用している方なら、プラグインという形で容易に導入できます。

まず、Eclipseを開き、「ヘルプ」→「Eclipseマーケットプレース」を開き、検索窓に「sts」と入力します。

![マーケットプレース.png](https://qiita-image-store.s3.amazonaws.com/0/78857/b44bbea8-f61a-67f2-066b-1e917a13d271.png)

![sts検索.png](https://qiita-image-store.s3.amazonaws.com/0/78857/45477ba0-232e-6070-7720-5005fbfc9879.png)

「インストール」を押下し、全ての項目をチェックし、条項にも同意して「完了」します。
完了後、再起動を求められるので、素直に再起動しましょう。

これで環境構築は完了です。

# サンプルPJの作成

まずは**簡単なプロジェクトを作成**してみましょう。
プロジェクトエクスプローラ上で右クリックし、「新規」→「その他」を選択します。
ウィザードの一覧から「Spring」を選択し、「Springプロジェクト」を選択した状態で「次へ」を押下します。
![newPj.png](https://qiita-image-store.s3.amazonaws.com/0/78857/71996df3-83b6-a6bd-1f23-a1ee5e17edf0.png)

「Springプロジェクト」と表示されたウィンドウが現れます。
以下の画面キャプチャに合わせて設定してください。
**※Select Spring version：はここでは一旦「Default」のままで構いません。後述しますが、後ほどMavenの方から指定します。**
![newSpPj.png](https://qiita-image-store.s3.amazonaws.com/0/78857/4d0f60e8-b186-3eed-a525-190b5ef77bde.png)

設定したら、「完了」を押します。
これでプロジェクトエクスプローラに「SpringKenshu」PJが作成・表示されましたね。

次に**pom.xmlを修正します。**
コンテキストルートに「pom.xml」という名前のファイルがあるので「ctr + Shift + r」でリソースを開き、pom.xmlを開きましょう。
開いた際に、「pom.xml」タブが選択されていなければ、それを選択してください。
エディターベースのUIでpom.xmlが表示されるかと思います。
![pom.png](https://qiita-image-store.s3.amazonaws.com/0/78857/ba91dc4a-9f57-ae88-61d8-d8a10b56f4f2.png)
開いたら、今回使用する予定のversionに各自書き換えていきます。

```
<!-- Generic properties -->
<java.version>1.7</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Web -->
<jsp.version>2.2</jsp.version>
<jstl.version>1.2</jstl.version>
<servlet.version>3.1.0</servlet.version>
<!-- Spring -->
<spring-framework.version>4.1.6.RELEASE</spring-framework.version>
```

依存関係のServletが「servlet-api」だと認識されないため、「javax.servlet-api」に修正する。

```
<dependency>
　<groupId>javax.servlet</groupId>
　<artifactId>javax.servlet-api</artifactId>
　<version>${servlet.version}</version>
　<scope>provided</scope>
</dependency>
```

修正が終わったら保存し、エラーが出ていないか確認してください。

次に**プロジェクトをアップデートする**作業を行います。
「SpringKenshu」フォルダを右クリックし、ポップアップして現れるメニューから、「Maven」を選択し、その中の「プロジェクトの更新」を選択します。
![mavenUpdate.png](https://qiita-image-store.s3.amazonaws.com/0/78857/33929ba3-09af-4a21-2a10-e1fad8b06aac.png)

次に**MavenInstall**を行います。
「SpringKenshu」フォルダを右クリックし、ポップアップして現れるメニューから、「実行」を選択し、その中の「MavenInstall」を選択します。
Instal結果がコンソールに表示されます。SUCCESSと表示されればOKです。

ただ、今の段階でプロジェクトフォルダがエラーを示していた場合、以下の設定齟齬が生じている可能性があります。
・Javaのコンパイラーが1.5になってる。
　→PJを右クリックし、「プロパティ」から「Javaコンパイラー」を選択してください。
　　もし、「1.7」になっていないようなら、設定する。
　　※Javaのビルドパスも同様。選択されているJREシステムライブラリーが1.5なら、「編集」を選択し、「1.7」にする。
<del>・サーブレット(動的WEBモジュール)が2.5になってる。
　→これはPJのファセットを修正する必要があります。キャプチャの通りに設定してください。</del>
**<font color="red">動的WEBモジュールはいじるとおかしくなる？のかわからないですが、上手くいかないケースが多いので触らないでおいた方が無難です！！</font>**
![ふぁセット.png](https://qiita-image-store.s3.amazonaws.com/0/78857/51ecb7ae-637a-8b13-67b8-100c7cad428e.png)


上記を設定してもエラーがとれない。けど、ビルドは成功する。ダイヤモンド演算子も書ける！使える！！と言うならば、
「ウィンドウ」→ヴューの表示→マーカーを確認し、エラーとなってる箇所を右クリックし「削除」しちゃって良いです。

# tcサーバの起動とサンプルの実行

ここまでで最低限動くソースの準備が整いました。
早速動かしてみましょう！

1. 組み込みサーバーの起動設定
「ウィンドウ」→「ビューの表示」→「サーバー」を選択し、以下の画面を表示する。

![notc.png](https://qiita-image-store.s3.amazonaws.com/0/78857/9e3923f9-b68b-54a5-3e39-0548f84c93b7.png)

見ての通り、まだ登録されたサーバが存在しないため、新規で追加する必要があります。
クリックしてみましょう。
クリックしたら、サーバタイプを選択します。今回はTomcat7を使用します。

![tcChoice.png](https://qiita-image-store.s3.amazonaws.com/0/78857/34233a74-c3c7-d2fa-3a5c-f69bcc15299c.png)


完了を押したくなりますが、ここは「次へ」を押し、続いてコンテキストの登録を行います。
SpriingKenshuを選択し、「追加」を押します。これでTomcatにコンテキストを登録したことになります。

![tcAdd.png](https://qiita-image-store.s3.amazonaws.com/0/78857/f7419592-62bb-82e8-cb87-3d990df339d7.png)

完了を押しましょう。
あとはサーバーを起動し、画面から確認するだけです！！
起動しましょう。
![tcExec.png](https://qiita-image-store.s3.amazonaws.com/0/78857/39de2723-52eb-2d6b-4031-1764cde295b1.png)

コンソールにログが流れます。成功したら、いつもおなじみの「StartUp」が表示されます。
画面で確認してみましょう！！
各自の環境から[http://localhost:8080/SpringKenshu/](http://localhost:8080/SpringKenshu/)にアクセス！！
画面が表示されましたね？！

なんとなく動いたと思うのでここからは解説になります。

# Mavenについて

みなさんが最初に作成したプロジェクトは実は**まだSpringプロジェクトではありません**。
作成されたのは「Maven(ApacheMaven)」と呼ばれるプログラムを利用したプロジェクトとなります。
※Springプロジェクトとなりえたのは、Maven Installが正常に行われた後になります！！

Mavenとは、Javaプロジェクト管理ツールです。pom.xmlにプロジェクトに必要なライブラリを記述することで、
ダウンロードや、プロジェクトのビルドを行ってくれます。今まで手作業で行っていたことがツールを介して自動化されます。
今までは、jstlやJUnitは自分達でjarを調達(DL)し、手作業でプロジェクトに組み込んでましたよね？？
そんな作業をも自動化するのです。

今回作成した「**SimpleWebMaven**」は、Mavenを利用したSpringプロジェクトの雛形を作成してくれるものです。

では今回行った作業を一つ一つ解説していきましょう。

　1. pomの修正

pomにはプロジェクトで使用するライブラリの情報を記述します。
今回使用するライブラリと、そのVersion番号を記述したのです。
例

```
<dependency>
　<groupId>javax.servlet</groupId>
　<artifactId>javax.servlet-api</artifactId>
　<version>${servlet.version}</version>
　<scope>provided</scope>
</dependency>
```

実際に必要な記述は上記の「dependency」のみです。
その上で記述していた

```
<servlet.version>3.1.0</servlet.version>
```

はdependencyタグの中で参照している、

```
<version>${servlet.version}</version>
```

で**${servlet.version}**を参照するためだけに定義しているだけです。
こうすることで、同じ記述を何度も手書きせずに済みます。変数と同じです。

　2. Mavenプロジェクトの更新

続いて、Mavenプロジェクトの更新です。
これは、pomに記述された情報を元にプロジェクトを更新する作業を行ってます。
必要なライブラリがなければ(依存関係があって)追加し、必要な設定を生成したりしてくれてます。

　3. Maven Install

そして次にMaven Installを行いました。
これはMavenによって、プロジェクトのコンパイル・ビルドを行い、生成されたプログラムをリポジトリに登録する作業を行っています。
これにより、プロジェクトのwarファイルを生成して必要な場所に組み込んでいます。
結果的に、Springプロジェクトに必要な構成を自動で生成し、私達がこれから学ぼうとしているSpringWebプロジェクトが
書けるようになります。
これで初めて、Springプロジェクトとなったわけです。
**※Mavenにより自動生成されたフォルダ構成を改変してはいけません。
変更してしまったら、正常に動作しない可能性がありますのでご注意ください。**

　4. tcServerの設定

STSには「**VMWare vFablic tc Server Developer Edition**」というサーバープログラムが組み込まれています。
この組み込みサーバを利用することで、ローカルで手軽に動作確認を行うことができます。
しかし、動作確認するためには以下の作業を行う必要があります。

　1. どのサーバを使用するか

今回はTomcat7にしました。そのまんまの意味です。

　2. コンテキストを追加する

これも今までやってきた「Tomcatプロジェクトの定義更新」と一緒ですね。

　3. サーバを起動する

これも説明不要でしょう。起動しないと見れないのは当たり前です。

※【番外編】　**自前で用意したアプリケーションサーバにデプロイするにはどうしたら良いか？？**

Mavenで自動生成されたフォルダの中に「target」というフォルダが存在してます。
これこそが今回作成したWebアプリケーションのデータとなります。
この中に「SpringKenshu-0.0.1-SNAPSHOT.war」というwarファイルが生成されていることがわかります。
![war.png](https://qiita-image-store.s3.amazonaws.com/0/78857/c3655288-d744-7b75-8ac0-8821b6f6589d.png)

これが、Maven Installを実行した際に生成されるwarファイルです。
このwarファイルを自前のTomcatのwebapp下に配備すれば移行が完了します。
※もしくはTomcatマネージャ経由でも問題ありません。

# Springの構成について

次に自動生成されたSpringプロジェクトのフォルダ構成について見ていきます。

* 「src」フォルダ
ソースコードを配置します。Javaだけでなく、JSPやHTML,imgなども、この中にまとめられます。

* 「target」フォルダ
アプリケーションのデータです。自動生成されます。

* 「.settings」フォルダ
プロジェクトの設定ファイルが格納されてます。STSによって作成されます。

* pom.xml
Mavenのビルド設定ファイルです。前述の通りです。

**私達開発者が意識しないといけないのは、「src」フォルダだけです。**

ではsrcフォルダの構成について俯瞰していきましょう。
![src構成.png](https://qiita-image-store.s3.amazonaws.com/0/78857/9eb9ca73-8e92-5112-f80a-5053aec78f84.png)

* javaフォルダ
Javaのプログラムの格納先。この中にソースコードを作成します。

* resourceフォルダ
リソースを扱うフォルダ。アプリケーションに必要な設定情報などをまとめたXMLが配置されます。

# Springの基本

構成がわかったところで、実際に先ほど確認した以下の画面について、簡単に挙動を追って見たいと思います。
ですが、その前にSpringの基本について知っておかなければなりません。

* MVC

SpringMVCはその名の通りMVCアーキテクチャに基づいて設計されています。
MVCはそれぞれ以下のような役割を果たします。

**Model(モデル)**
データベースなど、アプリケーションで必要となる各種データを管理します。

**View(ビュー)**
画面の表示を管理します。

**Controller(コントローラ)**
全体の処理・制御を管理します。
アプリケーションへのアクセスは、このコントローラを介して処理されます。

先ほど作成したSpringKenshuプロジェクトでは、MVCはそれぞれ以下の場所に作成します。

**Model / Controller**
「src/main/java」下にJavaファイルとして作成します。パッケージはデフォルトでは存在しないので、自由に作成してOKです。

**View**
「source」内にある「webapp」フォルダの中にある「WEB-INF/view」フォルダ内に作成します。
ViewはControllerを介してアクセスされるべきものです。
そのため、webapp下に直接配置したりはしません！！WEB-INF下、つまりは非公開ディレクトリに配置します。

ちなみに、現状ではviewの下に「showMessage.jsp」がデフォルトで作成されてますが、今は未使用です。

**今画面に表示されているのは、あくまで「index.jsp」**です。

# Controllerから文字列を渡して表示してみよう
いよいよコーディングです。
まずはControllerを作成してみましょう。

1. 「src/main/java」を右クリック
2. 新規→Java→クラスを選択
3. パッケージに「jp.co.kenshu」を記述
4. 名前にTestControllerを記述
イメージとしては以下のようになります。
![makeController.png](https://qiita-image-store.s3.amazonaws.com/0/78857/4be7e663-0239-fdba-55f3-3ebc79e8b29b.png)

▼作成後

```
package jp.co.kenshu;
public class TestController {
}
```

このように空のクラスが作成されます。
今回はデフォルトで作成された「showMessage.jsp」を表示させるよう、コーディングしてみましょう。

▼修正後

```
package jp.co.kenshu;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class TestController {
	@RequestMapping(value = "/show", method = RequestMethod.GET)
	public String showMessage(Model model) {
		model.addAttribute("message", "hello world!!");
		return "showMessage";
	}
}
```

ソースを書く際には、「Ctrl + shift + o」や「Ctrl + shift + f」、「Ctrl + space」を駆使し、自動保管を多用してより早く書き上げてください。

Controllerの記述が終わったら、続いては「mvc-config.xml」にアプリケーションのどこがControllerかを記述する必要があります。
mvc-config.xmlを開き、

```
<!-- Uncomment and your base-package here:
　<context:component-scanbase-package="org.springframework.samples.web"/>  --
　　<mvc:annotation-driven />
　　<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
　　　<!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
　　　<property name="prefix" value="/WEB-INF/view/"/>
　　　<property name="suffix" value=".jsp"/>
</bean>
```
を

```
　<context:component-scanbase-package="jp.co.kenshu"/>
　　<mvc:annotation-driven />
　　<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
　　　<!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
　　　<property name="prefix" value="/WEB-INF/view/"/>
　　　<property name="suffix" value=".jsp"/>
</bean>
```

に修正します。

では[http://localhost:8080/SpringKenshu/show](http://localhost:8080/SpringKenshu/show)にアクセスしてみましょう。
Hello Worldが表示されれば成功です！！

## 解説

今回はControllerの作成と「mvc-config.xml」と呼ばれる設定ファイルを修正しました。

1. TestControllerの解説

```
@Controller
public class TestController {
```

まず、クラス名の上に「@Controller」というアノテーションが付与されていますね。
これは、Springアプリケーションに「このクラスはControllerですよ～」ってことを教えいます。
マーカーみたいなものです。

SpringではStrutsのように設定ファイルにいちいちController(Strutsで言う、Action)を登録する記述をしたりはしません。
ただ、アプリケーションはどこの誰がControllerなのかが分からなければ、参照することができませんので、このアノテーションと後述するmvc-config.xmlへの記述により、Controllerを特定しているのです。

```
@RequestMapping(value = "/show", method = RequestMethod.GET)
public String showMessage(Model model) {
```

次に「@RequestMapping(value = "/show", method = RequestMethod.GET)」の記述についてです。
このアノテーションはvalueに記述した文字列で「このControllerの住所(URL)はここだよ～」ってのを教えています。
**※ちなみに「/」はコンテキストルートをあらわしています。今回であれば「/SpringKenshu」をさします。**

「method = RequestMethod.GET」はクライアントがGETでアクセスしたケースを指しています。
POSTであれば、「RequestMethod.POST」となります。SpringFrameworkが提供するAPIを利用しています。
内部を見て見ると、以下のようなENUMになっていることがわかります。

```
package org.springframework.web.bind.annotation;
public enum RequestMethod{
	GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
	private RequestMethod() {
	}
}
```

一通りのリクエストメソッドが定義されていますね。

```
model.addAttribute("message", "hello world!!");
```

Model#modelという変数になにやら、KV形式でvalueを登録しているようです。
パッと見た目はsetAttributeと似たような構図に見えますね。
Modelというクラスは、org.springframework.uiパッケージに用意されているクラスです。
このModelは、**Viewとの橋渡しをするためのクラス**です。
ここに必要な情報をまとめることで、Viewから利用できるようになります。

メソッドで行っているのは、Modelインスタンスへの属性を追加する処理です。
「**addAttribute**」メソッドは、Modelインスタンスに属性を追加するものです。
第一引数には属性のkey値を、第二引数には値をそれぞれ指定します。
つまり、ここでは"message"というkeyに、”hello World!”という文字列を詰めていることになります。

**【番外編】model.addAttributeのスコープは？？**
modelへの属性追加と言いましても、スコープはどこなの？？という疑問が浮かぶかと思います。
model.addAttributeは、内部では実はsessionに値を登録しています。
なので、実はmodelを使わなくても、もちろん自前でsessionに詰めてしまえば、Springで行っていることと同じことができます。
ただ、sessionでの値管理は緻密にやらないと思わぬバグの温床にもなります。
表面上記述量も減りますし、FWが用意してくれているなら素直に使ってあげるのもベターでしょう。



```
return "showMessage";
```

最後にreturnしている文字列は、この文字列でviewクラスを探索しにいってます。
この文字列に該当するViewファイル名をフレームワークが探しにいき、あればそのテンプレートを返却するという動きをします。
では、どういった規約で探しにいけているのか？？それは次の「mvc-config.xml」を見れば納得します。

```
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	        <!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
	        <property name="prefix" value="/WEB-INF/view/"/>
	        <property name="suffix" value=".jsp"/>
</bean>
```

「**org.springframework.web.servlet.view.InternalResourceViewResolver**」はフレームワークが提供するクラスです。
上記では、「**/WEB-INF/view/下の.jspをControllerからreturnされた文字列で保管するよ**」って挙動をとってくれます。
なので、今回は「/WEB-INF/view/**showMessage**.jsp」がControllerから呼ばれるという挙動をしています。

なお、内部では以下のようなメソッドが定義されています。

```
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
　AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
　view.setUrl(getPrefix() + viewName + getSuffix());
　String contentType = getContentType();
　if (contentType != null) {
　　view.setContentType(contentType);
　}
　view.setRequestContextAttribute(getRequestContextAttribute());
　view.setAttributesMap(getAttributesMap());
　Boolean exposePathVariables = getExposePathVariables();
　if (exposePathVariables != null) {
　　view.setExposePathVariables(exposePathVariables.booleanValue());
　}
　Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes();
　if (exposeContextBeansAsAttributes != null) {
　　view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes.booleanValue());
　}
　String[] exposedContextBeanNames = getExposedContextBeanNames();
　if (exposedContextBeanNames != null) {
　　view.setExposedContextBeanNames(exposedContextBeanNames);
　}
　return view;
}
```

よく見ると

```
view.setUrl(getPrefix() + viewName + getSuffix());
```

とあり、xmlで指定したprefix(前置詞)とsuffix(後置詞)でviewName(今回なら「showMessage」)が挟まれているのがわかります。
これをsetUriしているので、結果的に「showMessage.jsp」が呼ばれていることがわかります。

```
<context:component-scan　base-package="jp.co.kenshu"/>
```

これは、SpringKenshuプロジェクトがどこのパッケージ下をControllerとして認識するかを登録しています。
この記述のおかげで、先ほどの「TestController」は@Controllerと相まって、無事にControllerとして登録されることができたというカラクリになってます。

```
<mvc:annotation-driven />
```

この記述はSpringKenshuプロジェクトがアノテーションで駆動しますよってことを宣言・設定しています。
この記述があるおかげで、

```
@RequestMapping(value = "/show", method = RequestMethod.GET)
````

が機能しています。

今回はここまでです。
次回はクライアントからFORM経由で動的な値を受取、その結果を表示するといったサンプルを行う予定です。
併せて、DIについても触れていこうかと思っています。