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 : 전역적 예외처리 로직 생성 및 Success,ErrorResponse 리팩토링 #14

Merged
merged 18 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
e2a73d7
fix : rank 컬럼명이 mysql 예약어와 겹쳐, 임시로 ranking으로 수정 (CC-114)
j2noo Aug 3, 2024
d6c48dd
chore : jpa create option : update로 수정 (CC-114)
j2noo Aug 3, 2024
a8ec73b
feat : Http요청에 관한 응답 정보가 담긴 baseCode, SuccessCode, ErrorCode 생성(CC-114)
j2noo Aug 3, 2024
204f776
feat : Http요청에 관한 응답 본문에 담을 객체 생성(CC-114)
j2noo Aug 3, 2024
64dee34
feat : 전역 예외 처리 및 핸들링 로직 생성
j2noo Aug 3, 2024
0f8efe0
refactor : health check api에서 SuccessResponse를 사용하도록 수정
j2noo Aug 3, 2024
4fac3cb
feat : RacingGame 도메인에서 발생하는 에러만을 처리하는 로직 생성
j2noo Aug 3, 2024
e44a48e
feat : racingGame 도메인 아키텍처 유지를 위한 .gitkeep 생성
j2noo Aug 3, 2024
a14f138
feat : racingGame 도메인 아키텍처 유지를 위한 .gitkeep 생성
j2noo Aug 3, 2024
0ad61e9
feat : 엔티티 createAt, updateAt 어노테이션 추가
j2noo Aug 3, 2024
d177aae
refactor : @Controller 대신 @RestController를 사용
j2noo Aug 4, 2024
b9346c4
format : 코드 포매팅 통일
j2noo Aug 5, 2024
2010b62
test : 테스트코드 작성 연습을 위한 health check api 테스트 및 S3 통합테스트 코드 작성 (CC-111)…
j2noo Aug 5, 2024
c0a0e59
refactor : health check api에서 SuccessResponse를 사용하도록 수정
j2noo Aug 3, 2024
8bcb2b8
refactor : @Controller 대신 @RestController를 사용
j2noo Aug 4, 2024
c989f14
format : 코드 포매팅 통일
j2noo Aug 5, 2024
85c198e
fix : S3 컨트롤러에 존재하는 헬스체크 api 제거
j2noo Aug 5, 2024
888cbdd
rename : S3컨트롤러 디렉터리 수정
j2noo Aug 5, 2024
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
6 changes: 3 additions & 3 deletions src/main/java/ai/softeer/caecae/CaecaeApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
@SpringBootApplication
public class CaecaeApplication {

public static void main(String[] args) {
SpringApplication.run(CaecaeApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(CaecaeApplication.class, args);
}

}
11 changes: 5 additions & 6 deletions src/main/java/ai/softeer/caecae/admin/api/S3Controller.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package ai.softeer.caecae.admin.api;
package ai.softeer.caecae;

import ai.softeer.caecae.global.dto.response.SuccessResponse;
import ai.softeer.caecae.global.utils.S3Service;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -14,11 +12,12 @@
public class S3Controller {
private final S3Service s3Service;

//TODO : admin 도메인의 정답 정보 등록 컨트롤러로 종속시키기
@PostMapping("/api/s3")
public ResponseEntity<SuccessResponse<String>> upload(@RequestParam("file") MultipartFile file) {
public String upload(@RequestParam("file") MultipartFile file) {
String filePath = s3Service.uploadFile(file);
return ResponseEntity.ok(new SuccessResponse<>(filePath));
return filePath + "created!";
//TODO : ResponseEntity 생성하기

}

}
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package ai.softeer.caecae.global.controller;

import ai.softeer.caecae.global.dto.response.SuccessResponse;
import ai.softeer.caecae.global.enums.SuccessCode;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
@RequestMapping("/api/health")
@RestController
public class HealthTestController {
@GetMapping("")
@GetMapping("/api/health")
public ResponseEntity<SuccessResponse<String>> healthTest() {
return ResponseEntity.ok(new SuccessResponse<>(1000,"api health test에 성공했습니다.","health test v1"));
return SuccessResponse.of(SuccessCode.OK, "Caecae Spring Server Health Test ~!");
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
* Http 요청에 대한 응답(성공,실패)시 본문에 반환할 객체
*/
@Getter
@AllArgsConstructor
public abstract class BaseResponse {
// 커스텀 응답 코드 종류
// TODO : 커스텀 응답코드 문서화
private int responseCode;
// 응답 정보를 담은 메시지
private String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
package ai.softeer.caecae.global.dto.response;

import ai.softeer.caecae.global.enums.ErrorCode;
import lombok.Getter;
import org.springframework.http.ResponseEntity;

/**
* Http 요청에 대한 실패 응답 본문에 반환할 객체
*/
@Getter
public class ErrorResponse extends BaseResponse{
public ErrorResponse(int responseCode, String message) {
super(responseCode, message);
public class ErrorResponse extends BaseResponse {

private ErrorResponse(ErrorCode errorCode) {
super(errorCode.getResponseCode(), errorCode.getMessage());
}

public static ResponseEntity<ErrorResponse> of(ErrorCode errorCode) {
return ResponseEntity.status(errorCode.getHttpStatus())
.body(new ErrorResponse(errorCode));
}

}
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
package ai.softeer.caecae.global.dto.response;

import lombok.Builder;
import ai.softeer.caecae.global.enums.SuccessCode;
import lombok.Getter;
import org.springframework.http.ResponseEntity;

/**
* Http 요청에 대한 성공 응답 본문에 반환할 객체
*/
@Getter
public class SuccessResponse<T> extends BaseResponse {
// httpResponse 를 통해 넘겨 줄 응답 데이터
private T data;
// 응답 성공 관련 정보

// 응답코드, 메세지, 반환 데이터를 파라미터로 받는 생성자
public SuccessResponse(int responseCode, String message, T data) {
super(responseCode, message);
// 성공 관련 정보, 반환 데이터를 파라미터로 받는 생성자
private SuccessResponse(SuccessCode successCode, T data) {
super(successCode.getResponseCode(), successCode.getMessage());
this.data = data;
}

// 코드 및 메시지를 설정하지 않은 생성자
public SuccessResponse(T data) {
super(0, "요청 성공 기본 메시지 입니다.");
this.data = data;

// 팩토리 메서드 부분
// Controller 에서 사용할 ResponseEntity 를 반환하는 팩토리메서드
public static <T> ResponseEntity<SuccessResponse<T>> of(SuccessCode successCode, T data) {
return ResponseEntity.status(successCode.getHttpStatus())
.body(new SuccessResponse<>(successCode, data));
}


}
14 changes: 13 additions & 1 deletion src/main/java/ai/softeer/caecae/global/entity/BaseEntity.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
package ai.softeer.caecae.global.entity;

import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

//TODO : JPA 의존성 설정 후 Audit, CreatedAt 등 어노테이션 설정
@Getter
@MappedSuperclass // 상속받은 엔티티가 아래 컬럼을 인식할 수 있음
@EntityListeners(AuditingEntityListener.class) // 자동으로 컬럼에 해당 값을 넣어주는 audit 기능
public abstract class BaseEntity {
// 엔티티가 생성된 시간
@CreatedDate
private LocalDateTime createdAt;

// 엔티티가 업데이트된 시간
@LastModifiedDate
private LocalDateTime updatedAt;
}
20 changes: 20 additions & 0 deletions src/main/java/ai/softeer/caecae/global/enums/BaseCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ai.softeer.caecae.global.enums;

import org.springframework.http.HttpStatus;

/**
* Http 요청에 대한 응답과 관련있는 정보
*/
public interface BaseCode {
// 커스텀 응답 코드 종류
int getResponseCode();
// 응답 정보를 담은 메시지
String getMessage();
// HttpStatus
HttpStatus getHttpStatus();


}



35 changes: 35 additions & 0 deletions src/main/java/ai/softeer/caecae/global/enums/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ai.softeer.caecae.global.enums;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

/**
* Http 요청에 대한 에러 응답과 관련있는 정보
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public enum ErrorCode implements BaseCode {
//TODO : 코드 문서화
/**
* 1000 : 틀린그림찾기
*/
NOT_FOUND(1000, "잘못된 요청입니다.", HttpStatus.NOT_FOUND),

/**
* 2xxx : 레이싱게임 ..
*/
NEED_AUTHENICATE(1000, "권한이 필요한 요청입니다,", HttpStatus.UNAUTHORIZED),


/**
* 9xxx : 기타 에러
*/
INTERNAL_SERVER_ERROR(-1, "서버 내부 오류입니다.", HttpStatus.INTERNAL_SERVER_ERROR);

private final int responseCode;
private final String message;
private final HttpStatus httpStatus;

}
32 changes: 32 additions & 0 deletions src/main/java/ai/softeer/caecae/global/enums/SuccessCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package ai.softeer.caecae.global.enums;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

/**
* Http 요청에 대한 성공 응답과 관련있는 정보
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public enum SuccessCode implements BaseCode {
//TODO : 코드 문서화
/**
* 1000 : 틀린그림찾기
*/
OK(1000, "요청이 성공했습니다.", HttpStatus.OK),

/**
* 2xxx : 레이싱게임 ..
*/
CREATED(1001, "생성 요청이 성공했습니다.", HttpStatus.CREATED),
USER_CREATED(1001, "유저 회원가입이 성공했습니다.", HttpStatus.CREATED),
TEAM_CREATED(1001, "팀 등록에 성공했습니다.", HttpStatus.CREATED);

Copy link
Collaborator

Choose a reason for hiding this comment

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

,와 "사이에 공백 넣어주세요

private final int responseCode;
private final String message;
private final HttpStatus httpStatus;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ai.softeer.caecae.global.exception;

import ai.softeer.caecae.global.enums.ErrorCode;
import lombok.Getter;

@Getter
public class GlobalException extends RuntimeException {
private final ErrorCode errorCode;

public GlobalException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;


Copy link
Collaborator

Choose a reason for hiding this comment

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

불필요한 라인은 제거해주세요.

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ai.softeer.caecae.global.exception;

import ai.softeer.caecae.global.dto.response.ErrorResponse;
import ai.softeer.caecae.global.enums.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
* 전역 에러를 핸들링하여 HttpResponse 를 반환하는 핸들러
*/
@Slf4j
public class GlobalExceptionHandler {
// GlobalException 에 대한 에러 핸들링
@ExceptionHandler(value = GlobalException.class)
public ResponseEntity<ErrorResponse> handleGlobalException(GlobalException globalException) {
log.error(globalException.getMessage(), globalException);
return ErrorResponse.of(globalException.getErrorCode());
}

// 그 외 발생한 에러 핸들링
@ExceptionHandler(value = Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception exception) {
log.error(exception.getMessage(), exception);
return ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR);
}
}
10 changes: 5 additions & 5 deletions src/main/java/ai/softeer/caecae/global/utils/S3Service.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ai.softeer.caecae.global.utils;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import lombok.RequiredArgsConstructor;
Expand All @@ -10,9 +9,9 @@
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException; // 추가
import java.io.InputStream; // 추가
import java.util.UUID; // 추가
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

@Slf4j
@Service
Expand All @@ -26,6 +25,7 @@ public class S3Service {

/**
* S3에 파일을 업로드 하는 서비스 로직
*
* @param file
* @return 파일 이름
*/
Expand All @@ -40,7 +40,7 @@ public String uploadFile(MultipartFile file) {
try (InputStream inputStream = file.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata));
// 올린 오브젝트에 대한 s3 url
filePath = amazonS3.getUrl(bucket, fileName).toString();
filePath = amazonS3.getUrl(bucket, fileName).toString();
} catch (IOException e) {
throw new IllegalArgumentException("파일이 없습니다.");
//TODO : 커스텀 에러 관리하기
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ public class RacingGameWinner extends BaseEntity {
private User user;

@Column(nullable = false)
private int rank;
private int ranking;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ai.softeer.caecae.racinggame.domain.exception;

import ai.softeer.caecae.global.enums.ErrorCode;
import lombok.Getter;

@Getter
public class RacingGameException extends RuntimeException {
private final ErrorCode errorCode;

public RacingGameException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;


Copy link
Collaborator

Choose a reason for hiding this comment

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

불필요한 라인은 제거해주세요.

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ai.softeer.caecae.racinggame.domain.exception;

import ai.softeer.caecae.global.dto.response.ErrorResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
* RacingGame 도메인에서 에러를 핸들링하여 HttpResponse 를 반환하는 핸들러
*/
@Slf4j
public class RacingGameExceptionHandler {
// RacingGameException 에 대한 에러 핸들링
@ExceptionHandler(value = RacingGameException.class)
public ResponseEntity<ErrorResponse> handleRacingGameException(RacingGameException globalException) {
log.error(globalException.getMessage(), globalException);
return ErrorResponse.of(globalException.getErrorCode());
}
}
Empty file.
Empty file.
2 changes: 1 addition & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ spring:

jpa:
hibernate:
ddl-auto: create
ddl-auto: update
properties:
hibernate:
show_sql: true
Expand Down
Loading
Loading