관리 메뉴

너와 나의 스토리

[SpringBoot] @ControllerAdvice를 이용하여 exception handling - Custom Error Response 보내기 & message를 포함한 error response 본문

개발/Spring Boot

[SpringBoot] @ControllerAdvice를 이용하여 exception handling - Custom Error Response 보내기 & message를 포함한 error response

노는게제일좋아! 2022. 6. 3. 14:18
반응형

Exception Handler

  • Rest API로 받은 요청을 처리하다가 exception이 발생하는 경우가 있다.
  • 이러한 exception들을 한 곳에서 처리하도록 ExceptionHandler를 만들어보자.
  • @ControllerAdvice에 있는 메서드들은 모든 controller에 전역으로 적용된다. 어떤 controller에서 exception이 발생하던지 이 exception handler에 명시된 대로 response가 반환된다.
@ControllerAdvice
internal class DeviceExceptionHandler {

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(DeviceNotFoundException::class)
    fun deviceNotFoundException(response: HttpServletResponse, e: DeviceNotFoundException) {
        response.sendError(HttpStatus.NOT_FOUND.value(), e.message)
    }
    
    @ResponseStatus(HttpStatus.NOT_IMPLEMENTED)
    @ExceptionHandler(IosUnsupportedOperationException::class)
    fun iosUnsupportedException(response: HttpServletResponse, e: IosUnsupportedOperationException) {
        response.sendError(HttpStatus.NOT_IMPLEMENTED.value(), e.message)
    }
}
  • 다음과 같이 controller가 있다고 하자.
@RestController
@RequestMapping("/v1/devices")
internal class DevicesController {

    @Resource
    private lateinit var deviceRegistry: DeviceRegistry

    @GetMapping("/{udid}")
    fun get(@PathVariable udid: String): ResponseEntity<DeviceView> {
        return ResponseEntity.ok(
                deviceRegistry.get(udid).view
        )
    }
}
  • deviceRegistry에서 device를 조회하는 과정에서 DeviceNotFoundException이 던져졌다고 하자.
  • 그러면 DeviceExceptionHandler에 정의한 deviceNotFoundException() 메서드가 실행되게 된다.
  • 그 결과 다음과 같은 response를 받게 된다.

 

 

Custom Error Response

  • Custom Error Response를 생성하면 좀 더 많은 정보를 담아 응답으로 보낼 수 있다.
  • 기본 error body에 message를 추가해서 응답을 보내고 싶다면 다음과 같이 간단하게 ErrorResponse를 만들 수 있다.
data class ErrorResponse(val message: String?, val code: HttpStatus){
    val timestamp = LocalDateTime.now()
    val status = code.value()
}
  • 그리고 ExceptionHandler에서 이 error response를 리턴하도록 수정해주면 된다.
@ControllerAdvice
internal class ProviderExceptionHandler {

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(DeviceNotFoundException::class)
    fun deviceNotFoundException(
        response: HttpServletResponse,
        e: DeviceNotFoundException
    ): ResponseEntity<ErrorResponse> {
        return ResponseEntity(
            ErrorResponse(
                e.message,
                HttpStatus.NOT_FOUND
            ), HttpStatus.NOT_FOUND
        )
    }

	// ...
}
  • 그러면 다음과 같은 response를 받을 수 있다.

 

반응형
Comments