diff --git a/devlog_springboot b/devlog_springboot new file mode 160000 index 0000000..1238b94 --- /dev/null +++ b/devlog_springboot @@ -0,0 +1 @@ +Subproject commit 1238b947e2db605ccec4f0abded208c995c72ce5 diff --git a/src/main/java/com/com/cnu/devlog_springboot/DevlogSpringbootApplication.java b/src/main/java/com/com/cnu/devlog_springboot/DevlogSpringbootApplication.java index 6739bf0..1cd63ab 100644 --- a/src/main/java/com/com/cnu/devlog_springboot/DevlogSpringbootApplication.java +++ b/src/main/java/com/com/cnu/devlog_springboot/DevlogSpringbootApplication.java @@ -6,8 +6,7 @@ @SpringBootApplication public class DevlogSpringbootApplication { - public static void main(String[] args) { - SpringApplication.run(DevlogSpringbootApplication.class, args); + public static void main(String[] args) {SpringApplication.run(DevlogSpringbootApplication.class, args); } } diff --git a/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java b/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java new file mode 100644 index 0000000..21ea0d8 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java @@ -0,0 +1,54 @@ +package com.com.cnu.devlog_springboot.controller; + +import com.com.cnu.devlog_springboot.model.Post; +import com.com.cnu.devlog_springboot.model.request.PostRequest; +import com.com.cnu.devlog_springboot.service.PostService; +import com.com.cnu.devlog_springboot.type.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.lang.Nullable; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/posts") +@RequiredArgsConstructor +public class PostController { + private final PostService postService; + + // GET /posts?tag=JAVA + @GetMapping + public ResponseEntity> getPosts(@RequestParam("tag") @Nullable Tag tag) { + return ResponseEntity.ok(postService.getPosts(tag)); + } + + // GET /posts/{postId} + @GetMapping("{postId}") + public ResponseEntity getPost(@PathVariable("postId") Integer postId) { + return ResponseEntity.ok(postService.getPost(postId)); + } + + // POST /posts + @PostMapping + public ResponseEntity createPost(@RequestBody PostRequest postRequest) { + return ResponseEntity.ok(postService.createPost(postRequest)); + } + + // Put /posts/{postId} + // localhost:8080/posts/3 + @PutMapping("{postId}") + public ResponseEntity updatePost( + @PathVariable("postId") Integer postId, + @RequestBody PostRequest postRequest + ) { + return ResponseEntity.ok(postService.updatePost(postId, postRequest)); + } + + // DELETE //posts/{postId} + @DeleteMapping("{postId}") + public ResponseEntity deletePost(@PathVariable("postId") Integer postId) { + postService.deletePost(postId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/controller/ProjectController.java b/src/main/java/com/com/cnu/devlog_springboot/controller/ProjectController.java new file mode 100644 index 0000000..b4a1643 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/controller/ProjectController.java @@ -0,0 +1,53 @@ +package com.com.cnu.devlog_springboot.controller; + +import com.com.cnu.devlog_springboot.model.Project; +import com.com.cnu.devlog_springboot.model.request.ProjectRequest; +import com.com.cnu.devlog_springboot.service.ProjectService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/project") +@RequiredArgsConstructor +public class ProjectController { + + private final ProjectService projectService; + + @PostMapping + public ResponseEntity createPost(@RequestBody ProjectRequest projectRequest) { + return ResponseEntity.ok(projectService.createProject(projectRequest)); + } + + @GetMapping + public ResponseEntity> getProjects() { + return ResponseEntity.ok(projectService.getProjects()); + } + + @GetMapping("{projectId}") + public ResponseEntity getProject(@PathVariable("projectId") Integer projectId) { + return ResponseEntity.ok(projectService.getProject(projectId)); + } + + @PutMapping("{projectId}") + public ResponseEntity updateProject( + @PathVariable("projectId") Integer projectId, + @RequestBody ProjectRequest projectRequest + ) { + return ResponseEntity.ok(projectService.updateProject(projectId, projectRequest)); + } + + @DeleteMapping("{projectId}") + public ResponseEntity deletePost(@PathVariable("projectId") Integer projectId) { + projectService.deletePost(projectId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/exception/DevlogException.java b/src/main/java/com/com/cnu/devlog_springboot/exception/DevlogException.java new file mode 100644 index 0000000..b86c719 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/exception/DevlogException.java @@ -0,0 +1,11 @@ +package com.com.cnu.devlog_springboot.exception; + +import com.com.cnu.devlog_springboot.type.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class DevlogException extends RuntimeException { + private final ErrorCode errorCode; +} \ No newline at end of file diff --git a/src/main/java/com/com/cnu/devlog_springboot/exception/GlobalExceptionHandler.java b/src/main/java/com/com/cnu/devlog_springboot/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..239c600 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/exception/GlobalExceptionHandler.java @@ -0,0 +1,26 @@ +package com.com.cnu.devlog_springboot.exception; + +import com.com.cnu.devlog_springboot.model.response.ErrorResponse; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(DevlogException.class) + public ResponseEntity handlerDevlogException( + HttpServletRequest request, DevlogException e + ) { + return ResponseEntity.status(e.getErrorCode().getHttpStatus()) + .body( + new ErrorResponse( + e.getErrorCode().getDescription(), + e.getErrorCode().getHttpStatus().value(), + e.getErrorCode().getErrorCode(), + request.getRequestURI() + ) + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/com/cnu/devlog_springboot/model/Post.java b/src/main/java/com/com/cnu/devlog_springboot/model/Post.java new file mode 100644 index 0000000..8c5557f --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/model/Post.java @@ -0,0 +1,22 @@ +package com.com.cnu.devlog_springboot.model; + +import com.com.cnu.devlog_springboot.type.Tag; +import jakarta.persistence.*; +import lombok.*; + +@Getter @Setter +@Entity(name = "posts") +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true) +public class Post { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; + + String title; + + String contents; + + @Enumerated(value = EnumType.STRING) + Tag tag; +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/model/Project.java b/src/main/java/com/com/cnu/devlog_springboot/model/Project.java new file mode 100644 index 0000000..0265737 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/model/Project.java @@ -0,0 +1,25 @@ +package com.com.cnu.devlog_springboot.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.*; + +import java.time.LocalDate; + +@Getter +@Setter +@Entity(name = "projects") +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true) +public class Project { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; + String title; + String summary; + String contents; + LocalDate startDate; + LocalDate endDate; +} \ No newline at end of file diff --git a/src/main/java/com/com/cnu/devlog_springboot/model/request/PostRequest.java b/src/main/java/com/com/cnu/devlog_springboot/model/request/PostRequest.java new file mode 100644 index 0000000..f98f828 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/model/request/PostRequest.java @@ -0,0 +1,10 @@ +package com.com.cnu.devlog_springboot.model.request; + +import com.com.cnu.devlog_springboot.type.Tag; + +public record PostRequest( + String title, + String content, + Tag tag +) { +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/model/request/ProjectRequest.java b/src/main/java/com/com/cnu/devlog_springboot/model/request/ProjectRequest.java new file mode 100644 index 0000000..8716f42 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/model/request/ProjectRequest.java @@ -0,0 +1,12 @@ +package com.com.cnu.devlog_springboot.model.request; + +import java.time.LocalDate; + +public record ProjectRequest( + String title, + String summary, + String contents, + LocalDate startDate, + LocalDate endDate +) { +} \ No newline at end of file diff --git a/src/main/java/com/com/cnu/devlog_springboot/model/response/ErrorResponse.java b/src/main/java/com/com/cnu/devlog_springboot/model/response/ErrorResponse.java new file mode 100644 index 0000000..19f5c3e --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/model/response/ErrorResponse.java @@ -0,0 +1,8 @@ +package com.com.cnu.devlog_springboot.model.response; + +public record ErrorResponse( + String title, + Integer status, + Integer code, + String instance +) {} \ No newline at end of file diff --git a/src/main/java/com/com/cnu/devlog_springboot/repository/PostRepository.java b/src/main/java/com/com/cnu/devlog_springboot/repository/PostRepository.java new file mode 100644 index 0000000..13264f7 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/repository/PostRepository.java @@ -0,0 +1,13 @@ +package com.com.cnu.devlog_springboot.repository; + +import com.com.cnu.devlog_springboot.model.Post; +import com.com.cnu.devlog_springboot.type.Tag; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface PostRepository extends JpaRepository { + List findAllByTag(Tag tag); +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/repository/ProjectRepository.java b/src/main/java/com/com/cnu/devlog_springboot/repository/ProjectRepository.java new file mode 100644 index 0000000..6dd52f7 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/repository/ProjectRepository.java @@ -0,0 +1,6 @@ +package com.com.cnu.devlog_springboot.repository; + +import com.com.cnu.devlog_springboot.model.Project; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProjectRepository extends JpaRepository {} \ No newline at end of file diff --git a/src/main/java/com/com/cnu/devlog_springboot/service/PostService.java b/src/main/java/com/com/cnu/devlog_springboot/service/PostService.java new file mode 100644 index 0000000..64f49a6 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/service/PostService.java @@ -0,0 +1,58 @@ +package com.com.cnu.devlog_springboot.service; + +import com.com.cnu.devlog_springboot.exception.DevlogException; +import com.com.cnu.devlog_springboot.model.Post; +import com.com.cnu.devlog_springboot.model.request.PostRequest; +import com.com.cnu.devlog_springboot.repository.PostRepository; +import com.com.cnu.devlog_springboot.type.ErrorCode; +import com.com.cnu.devlog_springboot.type.Tag; +import jakarta.persistence.criteria.CriteriaBuilder; +import lombok.RequiredArgsConstructor; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Repository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class PostService { + private final PostRepository postRepository; + + public List getPosts(@Nullable Tag tag) { + if (tag != null) { + return postRepository.findAllByTag(tag); + } + return postRepository.findAll(); + } + + public Post createPost(PostRequest postRequest) { + return postRepository.save(new Post( + null, + postRequest.title(), + postRequest.content(), + postRequest.tag() + )); + } + + public Post updatePost(Integer postId, PostRequest postRequest) { + return postRepository.findById(postId) + .map(post -> { + post.setTitle(postRequest.title()); + post.setContents(postRequest.content()); + return postRepository.save(post); + }) + .orElseThrow(() -> new DevlogException(ErrorCode.POST_NOT_FOUND)); + } + + public Post getPost(Integer postId) { + return postRepository.findById(postId) + .orElseThrow(() -> new RuntimeException(String.valueOf(ErrorCode.POST_NOT_FOUND))); + } + + public void deletePost(Integer postId) { + postRepository.findById(postId) +// 같은코드 .ifPresent(post -> postRepository.delete(post)) + .ifPresent(postRepository::delete); + } +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java b/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java new file mode 100644 index 0000000..2a9971b --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java @@ -0,0 +1,56 @@ +package com.com.cnu.devlog_springboot.service; + +import com.com.cnu.devlog_springboot.exception.DevlogException; +import com.com.cnu.devlog_springboot.model.Project; +import com.com.cnu.devlog_springboot.model.request.ProjectRequest; +import com.com.cnu.devlog_springboot.repository.ProjectRepository; +import com.com.cnu.devlog_springboot.type.ErrorCode; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ProjectService { + + private final ProjectRepository projectRepository; + + public Project createProject(ProjectRequest projectRequest) { + return projectRepository.save(new Project( + null, + projectRequest.title(), + projectRequest.summary(), + projectRequest.contents(), + projectRequest.startDate(), + projectRequest.endDate() + )); + } + + public List getProjects() { + return projectRepository.findAll(); + } + + public Project getProject(Integer projectId) { + return projectRepository.findById(projectId) + .orElseThrow(() -> new DevlogException(ErrorCode.PROJECT_NOT_FOUND)); + } + + public Project updateProject(Integer projectId, ProjectRequest projectRequest) { + return projectRepository.findById(projectId) + .map(project -> { + project.setTitle(projectRequest.title()); + project.setContents(projectRequest.contents()); + project.setSummary(projectRequest.summary()); + project.setStartDate(projectRequest.startDate()); + project.setEndDate(projectRequest.endDate()); + return projectRepository.save(project); + }) + .orElseThrow(() -> new DevlogException(ErrorCode.PROJECT_NOT_FOUND)); + + } + + public void deletePost(Integer projectId) { + projectRepository.findById(projectId) + .ifPresent(projectRepository::delete); + } +} \ No newline at end of file diff --git a/src/main/java/com/com/cnu/devlog_springboot/type/ErrorCode.java b/src/main/java/com/com/cnu/devlog_springboot/type/ErrorCode.java new file mode 100644 index 0000000..d9cba9c --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/type/ErrorCode.java @@ -0,0 +1,27 @@ +package com.com.cnu.devlog_springboot.type; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public enum ErrorCode { + POST_NOT_FOUND( + HttpStatus.NOT_FOUND, + 4000, + "해당 게시글을 찾을 수 없습니다."), + + PROJECT_NOT_FOUND( + HttpStatus.NOT_FOUND, + 4001, + "해당 프로젝트를 찾을 수 없습니다."); + + private final HttpStatus httpStatus; + private final Integer errorCode; + private final String description; + + ErrorCode(HttpStatus httpStatus, Integer errorCode, String description) { + this.httpStatus = httpStatus; + this.errorCode = errorCode; + this.description = description; + } +} \ No newline at end of file