728x90
@ExceptionHandler 리팩토링 코드 가이드
1. CommonError enum 상수 추가
CommonError 경로: exception/common/constant/CommonError
enum
상수로 @ExceptionHandler
공통 메서드에서 처리할 Custom Error 정보를 작성한다
package com.iparking.exception.common.constant;
import com.iparking.common.constant.ResCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.slf4j.event.Level;
import java.util.HashMap;
import java.util.Map;
import static com.iparking.common.constant.ResCode.*;
/**
* Exception 타입에 따른 메세지 처리 상수
* Created by KMS on 06/03/2020.
*/
@Getter
@AllArgsConstructor
public enum CommonError {
/** HTTP 요청 에러 **/
HttpMessageNotReadableException(ERR_PARAMS, "HTTP 요청 에러: ", true, Level.ERROR),
/** 지원되지 않는 HTTP METHOD 에러 핸들러 **/
HttpRequestMethodNotSupportedException(ERR_PARAMS, "지원되지 않는 HTTP METHOD: ", true, Level.ERROR),
/** 데이터 등록 실패 에러핸들러 **/
DataRegistrationFailedException(DATA_NOT_FOUND, DATA_REGISTRATION_FAIL.getMessage()+": 데이터 등록이 실패했습니다: ",true, Level.ERROR),
/** 임시 파일 적용 시 BODY가 없을 때 **/
DataNotFoundException(DATA_NOT_FOUND, "Data not found: 요청하신 데이터를 찾을 수 없습니다: ", true, Level.ERROR),
/** 중복된 데이터 처리 에러 핸들러 **/
DuplicateDataException(DATA_DUPLICATE, DATA_DUPLICATE.getMessage()+": ", true, Level.ERROR),
/** 데이터베이스 중복 키 에러 **/
DuplicateKeyException(DATA_DUPLICATE, "중복된 키가 있어 데이터베이스 등록에 실패 했습니다: ", true, Level.ERROR),
/** RestTemplate API 통신 에러 핸들러 **/
ResourceAccessException(ERROR, "REST API 통신 에러: ", true, Level.ERROR),
/** RestTemplate API 통신 에러 핸들러 **/
RestClientException(ERROR, "REST API 통신 에러: ", true, Level.ERROR),
/** 파일이 용량 제한 에러 **/
MaxUploadSizeExceededException(FILE_MAX_UPLOAD_SIZE_EXCEEDED, "", false, Level.WARN),
/** 파일이 용량 제한 에러 **/
SizeLimitExceededException(FILE_MAX_UPLOAD_SIZE_EXCEEDED, "", false, Level.WARN),
/** MultiPart 파일 전송 누락 에러 **/
MissingServletRequestPartException(FILE_REQUEST_MISSING_PART, "잘못된 전송 파일명 또는 전송 파일 누락 에러: ", true, Level.ERROR),
/** MultiPart 파일 전송 요청 에러 **/
MultipartException(FILE_REQUEST_ERROR, "파일 전송 요청 에러: ", true, Level.ERROR),
/** 프로세스를 더이상 진행할 수 없을 때 **/
UnprocessableException(ERROR, "", true, Level.ERROR),
/** 파일이 존재하지 않을 때 **/
FileNotExistException(FILE_NOT_EXIST, "", true, Level.ERROR),
/** 파일 등록 필수 파라메터 체크 **/
FileRequestFileNotException(ERR_PARAMS, "", true, Level.ERROR),
/** 파일 덮어쓰기 여부 확인 **/
FileDuplicateException(ERR_PARAMS, "", true, Level.ERROR),
/** 파일 등록 필수 파라메터 체크 **/
FileRequestParamRequiredException(ERR_PARAMS, "", true, Level.ERROR),
/** JWT 토큰 복호화 ERROR 핸들러 **/
InvalidSignatureException(ERR_PARAMS, "JWT 토큰 복호화 ERROR: ", true, Level.ERROR),
/** 파라메터 유효성 체크 실패 에러 핸들러 **/
ParameterValidationFailedException(ERR_PARAMS, "", true, Level.WARN),
/** 사용자 정의 필수 파라메터 누락 에러 핸들러 **/
RequestParamRequiredException(ERR_PARAMS, "", true, Level.WARN),
/** Parameter Validation Error **/
MissingServletRequestParameterException(ERR_PARAMS, "", true, Level.ERROR),
/** Parameter Validation Error **/
BindException(ERR_PARAMS, "", true, Level.ERROR),
/** Parameter Validation Error **/
MethodArgumentNotValidException(ERR_PARAMS, "", true, Level.ERROR),
/** AES 복호화 에러 **/
AesDecryptException(ERROR, "AES 복호화 ERROR: ", true, Level.ERROR),
/** AES 암호화 에러 **/
AesEncryptException(ERROR, "AES 암호화 ERROR: ", true, Level.ERROR),
/** 엑셀 데이터 처리중 에러 **/
ExcelComponentException(ERROR, "엑셀 데이터 처리중 ERROR: ", true, Level.ERROR),
/** 엑셀 업로드 Field 에러 **/
ExcelReaderFieldException(EXCEL_READER_FIELD_ERROR, "엑셀 업로드 FIELD ERROR :: 입력 데이터를 확인하세요", false, Level.WARN),
/** 엑셀 업로드시 읽을 수 없는 엑셀 파일 에러 **/
ExcelReaderFileException(EXCEL_READER_FILE_ERROR, "읽을 수 없는 엑셀 파일 입니다 (DRM 적용 또는 다른이유)", false, Level.ERROR),
/** 엑셀 업로드시 엑셀 파일이 아닌 확장자 파일에 대한 에러 **/
ExcelReaderFileExtentionException(EXCEL_READER_FILE_ERROR, "엑셀 업로드는 [xlsx, xls] 확장자 파일만 처리가 가능합니다", false, Level.ERROR),
/** 엑셀 업로드 시 캐치 하지 못한 그외 에러 **/
ExcelReaderException(EXCEL_READER_ERROR, "엑셀 업로드 ERROR: ", true, Level.ERROR),
;
private static Map<String, CommonError> nameToMap;
/* 응답코드객체 */
private final ResCode resCode;
/* 응답메세지 */
private final String message;
/* e.getMessage true:추가, false:미추가 */
private final boolean exception;
/* Log Level */
private final Level level;
/**
* Exception 으로 CommonError 맵으로 맵핑
* @param e Exception 객체
* @return CommonError 맵
*/
public static CommonError getCommonError(Exception e) {
if(nameToMap == null) {
initMapping();
}
return nameToMap.get(e.getClass().getSimpleName());
}
/**
* 맵 초기화
*/
private static void initMapping() {
nameToMap = new HashMap<>();
for (CommonError commonError : values()) {
nameToMap.put(commonError.name(), commonError);
}
}
}
2. 공통 @ExceptionHandler
메서드
CommonErrorHandler 경로: exception/common/handler/CommonErrorHandler
아래 와 같이 enum
정의 한 모든 에러 클래스를 추가하여 공통으로 처리 할 수 있는 @ExceptionHandler
처리 메서드를 추가함
/**
* 공통 에러 처리 핸들러 (에러메세지 처리)
* 로그상에 ERROR 메세지로 기록되고 두레이 메신저 알림이 옴
* @param e
* @param request
* @param webRequest
* @return
* @throws Exception
*/
@ExceptionHandler({
// HTTP 요청 에러
HttpMessageNotReadableException.class,
// 지원되지 않는 HTTP METHOD 에러 핸들러
HttpRequestMethodNotSupportedException.class,
// 데이터 등록 실패 에러핸들러
DataRegistrationFailedException.class,
// 임시 파일 적용 시 BODY가 없을 때
DataNotFoundException.class,
// 중복된 데이터 처리 에러 핸들러
DuplicateDataException.class,
// 데이터베이스 중복 키 에러
DuplicateKeyException.class,
// RestTemplate API 통신 에러 핸들러
RestClientException.class,
// RestTemplate API 통신 에러 핸들러
ResourceAccessException.class,
// 최대 파일 용량 초과 에러
MaxUploadSizeExceededException.class,
// 파일이 용량 제한 에러
SizeLimitExceededException.class,
// MultiPart 파일 전송 누락 에러
MissingServletRequestPartException.class,
// MultiPart 파일 전송 요청 에러
MultipartException.class,
//프로세스를 더이상 진행할 수 없을 때
UnprocessableException.class,
// 파일이 존재하지 않을 때
FileNotExistException.class,
// 파일 등록 파일 유무 체크
FileRequestFileNotException.class,
// 파일 덮어쓰기 여부 확인
FileDuplicateException.class,
// 파일 등록 필수 파라메터 체크
FileRequestParamRequiredException.class,
// JWT 토큰 복호화 ERROR 핸들러
InvalidSignatureException.class,
// 파라메터 유효성 체크 실패 에러 핸들러
ParameterValidationFailedException.class,
// 사용자 정의 필수 파라메터 누락 에러 핸들러
RequestParamRequiredException.class,
// Parameter Validation Error
MissingServletRequestParameterException.class,
// Parameter Validation Error
BindException.class,
// Parameter Validation Error
MethodArgumentNotValidException.class,
// AES 복호화 에러
AesDecryptException.class,
// AES 암호화 에러
AesEncryptException.class,
// 엑셀 데이터 처리중 에러
ExcelComponentException.class,
// 엑셀 업로드 필드 에러 핸들러
ExcelReaderFieldException.class,
// 엑셀 업로드 파일 에러 핸들러
ExcelReaderFileException.class,
// 엑셀 업로드 파일 확장자 에러 핸들러
ExcelReaderFileExtentionException.class,
// 엑셀 업로드 시 캐치 하지 못한 그외 에러
ExcelReaderException.class,
})
public CommonResult<?> CommonErrorException(Exception e, HttpServletRequest request, WebRequest webRequest) throws Exception {
// 공통에러상수 객체 셋팅
CommonError error = CommonError.getCommonError(e);
String ERROR_MSG = error.isException() && StringUtils.isNotEmpty(e.getMessage()) ? error.getMessage()+e.getMessage() : error.getMessage();
errorMap = ErrorUtils.setErrorMap(request, webRequest, secretKey); // 에러 맵 기본 셋팅
CommonResult<?> commonResult = null;
String CUSTOM_MSG = null; //커스텀 Exception Message
/* Exception 별 커스텀 처리 */
switch (error) {
case MaxUploadSizeExceededException: // 최대 파일 용량 초과 에러
long permittedSize=0L; //제한용량
long actualSize=0L; //요청 파일용량
MaxUploadSizeExceededException me = (MaxUploadSizeExceededException) e;
Throwable cause = me.getCause();
if(cause instanceof SizeLimitExceededException) {
SizeLimitExceededException sizeLimit = (SizeLimitExceededException) cause;
permittedSize = sizeLimit.getPermittedSize() != 0L ? sizeLimit.getPermittedSize()/1024/1024 : 0L;
actualSize = sizeLimit.getActualSize() != 0L ? sizeLimit.getActualSize()/1024/1024 : 0L;
CUSTOM_MSG = "최대 업로드 파일용량 제한초과 :: 제한용량 = "+permittedSize+"MB, 요청 파일용량 = "+actualSize+"MB";
}
ERROR_MSG += "최대 "+permittedSize+"MB까지 등록할 수 있습니다: 요청 파일용량 = "+actualSize+"MB";
break;
case BindException: // Parameter Validation Error
ERROR_MSG = getBindResultFieldErrorMessage(((BindException) e).getBindingResult());
break;
case MethodArgumentNotValidException: // Parameter Validation Error
ERROR_MSG = getBindResultFieldErrorMessage(((MethodArgumentNotValidException) e).getBindingResult());
break;
case ExcelReaderFieldException: // 엑셀 업로드 필드 에러 핸들러
commonResult = new CommonResult<>(error.getResCode(), ERROR_MSG, ExcelReader.errorFieldList);
errorMap.put("CommonResult", commonResult);
break;
}
if(Objects.isNull(commonResult))
commonResult = new CommonResult<>(error.getResCode(), ERROR_MSG, errorMap);
// Level 별 에러메시지 출력
ErrorUtils.logWriter(error, CLASS_NAME, ERROR_MSG, errorMap, e, CUSTOM_MSG);
return commonResult;
}
3. 공통으로 처리할 수 없는 메서드
CommonErrorHandler 경로: exception/common/handler/CommonErrorHandler
MaxUploadSizeExceededException, BindException, MethodArgumentNotValidException, ExcelReaderFieldException 와 같이
응답 메세지 처리를 조금 다르게 해야하는 Exception 같은 경우에는 아래와 같이 switch case
문으로 분기 하여 처리 한다
/* Exception 별 커스텀 처리 */
switch (error) {
case MaxUploadSizeExceededException: // 최대 파일 용량 초과 에러
long permittedSize=0L; //제한용량
long actualSize=0L; //요청 파일용량
MaxUploadSizeExceededException me = (MaxUploadSizeExceededException) e;
Throwable cause = me.getCause();
if(cause instanceof SizeLimitExceededException) {
SizeLimitExceededException sizeLimit = (SizeLimitExceededException) cause;
permittedSize = sizeLimit.getPermittedSize() != 0L ? sizeLimit.getPermittedSize()/1024/1024 : 0L;
actualSize = sizeLimit.getActualSize() != 0L ? sizeLimit.getActualSize()/1024/1024 : 0L;
CUSTOM_MSG = "최대 업로드 파일용량 제한초과 :: 제한용량 = "+permittedSize+"MB, 요청 파일용량 = "+actualSize+"MB";
}
ERROR_MSG += "최대 "+permittedSize+"MB까지 등록할 수 있습니다: 요청 파일용량 = "+actualSize+"MB";
break;
case BindException: // Parameter Validation Error
ERROR_MSG = getBindResultFieldErrorMessage(((BindException) e).getBindingResult());
break;
case MethodArgumentNotValidException: // Parameter Validation Error
ERROR_MSG = getBindResultFieldErrorMessage(((MethodArgumentNotValidException) e).getBindingResult());
break;
case ExcelReaderFieldException: // 엑셀 업로드 필드 에러 핸들러
commonResult = new CommonResult<>(error.getResCode(), ERROR_MSG, ExcelReader.errorFieldList);
errorMap.put("CommonResult", commonResult);
break;
}
4. ErrorUtils에 logWriter
유틸 추가
ErrorUtils 경로: utils/common/ErrorUtils
Log Level 별로 분기하여 log
메세지를 출력해주는 유틸
/**
* Level 별 에러메세지 출력
* @param error
* @param CLASS_NAME
* @param ERROR_MSG
* @param errorMap
* @param e
*/
public static void logWriter(CommonError error, String CLASS_NAME, String ERROR_MSG, Map<String, Object> errorMap, Exception e, String CUSTOM_MSG) {
String EX_MSG = StringUtils.isEmpty(CUSTOM_MSG) ? ExceptionUtils.getMessage(e) : CUSTOM_MSG + "\n" + ExceptionUtils.getMessage(e);
//에러메세지 출력
switch (error.getLevel()){
case INFO:
ErrorUtils.infoWriter(CLASS_NAME, ERROR_MSG, errorMap, EX_MSG);
break;
case WARN:
ErrorUtils.warnWriter(CLASS_NAME, ERROR_MSG, errorMap, EX_MSG);
break;
case ERROR:
ErrorUtils.errorWriter(CLASS_NAME, ERROR_MSG, errorMap, EX_MSG);
break;
}
}
CommonErrorHandler 전체 소스코드
package com.iparking.exception.common.handler;
/**
* Created by KMS on 29/09/2019.
* 공통 Controller Exception Handler
*/
import com.iparking.common.domain.CommonResult;
import com.iparking.component.excel.service.ExcelReader;
import com.iparking.exception.common.*;
import com.iparking.exception.common.constant.CommonError;
import com.iparking.exception.excel.*;
import com.iparking.exception.file.FileDuplicateException;
import com.iparking.exception.file.FileNotExistException;
import com.iparking.exception.file.FileRequestFileNotException;
import com.iparking.exception.file.FileRequestParamRequiredException;
import com.iparking.utils.common.ErrorUtils;
import com.iparking.utils.common.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.jwt.crypto.sign.InvalidSignatureException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import static com.iparking.common.constant.ResCode.ERROR;
@Slf4j
@RestControllerAdvice
public class CommonErrorHandler {
private String CLASS_NAME = "Common";
private Map<String, Object> errorMap = new LinkedHashMap<>();
@Value("${jwt.secret-key}")
private String secretKey;
/**
* 공통 에러 처리 핸들러 (에러메세지 처리)
* 로그상에 ERROR 메세지로 기록되고 두레이 메신저 알림이 옴
* @param e
* @param request
* @param webRequest
* @return
* @throws Exception
*/
@ExceptionHandler({
// HTTP 요청 에러
HttpMessageNotReadableException.class,
// 지원되지 않는 HTTP METHOD 에러 핸들러
HttpRequestMethodNotSupportedException.class,
// 데이터 등록 실패 에러핸들러
DataRegistrationFailedException.class,
// 임시 파일 적용 시 BODY가 없을 때
DataNotFoundException.class,
// 중복된 데이터 처리 에러 핸들러
DuplicateDataException.class,
// 데이터베이스 중복 키 에러
DuplicateKeyException.class,
// RestTemplate API 통신 에러 핸들러
RestClientException.class,
// RestTemplate API 통신 에러 핸들러
ResourceAccessException.class,
// 최대 파일 용량 초과 에러
MaxUploadSizeExceededException.class,
// 파일이 용량 제한 에러
SizeLimitExceededException.class,
// MultiPart 파일 전송 누락 에러
MissingServletRequestPartException.class,
// MultiPart 파일 전송 요청 에러
MultipartException.class,
//프로세스를 더이상 진행할 수 없을 때
UnprocessableException.class,
// 파일이 존재하지 않을 때
FileNotExistException.class,
// 파일 등록 파일 유무 체크
FileRequestFileNotException.class,
// 파일 덮어쓰기 여부 확인
FileDuplicateException.class,
// 파일 등록 필수 파라메터 체크
FileRequestParamRequiredException.class,
// JWT 토큰 복호화 ERROR 핸들러
InvalidSignatureException.class,
// 파라메터 유효성 체크 실패 에러 핸들러
ParameterValidationFailedException.class,
// 사용자 정의 필수 파라메터 누락 에러 핸들러
RequestParamRequiredException.class,
// Parameter Validation Error
MissingServletRequestParameterException.class,
// Parameter Validation Error
BindException.class,
// Parameter Validation Error
MethodArgumentNotValidException.class,
// AES 복호화 에러
AesDecryptException.class,
// AES 암호화 에러
AesEncryptException.class,
// 엑셀 데이터 처리중 에러
ExcelComponentException.class,
// 엑셀 업로드 필드 에러 핸들러
ExcelReaderFieldException.class,
// 엑셀 업로드 파일 에러 핸들러
ExcelReaderFileException.class,
// 엑셀 업로드 파일 확장자 에러 핸들러
ExcelReaderFileExtentionException.class,
// 엑셀 업로드 시 캐치 하지 못한 그외 에러
ExcelReaderException.class,
})
public CommonResult<?> CommonErrorException(Exception e, HttpServletRequest request, WebRequest webRequest) throws Exception {
// 공통에러상수 객체 셋팅
CommonError error = CommonError.getCommonError(e);
String ERROR_MSG = error.isException() && StringUtils.isNotEmpty(e.getMessage()) ? error.getMessage()+e.getMessage() : error.getMessage();
errorMap = ErrorUtils.setErrorMap(request, webRequest, secretKey); // 에러 맵 기본 셋팅
CommonResult<?> commonResult = null;
String CUSTOM_MSG = null; //커스텀 Exception Message
/* Exception 별 커스텀 처리 */
switch (error) {
case MaxUploadSizeExceededException: // 최대 파일 용량 초과 에러
long permittedSize=0L; //제한용량
long actualSize=0L; //요청 파일용량
MaxUploadSizeExceededException me = (MaxUploadSizeExceededException) e;
Throwable cause = me.getCause();
if(cause instanceof SizeLimitExceededException) {
SizeLimitExceededException sizeLimit = (SizeLimitExceededException) cause;
permittedSize = sizeLimit.getPermittedSize() != 0L ? sizeLimit.getPermittedSize()/1024/1024 : 0L;
actualSize = sizeLimit.getActualSize() != 0L ? sizeLimit.getActualSize()/1024/1024 : 0L;
CUSTOM_MSG = "최대 업로드 파일용량 제한초과 :: 제한용량 = "+permittedSize+"MB, 요청 파일용량 = "+actualSize+"MB";
}
ERROR_MSG += "최대 "+permittedSize+"MB까지 등록할 수 있습니다: 요청 파일용량 = "+actualSize+"MB";
break;
case BindException: // Parameter Validation Error
ERROR_MSG = getBindResultFieldErrorMessage(((BindException) e).getBindingResult());
break;
case MethodArgumentNotValidException: // Parameter Validation Error
ERROR_MSG = getBindResultFieldErrorMessage(((MethodArgumentNotValidException) e).getBindingResult());
break;
case ExcelReaderFieldException: // 엑셀 업로드 필드 에러 핸들러
commonResult = new CommonResult<>(error.getResCode(), ERROR_MSG, ExcelReader.errorFieldList);
errorMap.put("CommonResult", commonResult);
break;
}
if(Objects.isNull(commonResult))
commonResult = new CommonResult<>(error.getResCode(), ERROR_MSG, errorMap);
// Level 별 에러메시지 출력
ErrorUtils.logWriter(error, CLASS_NAME, ERROR_MSG, errorMap, e, CUSTOM_MSG);
return commonResult;
}
/**
* Handler 에서 예외처리 되지 않은 Exception 처리
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public CommonResult<Map<String, Object>> allException(Exception e, HttpServletRequest request, WebRequest webRequest) throws Exception {
String ERROR_MSG = e.getMessage();
errorMap = ErrorUtils.setErrorMap(request, webRequest, secretKey); // 에러 맵 기본 셋팅
ErrorUtils.errorWriter(CLASS_NAME, ERROR_MSG, errorMap, e); //에러메세지 출력
return new CommonResult<>(ERROR, ERROR_MSG, errorMap);
}
/**
* BindException Field 메세지 가공
* @param bindingResult
* @return
*/
protected String getBindResultFieldErrorMessage(BindingResult bindingResult) {
Map<String, Object> resultMap = new LinkedHashMap<>();
resultMap.put("title","Parameter Validation Error");
List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
List<Map<String, Object>> paramList = new ArrayList<>();
for (FieldError fieldError: fieldErrorList){
Map<String, Object> resultParam = new LinkedHashMap<>();
resultParam.put(fieldError.getField(),fieldError.getRejectedValue());
resultParam.put("message",fieldError.getDefaultMessage());
paramList.add(resultParam);
/*
log.debug("## ERROR getField = {}", fieldError.getField());
log.debug("## ERROR getRejectedValue = {}", fieldError.getRejectedValue());
log.debug("## ERROR getArguments = {}", fieldError.getArguments());
log.debug("## ERROR getCode = {}", fieldError.getCode());
log.debug("## ERROR getCodes = {}", fieldError.getCodes());
log.debug("## ERROR getObjectName = {}", fieldError.getObjectName());
log.debug("## ERROR getDefaultMessage = {}", fieldError.getDefaultMessage());
*/
}
resultMap.put("fields",paramList);
return JsonUtils.toMapperPrettyJson(resultMap);
}
}
728x90
'프로젝트' 카테고리의 다른 글
[SpringBoot jooq] profile별 generate 설정 (0) | 2020.06.20 |
---|---|
[SpringBoot 예외처리] 커스텀 Exception 처리 (0) | 2020.06.20 |
[SpringBoot 예외처리] @ExceptionHandler 설정 (0) | 2020.06.20 |
[SpringBoot 예외처리] Exception 전략 (0) | 2020.06.20 |
[SpringBoot 설정]DB Connection 제외 설정 (0) | 2020.06.20 |
댓글