Spring MVC

Spring MVCでチェック処理を実装してみた

今回は、Spring MVC上で、チェック処理を行うプログラムを作成してみたので、そのサンプルプログラムを共有する。

前提条件

下記記事の実装が完了していること。

Spring MVCで複数画面をもつWEBアプリケーションを作成してみた今回は、Spring MVC上で、複数画面間で画面遷移するプログラムを作成してみたので、そのサンプルプログラムを共有する。 前提条...

また、下記サイトのプロパティエディタのインストールが完了していること。
https://www.saka-en.com/eclipse/eclipse-properties-editor-install/

流用ソース

Spring Bootを使っていた、下記記事のソースコードを流用するものとする。

Spring BootのWEB画面上でチェック処理を実装してみた(ソースコード編)今回も、引き続きチェック処理を含むそのサンプルプログラムについて共有する。前回は、サンプルプログラムの完成イメージについて記載していたが...

サンプルプログラムの実行結果

下記記事の「完成した画面イメージの共有」と同じ結果となる。ただし、初期表示画面へのアクセスパスは、「http://(サーバー名):(ポート番号)/(プロジェクト名)/」と読み替えること。

Spring BootのWEB画面上でチェック処理を実装してみた(完成イメージ編)今回は、以前作成した、入力画面・確認画面・完了画面の3画面を含み、HTMLオブジェクトとしてテキストボックス・セレクトボックス・ラジオボ...



サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、「前提条件」または「流用ソース」のプログラムから変更したプログラムである。

pom.xmlに追加した内容は以下の通りで、Validatorのライブラリ「validation-api」「hibernate-validator」を追加している。それぞれ、古いバージョンだと動かない場合があるため、Spring Bootでサンプル作成時と同じバージョンを指定している。

<!-- Validator -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.17.Final</version>
</dependency>

また、servlet-context.xmlに追加した内容は以下の通りで、メッセージリソース読み込み定義を追加している。この定義を追加することで、src/main/resources 下のmessages.propertiesが取得できるようになっている。

<!-- メッセージリソースの読み込み -->
<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <beans:property name="basename" value="classpath:messages" />
    <beans:property name="defaultEncoding" value="UTF-8" />
</beans:bean>
サラリーマン型フリーランスSEという働き方でお金の不安を解消しよう先日、「サラリーマン型フリーランスSE」という働き方を紹介するYouTube動画を視聴しましたので、その内容をご紹介します。 「サ...

さらに、メッセージプロパティの内容は以下の通りで、「流用ソース」と比べ、NotEmptyのメッセージ設定を「javax.validation.constraints.NotEmpty.message=~」⇒「NotEmpty=~」と変更している。

#メッセージ
validation.date-empty={0}を入力してください。
validation.date-invalidate=生年月日が存在しない日付になっています。
validation.date-future=生年月日が未来の日付になっています。
validation.empty-msg=
NotEmpty={0}を入力してください。
validation.sex-invalidate=性別に不正な値が入っています。

#フィールド名
name=名前
sex=性別
checked=確認チェック

また、CSSファイルの内容は以下の通りで、内容は「流用ソース」そのままで、webapp/resources/static 下に配置場所を変更している。

.errorMessage{
    color: #FF0000;
}
.fieldError{
    background-color: #FFCCFF;
}



さらに、コントローラクラスの内容は以下の通りで、@GetMapping、@PostMappingアノテーションの代わりに、@RequestMappingアノテーションでmethod属性を指定するようにしている。

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;

/**
 * コントローラクラス
 * 「@SessionAttributes(types = DemoForm.class)」により、
 * 生成したFormオブジェクトをセッションとしてもたせている
 */
@Controller
@SessionAttributes(types = DemoForm.class)
public class DemoController {

    /**
     * Formオブジェクトを初期化して返却する
     * @return Formオブジェクト
     */
    @ModelAttribute("demoForm")
    public DemoForm createDemoForm(){
        DemoForm demoForm = new DemoForm();
        return demoForm;
    }

    /**
     * 入力画面に遷移する
     * @return 入力画面へのパス
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index(){
        return "input";
    }

    /**
     * エラーチェックを行い、エラーが無ければ確認画面に遷移し、
     * エラーがあれば入力画面のままとする
     * @param demoForm Formオブジェクト
     * @param result バインド結果
     * @return 確認画面または入力画面へのパス
     */
    @RequestMapping(value = "/confirm", method = RequestMethod.POST)
    public String confirm(@Validated DemoForm demoForm, BindingResult result){
        //formオブジェクトのチェック処理を行う
        if(result.hasErrors()){
            //エラーがある場合は、入力画面のままとする
            return "input";
        }
        //アノテーション以外のチェック処理を行い、画面遷移する
        return checkOthers(demoForm, result, "confirm");
    }

