package com.common.demo.module.response;
import com.common.demo.module.status.StatusCode;
import lombok.Getter;
import org.springframework.http.ResponseEntity;
import java.time.LocalDateTime;
@Getter
public class ResponseDto {
private final Object data;
private final String message;
private final LocalDateTime timestamp = LocalDateTime.now();
private final int httpStatus;
private final int serviceStatus;
public ResponseDto(StatusCode statusCode, Object data) {
this.httpStatus = statusCode.getHttpStatus().value();
this.serviceStatus = statusCode.getServiceStatus();
this.message = statusCode.getMessage();
this.data = data;
}
public static ResponseEntity<ResponseDto> response(StatusCode statusCode, Object data) {
return ResponseEntity
.status(statusCode.getHttpStatus())
.body(new ResponseDto(statusCode, data));
}
}
<aside> 💡
응답 형식 클래스
</aside>
package com.common.demo.module.status;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
@Getter
@RequiredArgsConstructor
public enum StatusCode {
SUCCESS(HttpStatus.OK, 200, "정상적으로 요청이 완료되었습니다."),
BAD_REQUEST(HttpStatus.BAD_REQUEST, 400, "잘못된 요청입니다."),
NO_SUCH_ELEMENT(HttpStatus.OK,401,"정상적으로 요청이 완료되었지만, 요청 정보를 찾을 수 없습니다."),
UNAUTHORIZED_REQUEST(HttpStatus.BAD_REQUEST, 402, "로그인되지 않은 사용자입니다."),
FORBIDDEN_ACCESS(HttpStatus.BAD_REQUEST, 403, "권한이 없는 사용자입니다."),
NOT_FOUND(HttpStatus.NOT_FOUND, 404, "요청 정보를 찾을 수 없습니다."),
DUPLICATE_EMAIL(HttpStatus.BAD_REQUEST, 405, "중복된 이메일 입니다."),
DUPLICATE_ID(HttpStatus.BAD_REQUEST, 406, "중복된 아이디 입니다."),
INVALID_ID_OR_PASSWORD(HttpStatus.BAD_REQUEST, 407, "아이디/비밀번호가 일치하지 않습니다."),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 500, "서버에서 처리 중 에러가 발생했습니다."),
SERVICE_STOP(HttpStatus.INTERNAL_SERVER_ERROR, 501, "현재 서버가 이용 불가능 상태입니다.");
private final HttpStatus httpStatus;
private final int serviceStatus;
private final String message;
}
<aside> 💡
상태 코드 명명
</aside>
package com.common.demo.module.exception;
import com.common.demo.module.status.StatusCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
public class RestApiException extends RuntimeException {
private final StatusCode statusCode;
private final Object data;
public RestApiException(final StatusCode statusCode, final Object data) {
this.statusCode = statusCode;
this.data = data;
}
public RestApiException(final StatusCode statusCode) {
this(statusCode, null);
}
}
package com.common.demo.module.exception;
import com.common.demo.module.response.ResponseDto;
import com.common.demo.module.status.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
/**
* @ExceptionHandler(감지 할 예외)
* INTERNAL_SERVER_ERROR 예외의 상태 코드와 메시지를 ResponseEntity<ResponseDto> 만들어준다.
* return handleExceptionInternal(ErrorCode.INTERNAL_SERVER_ERROR);
*/
@ExceptionHandler({Exception.class})
public ResponseEntity<ResponseDto> handleAllException(Exception ex) {
log.error("[exceptionHandle] ex", ex);
return handleExceptionInternal(StatusCode.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(RestApiException.class)
public ResponseEntity<ResponseDto> handleRestApiException(RestApiException ex) {
return handleExceptionInternal(ex.getStatusCode());
}
private ResponseEntity<ResponseDto> handleExceptionInternal(StatusCode errorCode) {
return ResponseEntity
.status(errorCode.getHttpStatus())
.body(new ResponseDto(errorCode,null));
}
}
package com.common.demo.module;
import com.common.demo.module.exception.RestApiException;
import com.common.demo.module.response.ResponseDto;
import com.common.demo.module.status.StatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/exception")
public class ExceptionTestController {
// 정상 처리 시
@GetMapping("/ok")
public ResponseEntity<ResponseDto> ok(){
String data = "전송할 아무 객체";
return ResponseDto.response(StatusCode.SUCCESS, data);
}
// 로그인 안된 경우 예시
@GetMapping("/login")
public ResponseEntity<ResponseDto> login(){
String data = "전송할 아무 객체";
return ResponseDto.response(StatusCode.INVALID_ID_OR_PASSWORD, data);
}
// 예외 발생 예시
@GetMapping("/error")
public ResponseEntity<ResponseDto> error(){
throw new RestApiException(StatusCode.INTERNAL_SERVER_ERROR);
}
}