사용자 입력을 받는 모든 웹 애플리케이션에서는 그 입력을 유효성 검사하는 것이 필수적입니다. 우리는 JavaScript를 사용하여 클라이언트 측에서 사용자 입력을 유효성 검사할 수 있지만, 사용자가 JavaScript를 비활성화한 경우에도 서버 측에서 유효성을 검사하여 유효한 데이터를 처리하는 것이 필요합니다.
스프링 유효성 검사
스프링 MVC 프레임워크는 기본적으로 JSR-303 사양을 지원하며, 우리가 해야 할 일은 단지 스프링 MVC 애플리케이션에 JSR-303 및 그 구현 종속성을 추가하는 것입니다. 스프링은 또한 @Validator
주석과 BindingResult
클래스를 제공하여 컨트롤러 요청 핸들러 메서드에서 Validator 구현으로 인한 오류를 가져올 수 있습니다. 우리는 두 가지 방법으로 사용자 정의 validator 구현을 만들 수 있습니다. 첫 번째 방법은 JSR-303 사양을 준수하는 주석을 생성하고 해당 Validator 클래스를 구현하는 것입니다. 두 번째 접근 방식은 org.springframework.validation.Validator
인터페이스를 구현하고 이를 Controller 클래스에 @InitBinder
주석을 사용하여 validator로 설정하는 것입니다. 스프링 툴 스위트에서 간단한 스프링 MVC 프로젝트를 만들어 보겠습니다. 여기서 우리는 JSR-303 사양을 사용하며 그 구현 아티팩트인 하이버네이트-validator를 사용할 것입니다. 우리는 주석 기반의 폼 유효성 검사를 사용하고 JSR-303 사양 표준에 따라 사용자 정의 validator를 만들 것입니다. 또한 Validator
인터페이스를 구현하여 우리 자신의 사용자 정의 validator 클래스를 만들고 컨트롤러 핸들러 메서드 중 하나에서 사용할 것입니다. 최종 프로젝트는 아래 이미지와 같습니다. 각 구성 요소를 하나씩 살펴보겠습니다.
Spring MVC Form Validator
최종 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 프로젝트를 만들 때 두 개의 컨텍스트 구성 파일이 생성됩니다. 저는 조금 정리해서 하나의 스프링 빈 구성 파일만 남겼습니다. 최종 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 빈 구성 파일
보통 우리는 마지막에 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
빈이 하나의 컨트롤러에 주입될 것이고, 리소스 번들에서 로컬라이즈된 데이터를 읽을 messageSource
빈입니다. 나머지 부분은 어노테이션 지원, 뷰 리졸버 및 컨트롤러 클래스 및 기타 구성 요소를 스캔할 패키지를 제공하는 것입니다.
모델 클래스
이 프로젝트에는 두 가지 모델 클래스가 있습니다. 첫 번째 모델 클래스에서는 JSR-303 주석과 우리의 사용자 정의 주석 기반 유효성 검사기를 사용하고, 두 번째 모델 클래스에서는 우리의 Validator 구현만 사용할 것입니다. 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;
}
}
@Email, @NotEmpty, @DateTimeFormat 주석을 사용하고 있음을 주목하세요. 이들은 JSR-303에 추가되어 하이버네이트 유효성 검사기 구현에서 제공됩니다. 사용 중인 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는 표준 자바 빈이며, Employee 빈을 사용하여 폼을 유효성 검사하기 위해 사용자 정의 Validator 구현을 사용할 것입니다.
사용자 정의 Validator 구현
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에 특화된 유효성 검사기 구현입니다. supports()
메서드는 이 유효성 검사를 사용할 수 있는 객체를 Spring Framework에 의해 파악하는 데 사용됩니다. 우리는 validate()
메서드를 구현하고 필드 유효성 검사가 실패한 경우 오류를 추가합니다. Spring은 null 또는 비어 있는 것과 같은 기본적인 유효성 검사를 위해 org.springframework.validation.ValidationUtils
유틸리티 클래스를 제공합니다. 이 메서드가 반환되면 스프링 프레임워크가 Errors 객체를 BindingResult 객체에 바인딩합니다. 우리는 이를 컨트롤러 핸들러 메서드에서 사용합니다. ValidationUtils.rejectIfEmptyOrWhitespace()
메서드의 마지막 인수는 메시지 리소스의 키 이름을 가져옵니다. 이렇게 하면 사용자에게 로컬라이즈된 오류 메시지를 제공할 수 있습니다. Spring에서 i18n에 대한 자세한 정보는 Spring i18n Example를 읽어보세요.
컨트롤러 클래스
우리는 주석 기반의 양식 유효성 검사 및 사용자 정의 유효성 검사를 위해 두 개의 컨트롤러 클래스가 있습니다. 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";
}
}
어노테이션 기반의 폼 유효성 검사를 사용할 때는, 컨트롤러 핸들러 메소드 구현에 작은 변경만 필요합니다. 먼저, 검증을 원하는 모델 객체에 @Valid
어노테이션을 붙여야 합니다. 그런 다음 메소드에 BindingResult 인자를 가져야 합니다. 스프링이 에러 메시지로 채우는 것을 처리합니다. 핸들러 메소드 로직은 매우 간단합니다. 에러가 있는 경우에는 같은 페이지로 응답하고, 그렇지 않은 경우에는 사용자를 성공 페이지로 리디렉션합니다. 또 다른 중요한 점은 모델에 “customer” 속성을 추가하는 것입니다. 이는 스프링 프레임워크가 어떤 모델 객체를 폼 페이지에서 사용할지 알기 위해 필요합니다. 이를 수행하지 않으면 폼 데이터에 객체 바인딩이 이루어지지 않고 폼 유효성 검사가 작동하지 않습니다. EmployeeController.java 클래스 코드:
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() {
// ModelAttribute 값은 empSave.jsp에서 사용한 것과 동일해야 합니다.
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";
}
}
사용자 정의 유효성 검사기를 사용하기 위해 먼저 컨트롤러 클래스에 주입해야 합니다. 우리는 스프링 빈 자동 주입을 사용하여 @Autowired
및 @Qualifier
어노테이션을 사용합니다. 다음으로 WebDataBinder를 인자로 받는 메소드를 추가해야 하며, 사용할 사용자 정의 유효성 검사기를 설정합니다. 이 메소드는 @InitBinder
어노테이션으로 주석을 달아야 합니다. @ModelAttribute
를 사용하는 것은 모델에 빈 객체를 추가하는 또 다른 방법입니다. 나머지 코드는 고객 컨트롤러 구현과 유사합니다.
양식 유효성 검사 오류 메시지 리소스 번들
유효성 검사 오류에 사용할 다양한 유형의 메시지가 있는 리소스 번들을 살펴보는 시간입니다. 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 Form 태그를 사용해야 합니다. 우리의 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 Form 유효성 검사에 대한 여러 방법과 지역화된 오류 메시지에 리소스 번들을 사용한 내용입니다. 샘플 프로젝트는 아래 링크에서 다운로드하여 더 많이 배울 수 있습니다.
Source:
https://www.digitalocean.com/community/tutorials/spring-validation-example-mvc-validator