技術空間

Spring

SpringMVCの導入&サンプルプログラム


TOP > Spring > SpringMVCの導入&サンプルプログラム



■SpringMVCとは

■SpringMVCの導入
jarの入手

SpringMVCに必要なjarについてはSpringの導入&サンプルプログラムを参照。(SpringMVCのコアとなるのはspring-web*-4.2.4.RELEASE.jar)

■サンプル実行
web.xmlの作成

web.xmlを用意する。

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に定義した名前と合わせる(前述)。

spring-context.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の作成

姓と名の項目を入力してボタンを押すと、姓名を表示する単純なJSPを作成する。

- イメージ図 -

①姓名を入力してボタン押下

②姓名が右に表示される

画面の動きはすべて同じだが、3種類の実装方法を説明するため、JSPを3つほど作成する。

■1つ目(sample1.jsp)

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)

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)

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>

Javaの作成

作成した3つのJSPからサブミットされるリクエストは、次に作成する1つのコントローラクラスで処理する。

SampleDao.java
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


≪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) {

@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」の「*」の部分
methodRequestMethod.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リクエストパラメータ名リクエストパラメータ名と変数名が異なるときに記述
requiredtrue/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>


≪sample2.do用メソッド≫

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クラスである。

Person.java
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と同じ。


≪sample3.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" %>
- Springの入門本 -



TOP > Spring > SpringMVCの導入&サンプルプログラム

Tweet ̃Gg[͂ĂȃubN}[Nɒlj
技術空間