diff --git a/src/main/java/ai/softeer/caecae/CaecaeApplication.java b/src/main/java/ai/softeer/caecae/CaecaeApplication.java index 7b05da2..395996f 100644 --- a/src/main/java/ai/softeer/caecae/CaecaeApplication.java +++ b/src/main/java/ai/softeer/caecae/CaecaeApplication.java @@ -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); + } } diff --git a/src/main/java/ai/softeer/caecae/admin/api/S3Controller.java b/src/main/java/ai/softeer/caecae/admin/api/S3Controller.java index 0220b86..4ecb439 100644 --- a/src/main/java/ai/softeer/caecae/admin/api/S3Controller.java +++ b/src/main/java/ai/softeer/caecae/admin/api/S3Controller.java @@ -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; @@ -14,11 +12,12 @@ public class S3Controller { private final S3Service s3Service; - //TODO : admin 도메인의 정답 정보 등록 컨트롤러로 종속시키기 @PostMapping("/api/s3") - public ResponseEntity> 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 생성하기 + } } diff --git a/src/main/java/ai/softeer/caecae/global/controller/HealthTestController.java b/src/main/java/ai/softeer/caecae/global/controller/HealthTestController.java index 07fc29e..6efef7c 100644 --- a/src/main/java/ai/softeer/caecae/global/controller/HealthTestController.java +++ b/src/main/java/ai/softeer/caecae/global/controller/HealthTestController.java @@ -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> healthTest() { - return ResponseEntity.ok(new SuccessResponse<>(1000,"api health test에 성공했습니다.","health test v1")); + return SuccessResponse.of(SuccessCode.OK, "Caecae Spring Server Health Test ~!"); } - } diff --git a/src/main/java/ai/softeer/caecae/global/dto/response/BaseResponse.java b/src/main/java/ai/softeer/caecae/global/dto/response/BaseResponse.java index d9952ef..b63c1fb 100644 --- a/src/main/java/ai/softeer/caecae/global/dto/response/BaseResponse.java +++ b/src/main/java/ai/softeer/caecae/global/dto/response/BaseResponse.java @@ -3,10 +3,14 @@ import lombok.AllArgsConstructor; import lombok.Getter; +/** + * Http 요청에 대한 응답(성공,실패)시 본문에 반환할 객체 + */ @Getter @AllArgsConstructor public abstract class BaseResponse { // 커스텀 응답 코드 종류 + // TODO : 커스텀 응답코드 문서화 private int responseCode; // 응답 정보를 담은 메시지 private String message; diff --git a/src/main/java/ai/softeer/caecae/global/dto/response/ErrorResponse.java b/src/main/java/ai/softeer/caecae/global/dto/response/ErrorResponse.java index 265e29f..0fbc15a 100644 --- a/src/main/java/ai/softeer/caecae/global/dto/response/ErrorResponse.java +++ b/src/main/java/ai/softeer/caecae/global/dto/response/ErrorResponse.java @@ -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 of(ErrorCode errorCode) { + return ResponseEntity.status(errorCode.getHttpStatus()) + .body(new ErrorResponse(errorCode)); } } diff --git a/src/main/java/ai/softeer/caecae/global/dto/response/SuccessResponse.java b/src/main/java/ai/softeer/caecae/global/dto/response/SuccessResponse.java index 24e12bb..8c4c4d7 100644 --- a/src/main/java/ai/softeer/caecae/global/dto/response/SuccessResponse.java +++ b/src/main/java/ai/softeer/caecae/global/dto/response/SuccessResponse.java @@ -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 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 ResponseEntity> of(SuccessCode successCode, T data) { + return ResponseEntity.status(successCode.getHttpStatus()) + .body(new SuccessResponse<>(successCode, data)); } + + } diff --git a/src/main/java/ai/softeer/caecae/global/entity/BaseEntity.java b/src/main/java/ai/softeer/caecae/global/entity/BaseEntity.java index 8f03d91..f5b1631 100644 --- a/src/main/java/ai/softeer/caecae/global/entity/BaseEntity.java +++ b/src/main/java/ai/softeer/caecae/global/entity/BaseEntity.java @@ -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; } diff --git a/src/main/java/ai/softeer/caecae/global/enums/BaseCode.java b/src/main/java/ai/softeer/caecae/global/enums/BaseCode.java new file mode 100644 index 0000000..19549c6 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/global/enums/BaseCode.java @@ -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(); + + +} + + + diff --git a/src/main/java/ai/softeer/caecae/global/enums/ErrorCode.java b/src/main/java/ai/softeer/caecae/global/enums/ErrorCode.java new file mode 100644 index 0000000..6dc6c3d --- /dev/null +++ b/src/main/java/ai/softeer/caecae/global/enums/ErrorCode.java @@ -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; + +} diff --git a/src/main/java/ai/softeer/caecae/global/enums/SuccessCode.java b/src/main/java/ai/softeer/caecae/global/enums/SuccessCode.java new file mode 100644 index 0000000..67684a9 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/global/enums/SuccessCode.java @@ -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); + + private final int responseCode; + private final String message; + private final HttpStatus httpStatus; + + +} diff --git a/src/main/java/ai/softeer/caecae/global/exception/GlobalException.java b/src/main/java/ai/softeer/caecae/global/exception/GlobalException.java new file mode 100644 index 0000000..8df317f --- /dev/null +++ b/src/main/java/ai/softeer/caecae/global/exception/GlobalException.java @@ -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; + + + } + +} diff --git a/src/main/java/ai/softeer/caecae/global/exception/GlobalExceptionHandler.java b/src/main/java/ai/softeer/caecae/global/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..e22e310 --- /dev/null +++ b/src/main/java/ai/softeer/caecae/global/exception/GlobalExceptionHandler.java @@ -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 handleGlobalException(GlobalException globalException) { + log.error(globalException.getMessage(), globalException); + return ErrorResponse.of(globalException.getErrorCode()); + } + + // 그 외 발생한 에러 핸들링 + @ExceptionHandler(value = Exception.class) + public ResponseEntity handleGlobalException(Exception exception) { + log.error(exception.getMessage(), exception); + return ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/ai/softeer/caecae/global/utils/S3Service.java b/src/main/java/ai/softeer/caecae/global/utils/S3Service.java index 7f48e2a..76763c1 100644 --- a/src/main/java/ai/softeer/caecae/global/utils/S3Service.java +++ b/src/main/java/ai/softeer/caecae/global/utils/S3Service.java @@ -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; @@ -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 @@ -26,6 +25,7 @@ public class S3Service { /** * S3에 파일을 업로드 하는 서비스 로직 + * * @param file * @return 파일 이름 */ @@ -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 : 커스텀 에러 관리하기 diff --git a/src/main/java/ai/softeer/caecae/racinggame/api/.gitkeep b/src/main/java/ai/softeer/caecae/racinggame/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ai/softeer/caecae/racinggame/domain/entity/RacingGameWinner.java b/src/main/java/ai/softeer/caecae/racinggame/domain/entity/RacingGameWinner.java index 071828c..01bf940 100644 --- a/src/main/java/ai/softeer/caecae/racinggame/domain/entity/RacingGameWinner.java +++ b/src/main/java/ai/softeer/caecae/racinggame/domain/entity/RacingGameWinner.java @@ -12,5 +12,5 @@ public class RacingGameWinner extends BaseEntity { private User user; @Column(nullable = false) - private int rank; + private int ranking; } diff --git a/src/main/java/ai/softeer/caecae/racinggame/domain/exception/RacingGameException.java b/src/main/java/ai/softeer/caecae/racinggame/domain/exception/RacingGameException.java new file mode 100644 index 0000000..5544f2f --- /dev/null +++ b/src/main/java/ai/softeer/caecae/racinggame/domain/exception/RacingGameException.java @@ -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; + + + } + +} diff --git a/src/main/java/ai/softeer/caecae/racinggame/domain/exception/RacingGameExceptionHandler.java b/src/main/java/ai/softeer/caecae/racinggame/domain/exception/RacingGameExceptionHandler.java new file mode 100644 index 0000000..a0b68bb --- /dev/null +++ b/src/main/java/ai/softeer/caecae/racinggame/domain/exception/RacingGameExceptionHandler.java @@ -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 handleRacingGameException(RacingGameException globalException) { + log.error(globalException.getMessage(), globalException); + return ErrorResponse.of(globalException.getErrorCode()); + } +} diff --git a/src/main/java/ai/softeer/caecae/racinggame/repository/.gitkeep b/src/main/java/ai/softeer/caecae/racinggame/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ai/softeer/caecae/racinggame/service/.gitkeep b/src/main/java/ai/softeer/caecae/racinggame/service/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7327f1e..198a9ac 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,7 +7,7 @@ spring: jpa: hibernate: - ddl-auto: create + ddl-auto: update properties: hibernate: show_sql: true diff --git a/src/test/java/ai/softeer/caecae/CaecaeApplicationTests.java b/src/test/java/ai/softeer/caecae/CaecaeApplicationTests.java new file mode 100644 index 0000000..6de1c3d --- /dev/null +++ b/src/test/java/ai/softeer/caecae/CaecaeApplicationTests.java @@ -0,0 +1,12 @@ +package ai.softeer.caecae; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +class CaecaeApplicationTests { + + @Test + void contextLoads() { + } + +}