반응형

[Spring Boot 실습 #12] 에러 처리 (Exception Handling) - 임의의 http status code 반환

 

1. 정상 범위의 response code로 반환

2. 개발환경

    2.1. 개발환경

    2.2. 라이브러리

3. 구현

    3.1. 프로젝트 구조

    3.2. 구현 - 소스코드

4. 결과

    4.1. request param 값에 따라 throw error 결과

    4.2. 결과

 

 

1. 임의의 http status code 반환

http 호출로 에러 발생시 정상 범위로 판단하여 임의의 http status code 반환

 

2. 개발환경

 

2.1. 개발환경

MacOS M1 - macOS Monterey 12.0.1

IntelliJ IDEA 2021.2 (Community Edition)

 

2.2. 라이브러리

JDK 11

spring-boot-2.6.6

 

 

3. 구현

3.1. 프로젝트 구조

 

3.2. 구현 - 소스코드

 

[ pom.xml ]

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>io.home.test</groupId>
    <artifactId>spring-boot-exception-translator</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-exception-translator</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
</project>

 

 

[ ErrorModel.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
package io.home.test.base.exception;
 
import java.io.Serializable;
 
public class ErrorModel implements Serializable {
    private static final long serialVersionUID = 1L;
 
    private final String message;
    private final String description;
 
    public ErrorModel(String message) {
        this(message, null);
    }
 
    public ErrorModel(String message, String description) {
        this.message = message;
        this.description = description;
    }
 
    public String getMessage() {
        return message;
    }
 
    public String getDescription() {
        return description;
    }
}

 

[ ErrorMessage.java ] 반환할 에러 모델의 메세지

1
2
3
4
5
6
7
8
9
package io.home.test.base.exception;
 
public final class ErrorMessage {
 
    public static final String ERROR_TIMEOUT = "error.timeout";
 
    public ErrorMessage() {
    }
}

 

[ CustomHttpStatus.java ] 등록된 HttpStatus가 아닌 임의의 Status Code를 반환하도록 등록

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package io.home.test.base.exception;
 
public enum CustomHttpStatus {
    RESPONSE_OK(260"RESPONSE OK"),
    RESPONSE_ERROR(270"RESPONSE ERROR"),
    RESPONSE_TIMEOUT(271"RESPONSE TIMEOUT");
 
    private static final CustomHttpStatus[] VALUES = values();
    private final int value;
    private final String reasonPhrase;
 
    private CustomHttpStatus(int value, String reasonPhrase) {
        this.value = value;
        this.reasonPhrase = reasonPhrase;
    }
 
    public int value() {
        return this.value;
    }
 
    public String getReasonPhrase() {
        return this.reasonPhrase;
    }
}

 

[ CustomExceptionResponseCode.java ] ExceptionHandler를 활용하여 특정 에러 발생시 지정한 '에러 모델', '에러 메세지', '에러 코드'로 반환

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 io.home.test.base.exception;
 
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
 
import java.util.concurrent.TimeoutException;
 
import static io.home.test.base.exception.CustomHttpStatus.RESPONSE_TIMEOUT;
 
@ControllerAdvice
public class CustomExceptionResponseCode {
 
    @ExceptionHandler(TimeoutException.class)
    public ResponseEntity<ErrorModel> processTimeoutException(TimeoutException exception) {
        ResponseEntity.BodyBuilder builder;
        ErrorModel errorModel;
        ResponseStatus responseStatus = AnnotationUtils.findAnnotation(exception.getClass(), ResponseStatus.class);
        if (responseStatus != null) {
            builder = ResponseEntity.status(responseStatus.value());
            errorModel = new ErrorModel("error." + responseStatus.value().value(), responseStatus.reason());
        } else {
            builder = ResponseEntity.status(RESPONSE_TIMEOUT.value());
            errorModel = new ErrorModel(ErrorMessage.ERROR_TIMEOUT, "timeout");
        }
        return builder.body(errorModel);
    }
 
}

 

 

4. 결과

4.1. request param 값에 따라 throw error 결과

4.1.1 TimeoutException

GET

http://localhost:8080/api/timeout?sec=11

 

4.2. 결과

  • 사용자 정의 response code 혹은 http status code로 반환하기 위해 별도의 ResponseEntity 생성하여 반환
  • TimeoutException 발생시 일괄적으로 사용자가 정의한 response code로 반환 확인
  • 에러 처리시 유사한 방법으로 에러 처리 가능할듯

 

반응형