Spring MVC - 유효성 검사(@Valid,JSR-303)

2020. 9. 17. 21:06Java/Spring

반응형

JSR-303

- Spring MVCJSR-303 규격의 유효성 검사 라이브러리를 사용할 수 있다.

- Bean에 데이터가 입력될 때 어떤 검사를 할 것인지 어노테이션으로 지정하고 지정된 어노테이션의 조건에 맞지 않으면 개발자에게 입력값에 오류가 있다는 정보를 전달한다.

- 개발자는 이를 통해 유효성 검사를 진행할 수 있다.


1. Pom.xml에 라이브러리 추가

 

아래 사이트에서 validation maven 코드를 복사하여 붙여 넣는다.

mvnrepository.com/artifact/javax.validation/validation-api

 

Maven Repository: javax.validation » validation-api

 

mvnrepository.com

Hibernate Validator Engine도 추가한다.

mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator/6.1.5.Final

 

Maven Repository: org.hibernate.validator » hibernate-validator » 6.1.5.Final

Hibernate's Jakarta Bean Validation reference implementation. Note: There is a new version for this artifact org.hibernate.validator hibernate-validator 6.1.5.Final // https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator compile g

mvnrepository.com


2. bean 파일을 생성하여 유효성 검사를 할 변수에 아래와 같이 어노테이션을 준다.

public class DataBean1 {
	@Size(min=2,max=10)
	private String data1;
	@Max(100)
	private int data2;
	
	public String getData1() {
		return data1;
	}
	public void setData1(String data1) {
		this.data1 = data1;
	}
	public int getData2() {
		return data2;
	}
	public void setData2(int data2) {
		this.data2 = data2;
	}
	
	
}

@Size는 min ~ max 사이의 길이가 아니면 경고를 주고, @Max는 해당하는 자리수가 넘으면 경고를 준다.


빈 파일에 설정한 것은 체크만 해주고 값은 정상적으로 들어간다.

 

값이 들어가는 것을 막기 위해서는 @Value를 사용한다.

 

@Valid

- Controller의 메서드에서 주입 받는 Bean@Valid를 설정하면 유효성 검사를 실시한다.

- 유효성 검사 결과를 사용하고자 한다면 BindingResult 객체를 주입받아야 한다.

- 이 객체에는 유효성 검사를 실행한 결과 정보가 담겨있다.

- 이를 통해 Controller 에서 사용자가 입력한 값에 문제가 있는지 파악할 수 있다.

 

 

@PostMapping("/input_pro")
	public String input_pro(@Valid DataBean1 dataBean1, BindingResult result) {
		
		System.out.println(dataBean1.getData1());
		System.out.println(dataBean1.getData2());
		System.out.println("BindingResult =>"+result);
		return "input_success";
	}

Controller 메소드에서 빈 객체를 주입 받는 매개변수에 @Valid와 BindingResult를 주면 result에 결과가 담긴다.

 

오류를 내면 다음과 같은 오류 메세지가 담긴다.

BindingResult =>org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'dataBean1' on field 'data1': rejected value [sadasdasdasdas]; codes [Size.dataBean1.data1,Size.data1,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [dataBean1.data1,data1]; arguments []; default message [data1],10,2]; default message [크기가 2에서 10 사이여야 합니다]
Field error in object 'dataBean1' on field 'data2': rejected value [200]; codes [Max.dataBean1.data2,Max.data2,Max.int,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [dataBean1.data2,data2]; arguments []; default message [data2],100]; default message [100 이하여야 합니다]
if(result.hasErrors()) {
			for(ObjectError obj : result.getAllErrors()) {
				System.out.println("메시지=>"+obj.getDefaultMessage());
				System.out.println("code=>"+obj.getCode());
				System.out.println("object name=>"+obj.getObjectName());
				System.out.println("===================================");
		}
}

위 코드로 에러를 정리 할 수 있다.

만일 같은 Size에러가 두개 이상이면 아래와 같이 작성하여 출력한다.

String [] codes = obj.getCodes();
for(String c1:codes) {
		System.out.println(c1);
}

