もしウェブアプリケーションでユーザーの入力を受け入れる場合、それを検証する必要があります。クライアントサイドではJavaScriptを使用してユーザーの入力を検証できますが、ユーザーがJavaScriptを無効にしている場合にも、サーバーサイドで検証する必要があり、有効なデータを処理していることを確認します。
Springの検証
Spring MVC FrameworkはデフォルトでJSR-303仕様をサポートしており、必要なのはSpring MVCアプリケーションにJSR-303とその実装依存関係を追加するだけです。Springはまた、@Validator
アノテーションとBindingResult
クラスを提供しており、これらを使用してコントローラのリクエストハンドラメソッドでValidator実装によって発生したエラーを取得できます。カスタムのバリデータ実装を2つの方法で作成できます。最初の方法は、JSR-303仕様に準拠するアノテーションを作成し、そのValidatorクラスを実装することです。2番目のアプローチは、org.springframework.validation.Validator
インターフェースを実装し、@InitBinder
アノテーションを使用してControllerクラスにバリデータとして設定することです。Spring Tool SuiteでシンプルなSpring MVCプロジェクトを作成しましょう。ここではJSR-303仕様とその実装アーティファクトhibernate-validatorを使用します。アノテーションベースのフォームバリデーションを行い、JSR-303仕様に基づいた独自のカスタムバリデータを作成します。また、Validator
インターフェースを実装して独自のカスタムバリデータクラスを作成し、それをコントローラのハンドラメソッドの1つで使用します。最終的なプロジェクトは以下の画像のようになります。それでは、各コンポーネントを一つずつ見ていきましょう。
Spring MVC フォームバリデータ
最終的な pom.xml ファイルは以下のようになります。標準の Spring MVC アーティファクトに加えて、プロジェクトには validation-api と hibernate-validator の依存関係があります。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev</groupId>
<artifactId>spring</artifactId>
<name>SpringFormValidation</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.7</java-version>
<org.springframework-version>4.0.2.RELEASE</org.springframework-version>
<org.aspectj-version>1.7.4</org.aspectj-version>
<org.slf4j-version>1.7.5</org.slf4j-version>
</properties>
<dependencies>
<!-- Form Validation using Annotations -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.1.0.Final</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
デプロイメント記述子
STS から Spring MVC プロジェクトを作成すると、2つのコンテキスト設定ファイルが作成されます。少し整理して、1つの Spring Bean 設定ファイルだけを残しました。最終的な web.xml ファイルは以下のようになります。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Spring Bean 設定ファイル
通常、Spring ビーン設定ファイルの構成は最後に確認しますが、今回はあまり多くの構成がありません。最終的な spring.xml ファイルは以下のようになります。
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean id="employeeValidator" class="com.journaldev.spring.form.validator.EmployeeFormValidator" />
<beans:bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename" value="classpath:message" />
<beans:property name="defaultEncoding" value="UTF-8" />
</beans:bean>
<context:component-scan base-package="com.journaldev.spring" />
</beans:beans>
唯一重要なポイントは、employeeValidator
ビーンをコントローラの1つにインジェクトし、messageSource
ビーンをリソースバンドルからローカライズデータを読み取るために注入することです。残りの部分は、注釈のサポート、ビューリゾルバ、およびコントローラクラスおよびその他のコンポーネントのスキャン用のパッケージを提供するものです。
モデルクラス
このプロジェクトには2つのモデルクラスがあります。最初のクラスでは、JSR-303アノテーションとカスタムアノテーションベースのバリデータを使用し、2番目のクラスでは、当社のバリデータ実装のみを使用します。Customer.javaのコード:
package com.journaldev.spring.form.model;
import java.util.Date;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import com.journaldev.spring.form.validator.Phone;
public class Customer {
@Size(min=2, max=30)
private String name;
@NotEmpty @Email
private String email;
@NotNull @Min(18) @Max(100)
private Integer age;
@NotNull
private Gender gender;
@DateTimeFormat(pattern="MM/dd/yyyy")
@NotNull @Past
private Date birthday;
@Phone
private String phone;
public enum Gender {
MALE, FEMALE
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
JSR-303に追加された@Email、@NotEmpty、@DateTimeFormatアノテーションをHibernateのバリデータ実装で提供されたものに加えて使用していることに注意してください。使用しているJSR-303のアノテーションには、@Size、@NotNullなどがあります。使用されている@Phoneアノテーションは、JSR-303仕様に基づいた当社のカスタム実装です。次のセクションで詳細を調べます。Employee.javaのコード:
package com.journaldev.spring.form.model;
public class Employee {
private int id;
private String name;
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
Employeeは標準のJava Beanであり、フォームをEmployee Beanで検証するために当社のカスタムバリデータ実装を使用します。
カスタムバリデータの実装
Phone.javaのコード:
package com.journaldev.spring.form.validator;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import javax.validation.Constraint;
import javax.validation.Payload;
@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {
String message() default "{Phone}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
ほとんどの部分は、JSR-303仕様に準拠するためのボイラープレートコードです。最も重要な部分は、@Constraint注釈で、ここで検証に使用されるクラス、つまりPhoneValidator
を指定します。PhoneValidator.javaのコード:
package com.journaldev.spring.form.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PhoneValidator implements ConstraintValidator {
@Override
public void initialize(Phone paramA) {
}
@Override
public boolean isValid(String phoneNo, ConstraintValidatorContext ctx) {
if(phoneNo == null){
return false;
}
//フォーマット "1234567890"の電話番号を検証する
if (phoneNo.matches("\\d{10}")) return true;
//-, .、またはスペースで電話番号を検証する
else if(phoneNo.matches("\\d{3}[-\\.\\s]\\d{3}[-\\.\\s]\\d{4}")) return true;
//拡張子が3〜5桁の電話番号を検証する
else if(phoneNo.matches("\\d{3}-\\d{3}-\\d{4}\\s(x|(ext))\\d{3,5}")) return true;
//エリアコードが括弧()内にある電話番号を検証する
else if(phoneNo.matches("\\(\\d{3}\\)-\\d{3}-\\d{4}")) return true;
//入力が一致しない場合はfalseを返す
else return false;
}
}
JSR-303仕様のバリデータ実装は、javax.validation.ConstraintValidator
インターフェースを実装する必要があります。DataSourceなどのリソースを使用している場合は、initialize()
メソッドでそれらを初期化できます。検証メソッドはisValid
であり、データが有効であればtrueを返し、それ以外の場合はfalseを返す必要があります。正規表現に慣れていない場合は、Java正規表現チュートリアルで詳細を読むことができます。EmployeeFormValidator.javaクラスのコード:
package com.journaldev.spring.form.validator;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import com.journaldev.spring.form.model.Employee;
public class EmployeeFormValidator implements Validator {
//このバリデータで検証できるオブジェクト
@Override
public boolean supports(Class > paramClass) {
return Employee.class.equals(paramClass);
}
@Override
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "id", "id.required");
Employee emp = (Employee) obj;
if(emp.getId() <=0){
errors.rejectValue("id", "negativeValue", new Object[]{"'id'"}, "id can't be negative");
}
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "name.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "role", "role.required");
}
}
EmployeeFormValidatorは、Spring Frameworkに特化したバリデータの実装です。Spring Frameworkによってsupports()
メソッドが実装され、このバリデーションが使用できるオブジェクトを知ることができます。私たちはvalidate()
メソッドを実装し、フィールドのバリデーションが失敗した場合はエラーを追加します。Springは、nullまたは空などの基本的なバリデーションのためのorg.springframework.validation.ValidationUtils
ユーティリティクラスを提供しています。このメソッドが返されると、Spring FrameworkはErrorsオブジェクトをBindingResultオブジェクトにバインドし、私たちがコントローラーハンドラーメソッドで使用するものです。ValidationUtils.rejectIfEmptyOrWhitespace()
の最後の引数は、メッセージリソースのキー名を取ります。これにより、ユーザーにローカライズされたエラーメッセージを提供することができます。Springでi18nについての詳細は、Spring i18n Exampleを読んでください。
Controller Classes
私たちは2つのコントローラークラスを持っています。アノテーションベースのフォームバリデーション用とカスタムバリデータ用のものです。CustomerController.javaクラスのコード:
package com.journaldev.spring.form.controllers;
import java.util.HashMap;
import java.util.Map;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.journaldev.spring.form.model.Customer;
@Controller
public class CustomerController {
private static final Logger logger = LoggerFactory
.getLogger(CustomerController.class);
private Map<String, Customer> customers = null;
public CustomerController(){
customers = new HashMap<String, Customer>();
}
@RequestMapping(value = "/cust/save", method = RequestMethod.GET)
public String saveCustomerPage(Model model) {
logger.info("Returning custSave.jsp page");
model.addAttribute("customer", new Customer());
return "custSave";
}
@RequestMapping(value = "/cust/save.do", method = RequestMethod.POST)
public String saveCustomerAction(
@Valid Customer customer,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
logger.info("Returning custSave.jsp page");
return "custSave";
}
logger.info("Returning custSaveSuccess.jsp page");
model.addAttribute("customer", customer);
customers.put(customer.getEmail(), customer);
return "custSaveSuccess";
}
}
package com.journaldev.spring.form.controllers;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.journaldev.spring.form.model.Employee;
@Controller
public class EmployeeController {
private static final Logger logger = LoggerFactory
.getLogger(EmployeeController.class);
private Map emps = null;
@Autowired
@Qualifier("employeeValidator")
private Validator validator;
@InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
public EmployeeController() {
emps = new HashMap();
}
@ModelAttribute("employee")
public Employee createEmployeeModel() {
// アノテーションベースのフォーム検証を使用する場合、コントローラーハンドラーメソッドの実装にはわずかな変更が必要です。まず、検証したいモデルオブジェクトに@Valid
アノテーションを付ける必要があります。次に、メソッドにBindingResult引数が必要で、Springがエラーメッセージでそれを埋めるのを担当します。ハンドラーメソッドのロジックは非常にシンプルで、エラーがあれば同じページで応答し、それ以外の場合はユーザーを成功ページにリダイレクトします。もう1つ重要なポイントは、モデルに「customer」属性を追加していることです。これはSpringフレームワークにどのモデルオブジェクトをフォームページで使用するかを知らせるために必要です。これを行わないと、フォームデータへのオブジェクトのバインディングが行われず、フォームの検証が機能しません。EmployeeController.javaのクラスコード:
return new Employee();
}
@RequestMapping(value = "/emp/save", method = RequestMethod.GET)
public String saveEmployeePage(Model model) {
logger.info("Returning empSave.jsp page");
return "empSave";
}
@RequestMapping(value = "/emp/save.do", method = RequestMethod.POST)
public String saveEmployeeAction(
@ModelAttribute("employee") @Validated Employee employee,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
logger.info("Returning empSave.jsp page");
return "empSave";
}
logger.info("Returning empSaveSuccess.jsp page");
model.addAttribute("emp", employee);
emps.put(employee.getId(), employee);
return "empSaveSuccess";
}
}
// ModelAttributeの値はempSave.jspで使用されるものと同じである必要があります。// カスタムバリデータを使用するには、まずそれをコントローラークラスにインジェクトする必要があります。これには@Autowired
と@Qualifier
アノテーションを使用しています。次に、WebDataBinderを引数に取るメソッドが必要で、そこでカスタムバリデータを設定します。このメソッドは@InitBinder
アノテーションで注釈付けする必要があります。@ModelAttribute
を使用すると、ビーンオブジェクトをModelに追加する別の方法があります。残りのコードはcustomerコントローラーの実装と類似しています。
フォーム検証エラーメッセージリソースバンドル
検証エラーに使用する異なるタイプのメッセージを含むリソースバンドルを見てみる時が来ました。message_en.properties ファイル:
#アプリケーション定義エラーメッセージ
id.required=Employee ID is required
name.required=Employee Name is required
role.required=Employee Role is required
negativeValue={0} can't be negative or zero
#フォームデータからビーンへの変換が失敗した場合に使用されるSpringフレームワークのエラーメッセージ
typeMismatch.int={0} Value must be an integer
typeMismatch.java.lang.Integer={0} must be an integer
typeMismatch={0} is of invalid format
#アノテーションのアプリケーションメッセージ、{ValidationClass}.{modelObjectName}.{field}
# {0} はフィールド名であり、他のフィールドはアルファベット順で、max そして min
Size.customer.name=Customer {0} should be between {2} and {1} characters long
NotEmpty.customer.email=Email is a required field
NotNull.customer.age=Customer {0} should be in years
#汎用アノテーションクラスメッセージ
Email=Email address is not valid
NotNull=This is a required field
NotEmpty=This is a required field
Past=Date should be Past
#カスタム検証アノテーション
Phone=Invalid format, valid formats are 1234567890, 123-456-7890 x1234
I have provided message key details in the comment itself, so I will skip them here. The only important point to note here is the way messages will be looked up, first key name {ValidationClass}.{modelObjectName}.{field} is looked up and if that is not found then {ValidationClass}.{modelObjectName} is looked up. If that is missing, then finally {ValidationClass} key is looked up. If nothing is found then the default message provided will be returned. Read more about resource messages at Spring Localization Example.
フォームとエラーを含むビューページ
Springフレームワークの検証実装を使用しているため、エラーを取得してフォームビーンと変数名を設定するには、Springフォームタグを使用する必要があります。以下は、custSave.jsp ファイルのコードです。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="https://www.springframework.org/tags/form"
prefix="springForm"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Customer Save Page</title>
<style>
.error {
color: #ff0000;
font-style: italic;
font-weight: bold;
}
</style>
</head>
<body>
<springForm:form method="POST" commandName="customer"
action="save.do">
<table>
<tr>
<td>Name:</td>
<td><springForm:input path="name" /></td>
<td><springForm:errors path="name" cssClass="error" /></td>
</tr>
<tr>
<td>Email:</td>
<td><springForm:input path="email" /></td>
<td><springForm:errors path="email" cssClass="error" /></td>
</tr>
<tr>
<td>Age:</td>
<td><springForm:input path="age" /></td>
<td><springForm:errors path="age" cssClass="error" /></td>
</tr>
<tr>
<td>Gender:</td>
<td><springForm:select path="gender">
<springForm:option value="" label="Select Gender" />
<springForm:option value="MALE" label="Male" />
<springForm:option value="FEMALE" label="Female" />
</springForm:select></td>
<td><springForm:errors path="gender" cssClass="error" /></td>
</tr>
<tr>
<td>Birthday:</td>
<td><springForm:input path="birthday" placeholder="MM/dd/yyyy"/></td>
<td><springForm:errors path="birthday" cssClass="error" /></td>
</tr>
<tr>
<td>Phone:</td>
<td><springForm:input path="phone" /></td>
<td><springForm:errors path="phone" cssClass="error" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Save Customer"></td>
</tr>
</table>
</springForm:form>
</body>
</html>
commandName="customer"
は、フォームオブジェクトが公開されるモデル属性の名前を設定するために使用されます。デフォルト値は「command」ですので、コントローラクラスで使用しているモデル属性名に設定する必要があります。springForm:errors
は、ページがレンダリングされる際に見つかったエラーをレンダリングするために使用されます。path
属性は、データバインディングに使用されるオブジェクトプロパティを定義するために使用されます。残りのコードはエラーメッセージのスタイリングのためにいくつかのCSSを含む標準のHTMLです。custSaveSuccess.jspファイルは以下の通りです。
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fmt" uri="https://java.sun.com/jsp/jstl/fmt" %>
<%@ page session="false" %>
<html>
<head>
<title>Customer Saved Successfully</title>
</head>
<body>
<h3>
Customer Saved Successfully.
</h3>
<strong>Customer Name:${customer.name}</strong><br>
<strong>Customer Email:${customer.email}</strong><br>
<strong>Customer Age:${customer.age}</strong><br>
<strong>Customer Gender:${customer.gender}</strong><br>
<strong>Customer Birthday:<fmt:formatDate value="${customer.birthday}" type="date" /></strong><br>
</body>
</html>
バリデーションエラーがない場合には顧客の値を表示するシンプルなJSPページで、このページが応答として返されます。その名前はempSave.jspです。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="https://www.springframework.org/tags/form"
prefix="springForm"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Employee Save Page</title>
<style>
.error {
color: #ff0000;
font-style: italic;
font-weight: bold;
}
</style>
</head>
<body>
<springForm:form method="POST" commandName="employee"
action="save.do">
<table>
<tr>
<td>Employee ID:</td>
<td><springForm:input path="id" /></td>
<td><springForm:errors path="id" cssClass="error" /></td>
</tr>
<tr>
<td>Employee Name:</td>
<td><springForm:input path="name" /></td>
<td><springForm:errors path="name" cssClass="error" /></td>
</tr>
<tr>
<td>Employee Role:</td>
<td><springForm:select path="role">
<springForm:option value="" label="Select Role" />
<springForm:option value="ceo" label="CEO" />
<springForm:option value="developer" label="Developer" />
<springForm:option value="manager" label="Manager" />
</springForm:select></td>
<td><springForm:errors path="role" cssClass="error" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Save"></td>
</tr>
</table>
</springForm:form>
</body>
</html>
empSaveSuccess.jspファイル:
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Employee Saved Successfully</title>
</head>
<body>
<h3>
Employee Saved Successfully.
</h3>
<strong>Employee ID:${emp.id}</strong><br>
<strong>Employee Name:${emp.name}</strong><br>
<strong>Employee Role:${emp.role}</strong><br>
</body>
</html>
Spring MVCフォームバリデーションアプリケーションのテスト
アプリケーションはデプロイの準備が整い、いくつかのテストを実行する準備ができています。お好きなサーブレットコンテナにデプロイしてください。私はApache Tomcat 7を使用しており、以下の画像は検証エラーメッセージが表示されるいくつかのページを示しています。入力データに基づいて、異なるエラーメッセージが表示される可能性があります。
これがSpring MVCフォーム検証の異なる方法とローカライズされたエラーメッセージにリソースバンドルを使用するすべてです。サンプルプロジェクトは以下のリンクからダウンロードして詳細を学ぶことができます。
Source:
https://www.digitalocean.com/community/tutorials/spring-validation-example-mvc-validator