티스토리 뷰

1. Spring MVC Form Validation

 - 사용자가 입력한 input이 required field인지, 범위에 해당하는 유효한 숫자인지, 우편번호와 같은 구성방식(format)등을 체크할 수도 있고, custom business rule을 만들어 적용할 수도 있다.

 

(1) Java의 Standard Bean Validation API

 1) Java는 표준(standard) Bean validation API가 있다.

 2) 독립체들의 validation을 위해 metadata model과 API를 정의한다.

 3) server-side app과 client-side app에서 모두 이용가능하다. (JavaFX나 Swings를 이용해서)

  *www.beanvalidation.org에 모두 정의되어 있다.

 

Jakarta Bean Validation - Home

Jakarta Bean Validation is a Java specification which lets you express constraints on object models via annotations lets you write custom constraints in an extensible way provides the APIs to validate objects and object graphs provides the APIs to validate

beanvalidation.org

(2) Spring과 Validation

 1) Spring 버전 4 이상은 Bean Validation API를 지원한다.

 2) Sping app개발시 validation에 더 선호되는 방법이다.

 3) 그냥 간단히 JAR 파일들을 project에 추가시키기만 하면 된다.

 

(3) Bean Validation Features과 앞으로 다룰 개발 순서

 1) required (반드시 필요한 필드)

 2) validate length(길이 유효성검사)

 3) validate numbers (숫자 유효성 검사)

 4) validate with regular expressions(정규 표현식을 이용한 유효성 검사)

 5) custom validation (내가 validation 규칙을 만드는 것)

 

(4) Validation Annotation

 Validation Annotation

(5) Hibernate Validator에 대해서

위에서 자바의 Standard Bean Validation API(JSR-303)에 대해서 설명하였다. 하지만 자바 표준 Bean Validation API는 명세서라 보면 된다. 휴대가능한것이다. 하지만 우리는 이것을 구현시켜 사용해야 한다. 이 명세서(specification)을 구현한것이 필요하다. 이 문제를 Hibernate가 해결할 수 있다.

Hibernate는 ORM project(Object-relational mapping project)로서 시작했다. 하지만 몇년만에 영역을 넓혔는데, JSR-303 Implementation을 완전히 따랐고, ORM이나 database 작업에 묶인것이 아닌 오직 validation을 위한 독립적인 프로젝트로 분리되어있다.

Hibernate Validator는 완전히 Java Bean Validation API에 부응하기때문에, 완벽하게 그 specification을 구현한다.

참고 : www.hibernate.org/validator

 

The Bean Validation reference implementation. - Hibernate Validator

Express validation rules in a standardized way using annotation-based constraints and benefit from transparent integration with a wide variety of frameworks.

hibernate.org

 

* ORM이란

: 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해주는것을 말한다. 객체지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용하는데, 객체모델과 관계형 모델간의 불일치가 존재한다. ORM을 통해 객체간의 관계를 바탕으로 SQL을 자동으로 생성해 불일치를 해결한다. 객체를 통해 간접적으로 데이터베이스의 데이터를 다루며, Persistant API라고도 할 수 있다.

출처 :  gmlwjd9405.github.io/2019/02/01/orm.html

 

[DB] ORM이란 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

그러면 Hiberante validator를 쓰면 된다는것까지는 알았는데, 어떠한 버전을 써야할까?

Hibernate Validator 7은 Jakarta EE9에 기반해있다. 그러면 Jakarta EE는 무엇인가?

 

(6) Jakarta EE에 대해서

Jakarta EE란 Enterprise API (servlets, JSP, JDBC와 같은 기업형 API)의 collection인 Java EE의 커뮤니티 버전이다. 

그래서 기본적으로 Jarkarta EE는 Oracle에 의해서 더이상 운영되고 컨트롤 되는것이 아닌 현재 community에 의해서 운영되고 있다. Java EE와 대표적으로 다른 점은, 패키지 이름이 달라진것이다. javax.*가 jakarta.*로 이름이 바뀌었다.

따라서 예를들어 java.servlet.http.HttpServlet은 jakarta.servlet.http.HttpServlet이다.

더 많은 정보는 jakarta.ee/about/를 참고하면 된다.

 

Jakarta EE Working Group | the Future of Cloud Native Java Applications | The Eclipse Foundation

The Jakarta EE Working Group is evolving enterprise java as Jakarta EE, the future of open source, cloud native application development using java technologies.

jakarta.ee

 

* 커뮤니티 버전 (Community Edition)이란 :

A version of software that is offered under an open source license. Very often a paid product is also available as a community edition, which means that different programmers (the community) are supporting that version. Contrast with enterprise edition.

출처 : www.pcmag.com/encyclopedia/term/community-edition

 

Definition of community edition

What does community edition actually mean? Find out inside PCMag's comprehensive tech and computer-related encyclopedia.

www.pcmag.com

따라서 Hibernate Validator 7는 Jakarta EE9에 기초해있기 때문에, Java EE(javax.*)의 요소를 어느정도 기반해있는 Spring 5에 적용할수 없다. Spring이 미래에는 Jakarta EE 요소를 사용할수도 있지만, 아직은 모른다.

따라서 Spring 5에서는 Hibernate Validator 7를 사용할 수 없고 6.x버전을 사용해야 한다.

6.x버전은 7버전과 같은 feature, 특징을 가지고 있고 Java EE에 기반해 있기 때문에(javax.* 패키지 사용), Spring 5를 사용한다면 Hibernate Validator 6.x를, Jakarta EE 9을 사용한다면 Hibernate Validator 7을 사용하면된다.

 

