SpringMVCに必要なjarについてはSpringの導入&サンプルプログラムを参照。(SpringMVCのコアとなるのはspring-web*-4.2.4.RELEASE.jar)
web.xmlを用意する。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<-- ①リクエストパラメータのエンコーディング指定 -->
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<-- ②DispatcherServletサーブレットの定義 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<-- ③Springの設定ファイルの場所 -->
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-context.xml</param-value>
</init-param>
</servlet>
<-- ④DispatcherServletサーブレットのマッピング定義 -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
①リクエストパラメータのエンコーディング指定
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Spring提供のCharacterEncodingFilterを利用することでリクエストパラメータのエンコーディング指定ができる。サーブレットフィルタの機能を使用しているため<filter>タグと<filter-mapping>タグを記述する。
今回のサンプルではUTF-8を採用しているため「UTF-8」を指定。これを正しく指定しないと日本語が文字化けする。
②DispatcherServletサーブレットの定義
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-context.xml</param-value>
</init-param>
</servlet>
Springではリクエストの最初の受け口はすべてDispatcherServletとなる。DispatcherServletはSpringが提供しているフロントコントローラであり、実態はサーブレット。
③Springの設定ファイルの場所
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-context.xml</param-value>
</init-param>
Springの設定ファイルの場所を指定する。下記の2条件にあてはまる場合は省略可能。
④DispatcherServletサーブレットのマッピング定義
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
DispatcherServletを起動させるためのURLパターンを記述する。url-patternにマッチしたリクエストが来た場合、DispatcherServletが呼ばれる。今回はurl-patternを「*.do」にしている。
Springの設定ファイルを作成する。
下記のファイル(spring-context.xml)を作成し、クラスパス直下に配置する。ファイル名はweb.xmlに定義した名前と合わせる(前述)。
<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">
<-- ①component-scanの定義 -->
<context:component-scan base-package="mvctest" />
<-- ②アノテーション利用の定義 -->
<mvc:annotation-driven />
<-- ③ビュー解決の定義 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
①component-scanの定義
<context:component-scan base-package="mvctest" />
この定義により下記のアノテーションが付いているクラスがSpringにより検索され、自動的にインジェクションされる。bean定義を書く必要がないため便利。component-scanはSpringMVCに限らずSpring全般で使用できる。
なお自動インジェクション対象のパッケージをbase-package属性で絞り込むことができる。サンプルの場合、mvctestパッケージ配下(サブパッケージも含む)が対象となる。つまりmvctestパッケージ配下の上記アノテーションが付与されているクラスが対象となる。
②アノテーション利用の定義
<mvc:annotation-driven />
SpringMVC用のアノテーションを有効にする定義。これにより@Controllerや@RequestMappingなどアノテーションベースでコントローラが起動される。
③ビュー解決の定義
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
ビュー(jsp)のパスと拡張子を定義する。InternalResourceViewResolverは遷移先のビューを解決するSpring提供のクラス。 一般的にはpropertyタグのprefix属性にjspのパス、suffix属性に拡張子(.jsp)を指定することが多い。
この定義により、コントローラクラスで遷移先のビューを指定する際に、パスや拡張子無しのファイル名だけを記述すればよくなる。(詳細は後述のコントローラの説明を参照)
姓と名の項目を入力してボタンを押すと、姓名を表示する単純なJSPを作成する。
- イメージ図 -
①姓名を入力してボタン押下
②姓名が右に表示される
画面の動きはすべて同じだが、3種類の実装方法を説明するため、JSPを3つほど作成する。
■1つ目(sample1.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE>
<html>
<head>
<meta charset="UTF-8">
<script src="js/jquery-1.11.1.min.js"></script>
</head>
<body>
<-- submit1.do用フォーム -->
<form action="/test/sample/submit1.do" method="POST">
<input type="submit" value="submit1">
<input type="text" id="lastname" name="lastname" value="">
<input type="text" id="firstname" name="firstname" value="">
${lastname} ${firstname}
</form>
</body>
</html>
■2つ目(sample2.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE>
<html>
<head>
<meta charset="UTF-8">
<script src="js/jquery-1.11.1.min.js"></script>
</head>
<body>
<-- submit2.do用フォーム -->
<form action="/test/sample/submit2.do" method="POST">
<input type="submit" value="submit2">
<input type="text" id="lastname" name="lastname" value="">
<input type="text" id="firstname" name="firstname" value="">
${lastname} ${firstname}
</form>
</body>
</html>
■3つ目(sample3.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE>
<html>
<head>
<meta charset="UTF-8">
<script src="js/jquery-1.11.1.min.js"></script>
</head>
<body>
<-- submit3.do用フォーム -->
<form:form action="/test/sample/submit3.do" method="POST" modelAttribute="person">
<input type="submit" value="submit3">
姓<form:input id="lastname" path="lastname" />
名<form:input id="firstname" path="firstname" />
${person.lastname} ${person.firstname}
</form:form>
</body>
</html>
作成した3つのJSPからサブミットされるリクエストは、次に作成する1つのコントローラクラスで処理する。
package mvctest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
// ≪クラス宣言≫
@Controller
@RequestMapping("/sample")
public class SampleController {
// ≪sample1.do用メソッド≫
// ①メソッド宣言
@RequestMapping(value="/submit1", method={RequestMethod.POST, RequestMethod.GET })
public String submit1(Model model,
@RequestParam(required=false) String lastname,
@RequestParam(required=false) String firstname) {
// ②Modelに画面データを設定
model.addAttribute("lastname", lastname);
model.addAttribute("firstname", firstname);
// ③ビューの名前を返却
return "sample1";
}
// ≪sample2.do用メソッド≫
// ①メソッド宣言
@RequestMapping(value = "/submit2", method = { RequestMethod.POST, RequestMethod.GET })
public String submit2(Model model, Person person) {
// ②Modelに画面データを設定
model.addAttribute("lastname", person.getLastname());
model.addAttribute("firstname", person.getFirstname());
// ③ビューの名前を返却
return "sample2";
}
// ≪sample3.do用メソッド≫
// ①メソッド宣言
@RequestMapping(value = "/submit3", method = { RequestMethod.POST, RequestMethod.GET })
public String submit3(Model model, Person person) {
// ②ビューの名前を返却
return "sample3";
}
}
≪クラス宣言≫
コントローラとなるクラスには@Controllerと@RequestMappingを付ける。
@Controller
@RequestMapping("/sample")
public class SampleController {
@Controllerはコントローラを示すアノテーション。@Componentなどと同じくSpringのインジェクション対象となる。
@RequestMappingはリクエストURLとコントローラを紐づけるためのアノテーション。コントローラの@RequestMappingで指定したパスとコンテキストパスの次のパスが一致した場合、そのコントローラが呼ばれる。
【サンプルの場合】http://localhost:8080/test/sample/submit1.do
①メソッド宣言
@RequestMapping(value="/submit1", method={RequestMethod.POST, RequestMethod.GET })
public String submit1(Model model,
@RequestParam(required=false) String lastname,
@RequestParam(required=false) String firstname) {
@RequestMappingはリクエストURLとコントローラメソッドを紐づけるためのアノテーション。クラス宣言でも@RequestMappingを使用したが、指定するパラメータが異なる。
URLの最後のパスが@RequestMappingで指定したパスと一致したメソッドが呼ばれる。 サンプルの場合、URLの最後が「/submit1.do」だった場合に、このメソッドが呼ばれる。
【サンプルの場合】http://localhost:8080/test/sample/submit1.do
最終的に実行されるメソッドはクラス宣言のRequestMappingとメソッド宣言のRequestMappingによって決まる。
http://localhost:8080/{コンテキストパス}/{クラスのRequestMapping}/{メソッドRequestMapping}.do
よく使用する@RequestMappingのパラメータは以下のとおり。
パラメータ名 | 値 | 説明 |
---|---|---|
value | 任意の値 | URLの「*.do」の「*」の部分 |
method | RequestMethod.POST RequestMethod.GET など | POST/GETなどリクエストのメソッド |
- メソッド引数 -
public String submit1(Model model,
@RequestParam(required=false) String lastname,
@RequestParam(required=false) String firstname) {
Modelは遷移先ビュー名やビューへ連携する画面データを格納するSpring提供のクラス。ビューへデータを渡したい場合は、このModelに設定する。
引数に@RequestParamを付けると、引数の変数にリクエストパラメータをバインドしてくれる。デフォルトではリクエストパラメータ名と同じ名前の変数へ格納される。
リクエストパラメータ名と異なる変数名を使用したいときは@RequestParamのvalueパラメータに記述する。パラメータが1つしかない場合は""で括って記述すればよい。下記の場合、リクエストパラメータlastnameの値が変数seiに、firstnameの値が変数meiに格納される。
public String submit1(Model model,
@RequestParam(value="lastname", required=false)String sei,
@RequestParam("firstname") String mei) {
@RequestParamで指定できるパラメータは以下のとおり。
パラメータ名 | 値 | 説明 |
---|---|---|
value | リクエストパラメータ名 | リクエストパラメータ名と変数名が異なるときに記述 |
required | true/false | リクエストパラメータが必須かどうか。指定しないとデフォルトの必須になる。必須の場合にパラメータが存在しないとHTTPステータス400のエラー「Required String parameter 'XXX' is not present」となる。 |
②Modelに画面データを設定
Modelクラスに画面に渡したいデータを設定する。使い方はrequest.setAttribute()に似ている。
model.addAttribute("lastname", lastname);
model.addAttribute("firstname", firstname);
③ビューの名前を返却
遷移させたいビューの名前を文字列で戻り値に設定する。
return "sample1";
ビューの拡張子はspring-context.xmlにビュー解決定義のsuffix属性が指定してある場合、省略可能。同様にパスもprefix属性が指定してあれば省略可能。以下spring-context.xmlより抜粋
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
ビュー側(JSP)ではEL式で出力できる。以下sample1.jspより抜粋。
<form action="/test/sample/submit1.do" method="POST">
<input type="submit" value="submit1">
<input type="text" id="lastname" name="lastname" value="">
<input type="text" id="firstname" name="firstname" value="">
${lastname} ${firstname}
</form>
sample1.doとほぼ同じだが、引数にリクエストパラメータを直接もらうのではなく、Personクラスをもらう点が異なる。
@RequestMapping(value = "/submit2", method = { RequestMethod.POST, RequestMethod.GET })
public String submit2(Model model, Person person) {
model.addAttribute("lastname", person.getLastname());
model.addAttribute("firstname", person.getFirstname());
return "sample2";
}
Personクラスは、下記のようにリクエストパラメータのsetterとgetterを持つBeanクラスである。
package mvctest;
public class Person {
private String lastname;
private String firstname;
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
}
メソッドの引数にBeanクラスを指定するとリクエストパラメータ名と同じ変数にバインドして格納してくれる。また自動的にPersonクラスがModelに設定されるため、ビュー(jsp)からPersonクラスへの参照も可能(次のsample3.do用メソッド参照)。
たまに引数の前に@ModelAttributeを付けるコードも見られるが、省略可能。
public String submit2(Model model, @ModelAttribute Person person) {
リクエストパラメータを取得したい場合は、Personに格納されているためgetterメソッドで取得する。(実際には下記のコードは省略できる。次のsample3.do用メソッド参照。)
model.addAttribute("lastname", person.getLastname());
model.addAttribute("firstname", person.getFirstname());
JSPでの出力方法は、sample1.doと同じ。
sample2.doをさらに簡潔にしたサンプル。
引数に指定したBeanクラス(この場合Person)は、自動的にModelに設定される。 よって何も記述せずともビューからの参照が可能となる。@RequestMapping(value = "/submit3", method = { RequestMethod.POST, RequestMethod.GET })
public String submit3(Model model, Person person) {
return "sample3";
}
ビュー(JSP)では、modelAttribute属性にクラス名の先頭を小文字にした名前を指定するとEL式で参照が可能となる。Personクラスの場合"person"が参照名となる。
<form:form action="/test/sample/submit3.do" method="POST" modelAttribute="person">
<input type="submit" value="submit3">
姓<form:input id="lastname" path="lastname" />
名<form:input id="firstname" path="firstname" />
${person.lastname} ${person.firstname}
</form:form>
参照名を変えたい場合は、コントローラメソッドの引数に@ModelAttributeを記述し、valueパラメータに参照名を指定する。
public String submit2(Model model, @ModelAttribute("user") Person person) {
なおJSPで使用している<form:form>はSpring提供のHTMLラッパータグである。<form:form>を使うにはJSPの先頭に下記の定義が必要。
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>