@Import(EndpointExceptionHandler::class)
@SpringBootApplication
class Application {
companion object {
const val VERSION: String = "v1"
}
}
package net.test.exception
import io.jsonwebtoken.ExpiredJwtException
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.RestControllerAdvice
@RestControllerAdvice
class EndpointExceptionHandler {
@ExceptionHandler(ApplicationException::class)
fun handleResponse(t: ApplicationException): ResponseEntity<MessageResponse> = t.response(t.classify.statusCode)
private fun ApplicationException.response(status: Int): ResponseEntity<MessageResponse> = ResponseEntity.status(
status,
).body(MessageResponse(this.classify.code, this.message, this.classify.innerCode))
data class MessageResponse(
val classify: String,
val message: String?,
val innerCode: Int,
)
}
class ApplicationException(
val classify: ErrorCode,
override val cause: Throwable? = null,
) : RuntimeException(classify.label) {
override val message: String get() = classify.label
}
fun throwError(error: ErrorCode, t: Throwable? = null): Nothing {
if (t is ExpiredJwtException) {
throw ApplicationException(CommonErrorCode.TokenExpired, t)
}
throw ApplicationException(error, t)
}
interface ErrorCode {
val code: String
val label: String
val statusCode: Int
val innerCode: Int
}
package net.test.exception
import org.apache.http.HttpStatus
object CustomErrorCode {
object ParameterError : ErrorCode {
override val code = "PARAMETER_ERROR"
override val label = "데이터를 올바르게 입력해주세요"
override val statusCode = HttpStatus.SC_BAD_REQUEST
override val innerCode = 4000
}
object NotFoundUser : ErrorCode {
override val code = "NOT_FOUND_USER"
override val label = "사용자를 조회할 수 없습니다."
override val statusCode = HttpStatus.SC_NOT_FOUND
override val innerCode = 4001
}
object DuplicateUser : ErrorCode {
override val code = "DUPLICATE_USER"
override val label = "이미 등록된 사용자입니다."
override val statusCode = HttpStatus.SC_BAD_REQUEST
override val innerCode = 4002
}
object PasswordNotMatch : ErrorCode {
override val code = "PASSWORD_NOT_MATCH"
override val label = "비밀번호가 일치하지 않습니다."
override val statusCode = HttpStatus.SC_UNAUTHORIZED
override val innerCode = 4010
}
object UserSuspended : ErrorCode {
override val code = "USER_SUSPENDED"
override val label = "이용정지된 사용자입니다."
override val statusCode = HttpStatus.SC_UNAUTHORIZED
override val innerCode = 4010
}
object InvalidToken : ErrorCode {
override val code = "INVALID_TOKEN"
override val label = "유효하지 않은 토큰입니다."
override val statusCode = HttpStatus.SC_UNAUTHORIZED
override val innerCode = 4011
}
object GetFailed : ErrorCode {
override val code = "GET_FAILED"
override val label = "조회에 실패하였습니다."
override val statusCode = HttpStatus.SC_INTERNAL_SERVER_ERROR
override val innerCode = 5000
}
object DataIsEmpty : ErrorCode {
override val code: String = "DATA_IS_EMPTY"
override val label: String = "데이터가 없습니다."
override val statusCode = HttpStatus.SC_BAD_REQUEST
override val innerCode: Int = 999
}
}
실제사용
throwError(CommonErrorCode.TokenExpired)