Spring MVC
Spring MVCとは
Spring MVCは、現在よく使われている開発パターンの一つであるMVCパターンをもとにした仕組みである。
MVCは、画面に表示するView、データ処理を管理するModel、ViewとModelをつなぐControllerの頭文字を取ったものである。
Spring Frameworkは、MVCパターンで開発しやすいように機能を提供している。 一般的にはModel、View、Controllerの形で構成するが、最近はスケーリングや運用の都合からフロントエンドとバックエンドのサーバーを分離する構成も多い。
Spring MVCの構造と処理の流れ

- DispatcherServlet
- アプリケーションに入ってくるすべてのrequestを受け取る入口である。
- requestを実際に処理するcontrollerへ渡し、その結果を受け取ってviewに渡せるように全体の流れを制御する。
- HandlerMapping
- 各Request URLをどのControllerが処理するかを探す役割を持つ。
- Controller
- Requestを直接処理し、その結果をDispatcherServletへ返す。
- ModelAndView
- Controllerが処理した結果と、その結果を表示するViewの情報を保持するオブジェクトである。
- ViewResolver
- View関連情報をもとに実際のViewを探す。
- View
- Controllerが処理した結果を表示するViewを生成する。
SpringにおけるFilter、Interceptor、AOPの違い
Filter
- リクエストとレスポンスを通過させる前後で整える役割を持つ。
- Servlet FilterはDispatcherServletより前に実行され、指定されたリソースの前段でリクエスト内容の変更や各種チェックを行える。
- Springコンテキストの外側に存在し、Springとは独立したリソースに対して動作する。
- Springの領域には含まれない。
Interceptor
- リクエスト処理の前後に割り込むものと考えるとよい。
- SpringのDispatcherServletがコントローラーを呼び出す前後に介入するため、Springコンテキスト内部でControllerに関するリクエストとレスポンスを処理する。
AOP
- Aspect Oriented Programming、つまりアスペクト指向プログラミングである。
- OOPを補完する概念であり、OOPを置き換えるものではない。
- オブジェクト指向プログラムで重複を減らしにくい部分を、横断的な観点から扱って整理する。
- 主にロギング、トランザクション、エラー処理など、ビジネス層のメソッドをより細かく調整したい場合に使う。
- メソッド実行の前後などに柔軟に設定できる。
3つの違い
- 処理順序は一般に
Filter > DispatcherServlet > Interceptor > AOPである。 - InterceptorとFilterは主にアドレスを基準に対象を絞り込むが、AOPはアドレス、パラメーター、アノテーション、メソッドなど、より多様な方法で対象を指定できる。
Spring設定ファイル、web.xmlの作成
Spring設定ファイル、Bean定義ファイルの指定
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>springMVC</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- まず
org.springframework.web.context.ContextLoaderListenerクラスをリスナーとして登録する。 - これが登録されているため、Spring設定ファイル
/WEB-INF/applicationContext.xmlが読み込まれる。 - このパスとファイル名は
contextConfigLocationで変更できる。
Spring設定ファイル名の変更
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/app.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- Spring設定ファイルが
/WEB-INF/spring/app.xmlに変更される。
ServletにSpring設定ファイルを適用する
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/mvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
- Spring設定ファイルはServletごとに設定できる。
- 設定する場合は、
init-paramのcontextConfigLocationに指定する。 - Spring設定ファイルを
/WEB-INF/spring/mvc-servlet.xmlに指定している。
org.springframework.web.servlet.DispatcherServletについて
通常のWebアプリケーションではServletを作成するが、Spring Web MVCではSpringが提供するため、別途作成せずに org.springframework.web.servlet.DispatcherServlet を使用する。
DispatcherServletはクライアントからのリクエストを受け取り、@Controller が付いたコントローラークラスに割り当て、コントローラーの戻り値からJSPなどのViewを解決してクライアントへ返す。
Spring MVC全体を制御し、web.xml に設定される。
そのため、Spring MVCでWebアプリケーションを開発するときには普段あまり意識しないが、裏側でさまざまな処理を行っている。
CharacterEncodingFilter
- 前の例では省略したが、
CharacterEncodingFilterも指定する必要がある。 - クライアントから送信されたデータを、指定した文字コードで強制的にエンコードする。
- 内部では
HttpServletRequest#setCharacterEncodingを実行する。
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Bean定義ファイル
<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-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<context:component-scan base-package="spring.test" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
最初の component-scan 要素は、指定したパッケージ配下にあるアノテーション付きクラスを自動的に読み込む。
読み込まれるアノテーションには、@Controller、@Service、@Component、@Repository などがある。
次の annotation-driven 要素は、Spring Web MVCに必要な設定を自動的に有効化する。
対象となるアノテーションには、@RequestMapping、@ModelAttribute、@SessionAttribute、@RequestParam などがある。
最後に org.springframework.web.servlet.view.InternalResourceViewResolver を宣言している。
これはJSPファイルの場所を指定する。
prefix と suffix を宣言し、コントローラーの戻り値文字列と組み合わせてJSPファイルを解決する。
prefix文字列 + コントローラーの戻り値文字列 + suffix文字列
例えば、コントローラーが test を返した場合は次のようになる。
"/WEB-INF/" + test + ".jsp" > "/WEB-INF/test.jsp"
CSVダウンロードやExcelダウンロードなどのViewを扱う場合は、org.springframework.web.servlet.view.XmlViewResolver を指定する。
これは別の機会に説明する。
<mvc:resources> 要素
画像、CSS、JavaScriptなどの静的リソースへアクセスする場合、次のようにアクセス先ディレクトリを宣言する。
<mvc:resources mapping="/image/**" location="/WEB-INF/image/" />
上記のディレクトリにある画像を表示するJSPは、次のように記述する。
<img src="./image/test.png"/>
JSPでBeanを使用する
JSPでSpring Java Beanを便利に使うには、次のように呼び出す。
まず、Spring設定ファイルで InternalResourceViewResolver を設定するときに、exposeContextBeansAsAttributes 属性を true にする。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="exposeContextBeansAsAttributes" value="true" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
次のようにJava Beanファイルを作成する。
名前が foo のシングルトンオブジェクトが生成される。
@Component
public class Foo {
private String name;
public String getName() {
return name;
}
}
JSPでSpring Java Beanである foo をJSP ELから呼び出す。
<%@page language="java" contentType="text/html; charset=UTF-8"%>
<div class="foo-name">
<c:out value="${foo.name}"/>
</div>