[Spring Boot 실습 #11] 에러 처리(Exception Handling) - 정상 범위의 response code로 반환
1. 정상 범위의 response code로 반환
2. 개발환경
2.1. 개발환경
2.2. 라이브러리
3. 구현
3.1. 프로젝트 구조
3.2. 구현 - 소스코드
4. 결과
4.1. request param 값에 따라 throw error 결과
4.2. http method error
1. 정상 범위의 response 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
10
11
12
|
package io.home.test.base.exception;
public final class ErrorMessage {
public static final String ERROR_NOT_FOUND = "error.notFound";
public static final String ERROR_METHOD_NOT_ALLOWED = "error.methodNotAllowed";
public static final String ERROR_INTERNAL_SERVER_ERROR = "error.internalServerError";
public static final String ERROR_BAD_REQUEST = "error.badRequest";
public ErrorMessage() {
}
}
|
[ BadRequestException.java ] 내부 커스텀 에러 예시: HttpStatus.BAD_REQUEST 대체
1
2
3
4
5
6
7
|
package io.home.test.base.exception.exceptions;
public class BadRequestException extends Exception {
public BadRequestException(String message) {
super(message);
}
}
|
[ NotFoundException.java ] 내부 커스텀 에러 예시: HttpStatus.NOT_FOUND 대체
1
2
3
4
5
6
7
|
package io.home.test.base.exception.exceptions;
public class NotFoundException extends Exception {
public NotFoundException(String message) {
super(message);
}
}
|
[ CustomExceptionTranslator.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
32
33
34
35
36
37
38
|
package io.home.test.base.exception;
import io.home.test.base.exception.exceptions.BadRequestException;
import io.home.test.base.exception.exceptions.NotFoundException;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
public class CustomExceptionTranslator {
@ExceptionHandler(NotFoundException.class)
@ResponseStatus(HttpStatus.ACCEPTED)
@ResponseBody
public ErrorModel processNotFoundException(NotFoundException ex) {
return new ErrorModel(ErrorMessage.ERROR_NOT_FOUND, ex.getMessage());
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseBody
@ResponseStatus(HttpStatus.ACCEPTED)
public ErrorModel processMethodNotAllowedException(HttpRequestMethodNotSupportedException exception) {
return new ErrorModel(ErrorMessage.ERROR_METHOD_NOT_ALLOWED, exception.getMethod());
}
@ExceptionHandler(BadRequestException.class)
@ResponseBody
@ResponseStatus(HttpStatus.PARTIAL_CONTENT)
public ErrorModel processBadRequestException(BadRequestException exception) {
return new ErrorModel(ErrorMessage.ERROR_BAD_REQUEST, exception.getMessage());
}
}
|
[ StatusController.java ] http 호출로 error 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
25
|
package io.home.test.base.web;
import io.home.test.base.exception.exceptions.BadRequestException;
import io.home.test.base.exception.exceptions.NotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping(value = "/api")
@RestController
public class StatusController {
@GetMapping(value = "")
public ResponseEntity<?> paramCode(@RequestParam(value = "code", required = false, defaultValue = "0") Integer code) throws NotFoundException, BadRequestException {
if (code == 0) return ResponseEntity.ok().body("required integer parameter 'code' is not present");
if (code == 200) return ResponseEntity.ok().body(HttpStatus.OK.name());
if (code == 302) throw new NotFoundException("code: " + code);
if (code == 400) throw new BadRequestException("code: " + code);
return ResponseEntity.ok().body(HttpStatus.OK.name());
}
}
|
[ SpringBootExceptionTranslatorApplication.java ] 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package io.home.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootExceptionTranslatorApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootExceptionTranslatorApplication.class, args);
}
}
|
4. 결과
4.1. request param 값에 따라 throw error 결과
4.1.1 200
GET
http://localhost:8080/api?code=200
4.1.2 302
GET
http://localhost:8080/api?code=302
4.1.3 400
GET
http://localhost:8080/api?code=400
4.2. http method error
POST
http://localhost:8080/api
4.3. 결과
- 임의로 '에러 모델', '에러 메세지', '에러 코드' 반환 확인
- 에러 처리시 HttpStatus Code를 '정상' 영역으로 처리하기 위해 필요
- 사용자 정의 response code로 반환하기 위해서는 별도의 ResponseEntity 생성하여 반환 필요
'스프링 (Spring) > Spring Boot' 카테고리의 다른 글
[Spring Boot 실습 #13] MyBatis CRUD - H2 Database (0) | 2022.06.13 |
---|---|
[Spring Boot 실습 #12] 에러 처리 (Exception Handling) - 임의의 http status code 반환 (0) | 2022.04.20 |
[Spring Boot 실습 #10] Log4j2 설정 및 적용 - level 별 appender 분리 (0) | 2022.03.18 |
[Spring Boot 실습 #9] Logback 설정 및 적용 - level 별 appender 분리 (0) | 2022.03.17 |
[Spring Boot 실습 #8] Access Log - request body 포함 (0) | 2022.03.16 |