위 에러메세지는 다음과 같이 배열에서 꺼내 조건문을 주어 명령을 준다.

if(codes[0].equals("Size.databean1.data1")) {
	System.out.println("error1");
}else if(codes[0].equals("Size.databean1.data2")){
	System.out.println("error2");
}

 

전체 Controller 코드는 아래와 같다.

@Controller
public class TestController {

	@GetMapping("/input_data")
	public String input_data() {
		return "input_data";
	}
	@PostMapping("/input_pro")
	public String input_pro(@Valid DataBean1 dataBean1, BindingResult result) {
		
		System.out.println(dataBean1.getData1());
		System.out.println(dataBean1.getData2());
		System.out.println("BindingResult =>"+result);
		if(result.hasErrors()) {
			for(ObjectError obj : result.getAllErrors()) {
				System.out.println("메시지=>"+obj.getDefaultMessage());
				System.out.println("code=>"+obj.getCode());
				System.out.println("object name=>"+obj.getObjectName());
				
				String [] codes = obj.getCodes();
				for(String c1:codes) {
					System.out.println(c1);
				}
				System.out.println("===================================");
				if(codes[0].equals("Size.databean1.data1")) {
					System.out.println("error1");
				}else if(codes[0].equals("Size.databean1.data2")){
					System.out.println("error2");
				}
			}
			return "index";//에러 있을시 다시 원래 화면으로
		}
		
		return "input_success";// 에러 없으면 성공 화면
	}
}

3.유효성 검사 결과를 Jsp에서 사용

<%@ talib prefix='c' uri="http://java.sun.com/jsp/jstl/core"%>
<%@ talib prefix='spring' uri="http://www.springframework.org/tags"%> 

먼저, jstl과 spring tag를 선언한다

<form action="input_pro" method="post">
	data1 : <input type="text" name="data1" /><br>
	<spring:hasBindErrors name="dataBean1">
		<c:if test="${errors.hasFieldErrors('data1')}">
			${errors.getFieldError('data1').defaultMessage}
		</c:if>
	</spring:hasBindErrors>
	
	data2 : <input type="text" name="data2" /><br>
	<spring:hasBindErrors name="dataBean1">
		<c:if test="${errors.hasFieldErrors('data2')}">
			${errors.getFieldError('data2').defaultMessage}
		</c:if>
	</spring:hasBindErrors>
	<button type="submit">확인</button>
</form>

hasBindError은 controller의 result를 가지고 있다. error를 체크해서 message를 화면에 출력한다.


4. 출력 메세지 수정

 

유효성 검사의 출력 메세지는 properties에 등록하여 수정 가능하다.

위와 같이 오류 발생시 출력되는 코드를 통해 해당 데이터에 접근하여 설정한다.

 

ServletAppcontext에 아래와 같이 properties를 틍록한다. 

@Bean
public ReloadableResourceBundleMessageSource messageSource() {
		
ReloadableResourceBundleMessageSource res = new ReloadableResourceBundleMessageSource();
res.setBasenames("/WEB-INF/properties/error_message");
return res;
}

 

 

JSP에서 메세지를 출력하기 위해 Spring form 커스텀 태그를 사용한다.

<form:form modelAttribute="dataBean1" action='input_pro' method="post">
data1: <form:input path="data1" type="text"/><br/>
	   <form:errors path="data1"/><br/>
data1: <form:input path="data2" type="text"/><br/>
	   <form:errors path="data2"/><br/>
</form:form>

 

첫 로딩시에도 dataBean1이 주입되야 하므로 index.jsp를 로딩하는 controller에 dataBean1을 주입한다.

오류 메세지가 출력되고, 기존 입력도 남아있다.

반응형

'Java > Spring' 카테고리의 다른 글

Spring MVC - JSR-380 어노테이션 정리  (0) 2020.09.20
Spring MVC - JSR-303 어노테이션 정리  (0) 2020.09.19
Spring MVC - Message  (0) 2020.09.16
Spring MVC - Properties  (0) 2020.09.15
Spring MVC - Cookie  (0) 2020.09.14