-
Notifications
You must be signed in to change notification settings - Fork 0
(김기현) Todo 일기 작성하기 (Side-Project) 리뷰 부탁드립니다. #2
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
base: kihyun/main
Are you sure you want to change the base?
Changes from 28 commits
6a672c8
daaa823
e280990
18f5af4
1b36daf
89ae461
a57ef58
6bf1340
f3e4dc0
b7db802
7da10b1
3ec64f8
fe7c7d4
058728f
06413cf
54d72c0
970a123
f22869d
14a39fa
bab5a7c
3d82dee
ebef5f8
5f2b58f
60b2f2a
660ea95
b6a633d
91da852
6ab4cb3
ee7e7c7
be2b0e4
8ae4591
2fed5fb
0342a14
700f32e
d9917b3
c89f25c
b4f3ac0
c400005
0f0e229
d16cb02
f31e595
bdccfdd
9847235
23e1bda
4470800
3abb773
bb14106
4783817
cb0b484
e2f77e9
0108538
067294b
98c0374
9f94913
e8f6a51
d5a4661
7be9377
0976e81
ff93cf7
178fd36
59a7c6d
c05180b
b9dc272
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,74 @@ | ||
| # SELAB-TODO | ||
| > basic todo with spring-mvc | ||
| > basic diary with spring-mvc | ||
|
|
||
| [테스트링크](http://localhost:8080/swagger-ui/index.html#/TODO%20API) | ||
|
|
||
| # 요구명세서 | ||
| > 일기 작성 서비스 | ||
|
|
||
| ## 목차 | ||
| 1. 소개 | ||
| 1. 목적 | ||
| 2. 일반적인 기술 사항 | ||
| 1. 제품의 기능 | ||
| 2. 사용자 특성 | ||
| 3. 제약사항 | ||
| 4. 가정 및 의존성 | ||
| 3. 상세기능 요구 사항 | ||
| 1. 기능적 요구 사항 | ||
| 1. 기본적인 CRUD | ||
| 1. 등록 | ||
| 2. 조회 | ||
| 3. 수정 | ||
| 4. 삭제 | ||
|
|
||
| ## 소개 | ||
| ### 1.i 목적 | ||
| 동건이형께 Todo 스터디를 완료했으므로 사이드 프로젝트를 진행하기 위하여 시작함 | ||
| ## 일반적인 기술 사항 | ||
| ### 2. i 제품의 기능 | ||
| 앱은 아래와 같은 기능들을 주요 기능으로 갖는다 | ||
| * 단건 조회 | ||
| * 범위 조회 | ||
| * 전체 조회 | ||
| * 수정 | ||
| * 등록 | ||
| * 삭제 | ||
| * 전체 삭제 | ||
| ### 2.ii 사용자 특정 | ||
| 사용자는 일기를 생성할 수 있어야 한다. 생성은 Json 파일 형식으로 해야 한다 | ||
|
|
||
|
|
||
| 사용자는 일기 조회를 할 수 있어야 한다. 단건 조회는 ID를 입력했을 때 가능하며, 범위 조회는 | ||
| 월(Month)를 입력했을 때 가능해야 한다 | ||
|
|
||
|
|
||
| 사용자는 일기 수정이 가능해야 한다. 수정하는 것은 ID로 수정할 수 있도록 한다. | ||
|
|
||
|
|
||
| 사용자는 일기 삭제가 가능해야 한다. 삭제는 ID를 통해 이루어지도록 한다. | ||
| ### 2.iii 제약사항 | ||
| * spring framework를 사용하여 구현한다 | ||
| * MySQL과 Jpa를 사용하여 데이터베이스와 연결한다 | ||
| * create-drop을 사용하기 때문에 데이터베이스에 데이터베이스 스키마를 만들지 않아도 된다 | ||
|
|
||
| ## 상세기능 요구 사항 | ||
| ### 3.i. 기능적 요구 사항 | ||
| ### 3.i.a 기본적인 CRUD | ||
| ### 3.i.a.a 등록 | ||
| * request : id, 등록 날짜, 제목, 내용, 기분 | ||
| ### 3.i.a.b 조회 | ||
| #### 단건 조회 | ||
| * request : id | ||
| #### 범위 조회 | ||
| * request : Month | ||
| * response : page | ||
| #### 전체 조회 | ||
| * request : none | ||
| * response : page | ||
| ### 3.i.a.c 수정 | ||
| * request : id | ||
| ### 3.i.a.d 삭제 | ||
| * request : none | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package com.selab.todo.common; | ||
|
|
||
| import lombok.Getter; | ||
| import org.springframework.data.annotation.CreatedDate; | ||
| import org.springframework.data.annotation.LastModifiedDate; | ||
| import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
|
|
||
| import javax.persistence.EntityListeners; | ||
| import javax.persistence.MappedSuperclass; | ||
| import java.time.LocalDateTime; | ||
|
|
||
| @Getter | ||
| @MappedSuperclass | ||
| @EntityListeners(AuditingEntityListener.class) | ||
| public abstract class BaseEntity { | ||
| @CreatedDate | ||
| private LocalDateTime createdAt; | ||
|
|
||
| @LastModifiedDate | ||
| private LocalDateTime modifiedAt; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package com.selab.todo.common.dto; | ||
|
|
||
| import lombok.Data; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.data.domain.Page; | ||
| import org.springframework.http.ResponseEntity; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @Data | ||
| @RequiredArgsConstructor | ||
| public class PageDto<T> { | ||
| private final List<T> data; | ||
| private final int page; | ||
| private final int size; | ||
| private final long totalElements; | ||
|
|
||
| public static <T> ResponseEntity<PageDto<T>> ok(Page<T> data) { | ||
| var response = new PageDto<T>( | ||
| data.getContent(), | ||
| data.getPageable().getPageNumber(), | ||
| data.getPageable().getPageSize(), | ||
| data.getTotalElements() | ||
| ); | ||
|
|
||
| return ResponseEntity.ok(response); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.selab.todo.common.dto; | ||
|
|
||
| import lombok.Data; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
|
|
||
| @Data | ||
| @RequiredArgsConstructor | ||
| public class ResponseDto<T> { | ||
| private final T data; | ||
|
|
||
| public static <T> ResponseEntity<ResponseDto<T>> ok(T data) { | ||
| var response = new ResponseDto<T>(data); | ||
| return ResponseEntity.ok(response); | ||
| } | ||
|
|
||
| public static <T> ResponseEntity<ResponseDto<T>> created(T data) { | ||
| var response = new ResponseDto<T>(data); | ||
| return ResponseEntity | ||
| .status(HttpStatus.CREATED) | ||
| .body(response); | ||
| } | ||
|
|
||
| public static ResponseEntity<Void> noContent() { | ||
| return ResponseEntity | ||
| .status(HttpStatus.NO_CONTENT) | ||
| .build(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.selab.todo.config; | ||
|
|
||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.data.jpa.repository.config.EnableJpaAuditing; | ||
|
|
||
| @Configuration | ||
| @EnableJpaAuditing | ||
| public class JpaConfig { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| package com.selab.todo.config; | ||
|
|
||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import springfox.documentation.builders.ApiInfoBuilder; | ||
| import springfox.documentation.builders.PathSelectors; | ||
| import springfox.documentation.builders.RequestHandlerSelectors; | ||
| import springfox.documentation.oas.annotations.EnableOpenApi; | ||
| import springfox.documentation.service.ApiInfo; | ||
| import springfox.documentation.spi.DocumentationType; | ||
| import springfox.documentation.spring.web.plugins.Docket; | ||
|
|
||
| import javax.servlet.http.HttpServletRequest; | ||
|
|
||
| @Configuration | ||
| @EnableOpenApi | ||
| public class SwaggerConfig { | ||
| @Bean | ||
| public Docket restApi() { | ||
| return new Docket(DocumentationType.OAS_30) | ||
| .ignoredParameterTypes( | ||
| HttpServletRequest.class | ||
| ) | ||
| .useDefaultResponseMessages(false) | ||
| .apiInfo(apiInfo()) | ||
| .select() | ||
| .apis(RequestHandlerSelectors.basePackage("com.selab.todo")) | ||
| .paths(PathSelectors.regex("/api/.*")) | ||
| .build(); | ||
| } | ||
|
|
||
| private ApiInfo apiInfo() { | ||
| return new ApiInfoBuilder() | ||
| .title("Selab Diary api info") | ||
| .description("SE Diary API") | ||
| .version("1.0.0") | ||
| .build(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package com.selab.todo.config; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.web.cors.CorsConfiguration; | ||
| import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||
| import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
|
|
||
| // CORS --> 가장 많이 발생 | ||
| @Configuration | ||
| @RequiredArgsConstructor | ||
| public class WebConfig implements WebMvcConfigurer { | ||
| @Bean | ||
| public UrlBasedCorsConfigurationSource corsConfigurationSource() { | ||
| var corsConfig = new CorsConfiguration(); | ||
|
|
||
| corsConfig.addAllowedOriginPattern(CorsConfiguration.ALL); | ||
| corsConfig.addAllowedHeader(CorsConfiguration.ALL); | ||
| corsConfig.addAllowedMethod(CorsConfiguration.ALL); | ||
|
|
||
| corsConfig.setAllowCredentials(true); | ||
| corsConfig.setMaxAge(3600L); | ||
|
|
||
| var corsConfigSource = new UrlBasedCorsConfigurationSource(); | ||
| corsConfigSource.registerCorsConfiguration("/**", corsConfig); | ||
| return corsConfigSource; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,92 @@ | ||||||
| package com.selab.todo.controller; | ||||||
|
|
||||||
| import com.selab.todo.common.dto.PageDto; | ||||||
| import com.selab.todo.common.dto.ResponseDto; | ||||||
| import com.selab.todo.dto.request.DiaryRegisterRequest; | ||||||
| import com.selab.todo.dto.request.DiaryUpdateRequest; | ||||||
| import com.selab.todo.service.DiaryService; | ||||||
| import io.swagger.annotations.Api; | ||||||
| import io.swagger.annotations.ApiOperation; | ||||||
| import lombok.RequiredArgsConstructor; | ||||||
| import org.springframework.data.domain.Pageable; | ||||||
| import org.springframework.data.domain.Sort; | ||||||
| import org.springframework.data.web.PageableDefault; | ||||||
| import org.springframework.http.MediaType; | ||||||
| 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; | ||||||
|
|
||||||
| @Api(tags = {"Diary API"}) | ||||||
| @RestController | ||||||
| @RequestMapping(value = "/api/v1/Diarys", produces = MediaType.APPLICATION_JSON_VALUE) | ||||||
| @RequiredArgsConstructor | ||||||
| public class DiaryController { | ||||||
| private final DiaryService diaryService; | ||||||
|
|
||||||
| @ApiOperation(value = "Diary 등록하기") | ||||||
| @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, value = "/register") | ||||||
| public ResponseEntity<?> register(@RequestBody DiaryRegisterRequest request) { | ||||||
| var response = diaryService.register(request); | ||||||
| return ResponseDto.created(response); | ||||||
| } | ||||||
|
|
||||||
| @ApiOperation(value = "Diary 단건 조회하기") | ||||||
| @GetMapping("/search/single/{id}") | ||||||
|
||||||
| @GetMapping("/search/single/{id}") | |
| @GetMapping("/{id}") |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이런 경우에는 month를 Request Param으로
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
음 여러 조건으로 검색 기능을 만드신 것 같은데, API를 나누지 말고, 검색 모듈을 만드는게 어떨까요?
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @PutMapping("/update/{id}") // @PatchMapping | |
| @PutMapping("/{id}") |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @DeleteMapping("/delete/id/{id}") | |
| @DeleteMapping("/{id}") |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.selab.todo.dto.request; | ||
|
|
||
| import lombok.Data; | ||
|
|
||
| @Data | ||
| public class DiaryRegisterRequest { | ||
| private final String title; | ||
| private final String content; | ||
| private final String feel; | ||
| private int year; | ||
| private int month; | ||
| private int day; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
url path에 대해 다시 한번 더 점검 부탁드릅니다!
rest url 규칙 확인하기
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
적용해보았습니다