본문 바로가기

Spring 3/Form Validation

Spring Form Validation

Spring 3 JSR-303 폼 검증 예 ( Form Validation Example )


참고

http://www.mkyong.com/spring-mvc/spring-3-mvc-and-jsr303-valid-example/



Message Resource 를 이용한 검증방법은 여기를 참조하세요



테스트 환경

Windows 7, JDK 1.7, Eclipse luna, Spring 3.2, STS, Maven, Tomcat 8



라이브러리 추가

Spring MVC 를 위한 기본 라이브러리 외에 다음 라이브러리를 창아서 Maven 프로젝트에 추가한다

Java Bean Validation API

Hibernate Validation 



pom.xml 의 일부

<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.3.2.Final</version>

</dependency>




<mvc:annotation-driven/>

Annotation 을 이용한 데이터 검증을 가능하도록 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 -->

    <mvc: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="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

</beans:beans>




검증 대상 빈 클래스의 속성에 다음과 같이 Annotation을 설정한다


LoginBean.java

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;

}

}




LoginController 클래스의 메소드의 검증대상 파라미터에 @Valid 를 붙인다


package org.kdea.java;


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){

/* loginForm.jsp 가 처음 실행될 때 loginBean 이 없으면 오류발생하므로 아래처럼 하거나

메소드 레벨 @ModelAttribute("loginBean")을 사용하면 된다

*/

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

return "loginForm";

}


/*폼이 화면에 처음 보여질 때 오류를 방지하기 위해서 메소드 레벨 @ModelAttribute 를 사용하는 예

아래처럼 하면 콘트롤러 내의 모든 뷰에서 공유할 수 있는 커맨드 오브젝트를 설정할 수 있다 

*/

@ModelAttribute("loginBean")

public LoginBean commandObj() {

return new LoginBean();

}


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

// BindingResult 는 검증대상 오브젝트 바로 우측에 오도록 함

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

if(result.hasErrors()){

return "loginForm";

}

return "hello";

}

}

위의 login()의 커맨드 오브젝트인 LoginBean객체는 자동으로 모델에 저장될 때 클래스 이름을 key 로 사용하는데 클래스 이름의 첫자는 소문자로 변경하여 사용하므로 "loginBean" 이란 이름으로 모델에 저장되고 뷰에서 "loginBean" 이름으로 참조할 수 있다

모델에 저장되는 이름을 임의로 변경하려면 @ModelAttribute("login") LoginBean loginBean 과 같이 선언하면 된다



입력 폼(JSP)에 Spring bind Tag 를 이용한 오류 메시지 출력

아래의 내용 중에서 loginBean 은 서버측에서 폼 데이터를 영역객체에 저장할 때 사용한 키이다, 

예) 콘트롤러 메소드에서 커맨드 클래스의 이름이 public String login(@Valid LoginBean login, BindingResult result) 처럼 사용된 경우라면, 커맨드 오브젝트가 영역객체에 저장될 때는 클래스의 첫 문자를 소문자로 하여 'loginBean' 을 키로 사용하여 해당객체를 저장한다

<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>


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


<!DOCTYPE html>

<html>

<head>

<meta charset="EUC-KR">

<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>


</body>

</html>



테스트

http://localhost/SpringMVC/login.htm 으로 접속하면 GET 방식 요청이므로 LoginController 의 첫번째 메소드가 실행되고 그 결과 loginForm.jsp 가 실행되어 웹브라우저에 로그인 폼이 출력된다. 위에서 loginForm.jsp 의 내용을 보면 <spring:bind> 태그를 사용하고 있으므로 폼을 전송할 때가 아닌 브라우저에 폼이 처음 나타날 때도 LoginBean객체가 request 영역에 존재하는지 확인하게 되므로 만약 LoginBean 객체가 request 영역에 존재하지 않는다면 폼이 나타나는 대신 오류 메시지가 출력된다. 그러므로 서버측  LoginController 에서는 웹 브라우저에 빈 폼을 전송할 때라도 Model 오브젝트에 LoginBean 오브젝트를 저장하여 오류가 발생하는 것을 피해야 한다.



위의 loginForm.jsp 에서 사용된 <spring:bind> 태그 대신에 스프링에서 제공하는 <form:form> 태그를 사용할 수도 있다

<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>

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


<!DOCTYPE html>

<html>

<head>

<meta charset="EUC-KR">

<title>로그인 폼</title>

<style type="text/css">

   .errorMsg { color: red; }

</style>

</head>

<body>

<h2>로그인 폼</h2>


<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>