Spring MVCの主な機能

前置きが長くなったが、それでは早速Spring MVCの機能についてみていく。現在のSpring MVCでは、遷移先の情報は設定ファイルではなく、コントローラクラスに記述する。また、Spring 3.0からは、RESTスタイルのURLが簡単に実現出来るようになっている。

例えば、JSPからhttpのgetで送信する場合は以下のようになる。

JSP

<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> 
  <spring:url value="user/{userId}" var="userUrl"> 
    <spring:param name="userId" value="${userId}"/> 
  </spring:url> 
  <a href="${fn:escapeXml(userUrl)}">ユーザ</a>

上記の例では、URLは、「http://localhost:8080/mvc-sample/user/0001」のようになる。<spring:url>タグのvalue属性にはURLを記述する。{変数名}で動的に値を変更することが出来る。{変数名}の値は、<spring:param>タグのname属性で設定した値が使用される。<spring:param>タグのvalue属性には、EL式を利用して値を取得している。<spring:url>タグのvar属性に指定した値を利用して、<a>タグのhref属性に指定する。不正な値が設定されないようにJSTLの${fn:escapeXml}で文字列をエスケープしている。

リクエストを受け取るコントローラクラスは以下のようになる。

コントローラ

@Controller 
public class UserController { 
    @Autowired 
    private UserService userService; 
    @RequestMapping(value = "/user/{userId}", method = RequestMethod.GET) 
    public String show(@PathVariable String userId, ModelMap modelMap) { 
        modelMap.addAttribute("user", userService.show(userId)); 
        return "user/show"; 
    } 
}

コントローラクラスには、@Controllerを付与する必要がある。このとき、 Springのbean定義ファイルには「<mvc:annotation-driven />」という1行が必要になる。@RequestMappingは、value属性でURLのパスやmethod属性でhttpのメソッドを指定する。value属性には、{変数名}で動的な値も設定することが出来る。メソッドアノテーションに指定している@PathVariableは、@RequestMappingのvalue属性で指定した動的なURLの{変数名}部分がバインドされる。メソッド引数のModelMapは、次の画面に引き継ぎたいパラメータがあれば使用する。戻り値にuser/showを指定しているので、WEB-INF/views/user/show.jspに遷移する。show.jspでは、以下のようにEL式で値を取得することが出来る。

<c:out value="${user.userId}"/>

JSPからhttpのPOSTで送信する場合は以下のようになる。ここではあわせて、入力チェックも行う例を示す。入力チェックは、Spring 3.0からアノテーションで入力チェックを設定するBean Validationが使えるようになっている。なお、Bean Validationを使用するには、以下の設定をpom.xmlに追加する。

pom.xmlへの追加

No Group Id Artifact Id Version
1 javax.validation validation-api 1.0.0.GA
2 org.hibernate hibernate-validator 4.0.2.GA
3 joda-time joda-time 1.6

JSP

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<form:form modelAttribute="user" method="post"> 
  <p> 
    <form:label path="userId" for="userId">ユーザID</form:label> 
    <form:input path="userId"/><form:errors path="userId" cssClass="errors"/> 
  </p> 
  <p> 
    <form:label path="userName" for="userName">ユーザID</form:label> 
    <form:input path="userName"/><form:errors path="userName" cssClass="errors"/> 
  </p> 
  <p> 
    <form:label path="address" for="address">アドレス</form:label> 
    <form:input path="address"/><form:errors path="address" cssClass="errors" /> 
  </p> 
  <input type="submit"/> 
</form:form>

JSPの記述には、便利なSpringのformタグを使用している。<form:form>タグのmodelAttribute属性で使用するDTOを指定する。その為、<form:input>などで指定しているuserIdなどの変数を持っている必要がある。<form:errors>タグは、エラー時にエラーメッセージを表示する。入力チェックは、DTOにアノテーションを付与することで行う。

コントローラクラスは以下のようになる。

コントローラ

