Skip to content

Commit 6e80989

Browse files
committed
feat: 전역 예외 처리 클래스(GlobalExceptionHandler) 구현
1 parent 9432b27 commit 6e80989

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package com.example.log4u.common.advice;
2+
3+
import java.util.List;
4+
import java.util.stream.Collectors;
5+
6+
import org.springframework.http.HttpHeaders;
7+
import org.springframework.http.HttpStatusCode;
8+
import org.springframework.http.ResponseEntity;
9+
import org.springframework.lang.NonNull;
10+
import org.springframework.validation.BindException;
11+
import org.springframework.web.bind.MethodArgumentNotValidException;
12+
import org.springframework.web.bind.annotation.ExceptionHandler;
13+
import org.springframework.web.bind.annotation.RestControllerAdvice;
14+
import org.springframework.web.context.request.ServletWebRequest;
15+
import org.springframework.web.context.request.WebRequest;
16+
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
17+
18+
import com.example.log4u.common.exception.ApiErrorResponse;
19+
import com.example.log4u.common.exception.CommonErrorCode;
20+
import com.example.log4u.common.exception.base.ErrorCode;
21+
import com.example.log4u.common.exception.base.ServiceException;
22+
23+
import jakarta.servlet.http.HttpServletRequest;
24+
import lombok.extern.slf4j.Slf4j;
25+
26+
@RestControllerAdvice
27+
@Slf4j
28+
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
29+
30+
@Override
31+
public ResponseEntity<Object> handleMethodArgumentNotValid(
32+
MethodArgumentNotValidException e,
33+
@NonNull HttpHeaders headers,
34+
@NonNull HttpStatusCode status,
35+
@NonNull WebRequest request) {
36+
HttpServletRequest servletRequest = ((ServletWebRequest)request).getRequest();
37+
38+
String requestUrl = servletRequest.getRequestURI();
39+
String httpMethod = servletRequest.getMethod();
40+
List<String> errors = e.getBindingResult()
41+
.getFieldErrors()
42+
.stream()
43+
.map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage())
44+
.collect(Collectors.toList());
45+
46+
log.warn("Validation failed for request to {} {}. Errors: {}",
47+
httpMethod, requestUrl, errors);
48+
CommonErrorCode errorCode = CommonErrorCode.INVALID_PARAMETER;
49+
return handleExceptionInternal(e, errorCode);
50+
}
51+
52+
@ExceptionHandler(IllegalArgumentException.class)
53+
public ResponseEntity<ApiErrorResponse> handleIllegalArgument(IllegalArgumentException e) {
54+
String location = getExceptionLocation(e);
55+
56+
log.warn("Illegal argument encountered at {}: {}", location, e.getMessage());
57+
58+
CommonErrorCode errorCode = CommonErrorCode.INVALID_PARAMETER;
59+
return handleExceptionInternal(errorCode);
60+
}
61+
62+
@ExceptionHandler(ServiceException.class)
63+
public ResponseEntity<ApiErrorResponse> handleGiveMeTiConException(ServiceException e) {
64+
String location = getExceptionLocation(e);
65+
log.warn("Error invoke in our app at {}: {} ErrorCode: {}", location, e.getMessage(), e.getErrorCode());
66+
ErrorCode errorCode = e.getErrorCode();
67+
return handleExceptionInternal(errorCode);
68+
}
69+
70+
@ExceptionHandler({Exception.class})
71+
public ResponseEntity<ApiErrorResponse> handleAllException(Exception e) {
72+
String location = getExceptionLocation(e);
73+
log.warn("Unhandled exception occurred at {}: {}", location, e.getMessage());
74+
75+
CommonErrorCode errorCode = CommonErrorCode.INTERNAL_SERVER_ERROR;
76+
return handleExceptionInternal(errorCode);
77+
}
78+
79+
private ResponseEntity<ApiErrorResponse> handleExceptionInternal(ErrorCode errorCode) {
80+
return ResponseEntity.status(errorCode.getHttpStatus())
81+
.body(makeErrorResponse(errorCode));
82+
}
83+
84+
private ApiErrorResponse makeErrorResponse(ErrorCode errorCode) {
85+
return ApiErrorResponse.builder()
86+
.errorMessage(errorCode.getErrorMessage())
87+
.errorCode(errorCode.getHttpStatus().value())
88+
.build();
89+
}
90+
91+
private ResponseEntity<Object> handleExceptionInternal(BindException e, ErrorCode errorCode) {
92+
return ResponseEntity.status(errorCode.getHttpStatus())
93+
.body(makeErrorResponse(e, errorCode));
94+
}
95+
96+
private ApiErrorResponse makeErrorResponse(BindException e, ErrorCode errorCode) {
97+
List<ApiErrorResponse.ValidationError> validationErrorList = e.getBindingResult()
98+
.getFieldErrors()
99+
.stream()
100+
.map(ApiErrorResponse.ValidationError::of)
101+
.collect(Collectors.toList());
102+
103+
return ApiErrorResponse.builder()
104+
.errorMessage(errorCode.getErrorMessage())
105+
.errorCode(errorCode.getHttpStatus().value())
106+
.errors(validationErrorList)
107+
.build();
108+
}
109+
110+
private String getExceptionLocation(Exception e) {
111+
StackTraceElement element = e.getStackTrace()[0];
112+
return element.getClassName() + "." + element.getMethodName() + ":" + element.getLineNumber();
113+
}
114+
}

0 commit comments

Comments
 (0)