SpringBoot에서의 오류처리 흐름

try-catch -> 여기 코드에서 제어한다
throw를 날린다 -> 나를 호출하는 애한테 위임한다.
Repository
: 는 db와 연결하는 책임만 있기 때문에 repository에서 예외를 처리하지 않는다. → throw로 위임
import java.util.Arrays;
import java.util.List;
public class Repository {
public List<Integer> findAll() {//throws InterruptedException {
/* try {
Thread.sleep(1000); // thread는 쉴틈없이 일함
} catch (InterruptedException e) {
throw new RuntimeException(e);
}*/
return Arrays.asList(1,2,3,4,5);
}
public int findByID() {
/**
* 조회하다가 오류 [1.숫자를 리턴 -1을 받으면 오류] -> 안됨 : type이 달라질 수 있다.
* 오류가 난 곳에서 처리할 수 없다 : 책임이 분리되어 있다. (try-catch(:오류가 난 곳에서 바로 처리하겠다) 사용할 수 없다.)
* -> 예외를 처리하는 걸 만든다. aop
**/
/* 현재 안터지기 때문에 try-catch 로 안하고 throw로 그냥 터트린다.
try {
return 1;
}catch (Exception e) {
throw new RuntimeException("db에서 오류났어"); // 실행 중에 터지는 exception들의 최상위 부모
}*/
throw new RuntimeException("db에서 오류났어"); //-> service의 상세보기로 위임한다.
}
}
Service
: 에서 오류를 잡을 수 있지만 service 레이어의 책임이 아니므로 throw로 위임하거나 try-catch로 오류를 잡지 않고 controller로 자동위임시킨다.
import java.util.List;
public class Service {
private final Repository repo;
public Service(Repository repo) {
this.repo = repo;
}
public List<Integer> 목록보기() {
return repo.findAll();
}
public int 상세보기() {
return repo.findByID();
}
}
Controller
: 응답의 책임이 있으므로 오류를 try-catch로 controller에서 잡아도 되지만 오류를 자동위임시켜 DispatcherServlet으로 넘겨준다.
import java.util.List;
public class Controller {
private Service service;
public Controller(Service service) {
this.service = service;
}
public void list(){
List<Integer> models = service.목록보기();
for(Integer model : models){
System.out.println("rendering : "+model);
}
}
public void detail(){
// try{
int model = service.상세보기();
System.out.println("rendering : "+model);
// } catch (Exception e){
// System.out.println("error : "+e.getMessage());
// }
}
}
DispatcherServlet
: 위임받은 오류를 ControllerAdvice로 넘겨주기 위해 ControllerAdvice의 의존성을 주입한다.
// dispatcherServlet은 main으로 가니까 throw 날리면 걍 터져서 오류남 -> 여기서 오류처리해야한다.
public class DispatcherServlet {
private final Controller con;
private final ControllerAdvice controllerAdvice;
// 생성자
public DispatcherServlet(Controller con, ControllerAdvice controllerAdvice) {
this.con = con;
this.controllerAdvice = controllerAdvice;
}
public void route(String path){
try{
if(path.equals("/")){
con.list();
}else if(path.equals("/board")) {
con.detail();
}else{
// 여기서 못 찾으면 예외를 터트려야 해
System.out.println("404 not found");
}
}catch (RuntimeException e){
// 0. 컴퍼넌스 스캔과 인보크는 java의 reflection으로 프로세스를 때릴 때 발생한다.
// 1. 컴퍼넌트 스캔 @ControllerAdvice
// 2. invoke(호출): 맞는 매개변수 타입을 찾아 때려준다.
// -> 여기에서는 RuntimeException이므로 RuntimeException 매개변수를 가진 친구를 찾아서 때린다.
controllerAdvice.process(e);
}
}
}
ControllerAdvice
: 에러 처리
public class ControllerAdvice {
public void process(RuntimeException e){
System.out.println("에러 공통 처리 : " + e.getMessage());
}
}
Share article