(7) 설치방법

www.hibernate.org에 들어가서 Hibernate Validator 6.x버전(6버전 중 가장 최신버전) zip을 다운 받아 dist폴더 안의 jar file 3개와 lib/required 폴더안의 jar file 4개를 현재 프로젝트의 lib폴더 안에 넣어주면 된다.

 

Hibernate. Everything data. - Hibernate

More than an ORM, discover the Hibernate galaxy.

hibernate.org

2. Spring MVC Form Validation Required Fields

 

(1) Development process

 

예시로 form 작성시 firstname과 lastname을 입력받아 confirmation page에서 출력하는데, 반드시 lastname을 입력해야만 하도록 만들것이다.

customer-form.jsp에서 submit을 하게 되면 customer Controller로 가게되고 customer-confirmation.jsp로 이동하는데, 조건을 성공적으로 만족시키지 못하면 controller에서 다시 form page로 다시 이동해 다시 submit하도록 하게 된다.

 

1) Customer class에 validation rule 추가하기

2) HTML form에 에러메세지 배치하기

3) controller class에서 validation을 수행하기

4) confirmation page update하기

 

(2)  코드예시

1) Customer class에 validation rule 추가하기

package com.luv2code.springdemo.mvc;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Customer {
	
	private String firstName;

	@NotNull(message="is required")
	@Size(min=1, message="is required")
	private String lastName;

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
}

2) HTML form에 에러메세지 배치하기

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

<html>
<head>
	<title>Customer Registration Form</title>
	
	<style>
		.error {color:red}
	</style>
</head>

<body>
<i>Fill out the form. Asterisk (*) means required.</i>

	<form:form action="processForm" modelAttribute="customer">
		First name : <form:input path="firstName"/>
		<br><br>
		Last name (*) : <form:input path="lastName"/>
		<form:errors path="lastName" cssClass="error"/>
		
		<br><br>
			
		<input type="submit" value="Submit"/>
	</form:form>
</body>
</html>

다음과 같이 spring form tag을 이용해서 작성해 준다. 

<form:errors path="lastName" cssClass="error"/>을 통해서 lastName에 대한 에러메세지를 출력해주고, style을 css로 위와같이 준다.

 

3) controller class에서 validation을 수행하기

package com.luv2code.springdemo.mvc;

@Controller
@RequestMapping("/customer")
public class CustomerController {
	
	@RequestMapping("/showForm")
	public String showForm(Model theModel) {
		theModel.addAttribute("customer",new Customer());
		
		return "customer-form";
	}
	
	@RequestMapping("/processForm")
	public String processForm(
			@Valid @ModelAttribute("customer") Customer theCustomer,
			BindingResult theBindingResult) {
		//for debugging
		System.out.println("Last name : |" + theCustomer.getLastName() + "|");
		if(theBindingResult.hasErrors()) {
			return "customer-form";
		}else {
			return "customer-confirmation";
		}	
	}
}

@Valid의 역할은 이 customer 객체에 validation rule을 수행하겠다는 의미이다.

그리고 validation test의 결과가 BindingResult에 위치하게 될것이다.

Spring이 위 해당 메소드를 호출할때, 뒤에서 hibernate validation API를 사용해 validation rule을 적용하고, 그 결과값을 BindingResult에 저장한다.

 

Controller에서 따라서 model attribute가 customer인 form에서 넘어오는 데이터가 validation rule에 의해서 에러가 있으면 customer-form 페이지로 다시 이동하고, 에러가 없으면 customer-confirmation페이지로 이동하도록 설정해 주는 것이다.

** BindingResult parameter의 순서, 위치는 매우 중요하다.

BindingResult parameter는 반드시 model attribute 바로 다음에 와야한다.

출처 : https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-methods

 

4) confirmation page update하기

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>

<html>
<head>
	<title>Customer Confirmation</title>
</head>
<body>

	The Customer is confirmed : ${customer.firstName} ${customer.lastName}

</body>
</html>

 

3. @InitBinder

(1) 문제점

하지만 위 코드를 실행해보면 공백, spacebar는 null로 인식하지 못하는 문제가 있다. spacebar또한 문자로 인식하기 때문에 confirmation page로 넘어가게 되는것이다.

이 문제를 해결하기 위해서 input field에 넘어오는것의 공백을 없애줄 필요가 있다.

(2) @InitBinder

 1) pre-processor로서 역할을 하는 annotation이다. 모든 controller를 통해서 오는 web request에 이 코드가 먼저 실행된다.

 2) 이것을 String을 자르기 위해서 사용할 것이다.

 3) 공백(white space)로만 이루어 져있다면, null로 반환할 것이다.

 

(3) 코드

// add an initbinder ... to convert trim input strings
	// remove leading and trailing whitespace
	// resolve issue for our validation
	
	@InitBinder
	public void initBinder(WebDataBinder dataBinder) {
		
		StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);
		// 모두 white space라면 null로 잘라버린다.
		dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
		//register custom editor를 databinder에 등록한다.
	}

CustomerController에 위와같이 추가해 주면 된다.

StringTrimmerEditor 객체는 Spring API에 정의되어 있는데, string을 자르는 기능을 한다. 

constructor에 true를 넣는것은 공백만으로 이루어져 있으면 null로 자르는 기능을 한다.

그리고 모든 String 클래스에 대해서, StringTrimmerEditor를 적용해주는것이 마지막 줄이다.

 

그러면 공백문제가 해결되는것을 볼 수 있다.

 

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday