Contents

[Mastering Spring 5.0] 6.1 μ˜ˆμ™Έμ²˜λ¦¬

Mastering Spring 5.0 μŠ€ν„°λ””

μŠ€ν”„λ§ 5.0 λ§ˆμŠ€ν„° μŠ€ν„°λ””
μŠ€ν”„λ§ 5.0 λ§ˆμŠ€ν„° μŠ€ν„°λ”” ν•™μŠ΅ λ‚΄μš© μ •λ¦¬μž…λ‹ˆλ‹€.

1. μŠ€ν”„λ§ λΆ€νŠΈμ˜ κΈ°λ³Έ μ˜ˆμ™Έμ²˜λ¦¬

  • μŠ€ν”„λ§λΆ€νŠΈμ˜ κΈ°λ³Έ μ˜ˆμ™Έ ν˜•μ‹μ€ throw 된 μ˜ˆμ™Έ 메세지 와 ν•¨κ»˜ JSON ν˜•νƒœλ‘œ μ—λŸ¬λ₯Ό λ¦¬ν„΄ν•œλ‹€.
  • λΈŒλΌμš°μ €κ²½μš° κΈ°λ³Έ 였λ₯˜ νŽ˜μ΄μ§€ (Whilelabel Error Page) λ₯Ό 좜λ ₯ν•œλ‹€.
1
2
3
4
5
6
7
{
    "timestamp": "2018-12-07T05:01:26.483+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Some Exception Occurred",
    "path": "/users/dummy-service"
}

2. μŠ€ν”„λ§ μ‚¬μš©μž μ •μ˜ μ˜ˆμ™Έμ²˜λ¦¬

μŠ€ν”„λ§μ—μ„œλŠ” 였λ₯˜μ— λŒ€ν•œ 응닡을 μ‚¬μš©μžκ°€ μ •μ˜ν•˜λŠ” μ—¬λŸ¬ μ˜΅μ…˜μ„ μ œκ³΅ν•œλ‹€.

2.1 응닡 메세지 μ‚¬μš©μž μ •μ˜ ν•˜κΈ°

주어진 IDκ°€ 가지고 μžˆλŠ” todo λ¦¬μŠ€νŠΈκ°€ λ°œκ²¬λ˜μ§€ μ•Šμ•˜μ„ λ•Œ λ°œμƒμ‹œν‚¬ μ‚¬μš©μž μ •μ˜ TodoNotFoundException와 메세지 처리λ₯Ό ν•  ExceptionResponse 객체λ₯Ό μƒμ„±ν•œλ‹€.

TodoNotFoundException.java

1
2
3
4
5
6
7
package com.mastering.spring.springboot.exception;

public class TodoNotFoundException extends RuntimeException {
    public TodoNotFoundException(String msg) {
        super(msg);
    }
}

ExceptionResponse.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.mastering.spring.springboot.bean;
import java.util.Date;

public class ExceptionResponse {
    private Date timestamp = new Date();
    private String message;
    private String details;
    public ExceptionResponse(String message, String details) {
        super();
        this.message = message;
        this.details = details;
    }
    public Date getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(Date timestamp) {
        this.timestamp = timestamp;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public String getDetails() {
        return details;
    }
    public void setDetails(String details) {
        this.details = details;
    }
}

TodoNotFoundExcption 이 λ°œμƒν•˜λ©΄ ExceptionResponse Bean 을 μ‚¬μš©ν•΄ 응닡을 λ°˜ν™˜ν•  컨트둀러λ₯Ό μƒμ„±ν•œλ‹€.

1
2
3
4
5
6
7
8
9
@ControllerAdvice
@RestController
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(TodoNotFoundException.class)
    public final ResponseEntity<ExceptionResponse> todoNotFound(TodoNotFoundException ex) {
        ExceptionResponse exceptionResponse = new ExceptionResponse(ex.getMessage(), "Any details you would want to add.");
        return new ResponseEntity<ExceptionResponse>(exceptionResponse, new HttpHeaders(), HttpStatus.NOT_FOUND);
    }
}

2.2 λͺ¨λ“  μ˜ˆμ™Έμ— μ‚¬μš©μž μ •μ˜ μ˜ˆμ™Έμ²˜λ¦¬ μ •μ˜ν•˜κΈ°

μ•„λž˜ μ½”λ“œλŠ” μ‚¬μš©μž μ •μ˜ μ˜ˆμ™Έ 이외에 λͺ¨λ“  μ˜ˆμ™Έμ— λŒ€ν•΄ μ‚¬μš©μž μ •μ˜ μ˜ˆμ™Έ 메세지λ₯Ό μ‘λ‹΅ν•˜λ„λ‘ μ„€μ •ν•œλ‹€.

1
2
3
4
5
@ExceptionHandler(Exception.class)
public ResponseEntity<ExceptionResponse> defaultError(Exception ex) {
    ExceptionResponse exceptionResponse = new ExceptionResponse(ex.getMessage(), "μ•Œμˆ˜μ—†λŠ” μ—λŸ¬...");
    return new ResponseEntity<ExceptionResponse>(exceptionResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}
  • @ControllerAdvice λ₯Ό μ΄μš©ν•˜μ—¬ @ExceptionHander λ₯Ό λͺ¨λ“  νŒ¨ν‚€μ§€ 및 μ»¨νŠΈλ‘€λŸ¬μ—μ„œ μ „μ—­μ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ„λ‘ μ •μ˜ν•œλ‹€.
  • @ExceptionHandler(TodoNotFoundException.class) κ°€ νŠΉμ • μ—λŸ¬ μœ ν˜•(클래슀) 에 λŒ€ν•΄ μ˜ˆμ™Έμ²˜λ¦¬ ν•˜λ„λ‘ μ •μ˜ν•œλ‹€. μ‚¬μš©μž μ˜ˆμ™Έ μ²˜λ¦¬κ°€ λ˜μ–΄ μžˆμ§€ μ•Šμ€ λ‹€λ₯Έ μ˜ˆμ™ΈλŠ” μŠ€ν”„λ§λΆ€νŠΈμ˜ κΈ°λ³Έ μ˜ˆμ™Έμ²˜λ¦¬ ν˜•νƒœλ₯Ό λ”°λ₯Έλ‹€.
  • @RestController 을 μ‚¬μš©ν•˜μ—¬ ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ μ‘λ‹΅μ²˜λ¦¬λ₯Ό ν•  수 있게 ν•œλ‹€.

2.3 μ‚¬μš©μž μ •μ˜ μ—λŸ¬μ— νŠΉμ • HTTP 응닡 μƒνƒœ μ§€μ •ν•˜κΈ°

@ResponseStatus μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜μ—¬ μ»€μŠ€ν…€ μ—λŸ¬μ— νŠΉμ • HTTP 응닡 μƒνƒœλ₯Ό 지정할 수 μžˆλ‹€.

1
2
3
4
5
6
@ResponseStatus(HttpStatus.NOT_FOUND)
public class TodoNotFoundException extends RuntimeException {
    public TodoNotFoundException(String msg) {
        super(msg);
    }
}

3. HTTP 응닡 μƒνƒœ μ½”λ“œ

응닡 μƒνƒœ 상황
400 - BAD REQUEST μš”μ²­λ³Έλ¬Έμ΄ API μŠ€νŽ™μ„ μΆ©μ‘±ν•˜μ§€ λͺ»ν•˜μ—¬ μ„œλ²„κ°€ μš”μ²­μ„ 이해할 수 μ—†μŒμ„ 의미.
401 - UNAUTHORIZED 인증 λ˜λŠ” κΆŒν•œ λΆ€μ—¬ μ‹€νŒ¨
403 - RESOURCE FORBIDDEN ν΄λΌμ΄μ–ΈνŠΈκ°€ 컨텐츠에 μ ‘κ·Όν•  ꢌ리λ₯Ό κ°–κ³  μžˆμ§€ μ•ŠμŒ. 401 κ³Ό λ‹€λ₯Έ 점은 ν΄λΌμ΄μ–ΈνŠΈκ°€ λˆ„κ΅¬μΈμ§€ μ•Œκ³  있음.
404 - RESOURCE NOT FOUND μš”μ²­ν•œ λ¦¬μ†ŒμŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŒ
405 - METHOD NOT ALLOWED μ§€μ›λ˜μ§€ μ•ŠλŠ” μ˜€νΌλ ˆμ΄μ…˜ (ex : GET μš”μ²­ν•œ ν—ˆμš©λ˜λŠ” λ¦¬μ†ŒμŠ€μ— POST μš”μ²­μ„ μ‹œλ„)
500 - INTERNAL SERVER ERROR μ„œλ²„μ—μ„œ μ—λŸ¬κ°€ λ°œμƒν•˜μ—¬, μ†ŒλΉ„μžλŠ” 이 문제λ₯Ό ν•΄κ²° ν•  수 μ—†μŒ.

4. ResponseStatusException (Spring 5 and Above)