Wanna be Brilliant Full-Stack Developer

SpringBoot 글로벌 예외 처리하기 본문

Back-End/Spring Boot

SpringBoot 글로벌 예외 처리하기

Flashpacker 2022. 2. 10. 13:03

@ResponseBody를 지우고 return을 하는것이아니라 throw new RuntimeException("유효성검사 실패함");을 강제로 발생시키면

이러한 화면이 나오는데 좋은 사용자 환경이 아니기 때문에 이 익셉션이 터진것을 가로채기를 할것이다?

핸들러라는 패키지를 만들것이다

 

ControllerExceptionHandler라는 클래스를 만들고 어노테이션 @ControllerAdvice를 모든 익셉션을 낚아 챈다.

낚아채면 응답을 해야하는데 데이터를 리턴을 하기 위해서 @RestController로 한다

 

package com.cos.photogramstart.handler;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

@RestController
@ControllerAdvice
public class ControllerExceptionHandler {
	
	@ExceptionHandler(RuntimeException.class)
	public String validationException(RuntimeException e) {
		return e.getMessage();
	}

}

RuntimeException이 발동하는 모든 Exception을 validationException 이 함수가 가로챈다. 

애는 return 타입이 String 이긴한데 @RestController 니까 e.getMessage (데이터)를 리턴!

훨씬더 UX가 좋아졌다!

왜냐하면 컨트롤러에서 터진 익셉션을 핸들러가 낚아채서 런타임 익셉션인것을 확인하면 클래스에 있는 ValidationException 함수가 실행되어서 e.getMessage(); 를 리턴하기때문! 

 

하지만 여기서 문제는 우리는 유효성 검사 실패함이 아니라 HashMap에 담은  eroorMap 에 있는 getDefaultMessage들을 리턴하고 싶다. 지금은 불가능하다 왜냐하면 RuntimeException은 String만 받기떄문에 

그래서 이렇게 할수는 없고 핸들러에 새로운 패키지에 새로운 클래스를 만들어서 이것이 익셉션이 되려면

RuntimeException만 상속하면된다.

package com.cos.photogramstart.handler.ex;

import java.util.Map;

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;
	}
	
	//eroorMap을 리턴해주는 getter을 만든다 
	
	public Map<String,String> getErrorMap(){
		return errorMap;
	}

}
package com.cos.photogramstart.handler;

import java.util.Map;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import com.cos.photogramstart.handler.ex.CustomValidationException;

@RestController
@ControllerAdvice
public class ControllerExceptionHandler {
	
	@ExceptionHandler(CustomValidationException.class) // RuntimeExcpetion -> CustomValidaionException 으로 변경 
	public Map<String, String> validationException(CustomValidationException e) {
		return e.getErrorMap();
	}

}

컨트롤러에서도 Exception을 우리가 만든 CustomValidationException으로 바꾸게 되면

SignupDto에서 하나라도 유효성이 실패하게 되면 컨트롤러에 bindingResult에 다담기게 되고 

bindingResult에 에러가 하나라도 있으면 내가 만든 HashMap에 에러들을 담고 다담기면 throw 익셉션을  강제로 발동시켜서 errorMap을 통해  데이터를 던진다. 그러면 밑에 있는 회원가입이 실행되지않는다.