본문 바로가기

Spring 3/JSR-303 Validation

Spring JSR-303 Validation example

Spring JSR-303 Validation example



Message Resource 를 이용하지 않는 JSR-303 데이터 검증 방법은 여기를 참조하세요


테스트 환경

Windows 7, JDK1.7, Tomcat 8, Eclipse luna, Spring 3.2, STS, Maven



필요한 라이브러리(https://mvnrepository.com/ )

  • Java Bean Validation API
  • Hibernate Validation 



서블릿 설정파일에 추가할 내용은 여기를 참조하세요



Message Resource 파일의 생성

messages_ko.properties, messages_en.properties, messages.properties

위의 이름으로 메시지 리소스파일을 생성한다



Message Resource 파일이 위치

메시지 리소스파일은 클래스패스에 두면 되므로...

WEB-INF/ 아래에 classes 라는 폴더를 만들고 그 안에 위의 3가지 파일을 저장해둔다

classes/ 안에 messages 라는 폴더를 생성하고 그 안에 둘 수도 있는데, 클래스패스 안에만 두면 된다.

여기서는 메시지 리소스 파일의 경로를 WEB-INF/classes/messages/messages_ko.properties 으로 설정했다.

각 언어 환경에 따라서 자동으로 위의 3가지 파일 중에서 한가지가 사용된다.





Message Resource 파일의 경로 등록


servlet-context.xml 파일에 다음과 같이 등록한다

<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/mvc"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:beans="http://www.springframework.org/schema/beans"

    xmlns:mvc="http://www.springframework.org/schema/mvc"

    xmlns:context="http://www.springframework.org/schema/context"

    xsi:schemaLocation="http://www.springframework.org/schema/mvc 

    http://www.springframework.org/schema/mvc/spring-mvc.xsd

        http://www.springframework.org/schema/beans 

        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context 

        http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Process annotations on registered beans like @Autowired... -->

    <context:annotation-config/>

    

    <!-- Enables the Spring MVC @Controller programming model -->

    <annotation-driven/>


    <context:component-scan base-package="org.kdea.java" />

    <context:component-scan base-package="org.kdea.service" />


    <!-- 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:property name="contentType" value="text/html; charset=UTF-8"/>

    </beans:bean>


    <beans:bean id="messageSource" 

  class="org.springframework.context.support.ResourceBundleMessageSource">

    <beans:property name="basename" value="messages/messages"/> 

    </beans:bean>

<beans:bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />


</beans:beans>




데이터 검증대상 빈의 속성에 Annotation 적용


아래에서 사용된 디폴트 메시지의 내용은 메시지 리소스를 사용하지 않을 때에 자동으로 사용된다

package org.kdea.java;


import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotEmpty;


public class LoginBean {


// 아래에 사용된 디폴트 메시지는 메시지 리소스를 사용하지 않을 때 자동으로 사용된다

@Size(min=1,max=10, message="1~10 자 사이")

private String id;

@NotEmpty(message="필수입력")

private String pwd;

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getPwd() {

return pwd;

}

public void setPwd(String pwd) {

this.pwd = pwd;

}

}



위의 Annotation 외에도 다음과 같은 것들이 사용된다

@Range(min = 1, max = 10)

int age;


@Min(1)

@Max(10)

int age;


@NotNull

@Size(min=4, max=10, message="아이디는 4자 ~ 10자 사이로 입력하세요!")

private String id;


@NotNull

@Size(min=6, max=12, message="비밀번호는 6자에서12자 사이로 입력하세요!")

private String pwd


@NotEmpty(message="필수입력")

private String pwd;


@NotNull(message="이름을 입력하세요!")

@Size(max=10, message="한글이름은 공백포함 5자, 영문은 공백포함 10자 사이로 입력하세요!")

private String name;


@Length(min=6,max=20)

private String name;


@Pattern(regexp=".+@.+\\.[a-z]+")

private String email;


@NotEmpty @Pattern(".+@.+\\.[a-z]+")

private String from;


@Past(message="생일은 과거날짜만 입력하세요")

private Date dateOfBirth;


@Email

private String email;


@DateTimeFormat(pattern="MM/dd/yyyy")

@NotNull @Past

private Date birthday;


@DecimalMax(value="180") @DecimalMin(value="20")

@Digits(integer=3, fraction=0)

private int weight;


@DateTimeFormat(iso = ISO.DATE)

@Future

private Date releaseDate;


@NumberFormat(pattern = "#,###")

@Digits(integer=5, fraction=0)

private int ticketPrice;


@AssertFalse

@AssertTrue



Message Resource 파일에 메시지 입력

위의 빈 속성에 적용한 Annotation의 이름과 빈객체의 참조변수 이름, 속성이름메시지 내용을 입력한다.

한글을 입력하면 자동으로 유니코드 16진수 숫자로 변경되어 저장된다.


WEB-INF/classes/messages/messages_ko.properties 의 내용

NotEmpty.loginBean.pwd=\uC554\uD638\uB294 \uD544\uC218\uD56D\uBAA9\uC785\uB2C8\uB2E4

Size.loginBean.id=\uC544\uC774\uB514\uB294 1~10\uC790 \uC0AC\uC774\uB85C \uC785\uB825\uD574\uC8FC\uC138\uC694



Controller 클래스의 검증대상 파라미터에 @Valid 를 붙인다

package org.kdea.java;


import javax.annotation.Resource;

import javax.validation.Valid;


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;


@Controller

public class LoginController {


@RequestMapping(value="/login.htm", method=RequestMethod.GET)

public String login(Model model){

model.addAttribute("loginBean", new LoginBean());

return "loginForm"; 

}

// 데이터 검증시 오류가 있으면 request 영역에 저장되므로 

// forward 목적 jsp에서는 오류 메시지에 접근할 수 있다

// 그러므로 redirect:/login.htm을 사용하면 오류 메시지가 폼에 전달되지 않음

@RequestMapping(value="/login.htm", method=RequestMethod.POST)

public String login(@Valid LoginBean loginBean, BindingResult result){

if(result.hasErrors()){

System.out.println(result);

return "loginForm"; 

}

return "hello";

}

}


위의 내용은 LoginBean 에서 데이터 검증오류가 발생하면 loginForm.jsp 가 다시 브라우저에 전송되고 브라우저의 폼에는 오류 메시지가 출력된다.

폼에서 오류 메시지가 출력되도록 하려면 아래와 같이 스프링에서 제공하는 태그를 이용하는 것이 간편하다



폼에서 데이터 검증오류 출력하기

loginForm.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"

    pageEncoding="utf-8"%>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>


<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>로그인 폼</title>

<style type="text/css">

   .errorMsg { color: red; }

</style>

</head>

<body>

<h2>로그인 폼</h2>

<%--

<div class="errorMsg">

<spring:bind path="loginBean.id">

${status.errorMessage }

</spring:bind>

<spring:bind path="loginBean.pwd">

${status.errorMessage }

</spring:bind>

</div>


<form action="login.htm" method="post">

I D <input type="text" name="id"><br>

PWD <input type="password" name="pwd"><br>

<input type="submit" value="Login">

</form>

 --%>

<form:form method="POST" commandName="loginBean" action="login.htm">


<!--loginBean의 모든 속성에 대한 오류를 아래에 출력한다-->

<form:errors path="*" cssClass="errorMsg" element="div" />

<table>

<tr>

<td>I D :</td>

<td><form:input path="id" /></td>

<td><form:errors path="id" cssClass="errorMsg" /></td>

</tr>

<tr>

<td>PWD :</td>

<td><form:input path="pwd" /></td>

<td><form:errors path="pwd" cssClass="errorMsg" /></td>

</tr>

<tr>

<td colspan="3"><input type="submit" /></td>

</tr>

</table>

</form:form>


</body>

</html>


위의 코드에서 loginBean 은 서버측에서 폼 데이터를 저장하는 커맨드 오브젝트의 이다



테스트

http://localhost:8080/SpringMVC/login.htm 으로 접속하여 폼이 출력되면 폼을 비워둔채로 전송버튼을 눌러서 결과를 확인한다