    /**
     * エラーチェックを行い、エラーが無ければ完了画面へのリダイレクトパスに遷移し、
     * エラーがあれば入力画面に戻す
     * @param demoForm Formオブジェクト
     * @param result バインド結果
     * @return 完了画面へのリダイレクトパスまたは入力画面へのパス
     */
    @RequestMapping(value = "/send", params = "next", method = RequestMethod.POST)
    public String send(@Validated DemoForm demoForm, BindingResult result){
        //formオブジェクトのチェック処理を行う
        if(result.hasErrors()){
            //エラーがある場合は、入力画面に戻す
            return "input";
        }
        //アノテーション以外のチェック処理を行い、画面遷移する
        return checkOthers(demoForm, result, "redirect:/complete");
    }

    /**
     * 完了画面に遷移する
     * @param sessionStatus セッションステータス
     * @return 完了画面
     */
    @RequestMapping(value = "/complete", method = RequestMethod.GET)
    public String complete(SessionStatus sessionStatus){
        //セッションオブジェクトを破棄
        sessionStatus.setComplete();
        return "complete";
    }

    /**
     * 入力画面に戻る
     * @return 入力画面
     */
    @RequestMapping(value = "/send", params = "back", method = RequestMethod.POST)
    public String back(){
        return "input";
    }

    /**
     * アノテーション以外のチェック処理を行い、画面遷移先を返却
     * @param demoForm Formオブジェクト
     * @param result バインド結果
     * @param normalPath 正常時の画面遷移先
     * @return 正常時の画面遷移先または入力画面へのパス
     */
    private String checkOthers(DemoForm demoForm, BindingResult result, String normalPath){
        //** アノテーション以外のチェック処理を行う
        //** エラーがある場合は、エラーメッセージ・(エラー時に赤反転するための)
        //** エラーフィールドの設定を行い、入力画面のままとする
        //生年月日のチェック処理
        int checkDate = DateCheckUtil.checkDate(demoForm.getBirthYear()
                , demoForm.getBirthMonth(), demoForm.getBirthDay());
        switch(checkDate){
            case 1:
                //生年月日_年が空文字の場合のエラー処理
                result.rejectValue("birthYear", "validation.date-empty"
                        , new String[]{"生年月日_年"}, "");
                return "input";
            case 2:
                //生年月日_月が空文字の場合のエラー処理
                result.rejectValue("birthMonth", "validation.date-empty"
                        , new String[]{"生年月日_月"}, "");
                return "input";
            case 3:
                //生年月日_日が空文字の場合のエラー処理
                result.rejectValue("birthDay", "validation.date-empty"
                        , new String[]{"生年月日_日"}, "");
                return "input";
            case 4:
                //生年月日の日付が不正な場合のエラー処理
                result.rejectValue("birthYear", "validation.date-invalidate");
                //生年月日_月・生年月日_日は、エラーフィールドの設定を行い、
                //メッセージを空文字に設定している
                result.rejectValue("birthMonth", "validation.empty-msg");
                result.rejectValue("birthDay", "validation.empty-msg");
                return "input";
            case 5:
                //生年月日の日付が未来日の場合のエラー処理
                result.rejectValue("birthYear", "validation.date-future");
                //生年月日_月・生年月日_日は、エラーフィールドの設定を行い、
                //メッセージを空文字に設定している
                result.rejectValue("birthMonth", "validation.empty-msg");
                result.rejectValue("birthDay", "validation.empty-msg");
                return "input";
            default:
                //性別が不正に書き換えられていないかチェックする
                if(!demoForm.getSexItems().keySet().contains(demoForm.getSex())){
                    result.rejectValue("sex", "validation.sex-invalidate");
                    return "input";
                }
                //エラーチェックに問題が無いので、正常時の画面遷移先に遷移
                return normalPath;
        }
    }
}

他、DateCheckUtil.java、DemoForm.java、HTML各ソースは「流用ソース」と同じ内容となる。そのソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-mvc-web-check/demo

要点まとめ

  • Spring MVCプロジェクトでチェック処理を実装するには、Validatorのライブラリ「validation-api」「hibernate-validator」を追加し、servlet-context.xmlにメッセージリソース読み込み定義を追加する必要がある。
  • CSSファイルはWEB-INFディレクトリの外側の、webapp/resources下等に配置する必要がある。