JAVA

스프링부트 블로그 만들기 – 예외처리

blog app

스프링부트 블로그 만들기 – 예외처리

예외처리(Exception)하는 방법

모든 익셉션에 대한 함수를 만든다.

함수가 세분화 되지만 함수 개수가 많아진다.

RuntimeException 함수로 처리한다.

모든 예외를 처리할 수 있는데 세분화 할 수 없다.

IllegalArgumentException 함수를 사용한다.

어떤 익셉션이 발생하더라도 내가 정의한 익셉션을 던질 수 있다.

커스텀 익셉션으로 처리한다.

예외처리

1.존재하지 않는 게시글을 주소창에서 강제 요청했을 때의 예외처리를 해준다.
    @GetMapping("/board/{id}") 
  public String detail(@PathVariable int id, Model model) {
    //select * from board where id = :id
    //1.orElse : 값을 찾으면 Board가 리턴, 못찾으면 (괄호안 내용 리턴)
    //		Board boardEntity =  boardRepository.findById(id)
    //				.orElse(new Board(100, "글없어요", "글없어요", null));
    
    //2.orElseThrow
    Board boardEntity = boardRepository.findById(id)
        .orElseThrow();
    
    model.addAttribute("boardEntity",boardEntity);
    return "board/detail";
  }

 

Optional

null을 가질 수도 혹은 안 가질 수도 있는 박스

orElse
값을 찾으면 Board가 리턴, 못찾으면 괄호안 내용 리턴한다. 주로 디폴트값으로 지정하고 싶을 때 사용한다.

Board boardEntity = boardRepository.findById(id).orElse(new Board());

orElseThrow

Board boardEntity = boardRepository.findById(id)
.orElseThrow();

 

2.throw로 던진 예외처리를 받아줄 클래스 GlobalExceptionHandler.java를 만들어준다.
package com.cos.blogapp.handler;

import java.util.NoSuchElementException;

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

import com.cos.blogapp.util.Script;

@ControllerAdvice  
public class GlobalExceptionHandler {
  
  @ExceptionHandler(value = NoSuchElementException.class)
  public @ResponseBody String error1(NoSuchElementException e) {
    System.out.println("Error:"+e.getMessage());
    return Script.href("/","게시글 id를 찾을 수 없습니다."); 
  }
  
}

@ControllerAdvice 가 하는일
1.Exception을 Handling한다.
2.@Controller의 역활을 한다.

익셉션 처리 결과 화면
exception

예외처리 Test

catch/try와 throw 비교

package com.cos.blogapp.web;

import org.junit.jupiter.api.Test;

import com.cos.blogapp.domain.board.Board;

public class BoardControllerTest {
  
  @Test
  public void 익셉션테스트() {
    try {
      Board b = null;
      System.out.println(b.getContent());
    } catch (Exception e) {
      System.out.println("오류가 났어요");
      System.out.println(e.getMessage());
    }
  }
  
  @Test
  public void 익셉션테스트2() throws Exception{
    throw new Exception();
  }
}

 

하나하나 일일이 코드를 적어줘야하는 try catch로 처리하는 거보다 throw로 던져서 재사용하는 것이 더 편리해요.

존재하지 않는 게시글에 대한 Exception 처리 외에도 다른 Exception이 발생한다면 위와 같은 방법은 범용성이 없다. 모든 익셉션에 대한 함수를 각각 만들어 둘 수도 있지만 어떤 익셉션 상황이 발생할 지는 일어나지 않고 우리가 미리 추측하는데는 한계가 있다. RuntimeException을 사용하면 한번에 모든 익셉션에 적용할 수 있지만 각각의 익셉션에 대한 세분화를 할 수 없게된다. 이에 자바에서는 IllegalArgumentException이라는 함수를 제공하여 커스텀화 할 수 있게 만들었다. 여기서 더 나아가 개발자가 직접 함수를 만들어 커스텀할 수도 있다.

커스텀 익셉션 처리

1.handler.ex 패키지 안에 커스텀 익셉션 처리할 MyNotFountException.java 파일을 만들어준다.
package com.cos.blogapp.handler.ex;
/**
 * 
 * @author dahyechoi 2021.09.16
 * 1.id를 못찾았을 때 사용
 * 
 *
 */

public class MyNotFountException extends RuntimeException{
  
  public MyNotFountException(String msg) {
    super(msg);
  }
  
}
주석으로 내가 커스텀한 익셉션에 대한 설명을 적어주면 협업할 때 좋아요.

 

2.GlobalExceptionHandler에서 만들어둔 커스텀 익셉션을 사용하는 코드로 수정한다
package com.cos.blogapp2.handler;

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

import com.cos.blogapp2.handler.ex.MyNotFountException;
import com.cos.blogapp2.util.Script;

//Throw 받아주는 클래스
//@ControllerAdvice 가 하는일 - 1.익셉션을 핸들링, 2.@Controller의 역활까지 한다.
@ControllerAdvice  
public class GlobalExceptionHandler {
  
  @ExceptionHandler(value = MyNotFountException.class)
  public @ResponseBody String error1(MyNotFountException e) { //@ResponseBody = 자바스크립트 리턴 
    System.out.println("Error:"+e.getMessage());
    return Script.href("/",e.getMessage()); //file return
  }
  
}
3.BoardController에서 게시글 상세보기 코드를 수정한다.
@GetMapping("/board/{id}") 
  public String detail(@PathVariable int id, Model model) {

    Board boardEntity = boardRepository.findById(id).orElseThrow(() -> new MyNotFountException(id+"를 못 찾았어요."));   

    model.addAttribute("boardEntity",boardEntity);
    return "board/detail";
  }
위 코드는 람다식을 사용하여 간결하게 만들었어요.

람다식

Java 1.8 버전부터 등장한 람다식은 클래스가 1급 객체인 자바에서 함수를 넘기기 위한 목적으로 만들어졌다. 코드가 매우 간결해지고 따로 타입을 적지 않기 때문에 인터페이스에서 함수를 하나만 사용해야한다.

커스텀 익셉션 처리 결과화면
exception
최신글