@Controller 
public class UserController { 
    @Autowired 
    private UserService userService; 
    @RequestMapping(method = RequestMethod.POST) 
    public String create(@Valid User user, BindingResult result, 
            ModelMap modelMap) { 
        if (result.hasErrors()) { 
            modelMap.addAttribute("user", user); 
            return "user/create"; 
        } 
        userService.create(user); 
        return "user/show"; 
    } 
}

コントローラクラスでは、メソッド引数として@Validを指定する。BindingResultに入力チェックされた結果が格納されているので、チェック結果に応じてハンドリングを行う。

なお、入力エラー時のメッセージは、デフォルトでは、hibernate-validator-4.0.2.GA.jarのorg.hibernate.validatorに含まれるValidatorMessages.propertiesのメッセージが使用される。ここには日本語用のメッセージがないため、ValidationMessages_ja.propertiesというファイルを作成してクラスパス上に配置する必要がある。設定例を以下に示すので参考にしてほしい。キーは、「javax.validation.constraints.[入力チェックルール].message」となる。これらは、JSR-303というJava標準で決められているルールに準拠している。

ValidationMessages_ja.propertiesの記述例

javax.validation.constraints.AssertFalse.message=不正な値が入力されました。
javax.validation.constraints.AssertTrue.message=不正な値が入力されました。
javax.validation.constraints.DecimalMax.message={value}より同じか小さい値を入力してください。 
javax.validation.constraints.DecimalMin.message={value}より同じか大きい値を入力してください。 
javax.validation.constraints.Digits.message=整数{integer}桁以内、小数{fraction}桁以内で入力してください。
javax.validation.constraints.Future.message=未来の日付を入力してください。
javax.validation.constraints.Max.message={value}より同じか小さい値を入力してください。 
javax.validation.constraints.Min.message={value}より同じか大きい値を入力してください。
javax.validation.constraints.NotNull.message=値が未入力です。 
javax.validation.constraints.Null.message=値は未入力でなければいけません。
javax.validation.constraints.Past.message=過去の日付を入力してください。
javax.validation.constraints.Pattern.message="{regexp}"にマッチしていません。
javax.validation.constraints.Size.message=サイズは{min}から{max}の間の値を入力してください。
org.hibernate.validator.constraints.Email.message=E-mail形式で入力してください。
org.hibernate.validator.constraints.Length.message=文字の長さは{min}から{max}の間で入力してください。
org.hibernate.validator.constraints.NotEmpty.message=値が未入力です。 
org.hibernate.validator.constraints.Range.message={min}から{max}の間の値を入力してください。

アノテーションの設定例

   @AssertFalse
    private boolean assertFalse;
    @AssertTrue
    private boolean assertTrue;
    @DecimalMax(value="5.5")
    private BigDecimal decimalMax;
    @DecimalMin(value="5.5")
    private BigDecimal decimalMin;
    @Digits(integer=3,fraction=2)
    private BigDecimal digits;
    @Future
    @DateTimeFormat(pattern="yyyy/MM/dd")
    private Date futureDate;
    @Max(value=3)
    private int max;
    @Min(value=3)
    private int min;
    @NotNull
    private String notNull;
    @Null
    private String nul;
    @Past
    @DateTimeFormat(pattern="yyyy/MM/dd")
    private Date pastDate;
    @Pattern(regexp="[a-z]+")
    private String pattern;
    @Size(min=3,max=5)
    private String size;
    @Email
    private String email;
    @Length(min=3,max=5)
    private String length;
    @NotEmpty
    private String notEmpty;
    @Range(min=3,max=5)
    private BigDecimal range;

*  *  *

本稿ではSpring MVCの基本的な機能について紹介した。最新のMVCフレームワークとしては、格段目立った機能がないもののシンプルで使いやすいフレームワークとなっている。フレームワークを検討している方は選択肢の一つに加える価値はあるだろう。

執筆者紹介

石橋 稔章(ISHIBASHI Toshiaki) - DTS


JavaEEのフレームワーク開発などを経験した後、業務システム向けアーキテクトに。現在は、金融系の大規模プロジェクトに参画し、リリースに向けて奮闘中。

最近は温泉旅行に行きたくてしかたがない。好きな食べものは、イチゴ。