Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat! : 예외 처리 설정 #68

Merged
merged 5 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/main/java/space/space_spring/exception/CustomException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package space.space_spring.exception;

import lombok.Getter;
import space.space_spring.response.status.ResponseStatus;
@Getter
public class CustomException extends RuntimeException{

private final ResponseStatus exceptionStatus;

public CustomException(ResponseStatus exceptionStatus) {
super(exceptionStatus.getMessage());
this.exceptionStatus = exceptionStatus;
}

public CustomException(ResponseStatus exceptionStatus, String message) {
super(message);
this.exceptionStatus = exceptionStatus;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package space.space_spring.exception;

import lombok.Getter;
import space.space_spring.response.status.ResponseStatus;
@Getter
public class InternalServerErrorException extends RuntimeException{
private final ResponseStatus exceptionStatus;

public InternalServerErrorException(ResponseStatus exceptionStatus) {
super(exceptionStatus.getMessage());
this.exceptionStatus = exceptionStatus;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package space.space_spring.exceptionHandler;

import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import space.space_spring.exception.BadRequestException;
import space.space_spring.exception.InternalServerErrorException;
import space.space_spring.response.BaseErrorResponse;

import static space.space_spring.response.status.BaseExceptionResponseStatus.*;

@Slf4j
@RestControllerAdvice
public class BaseExceptionControllerAdvice {

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({BadRequestException.class, NoHandlerFoundException.class, TypeMismatchException.class})
public BaseErrorResponse handle_BadRequest(Exception e) {
log.error("[handle_BadRequest]", e);
return new BaseErrorResponse(URL_NOT_FOUND);
}

// 위와 동일 (return ResponseEntity<>)
/*
@ExceptionHandler({BadRequestException.class, NoHandlerFoundException.class, TypeMismatchException.class, HttpRequestMethodNotSupportedException.class})
public ResponseEntity<BaseErrorResponse> handle_BadRequest(BadRequestException e) {
log.error("[handle_BadRequest]", e);
return ResponseEntity.badRequest().body(new BaseErrorResponse(e.getExceptionStatus()));
}
*/

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public BaseErrorResponse handle_HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
log.error("[handle_HttpRequestMethodNotSupportedException]", e);
return new BaseErrorResponse(METHOD_NOT_ALLOWED);
}

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public BaseErrorResponse handle_ConstraintViolationException(ConstraintViolationException e) {
log.error("[handle_ConstraintViolationException]", e);
return new BaseErrorResponse(BAD_REQUEST, e.getMessage());
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(InternalServerErrorException.class)
public BaseErrorResponse handle_InternalServerError(InternalServerErrorException e) {
log.error("[handle_InternalServerError]", e);
return new BaseErrorResponse(e.getExceptionStatus());
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(RuntimeException.class)
public BaseErrorResponse handle_RuntimeException(Exception e) {
log.error("[handle_RuntimeException]", e);
return new BaseErrorResponse(SERVER_ERROR);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package space.space_spring.exceptionHandler;

import jakarta.annotation.Priority;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import space.space_spring.exception.CustomException;
import space.space_spring.response.BaseErrorResponse;

@Slf4j
@Priority(0)
@RestControllerAdvice
public class CustomExceptionControllerAdvice {

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(CustomException.class)
public ResponseEntity<BaseErrorResponse> handle_JwtBadRequestException(CustomException e) {
log.error("[handle_JwtBadRequestException]", e);
BaseErrorResponse errorResponse = new BaseErrorResponse(e.getExceptionStatus());
return ResponseEntity.status(e.getExceptionStatus().getStatus()).body(errorResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package space.space_spring.exceptionHandler;

import jakarta.annotation.Priority;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import space.space_spring.exception.jwt.bad_request.JwtBadRequestException;
import space.space_spring.exception.jwt.unauthorized.JwtUnauthorizedTokenException;
import space.space_spring.response.BaseErrorResponse;

@Slf4j
@Priority(0)
@RestControllerAdvice
public class JwtExceptionControllerAdvice {

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(JwtBadRequestException.class)
public BaseErrorResponse handle_JwtBadRequestException(JwtBadRequestException e) {
log.error("[handle_JwtBadRequestException]", e);
return new BaseErrorResponse(e.getExceptionStatus());
}

@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(JwtUnauthorizedTokenException.class)
public BaseErrorResponse handle_JwtUnauthorizedException(JwtUnauthorizedTokenException e) {
log.error("[handle_JwtUnauthorizedException]", e);
return new BaseErrorResponse(e.getExceptionStatus());
}
}
2 changes: 1 addition & 1 deletion src/main/java/space/space_spring/jwt/JwtLoginProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public boolean isExpiredToken(String accessToken) {
} catch (ExpiredJwtException e) {
return true;

} catch (UnsupportedJwtException e) {
}catch (UnsupportedJwtException e) {
throw new JwtUnsupportedTokenException(UNSUPPORTED_TOKEN_TYPE);
} catch (MalformedJwtException e) {
throw new JwtMalformedTokenException(MALFORMED_TOKEN);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import space.space_spring.response.status.ResponseStatus;

import java.time.LocalDateTime;
Expand All @@ -11,7 +12,7 @@
public class BaseErrorResponse implements ResponseStatus {

private final int code;
private final int status;
private final HttpStatus status;
private final String message;
private final LocalDateTime timestamp;

Expand All @@ -35,7 +36,7 @@ public int getCode() {
}

@Override
public int getStatus() {
public HttpStatus getStatus() {
return status;
}

Expand Down
5 changes: 3 additions & 2 deletions src/main/java/space/space_spring/response/BaseResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import space.space_spring.response.status.ResponseStatus;

import static space.space_spring.response.status.BaseExceptionResponseStatus.SUCCESS;
Expand All @@ -12,7 +13,7 @@
public class BaseResponse<T> implements ResponseStatus {

private final int code;
private final int status;
private final HttpStatus status;
private final String message;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int 에서 HttpStatus로 타입을 변경해서 .values() 메서드의 중복사용을 없앨 수 있어 좋아보입니다!

@JsonInclude(JsonInclude.Include.NON_NULL)
Expand All @@ -31,7 +32,7 @@ public int getCode() {
}

@Override
public int getStatus() {
public HttpStatus getStatus() {
return status;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,95 +10,99 @@ public enum BaseExceptionResponseStatus implements ResponseStatus {
/**
* 1000: 요청 성공 (OK)
*/
SUCCESS(1000, HttpStatus.OK.value(), "요청에 성공하였습니다."),
SUCCESS(1000, HttpStatus.OK, "요청에 성공하였습니다."),

/**
* 2000: Request 오류 (BAD_REQUEST)
*/
BAD_REQUEST(2000, HttpStatus.BAD_REQUEST.value(), "유효하지 않은 요청입니다."),
URL_NOT_FOUND(2001, HttpStatus.BAD_REQUEST.value(), "유효하지 않은 URL 입니다."),
METHOD_NOT_ALLOWED(2002, HttpStatus.METHOD_NOT_ALLOWED.value(), "해당 URL에서는 지원하지 않는 HTTP Method 입니다."),
BAD_REQUEST(2000, HttpStatus.BAD_REQUEST, "유효하지 않은 요청입니다."),
URL_NOT_FOUND(2001, HttpStatus.BAD_REQUEST, "유효하지 않은 URL 입니다."),
METHOD_NOT_ALLOWED(2002, HttpStatus.METHOD_NOT_ALLOWED, "해당 URL에서는 지원하지 않는 HTTP Method 입니다."),

/**
* 3000: Server, Database 오류 (INTERNAL_SERVER_ERROR)
*/
SERVER_ERROR(3000, HttpStatus.INTERNAL_SERVER_ERROR.value(), "서버에서 오류가 발생하였습니다."),
DATABASE_ERROR(3001, HttpStatus.INTERNAL_SERVER_ERROR.value(), "데이터베이스에서 오류가 발생하였습니다."),
BAD_SQL_GRAMMAR(3002, HttpStatus.INTERNAL_SERVER_ERROR.value(), "SQL에 오류가 있습니다."),
SERVER_ERROR(3000, HttpStatus.INTERNAL_SERVER_ERROR, "서버에서 오류가 발생하였습니다."),
DATABASE_ERROR(3001, HttpStatus.INTERNAL_SERVER_ERROR, "데이터베이스에서 오류가 발생하였습니다."),
BAD_SQL_GRAMMAR(3002, HttpStatus.INTERNAL_SERVER_ERROR, "SQL에 오류가 있습니다."),

/**
* 4000: Authorization 오류
*/
JWT_ERROR(4000, HttpStatus.UNAUTHORIZED.value(), "JWT에서 오류가 발생하였습니다."),
TOKEN_NOT_FOUND(4001, HttpStatus.BAD_REQUEST.value(), "토큰이 HTTP Header에 없습니다."),
UNSUPPORTED_TOKEN_TYPE(4002, HttpStatus.BAD_REQUEST.value(), "지원되지 않는 토큰 형식입니다."),
INVALID_TOKEN(4003, HttpStatus.UNAUTHORIZED.value(), "유효하지 않은 토큰입니다."),
MALFORMED_TOKEN(4004, HttpStatus.UNAUTHORIZED.value(), "토큰이 올바르게 구성되지 않았습니다."),
EXPIRED_TOKEN(4005, HttpStatus.UNAUTHORIZED.value(), "만료된 토큰입니다."),
TOKEN_MISMATCH(4006, HttpStatus.UNAUTHORIZED.value(), "로그인 정보가 토큰 정보와 일치하지 않습니다."),
JWT_ERROR(4000, HttpStatus.UNAUTHORIZED, "JWT에서 오류가 발생하였습니다."),
TOKEN_NOT_FOUND(4001, HttpStatus.BAD_REQUEST, "토큰이 HTTP Header에 없습니다."),
UNSUPPORTED_TOKEN_TYPE(4002, HttpStatus.BAD_REQUEST, "지원되지 않는 토큰 형식입니다."),
INVALID_TOKEN(4003, HttpStatus.UNAUTHORIZED, "유효하지 않은 토큰입니다."),
MALFORMED_TOKEN(4004, HttpStatus.UNAUTHORIZED, "토큰이 올바르게 구성되지 않았습니다."),
EXPIRED_TOKEN(4005, HttpStatus.UNAUTHORIZED, "만료된 토큰입니다."),
TOKEN_MISMATCH(4006, HttpStatus.UNAUTHORIZED, "로그인 정보가 토큰 정보와 일치하지 않습니다."),

/**
* 5000: User 오류
*/
INVALID_USER_SIGNUP(5000, HttpStatus.BAD_REQUEST.value(), "회원가입 요청에서 잘못된 값이 존재합니다."),
DUPLICATE_EMAIL(5001, HttpStatus.BAD_REQUEST.value(), "이미 존재하는 이메일입니다."),
DUPLICATE_NICKNAME(5002, HttpStatus.BAD_REQUEST.value(), "이미 존재하는 닉네임입니다."),
USER_NOT_FOUND(4003, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 회원입니다."),
PASSWORD_NO_MATCH(4004, HttpStatus.BAD_REQUEST.value(), "비밀번호가 일치하지 않습니다."),
INVALID_USER_STATUS(4005, HttpStatus.BAD_REQUEST.value(), "잘못된 회원 status 값입니다."),
EMAIL_NOT_FOUND(4006, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 이메일입니다."),
INVALID_USER_LOGIN(4007, HttpStatus.BAD_REQUEST.value(), "로그인 요청에서 잘못된 값이 존재합니다."),
INVALID_USER_SIGNUP(5000, HttpStatus.BAD_REQUEST, "회원가입 요청에서 잘못된 값이 존재합니다."),
DUPLICATE_EMAIL(5001, HttpStatus.BAD_REQUEST, "이미 존재하는 이메일입니다."),
DUPLICATE_NICKNAME(5002, HttpStatus.BAD_REQUEST, "이미 존재하는 닉네임입니다."),
USER_NOT_FOUND(4003, HttpStatus.BAD_REQUEST, "존재하지 않는 회원입니다."),
PASSWORD_NO_MATCH(4004, HttpStatus.BAD_REQUEST, "비밀번호가 일치하지 않습니다."),
INVALID_USER_STATUS(4005, HttpStatus.BAD_REQUEST, "잘못된 회원 status 값입니다."),
EMAIL_NOT_FOUND(4006, HttpStatus.BAD_REQUEST, "존재하지 않는 이메일입니다."),
INVALID_USER_LOGIN(4007, HttpStatus.BAD_REQUEST, "로그인 요청에서 잘못된 값이 존재합니다."),


/**
* 6000: Space 오류
*/
INVALID_SPACE_CREATE(6000, HttpStatus.BAD_REQUEST.value(), "스페이스 생성 요청에서 잘못된 값이 존재합니다."),
SPACE_NOT_FOUND(6001, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 스페이스입니다."),
adff(6002, HttpStatus.BAD_REQUEST.value(), "이미 존재하는 닉네임입니다."),
baab(6003, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 회원입니다."),
nff(6004, HttpStatus.BAD_REQUEST.value(), "비밀번호가 일치하지 않습니다."),
gnf(6005, HttpStatus.BAD_REQUEST.value(), "잘못된 회원 status 값입니다."),
fb(6006, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 이메일입니다."),
INVALID_SPACE_CREATE(6000, HttpStatus.BAD_REQUEST, "스페이스 생성 요청에서 잘못된 값이 존재합니다."),
SPACE_NOT_FOUND(6001, HttpStatus.BAD_REQUEST, "존재하지 않는 스페이스입니다."),
adff(6002, HttpStatus.BAD_REQUEST, "이미 존재하는 닉네임입니다."),
baab(6003, HttpStatus.BAD_REQUEST, "존재하지 않는 회원입니다."),
nff(6004, HttpStatus.BAD_REQUEST, "비밀번호가 일치하지 않습니다."),
gnf(6005, HttpStatus.BAD_REQUEST, "잘못된 회원 status 값입니다."),
fb(6006, HttpStatus.BAD_REQUEST, "존재하지 않는 이메일입니다."),


/**
* 7000: UserSpace 오류
*/
USER_IS_NOT_IN_SPACE(7000, HttpStatus.BAD_REQUEST.value(), "해당 스페이스에 속하지 않는 유저입니다."),
UNAUTHORIZED_USER(7001, HttpStatus.UNAUTHORIZED.value(), "해당 스페이스에 관리자 권한이 없는 유저입니다."),
USER_IS_ALREADY_IN_SPACE(7002, HttpStatus.BAD_REQUEST.value(), "해당 스페이스에 이미 가입되어 있는 유저입니다"),
D(7003, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 회원입니다."),
E(7004, HttpStatus.BAD_REQUEST.value(), "비밀번호가 일치하지 않습니다."),
F(7005, HttpStatus.BAD_REQUEST.value(), "잘못된 회원 status 값입니다."),
G(7006, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 이메일입니다."),

USER_IS_NOT_IN_SPACE(7000, HttpStatus.BAD_REQUEST, "해당 스페이스에 속하지 않는 유저입니다."),
UNAUTHORIZED_USER(7001, HttpStatus.UNAUTHORIZED, "해당 스페이스에 관리자 권한이 없는 유저입니다."),
USER_IS_ALREADY_IN_SPACE(7002, HttpStatus.BAD_REQUEST, "해당 스페이스에 이미 가입되어 있는 유저입니다"),
D(7003, HttpStatus.BAD_REQUEST, "존재하지 않는 회원입니다."),
E(7004, HttpStatus.BAD_REQUEST, "비밀번호가 일치하지 않습니다."),
F(7005, HttpStatus.BAD_REQUEST, "잘못된 회원 status 값입니다."),
G(7006, HttpStatus.BAD_REQUEST, "존재하지 않는 이메일입니다."),





/**
* 8000: Chat 오류
*/
INVALID_CHATROOM_CREATE(8000, HttpStatus.BAD_REQUEST.value(), "채팅방 생성 요청에서 잘못된 값이 존재합니다."),
INVALID_CHATROOM_CREATE(8000, HttpStatus.BAD_REQUEST, "채팅방 생성 요청에서 잘못된 값이 존재합니다."),

/**
* 9000 : MultipartFile 오류
*/
IS_NOT_IMAGE_FILE(9000, HttpStatus.BAD_REQUEST.value(), "지원되는 이미지 파일의 형식이 아닙니다."),

IS_NOT_IMAGE_FILE(9000, HttpStatus.BAD_REQUEST, "지원되는 이미지 파일의 형식이 아닙니다."),

/*
* 10000: voice room 오류
*/
VOICEROOM_NOT_EXIST(10001, HttpStatus.BAD_REQUEST.value(),"존재하지 않는 보이스룸 id입니다."),
INVALID_VOICEROOM_REQUEST(10002, HttpStatus.BAD_REQUEST.value(),"잘못된 요청 인자 입니다."),
VOICEROOM_NOT_EXIST(10001, HttpStatus.BAD_REQUEST,"존재하지 않는 보이스룸 id입니다."),
INVALID_VOICEROOM_REQUEST(10002, HttpStatus.BAD_REQUEST,"잘못된 요청 인자 입니다."),

VOICEROOM_NAME_ALREADY_EXIST(10003, HttpStatus.BAD_REQUEST,"이미 존재하는 VoiceRoom 이름 입니다."),
VOICEROOM_NOT_IN_SPACE(10004, HttpStatus.BAD_REQUEST,"이미 존재하는 VoiceRoom 이름 입니다."),
VOICEROOM_DO_NOT_HAVE_PERMISSION(10005,HttpStatus.FORBIDDEN,"해당 작업은 관리자 권한이 필요합니다." );

VOICEROOM_NAME_ALREADY_EXIST(10003, HttpStatus.BAD_REQUEST.value(),"이미 존재하는 VoiceRoom 이름 입니다."),
VOICEROOM_NOT_IN_SPACE(10004, HttpStatus.BAD_REQUEST.value(),"이미 존재하는 VoiceRoom 이름 입니다."),
VOICEROOM_DO_NOT_HAVE_PERMISSION(10005,HttpStatus.FORBIDDEN.value(),"해당 작업은 관리자 권한이 필요합니다." );


private final int code;
private final int status;
private final HttpStatus status;
private final String message;

@Override
Expand All @@ -107,7 +111,7 @@ public int getCode() {
}

@Override
public int getStatus() {
public HttpStatus getStatus() {
return status;
}

Expand All @@ -116,4 +120,5 @@ public String getMessage() {
return message;
}


}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package space.space_spring.response.status;

import org.springframework.http.HttpStatus;

public interface ResponseStatus {


int getCode();

int getStatus();
HttpStatus getStatus();

String getMessage();
}
Loading
Loading