전처리 후처리(2)

tyghu77·2021년 12월 14일
0

SpringbootAOP

목록 보기
3/3

전처리

Springboot에서 유효성검사를 위해서는 Spring Boot Starter Validation이라는 라이브러리가 필요하다.
mvnrepository에서 다운로드 할 수 있다.
dependency를 추가하면 Controller에서 @valid라는 어노테이션을 사용할 수 있게된다.
(java.validation 어노테이션 종류는 여기서 확인할 수 있다.)

	//SignupReqDto
	@Data //lombok
	public class SignupReqDto {
	
		@Size(min = 2, max = 20)
		@NotBlank()
		private String username;
		@NotBlank()
		private String password;
	}
	//Controller
	@PostMapping("/")
	public String signup(@Valid SignupReqDto signupReqDto, BindingResult bindingResult){
		if (bindingResult.hasErrors()) {
			Map<String,String> errorMap = new HashMap<>();
			
			for(FieldError error:bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(), error.getDefaultMessage());
			}
			
			throw new RuntimeException("유효성 검사 실패");
		} else {
			//회원가입 진행
			
			return "signin";
		}
	}

SignupReqDto에 어노테이션을 붙여서 유효성 검사를 하여 문제가 생기면 BindingResult 클래스를 통해 전달 받을 수 있다.
Controller에서 다음 코드를 보자.

	if (bindingResult.hasErrors()) {
			Map<String,String> errorMap = new HashMap<>();
			
			for(FieldError error:bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(), error.getDefaultMessage());
			}
			
			throw new RuntimeException("유효성 검사 실패");
		} else {
			//회원가입 진행
			
			return "signin";
		}

bindingResult에 error가 있으면 문제가 있는 필드 네임과 오류메시지를 Map에 저장하고 RuntimeException을 던진다.

하지만 이렇게 하면 사용자에게 오류 화면 전체가 넘어가게 된다. 이것을 더 깔끔하게 전달하기 위해서 다음과 같이 한다.

	//ControllerExceptionHandler
    	@RestController
    	@ControllerAdvice //모든 exception을 낚아챔
    	public class ControllerExceptionHandler {
    
    		@ExceptionHandler(RuntimeException.class)
    		public String validationException(RuntimeException e) {
        		return e.getMessage();
        	}

그런데 RunTimeException은 string만 받기 때문에 errorMap을 넘길 수가 없다.
따라서 RunTimeException을 상속한 클래스를 하나 만들어줘야한다.

	//CustomValidationException
	public class CustomValidationException extends RuntimeException{
	
        // 객체를 구분할 때 사용
        private static final long serialVersionUID = 1L;

        private Map<String, String> errorMap;

        public CustomValidationException(String message, Map<String, String> errorMap) {
            super(message);
            this.errorMap = errorMap;
        }

        public Map<String, String> getErrorMap() {
            return errorMap;
        }
    }

RuntimeException에 메시지를 던지면 RuntimeException이 그 메시지를 부모(Exception)에게 던지고 Exception은 그것을 또 부모(Throwable)로 던진다. 그 후, Throwable의 getMessage함수를 통해 메시지를 받기 때문에 super(message)를 해주면 메시지를 받을 수 있다.
이렇게 CustomValidationException를 만들어주고 RuntimeException부분을 CustomValidationException로 바꿔준 후 return 타입을 Map<String, String>으로 바꿔준다

	//ControllerExceptionHandler
    	@RestController
    	@ControllerAdvice //모든 exception을 낚아챔
    	public class ControllerExceptionHandler {
    
    		@ExceptionHandler(CustomValidationException.class)
    		public Map<String, String> validationException(CustomValidationException e) {
        		return e.getMessage();
        	}

"유효성 검사 실패" 라는 메시지도 같이 띄우고싶다면 공통Dto를 만들어서 ControllerExceptionHandler의 return 타입을 공통Dto로 바꿔 주면 된다.

	//CommonResDto
	@AllArgsConstructor
	@NoArgsConstructor
	@Data
	public class CommonResDto<T>{
    		private String message;
        	private T data;
    }
	//ControllerExceptionHandler
    	@RestController
    	@ControllerAdvice //모든 exception을 낚아챔
    	public class ControllerExceptionHandler {
    
    		@ExceptionHandler(CustomValidationException.class)
    		public CommonResDto<?>validationException(CustomValidationException e) {
        		return new CommpnResDto<Map<String, String>>(e.getMessage(), e.getErrorMap();
        	}
profile
배운것을 기록하자

0개의 댓글