From d7c17cdfa617df8deb24e05c4aa3ac181c4eacf8 Mon Sep 17 00:00:00 2001 From: dongHyo Date: Thu, 23 Jun 2022 15:26:34 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20Exception=20Handler=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handle/AlreadyDeletedHandler.java | 22 ++++++++ .../CustomMethodArgumentNotValidHandler.java | 50 +++++++++++++++++++ .../handle/EmailNotFoundHandler.java | 22 ++++++++ .../handle/PasswordMismatchHandler.java | 25 ++++++++++ .../exception/handle/RuntimeHandler.java | 22 ++++++++ .../handle/dto/ErrorResponseDTO.java | 24 +++++++++ .../server/user/service/UserServiceImpl.java | 2 +- .../main/resources/i18n/messages.properties | 20 ++++---- .../resources/i18n/messages_en.properties | 20 ++++---- .../resources/i18n/messages_ko.properties | 20 ++++---- 10 files changed, 196 insertions(+), 31 deletions(-) create mode 100644 server/src/main/java/com/ticketing/server/global/exception/handle/AlreadyDeletedHandler.java create mode 100644 server/src/main/java/com/ticketing/server/global/exception/handle/CustomMethodArgumentNotValidHandler.java create mode 100644 server/src/main/java/com/ticketing/server/global/exception/handle/EmailNotFoundHandler.java create mode 100644 server/src/main/java/com/ticketing/server/global/exception/handle/PasswordMismatchHandler.java create mode 100644 server/src/main/java/com/ticketing/server/global/exception/handle/RuntimeHandler.java create mode 100644 server/src/main/java/com/ticketing/server/global/exception/handle/dto/ErrorResponseDTO.java diff --git a/server/src/main/java/com/ticketing/server/global/exception/handle/AlreadyDeletedHandler.java b/server/src/main/java/com/ticketing/server/global/exception/handle/AlreadyDeletedHandler.java new file mode 100644 index 0000000..4f7ad71 --- /dev/null +++ b/server/src/main/java/com/ticketing/server/global/exception/handle/AlreadyDeletedHandler.java @@ -0,0 +1,22 @@ +package com.ticketing.server.global.exception.handle; + +import com.ticketing.server.global.exception.AlreadyDeletedException; +import com.ticketing.server.global.exception.handle.dto.ErrorResponseDTO; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class AlreadyDeletedHandler { + + @ExceptionHandler(value = AlreadyDeletedException.class) + protected ResponseEntity handleException(AlreadyDeletedException e) { + ErrorResponseDTO errorDTO = ErrorResponseDTO.of(e.getClass().getSimpleName(), List.of(e.getMessage())); + return ResponseEntity.status(HttpStatus.CONFLICT).body(errorDTO); + } + +} diff --git a/server/src/main/java/com/ticketing/server/global/exception/handle/CustomMethodArgumentNotValidHandler.java b/server/src/main/java/com/ticketing/server/global/exception/handle/CustomMethodArgumentNotValidHandler.java new file mode 100644 index 0000000..fc31f02 --- /dev/null +++ b/server/src/main/java/com/ticketing/server/global/exception/handle/CustomMethodArgumentNotValidHandler.java @@ -0,0 +1,50 @@ +package com.ticketing.server.global.exception.handle; + +import com.ticketing.server.global.exception.handle.dto.ErrorResponseDTO; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class CustomMethodArgumentNotValidHandler { + + @ExceptionHandler(value = MethodArgumentNotValidException.class) + protected ResponseEntity handleException(MethodArgumentNotValidException e) { + List allErrors = e.getBindingResult().getAllErrors(); + List messages = getMessages(allErrors.iterator()); + + ErrorResponseDTO result = ErrorResponseDTO.of(e.getClass().getSimpleName(), messages); + return ResponseEntity.badRequest().body(result); + } + + private List getMessages(Iterator errorIterator) { + List messages = new ArrayList<>(); + + while (errorIterator.hasNext()) { + StringBuilder messageBuilder = new StringBuilder(); + ObjectError error = errorIterator.next(); + messageBuilder + .append("['") + .append(((FieldError) error).getField()) // 유효성 검사가 실패한 속성 + .append("' is '") + .append(((FieldError) error).getRejectedValue()) // 유효하지 않은 값 + .append("' :: ") + .append(error.getDefaultMessage()) // 유효성 검사 실패 시 메시지 + .append("]"); + + log.error(messageBuilder.toString()); + messages.add(messageBuilder.toString()); + } + + return messages; + } + +} diff --git a/server/src/main/java/com/ticketing/server/global/exception/handle/EmailNotFoundHandler.java b/server/src/main/java/com/ticketing/server/global/exception/handle/EmailNotFoundHandler.java new file mode 100644 index 0000000..11f09d3 --- /dev/null +++ b/server/src/main/java/com/ticketing/server/global/exception/handle/EmailNotFoundHandler.java @@ -0,0 +1,22 @@ +package com.ticketing.server.global.exception.handle; + +import com.ticketing.server.global.exception.EmailNotFoundException; +import com.ticketing.server.global.exception.handle.dto.ErrorResponseDTO; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class EmailNotFoundHandler { + + @ExceptionHandler(value = EmailNotFoundException.class) + protected ResponseEntity handleException(EmailNotFoundException e) { + ErrorResponseDTO errorDTO = ErrorResponseDTO.of(e.getClass().getSimpleName(), List.of(e.getMessage())); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorDTO); + } + +} diff --git a/server/src/main/java/com/ticketing/server/global/exception/handle/PasswordMismatchHandler.java b/server/src/main/java/com/ticketing/server/global/exception/handle/PasswordMismatchHandler.java new file mode 100644 index 0000000..3519c29 --- /dev/null +++ b/server/src/main/java/com/ticketing/server/global/exception/handle/PasswordMismatchHandler.java @@ -0,0 +1,25 @@ +package com.ticketing.server.global.exception.handle; + +import com.ticketing.server.global.exception.PasswordMismatchException; +import com.ticketing.server.global.exception.handle.dto.ErrorResponseDTO; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class PasswordMismatchHandler { + + private static final String MESSAGE = "패스워드가 일치하지 않습니다"; + + @ExceptionHandler(value = {PasswordMismatchException.class, BadCredentialsException.class}) + protected ResponseEntity handleException(RuntimeException e) { + ErrorResponseDTO errorDTO = ErrorResponseDTO.of(e.getClass().getSimpleName(), List.of(MESSAGE)); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorDTO); + } + +} diff --git a/server/src/main/java/com/ticketing/server/global/exception/handle/RuntimeHandler.java b/server/src/main/java/com/ticketing/server/global/exception/handle/RuntimeHandler.java new file mode 100644 index 0000000..e74aed2 --- /dev/null +++ b/server/src/main/java/com/ticketing/server/global/exception/handle/RuntimeHandler.java @@ -0,0 +1,22 @@ +package com.ticketing.server.global.exception.handle; + +import com.ticketing.server.global.exception.handle.dto.ErrorResponseDTO; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.annotation.Order; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +@Order +public class RuntimeHandler { + + @ExceptionHandler(value = RuntimeException.class) + protected ResponseEntity handleException(RuntimeException e) { + ErrorResponseDTO errorDTO = ErrorResponseDTO.of(e.getClass().getSimpleName(), List.of(e.getMessage())); + return ResponseEntity.badRequest().body(errorDTO); + } + +} diff --git a/server/src/main/java/com/ticketing/server/global/exception/handle/dto/ErrorResponseDTO.java b/server/src/main/java/com/ticketing/server/global/exception/handle/dto/ErrorResponseDTO.java new file mode 100644 index 0000000..764d653 --- /dev/null +++ b/server/src/main/java/com/ticketing/server/global/exception/handle/dto/ErrorResponseDTO.java @@ -0,0 +1,24 @@ +package com.ticketing.server.global.exception.handle.dto; + +import java.util.List; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ErrorResponseDTO { + + private String code; + private List messages; + + private ErrorResponseDTO(String code, List messages) { + this.code = code; + this.messages = messages; + } + + public static ErrorResponseDTO of(String code, List messages) { + return new ErrorResponseDTO(code, messages); + } + +} diff --git a/server/src/main/java/com/ticketing/server/user/service/UserServiceImpl.java b/server/src/main/java/com/ticketing/server/user/service/UserServiceImpl.java index d507cbb..388591e 100644 --- a/server/src/main/java/com/ticketing/server/user/service/UserServiceImpl.java +++ b/server/src/main/java/com/ticketing/server/user/service/UserServiceImpl.java @@ -29,7 +29,7 @@ public class UserServiceImpl implements UserService { public User register(@Valid SignUpDTO signUpDto) { Optional user = userRepository.findByEmail(signUpDto.getEmail()); if (user.isPresent()) { - log.error("이미 존재하는 이메일이기 때문에 신규 회원가입을 진행할 수 없습니다. :: {}", signUpDto); + log.error("이미 존재하는 이메일이기 때문에 신규 회원가입을 진행할 수 없습니다. :: {}", signUpDto.getEmail()); throw new IllegalArgumentException("이미 존재하는 이메일이기 때문에 신규 회원가입을 진행할 수 없습니다."); } diff --git a/server/src/main/resources/i18n/messages.properties b/server/src/main/resources/i18n/messages.properties index d356a7f..0f011da 100644 --- a/server/src/main/resources/i18n/messages.properties +++ b/server/src/main/resources/i18n/messages.properties @@ -1,10 +1,10 @@ -validation.not.empty.name="\uC774\uB984\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.email="\uC774\uBA54\uC77C\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.password="\uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.oldpassword="\uD604\uC7AC \uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.newpassword="\uBCC0\uACBD\uD560 \uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.grade="\uC0AC\uC6A9\uC790 \uB4F1\uAE09\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.phone="\uD734\uB300\uBC88\uD638\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.email="\uC774\uBA54\uC77C\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4." -validation.phone="\uD734\uB300\uBC88\uD638\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4." -validation.password.not.change="\uB3D9\uC77C\uD55C \uD328\uC2A4\uC6CC\uB4DC\uB85C \uBCC0\uACBD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." +validation.not.empty.name=\uC774\uB984\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.email=\uC774\uBA54\uC77C\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.password=\uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.oldpassword=\uD604\uC7AC \uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.newpassword=\uBCC0\uACBD\uD560 \uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.grade=\uC0AC\uC6A9\uC790 \uB4F1\uAE09\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.phone=\uD734\uB300\uBC88\uD638\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.email=\uC774\uBA54\uC77C\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. +validation.phone=\uD734\uB300\uBC88\uD638\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. +validation.password.not.change=\uB3D9\uC77C\uD55C \uD328\uC2A4\uC6CC\uB4DC\uB85C \uBCC0\uACBD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. diff --git a/server/src/main/resources/i18n/messages_en.properties b/server/src/main/resources/i18n/messages_en.properties index 6538fff..1972374 100644 --- a/server/src/main/resources/i18n/messages_en.properties +++ b/server/src/main/resources/i18n/messages_en.properties @@ -1,10 +1,10 @@ -validation.not.empty.name="name is required." -validation.not.empty.email="email is required." -validation.not.empty.password="password is required." -validation.not.empty.oldpassword="Old Password is required." -validation.not.empty.newpassword="New Password is required." -validation.not.empty.grade="user grade is required." -validation.not.empty.phone="phone is required." -validation.email="email is not valid." -validation.phone="phone is not valid." -validation.password.not.change="password not change." +validation.not.empty.name=name is required. +validation.not.empty.email=email is required. +validation.not.empty.password=password is required. +validation.not.empty.oldpassword=Old Password is required. +validation.not.empty.newpassword=New Password is required. +validation.not.empty.grade=user grade is required. +validation.not.empty.phone=phone is required. +validation.email=email is not valid. +validation.phone=phone is not valid. +validation.password.not.change=password not change. diff --git a/server/src/main/resources/i18n/messages_ko.properties b/server/src/main/resources/i18n/messages_ko.properties index d356a7f..0f011da 100644 --- a/server/src/main/resources/i18n/messages_ko.properties +++ b/server/src/main/resources/i18n/messages_ko.properties @@ -1,10 +1,10 @@ -validation.not.empty.name="\uC774\uB984\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.email="\uC774\uBA54\uC77C\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.password="\uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.oldpassword="\uD604\uC7AC \uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.newpassword="\uBCC0\uACBD\uD560 \uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.grade="\uC0AC\uC6A9\uC790 \uB4F1\uAE09\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.not.empty.phone="\uD734\uB300\uBC88\uD638\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4." -validation.email="\uC774\uBA54\uC77C\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4." -validation.phone="\uD734\uB300\uBC88\uD638\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4." -validation.password.not.change="\uB3D9\uC77C\uD55C \uD328\uC2A4\uC6CC\uB4DC\uB85C \uBCC0\uACBD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." +validation.not.empty.name=\uC774\uB984\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.email=\uC774\uBA54\uC77C\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.password=\uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.oldpassword=\uD604\uC7AC \uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.newpassword=\uBCC0\uACBD\uD560 \uD328\uC2A4\uC6CC\uB4DC\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.grade=\uC0AC\uC6A9\uC790 \uB4F1\uAE09\uC740 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.not.empty.phone=\uD734\uB300\uBC88\uD638\uB294 \uD544\uC218 \uC785\uB2C8\uB2E4. +validation.email=\uC774\uBA54\uC77C\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. +validation.phone=\uD734\uB300\uBC88\uD638\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. +validation.password.not.change=\uB3D9\uC77C\uD55C \uD328\uC2A4\uC6CC\uB4DC\uB85C \uBCC0\uACBD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.