[Spring boot 7일차] spring validation

이경영·2022년 10월 31일
0

스프링부트

목록 보기
7/12
post-custom-banner

Validation

어떤 데이터의 값이 유효한지, 잘못된 내용이 있는지 확인하는 단계.

전체적 흐름
자바빈 validation을 이용해서 DTO 단에서 데이터를 간단하게 검증하고. 2차적으로 메서드 내부로 진입함. 로직으로 넘어와 권한, 서비스정책, API 호출이나 DB조회 등 데이터 검증을 실시하고 검증 실패시에 Exception으로 예외 던지고 처리하는 방식으로 사용함.

자바빈을 이용한 구현

Maven프로젝트의 pom.xml에 디펜던시 추가한다.

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>

JavaBean내의 어노테이션으로 검증방법을 명시할 수 있음

BoardSaveForm.java 생성 (DTO 생성)

package com.example.controller.form;

import javax.validation.GroupSequence;
import javax.validation.constraints.NotEmpty;

import org.hibernate.validator.constraints.Length;

import com.example.validation.ValidationSteps;

import lombok.Data;

@Data
@GroupSequence({
	BoardSaveForm.class,
	ValidationSteps.Step1.class,
	ValidationSteps.Step2.class,
	ValidationSteps.Step3.class,
	ValidationSteps.Step4.class,
	ValidationSteps.Step5.class,
})
public class BoardSaveForm {
	
	private int boardSeq; 
	
	@NotEmpty(groups = ValidationSteps.Step4.class, message = "{BoardSaveForm.boardType.notEmpty}")
	private String boardType; 
	
	@NotEmpty(groups = ValidationSteps.Step1.class,message = "{BoardSaveForm.title.notEmpty}")
	@Length(groups=ValidationSteps.Step3.class, 
			min=2, max=10,
			message="{BoardSaveForm.title.length}")
	private String title;
	
	@NotEmpty(groups = ValidationSteps.Step5.class,message = "{BoardSaveForm.contents.notEmpty}")
	private String contents;
	
	//입력으로 받는것이 아니기 때문에 필드가 필요없음
//	private String regDate;
	@NotEmpty(groups = ValidationSteps.Step2.class,message = "{BoardSaveForm.userName.notEmpty}")
	private String userName;
	
    
}
  • @NotEmpty (javax.validation.constraints.NotEmpty) : null, 공백체크하는 어노테이션
  • @Length(org.hibernate.validator.constraints.Length) : min, max 길이체크
  • @NotEmpty내 원하는 메세지 넣기 : 여기서는 따로 message.properties에 작성하여 매핑함.

BoardController.java

	@PostMapping("/save")
	public String save(@Validated BoardSaveForm form) { //**Validated 추가후 BoardSaveForm 으로 변경
		//hasLength가 아니면 예외를 던짐 
//		Assert.hasLength(board.getUserName(),"회원 이름을 입력해주세요");
//		Assert.hasLength(board.getTitle(),"제목을 입력해주세요");
//		Assert.hasLength(board.getBoardType(),"종류를 입력해주세요");
//		Assert.hasLength(board.getContents(),"내용을 입력해주세요");
		
		
		Board selectBoard = null;
		//게시글 수정으로 요청인 경우
		if(form.getBoardSeq() > 0) {
			selectBoard=boardService.selectBoard(form.getBoardSeq());
		}
		// 수정인 경우 업데이트
		if(selectBoard != null) {
			boardService.updateBoard(form);
		}else {
			//새로 작성인 경우 인서트
			boardService.insertBoard(form);
		}
			
		return "redirect:/board";
	}
	
  • Board를 BoardSaveForm으로 import 변경. 변수도 board에서 form으로 변경
  • @Validated (org.springframework.validation.annotation.Validated) : 유효성검증체크수행

BoardService, BoardMapper 수정

package com.example.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.controller.form.BoardSaveForm;
import com.example.mapper.Board;
import com.example.mapper.BoardMapper;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class BoardService {
	
	@Autowired
	private final BoardMapper boardMapper;
	/**
	 * 게시물 목록 조회후 리턴
	 * 
	 * @return
	 *
	 */
	
	public List<Board> selectBoardList() {
		return boardMapper.selectBoardList();
	}
	
	public Board selectBoard(int boardSeq){
		return boardMapper.selectBoard(boardSeq);
	}
	
	public void insertBoard(BoardSaveForm board) {
		boardMapper.insertBoard(board);
	} //변경
	
	public void deleteBoard(int boardSeq) {
		boardMapper.deleteBoard(boardSeq);
	}

	public void updateBoard(BoardSaveForm board) {
		boardMapper.updateBoard(board);
	} //변경

}
  • insertBoard, updateBoard 부분에 BoardSaveForm 변경

등록 버튼 눌렀을시 결과

Validation 순서대로 검증

com.example.vaildation 패키지 생성 : ValidationSteps 생성

package com.example.validation;

public class ValidationSteps {
	
	public interface Step1 {}
	public interface Step2 {}
	public interface Step3 {}
	public interface Step4 {}
	public interface Step5 {}
}

BoardService에서 @GroupSequence 어노테이션을 선언하여
첫번째는 검증할 클래스, 두번째부터는 순서대로 검증할 인터페이스를 추가함.
(안해줄시, 검증안되는 필드 에러가 여러개라면, 돌아가면서 뜸)

message.properties생성

BoardSaveForm.boardType.notEmpty=종류를 선택하세요.
BoardSaveForm.title.notEmpty=제목을 입력해주세요.
BoardSaveForm.contents.notEmpty=내용을 입력해주세요.
BoardSaveForm.userName.notEmpty=회원이름을 입력해주세요.
BoardSaveForm.title.length=제목을 2이상 10이하로 설정해주세요

WebMvcConfiguration.java

웹관련 설정 파일 : 웹과 관련된 처리를 구현하기 위해 WebMvcConfigurer를 구현
참고 : https://kdevkr.github.io/all-message-codes-in-spring-boot/

package com.example.configuration;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer{
	
	/**
	 * 다국어 설정 및 메세지 프로퍼티 사용을 위한 빈 등록
	 * @return
	 */
	@Bean
	public MessageSource messageSource() {
		ReloadableResourceBundleMessageSource
			messagesSource=new ReloadableResourceBundleMessageSource();
		// 다국어 파일 경로 set
		messagesSource.setBasename("classpath:config/messages/message");
		messagesSource.setDefaultEncoding("UTF-8");
		return messagesSource;
	}
	
	/**
	 * Validator 메시지 설정을 하기 위한 빈 등록 : 
	 * message.properties에서 설정가능
	 */
	@Override
	public Validator getValidator() {
		LocalValidatorFactoryBean
			factory=new LocalValidatorFactoryBean();
		factory.setValidationMessageSource(messageSource());
		return factory;
	}
}

:WebMvcConfigurer 인터페이스를 구현하고 getValidator() 메소드를 오버라이드하여 ValidatorFactoryBean을 등록

결과 : 회원이름 입력안했을시


  • 콘솔 에러코드
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'boardSaveForm' on field 'userName': rejected value []; codes [NotEmpty.boardSaveForm.userName,NotEmpty.userName,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [boardSaveForm.userName,userName]; arguments []; default message [userName]]; default message [회원이름을 입력해주세요.]
profile
꾸준히
post-custom-banner

0개의 댓글