From b1904d072b75559bfff270dadd299c37ae4124f7 Mon Sep 17 00:00:00 2001 From: Subin Min Date: Thu, 27 Oct 2022 17:24:11 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Problem - Level : Problem만 단방향으로 연관 가짐 - Problem - ProblemCategory - Category : Problem만 ProblemCategory와 양방향 연관 가짐 (카테고리별 문제 조회 필요할 경우에 Category에 연관 설정할 것) - Problem 연관 객체 Eager로 가져오도록 설정 (논의 필요) --- .../oncoding/concoder/model/Category.java | 17 ++++++++ .../concoder/model/JpaBaseEntity.java | 15 +++++++ .../java/oncoding/concoder/model/Level.java | 17 ++++++++ .../java/oncoding/concoder/model/Problem.java | 41 +++++++++++++++++++ .../concoder/model/ProblemCategory.java | 18 ++++++++ 5 files changed, 108 insertions(+) create mode 100644 src/main/java/oncoding/concoder/model/Category.java create mode 100644 src/main/java/oncoding/concoder/model/JpaBaseEntity.java create mode 100644 src/main/java/oncoding/concoder/model/Level.java create mode 100644 src/main/java/oncoding/concoder/model/Problem.java create mode 100644 src/main/java/oncoding/concoder/model/ProblemCategory.java diff --git a/src/main/java/oncoding/concoder/model/Category.java b/src/main/java/oncoding/concoder/model/Category.java new file mode 100644 index 0000000..b1ad847 --- /dev/null +++ b/src/main/java/oncoding/concoder/model/Category.java @@ -0,0 +1,17 @@ +package oncoding.concoder.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Category extends JpaBaseEntity { + @Column + @NotNull + private String name; +} diff --git a/src/main/java/oncoding/concoder/model/JpaBaseEntity.java b/src/main/java/oncoding/concoder/model/JpaBaseEntity.java new file mode 100644 index 0000000..ab1b6d6 --- /dev/null +++ b/src/main/java/oncoding/concoder/model/JpaBaseEntity.java @@ -0,0 +1,15 @@ +package oncoding.concoder.model; + +import java.util.UUID; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import lombok.Getter; + +@Getter +@MappedSuperclass +public class JpaBaseEntity { + @Id + @GeneratedValue + private UUID id; +} diff --git a/src/main/java/oncoding/concoder/model/Level.java b/src/main/java/oncoding/concoder/model/Level.java new file mode 100644 index 0000000..94cac7f --- /dev/null +++ b/src/main/java/oncoding/concoder/model/Level.java @@ -0,0 +1,17 @@ +package oncoding.concoder.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Level extends JpaBaseEntity { + @Column + @NotNull + private String name; +} diff --git a/src/main/java/oncoding/concoder/model/Problem.java b/src/main/java/oncoding/concoder/model/Problem.java new file mode 100644 index 0000000..e6b02ad --- /dev/null +++ b/src/main/java/oncoding/concoder/model/Problem.java @@ -0,0 +1,41 @@ +package oncoding.concoder.model; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.validation.constraints.NotNull; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Problem extends JpaBaseEntity { + @Column(unique = true) + @NotNull + private Integer number; + + @Column + @NotNull + private String title; + + @Column + private Float rate; + + @Column + @NotNull + private String content; + + @ManyToOne(fetch = FetchType.EAGER) + private Level level; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "problem") + private List categories = new ArrayList<>(); + +} diff --git a/src/main/java/oncoding/concoder/model/ProblemCategory.java b/src/main/java/oncoding/concoder/model/ProblemCategory.java new file mode 100644 index 0000000..38588c5 --- /dev/null +++ b/src/main/java/oncoding/concoder/model/ProblemCategory.java @@ -0,0 +1,18 @@ +package oncoding.concoder.model; + +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class ProblemCategory extends JpaBaseEntity { + @ManyToOne + private Problem problem; + + @ManyToOne + private Category category; +} From 9d4fe17ac860ef945f58b93257f8e80f3612511f Mon Sep 17 00:00:00 2001 From: Subin Min Date: Thu, 27 Oct 2022 17:28:05 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20Repository=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oncoding/concoder/repository/CategoryRepository.java | 9 +++++++++ .../oncoding/concoder/repository/LevelRepository.java | 9 +++++++++ .../concoder/repository/ProblemCategoryRepository.java | 9 +++++++++ .../oncoding/concoder/repository/ProblemRepository.java | 9 +++++++++ 4 files changed, 36 insertions(+) create mode 100644 src/main/java/oncoding/concoder/repository/CategoryRepository.java create mode 100644 src/main/java/oncoding/concoder/repository/LevelRepository.java create mode 100644 src/main/java/oncoding/concoder/repository/ProblemCategoryRepository.java create mode 100644 src/main/java/oncoding/concoder/repository/ProblemRepository.java diff --git a/src/main/java/oncoding/concoder/repository/CategoryRepository.java b/src/main/java/oncoding/concoder/repository/CategoryRepository.java new file mode 100644 index 0000000..d53c55a --- /dev/null +++ b/src/main/java/oncoding/concoder/repository/CategoryRepository.java @@ -0,0 +1,9 @@ +package oncoding.concoder.repository; + +import java.util.UUID; +import oncoding.concoder.model.Category; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CategoryRepository extends JpaRepository { + +} diff --git a/src/main/java/oncoding/concoder/repository/LevelRepository.java b/src/main/java/oncoding/concoder/repository/LevelRepository.java new file mode 100644 index 0000000..dca73e9 --- /dev/null +++ b/src/main/java/oncoding/concoder/repository/LevelRepository.java @@ -0,0 +1,9 @@ +package oncoding.concoder.repository; + +import java.util.UUID; +import oncoding.concoder.model.Level; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface LevelRepository extends JpaRepository { + +} diff --git a/src/main/java/oncoding/concoder/repository/ProblemCategoryRepository.java b/src/main/java/oncoding/concoder/repository/ProblemCategoryRepository.java new file mode 100644 index 0000000..21501fb --- /dev/null +++ b/src/main/java/oncoding/concoder/repository/ProblemCategoryRepository.java @@ -0,0 +1,9 @@ +package oncoding.concoder.repository; + +import java.util.UUID; +import oncoding.concoder.model.ProblemCategory; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProblemCategoryRepository extends JpaRepository { + +} diff --git a/src/main/java/oncoding/concoder/repository/ProblemRepository.java b/src/main/java/oncoding/concoder/repository/ProblemRepository.java new file mode 100644 index 0000000..b8a8fe5 --- /dev/null +++ b/src/main/java/oncoding/concoder/repository/ProblemRepository.java @@ -0,0 +1,9 @@ +package oncoding.concoder.repository; + +import java.util.UUID; +import oncoding.concoder.model.Problem; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProblemRepository extends JpaRepository { + +} From 2b61f1c74da3270db000e2a10586a7e595782c0a Mon Sep 17 00:00:00 2001 From: Subin Min Date: Thu, 27 Oct 2022 17:28:49 +0900 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20=ED=95=84=EC=9A=94=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20gitkeep=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/oncoding/concoder/model/.gitkeep | 0 src/main/java/oncoding/concoder/repository/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/oncoding/concoder/model/.gitkeep delete mode 100644 src/main/java/oncoding/concoder/repository/.gitkeep diff --git a/src/main/java/oncoding/concoder/model/.gitkeep b/src/main/java/oncoding/concoder/model/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/oncoding/concoder/repository/.gitkeep b/src/main/java/oncoding/concoder/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 From a4b4b56884c96232894452862fde905062ec223c Mon Sep 17 00:00:00 2001 From: Jeong <63828202+JeongA-Shin@users.noreply.github.com> Date: Tue, 8 Nov 2022 18:37:24 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[Resolves=20#6]=20redis=20config=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20(#5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore : add config for redis * chore: add config for redis * test: add test for redis * feat: 엔티티 작성 - Problem - Level : Problem만 단방향으로 연관 가짐 - Problem - ProblemCategory - Category : Problem만 ProblemCategory와 양방향 연관 가짐 (카테고리별 문제 조회 필요할 경우에 Category에 연관 설정할 것) - Problem 연관 객체 Eager로 가져오도록 설정 (논의 필요) * feat: Repository 작성 * refactor: 필요 없는 gitkeep 삭제 * feat: 엔티티 작성 https://github.com/KHUCapston-concoder/Backend/issues/1 * refactor : 필요없는 주석 삭제 https://github.com/KHUCapston-concoder/Backend/issues/6 * refactor : 콘솔 확인 삭제 https://github.com/KHUCapston-concoder/Backend/issues/6 Co-authored-by: Subin Min --- build.gradle | 1 + .../concoder/ConcoderApplication.java | 2 + .../oncoding/concoder/config/RedisConfig.java | 62 +++++++++++++ .../oncoding/concoder/model/Snapshot.java | 35 ++++++++ src/main/resources/application.yml | 5 +- .../concoder/config/RedisBasicTest.java | 88 +++++++++++++++++++ .../java/oncoding/concoder/service}/.gitkeep | 0 7 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/main/java/oncoding/concoder/config/RedisConfig.java create mode 100644 src/main/java/oncoding/concoder/model/Snapshot.java create mode 100644 src/test/java/oncoding/concoder/config/RedisBasicTest.java rename src/{main/java/oncoding/concoder/config => test/java/oncoding/concoder/service}/.gitkeep (100%) diff --git a/build.gradle b/build.gradle index 5d3b022..22a714a 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'mysql:mysql-connector-java' diff --git a/src/main/java/oncoding/concoder/ConcoderApplication.java b/src/main/java/oncoding/concoder/ConcoderApplication.java index 82ca4f3..0f57bed 100644 --- a/src/main/java/oncoding/concoder/ConcoderApplication.java +++ b/src/main/java/oncoding/concoder/ConcoderApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing @SpringBootApplication public class ConcoderApplication { diff --git a/src/main/java/oncoding/concoder/config/RedisConfig.java b/src/main/java/oncoding/concoder/config/RedisConfig.java new file mode 100644 index 0000000..2e61430 --- /dev/null +++ b/src/main/java/oncoding/concoder/config/RedisConfig.java @@ -0,0 +1,62 @@ +package oncoding.concoder.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.lettuce.LettuceConnection; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private int port; + + /* + Spring Data Redis는 Redis에 두 가지 접근 방식을 제공합니다. + 하나는 RedisTemplate을 이용한 방식이며, 다른 하나는 RedisRepository를 이용한 방식 + + 두 방식 모두 Redis에 접근하기 위해서는 Redis 저장소와 연결하는 과정이 필요 + 이 과정을 위해 RedisConnectionFactory 인터페이스(LettuceConnectionFactory )를 사용 + * */ + @Bean //redisConnectionFactory 이름의 빈(역할)은 LettuceConnectionFactory(host, port)를 구현체로 선택한 것 + public LettuceConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(host, port); + } + + /* + redisTemplate을 사용하여 Redis 저장소에 접근하기로 한다 + RedisTemplate은 Redis 저장소에 오브젝트를 저장할 때 기본값으로 정의된 JdkSerializationRedisSerializer을 이용 + */ + @Bean + public RedisTemplate redisTemplate(){ + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + return redisTemplate; + } + + /* + 대부분 레디스 key-value 는 문자열 위주이기 때문에 문자열에 특화된 템플릿을 제공 + RedisTemplate 을 상속받은 클래스임. + StringRedisSerializer로 직렬화함 + */ + @Bean + public StringRedisTemplate stringRedisTemplate(){ + final StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(); + stringRedisTemplate.setKeySerializer(new StringRedisSerializer()); + stringRedisTemplate.setValueSerializer(new StringRedisSerializer()); + stringRedisTemplate.setConnectionFactory(redisConnectionFactory()); + return stringRedisTemplate; + } + + + +} diff --git a/src/main/java/oncoding/concoder/model/Snapshot.java b/src/main/java/oncoding/concoder/model/Snapshot.java new file mode 100644 index 0000000..c5d0f7a --- /dev/null +++ b/src/main/java/oncoding/concoder/model/Snapshot.java @@ -0,0 +1,35 @@ +package oncoding.concoder.model; + +import java.time.LocalDateTime; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Entity +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) +public class Snapshot extends JpaBaseEntity { + + @CreatedDate + @Column(updatable=false, nullable = false) + private LocalDateTime createdDate; + + @Column + @NotNull + private String memo; + + @Column + @NotNull + private String content; +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8b13789..d7a5998 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1 +1,4 @@ - +spring: + redis: + host: localhost + port: 6379 diff --git a/src/test/java/oncoding/concoder/config/RedisBasicTest.java b/src/test/java/oncoding/concoder/config/RedisBasicTest.java new file mode 100644 index 0000000..811f31f --- /dev/null +++ b/src/test/java/oncoding/concoder/config/RedisBasicTest.java @@ -0,0 +1,88 @@ +package oncoding.concoder.config; + + +import java.util.concurrent.TimeUnit; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; + +@SpringBootTest +@AutoConfigureTestDatabase(replace = Replace.NONE) +public class RedisBasicTest { + + @Autowired + RedisTemplate redisTemplate; + + + public static class RedisUserDto{ + private String name; + private String password; + + public RedisUserDto(String name, String password){ + this.name = name; + this.password = password; + } + + public RedisUserDto() { + + } + + public String getName(){ + return this.name; + } + + public String getPassword(){ + return this.password; + } + + } + + /** + * 단순 연결 테스트 - key와 value 삽입 + */ + @Test + void redisConnectionTest() { + final String key = "a"; + final String data = "1"; + + final ValueOperations valueOperations = redisTemplate.opsForValue(); + valueOperations.set(key, data); + + final String s = valueOperations.get(key); + Assertions.assertThat(s).isEqualTo(data); + } + + @Test + void redisInsertObject(){ + RedisUserDto redisUserDto = new RedisUserDto("kenux", "password"); + + final ValueOperations valueOperations = redisTemplate.opsForValue(); + valueOperations.set(redisUserDto.getName(), String.valueOf(redisUserDto)); + + final String result = valueOperations.get(redisUserDto.getName()); + + } + + /** + * 위 코드 redis에 삽입한 아이템에 대해서 5초의 expire time을 설정하고, 5초가 지난 후에 redis에서 해당 키가 조회되는지 테스트하는 코드 + * @throws InterruptedException + */ + @Test + void redisExpireTest() throws InterruptedException { + final String key = "a"; + final String data = "1"; + + final ValueOperations valueOperations = redisTemplate.opsForValue(); + valueOperations.set(key, data); + final Boolean expire = redisTemplate.expire(key, 5, TimeUnit.SECONDS); + Thread.sleep(6000); + final String s = valueOperations.get(key); + + } + +} diff --git a/src/main/java/oncoding/concoder/config/.gitkeep b/src/test/java/oncoding/concoder/service/.gitkeep similarity index 100% rename from src/main/java/oncoding/concoder/config/.gitkeep rename to src/test/java/oncoding/concoder/service/.gitkeep From 8b581f7f196b0fe66191d6fb2e1b7755db260205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EC=A0=95=EC=95=84?= Date: Tue, 8 Nov 2022 23:19:19 +0900 Subject: [PATCH 5/5] =?UTF-8?q?feature=20:=20custom=20global=20exception?= =?UTF-8?q?=20handler=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/KHUCapston-concoder/Backend/issues/7 --- .../java/oncoding/concoder/exception/.gitkeep | 0 .../exception/CustomGlobalException.java | 21 +++++++++ .../CustomGlobalExceptionHandler.java | 43 +++++++++++++++++++ .../concoder/exception/ErrorCode.java | 19 ++++++++ .../concoder/exception/ErrorResponse.java | 35 +++++++++++++++ 5 files changed, 118 insertions(+) delete mode 100644 src/main/java/oncoding/concoder/exception/.gitkeep create mode 100644 src/main/java/oncoding/concoder/exception/CustomGlobalException.java create mode 100644 src/main/java/oncoding/concoder/exception/CustomGlobalExceptionHandler.java create mode 100644 src/main/java/oncoding/concoder/exception/ErrorCode.java create mode 100644 src/main/java/oncoding/concoder/exception/ErrorResponse.java diff --git a/src/main/java/oncoding/concoder/exception/.gitkeep b/src/main/java/oncoding/concoder/exception/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/oncoding/concoder/exception/CustomGlobalException.java b/src/main/java/oncoding/concoder/exception/CustomGlobalException.java new file mode 100644 index 0000000..5c7365d --- /dev/null +++ b/src/main/java/oncoding/concoder/exception/CustomGlobalException.java @@ -0,0 +1,21 @@ +package oncoding.concoder.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public class CustomGlobalException extends RuntimeException { + + private final ErrorCode errorCode; + private final String message; + private final HttpStatus status; + + + public CustomGlobalException(ErrorCode errorCode){ + this.errorCode = errorCode; + this.message = errorCode.getMessage(); + this.status = errorCode.getStatus(); + } + + +} diff --git a/src/main/java/oncoding/concoder/exception/CustomGlobalExceptionHandler.java b/src/main/java/oncoding/concoder/exception/CustomGlobalExceptionHandler.java new file mode 100644 index 0000000..ef75eea --- /dev/null +++ b/src/main/java/oncoding/concoder/exception/CustomGlobalExceptionHandler.java @@ -0,0 +1,43 @@ +package oncoding.concoder.exception; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class CustomGlobalExceptionHandler { + + @ExceptionHandler(CustomGlobalException.class) + public ResponseEntity handleCustomException(final CustomGlobalException globalException){ + log.error("Custom Exception!", globalException); + return ResponseEntity.status(globalException.getErrorCode().getStatus().value()) + .body(new ErrorResponse(globalException.getErrorCode())); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + protected ResponseEntity handleHttpRequestMethodNotSupportedException(final HttpRequestMethodNotSupportedException e) { + log.error("Method Not Supported!", e); + return ResponseEntity.status(ErrorCode.INTERNAL_SERVER_ERROR.getStatus().value()) + .body(new ErrorResponse(ErrorCode.METHOD_NOT_ALLOWED)); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + protected ResponseEntity handleNotBlankValid(MethodArgumentNotValidException e){ + log.error("NotValid!", e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST.value()) + .body(new ErrorResponse(e.getFieldError().getDefaultMessage())); + } + + @ExceptionHandler(Exception.class) + protected ResponseEntity handleException(Exception e) { + log.error("Error!", e); + return ResponseEntity.status(ErrorCode.INTERNAL_SERVER_ERROR.getStatus().value()) + .body(new ErrorResponse(ErrorCode.INTERNAL_SERVER_ERROR)); + } + +} diff --git a/src/main/java/oncoding/concoder/exception/ErrorCode.java b/src/main/java/oncoding/concoder/exception/ErrorCode.java new file mode 100644 index 0000000..974f224 --- /dev/null +++ b/src/main/java/oncoding/concoder/exception/ErrorCode.java @@ -0,0 +1,19 @@ +package oncoding.concoder.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum ErrorCode { + + BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."), + POSTS_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 요청의 리소스를 찾을 수 없습니다."), + METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, "허용되지 않은 메서드입니다."), + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "내부 서버 오류입니다."); + + private final HttpStatus status; + private final String message; + +} diff --git a/src/main/java/oncoding/concoder/exception/ErrorResponse.java b/src/main/java/oncoding/concoder/exception/ErrorResponse.java new file mode 100644 index 0000000..8acab0c --- /dev/null +++ b/src/main/java/oncoding/concoder/exception/ErrorResponse.java @@ -0,0 +1,35 @@ +package oncoding.concoder.exception; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class ErrorResponse { + + private int status; + private String error; + private String code; + private String message; + + + @Builder + public ErrorResponse(ErrorCode errorCode){ + this.status = errorCode.getStatus().value(); + this.error= errorCode.getStatus().name(); + this.code = errorCode.name(); + this.message = errorCode.getMessage(); + } + + @Builder + public ErrorResponse(int status, String error, String code, String message) { + this.status = status; + this.error = error; + this.code = code; + this.message = message; + } + + public ErrorResponse(String defaultMessage) { + this.message = defaultMessage; + } + +}