JAVA를 잡아라!...

Spring Boot_Validation 본문

Spring

Spring Boot_Validation

onivv 2024. 3. 13. 09:18

[ 사용자 입력값 검증 ]

  • 사용자가 입력값을 요청에 넣어서 보냈을 때,
    최소한의 조건을 만족한 값인지 확인하는 Spring의 기본제공기능
  • 유효성 검증 객체 : Validator


#1 Validation 검증하는 객체 사용

MemberDTOValidation.java

  • MemberDTO를 검증하는 객체
  • Spring에서 기본제공하는 Validator를 implements
  • supports() : 내가 검증하고 싶은 객체의 자료형(클래스 타입)에 대한 정보를 제공하는 메서드
  • validate() : 실질적인 검증을 수행하는 메서드
package com.koreait.validation;

import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

public class MemberDTOValidation implements Validator {
	
	@Override
	public boolean supports(Class<?> clazz) {
		System.out.println("로그01");
		// return 타입정보 : MemberDTO클래스랑 타입이 맞니?
		return MemberDTO.class.isAssignableFrom(clazz);
	}
	
	@Override
	public void validate(Object target, Errors errors) {
		System.out.println("로그02");
		// target의 타입 다운 캐스팅(형변환)
		MemberDTO mDTO = (MemberDTO)target;
		
		String name = mDTO.getName();
		if(name == null || name.isEmpty() || name.isBlank() || name.trim().isEmpty()) {
			System.out.println("name에 값이 입력되지 않음");
			errors.rejectValue("name", "NULL");	// rejectValue(멤버변수(필드), 에러메시지)
		}
		else if(name.length() < 2 || 6 < name.length()) {
			System.out.println("name의 길이가 2~6이 아님");
			errors.rejectValue("name", "NOT 2~6");	// rejectValue(멤버변수(필드), 에러메시지)
		}
		
		int age = mDTO.getAge();
		if(age < 0 || 200 < age) {
			System.out.println("age가 0~200이 아님");
			errors.rejectValue("age", "ERROR");	// rejectValue(멤버변수(필드), 에러메시지)
		}
	}
	
}

 

TestController.java

package com.koreait.validation;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import jakarta.validation.Valid;

@Controller
public class TestController {
	
	@RequestMapping("/")
	public String root() {
		return "index";
	}
	
	@RequestMapping("/test")
	public @ResponseBody String test(@Valid MemberDTO mDTO, BindingResult result) {
		System.out.println(mDTO);
		
		// validator --> @Valid ↑, 검사 결과 : BindingResult
		/* 결합도가 높은 코드
		MemberDTOValidation validator = new MemberDTOValidation();
		validator.validate(mDTO, result);
		*/
		
		if(result.hasErrors()) {
			
			if(result.getFieldError("name") != null) {
				// DTO 멤버변수 "name"에 값이 있어? 에러났구나... 에러 메시지 보여줘
				System.out.println(result.getFieldError("name").getDefaultMessage());
			}
			if(result.getFieldError("age") != null) {
				// DTO 멤버변수 "age"에 값이 있어? 에러났구나... 에러 메시지 보여줘
				System.out.println(result.getFieldError("age").getDefaultMessage());
			}
			
			return "실패";
		}
		
		return "성공";
	}
    
	// new MemberDTOValidation() --> @InitBinder
	// 결합도가 낮은 코드
	@InitBinder
	void initBinder(WebDataBinder binder) {
		binder.setValidator(new MemberDTOValidation());
	}
	
}

 

#2 DTO에 직접 validation 적용

MemberDTO.java

package com.koreait.validation;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;

@Data
public class MemberDTO {
	
	@NotNull(message = "name NULL")
	@NotEmpty(message = "name EMPTY")
	@Size(min = 2, max = 6, message = "name ERROR")
	private String name;
	private int age;
	
}

 

TestController.java

MemberDTOValidation 객체로 유효성 xx, @ModelAttribute!

package com.koreait.validation;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import jakarta.validation.Valid;

@Controller
public class TestController {
	
	@RequestMapping("/")
	public String root() {
		return "index";
	}
	
	@RequestMapping("/test")
	public String test(@Valid @ModelAttribute("member") MemberDTO mDTO, BindingResult result) {
		System.out.println(mDTO);
		
		if(result.hasErrors()) {
			
			if(result.getFieldError("name") != null) {
				System.out.println(result.getFieldError("name").getDefaultMessage());
			}
			if(result.getFieldError("age") != null) {
				System.out.println(result.getFieldError("age").getDefaultMessage());
			}
			
			return "index";	// 실패했을 때 이동
		}
		/*
		model.addAttribute("name", mDTO.getName());
		model.addAttribute("age", mDTO.getAge());
		*/
		return "main";	// 성공했을 때 이동
	}
	
	/* 결합도가 낮은 코드
	@InitBinder
	void initBinder(WebDataBinder binder) {
		binder.setValidator(new MemberDTOValidation());
	}
	*/
}

 

++ plus

  • model 객체를 활용해서 View에 data를 보내도 되지만,
  • 귀찮을...때...... @ModelAttribute 어노테이션으로 객체의 모든 값을 줄 수 있음
  • View에서 커맨드 객체를 사용할 수 있음

TestController.java

 

View

  1. Model 객체 활용 : model.addAttribute로 하나하나 보내줬을 때
  2. @ModelAttribute : 자료형 소문자로 시작해서 view에서 사용
  3. @ModelAttribute("member") : 이름까지 정해줬을 때 (id라서 이름 중복되면 안됨)

main.jsp

'Spring' 카테고리의 다른 글

Spring Framework_DAO_MyBatis  (0) 2024.03.25
Spring Boot_Lombok_@Data  (0) 2024.03.12
Spring Boot_MVC data 전달, +@PathVariable  (0) 2024.03.11
Spring Boot_Gradle Project  (0) 2024.03.07
Spring Framework_커맨드 객체(Command Object)  (0) 2024.03.07