Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
6a672c8
feat: 기본적인 CRUD
DongGeon0908 Jan 25, 2023
daaa823
fix: jpa config and webconfig cors
DongGeon0908 Jan 25, 2023
e280990
fix: 자원 없을시 exception
DongGeon0908 Jan 25, 2023
18f5af4
fix: 삽입, 삭제, 수정시 로그 출력
DongGeon0908 Jan 25, 2023
1b36daf
fix: todo
DongGeon0908 Jan 25, 2023
89ae461
fix: todo
DongGeon0908 Jan 25, 2023
a57ef58
feat: Response wrapping 변경
DongGeon0908 Feb 1, 2023
6bf1340
정적 펙토리 매서드 패턴 적용
DongGeon0908 Feb 1, 2023
f3e4dc0
exception 처리
DongGeon0908 Feb 1, 2023
b7db802
todo swagger 적용
DongGeon0908 Feb 1, 2023
7da10b1
데이터베이스 연결 수정
Duskafka Feb 2, 2023
3ec64f8
fix : 요구명세서 작성
Duskafka Feb 2, 2023
fe7c7d4
fix : request, response
Duskafka Feb 2, 2023
058728f
fix : Range Search
Duskafka Feb 3, 2023
06413cf
complete : today`s feeling
Duskafka Feb 3, 2023
54d72c0
fix : 요구사항 수정
Duskafka Feb 3, 2023
970a123
fix : 불필요한 PathVariable 삭제
Duskafka Feb 3, 2023
f22869d
develop : month delete
Duskafka Feb 6, 2023
14a39fa
fix : add year, month, day
Duskafka Feb 6, 2023
bab5a7c
fix : 클래스명 변경
Duskafka Feb 6, 2023
3d82dee
fix : 클래스명 삭제
Duskafka Feb 6, 2023
ebef5f8
develop : month delete 추가
Duskafka Feb 6, 2023
5f2b58f
fix : Diary 수정
Duskafka Feb 6, 2023
60b2f2a
fix : Diary 수정
Duskafka Feb 6, 2023
660ea95
fix : delete test
Duskafka Feb 6, 2023
b6a633d
fix : month search
Duskafka Feb 6, 2023
91da852
fix : 스웨거 링크 추가
Duskafka Feb 7, 2023
6ab4cb3
develop : Feeling 항목 추가
Duskafka Feb 7, 2023
ee7e7c7
update : Feeling 테이블 추가 및 update , findAll 추가
Duskafka Feb 19, 2023
be2b0e4
update : 검색 모듈 추가
Duskafka Feb 19, 2023
8ae4591
fix : log
Duskafka Feb 19, 2023
2fed5fb
fix : URL
Duskafka Feb 19, 2023
0342a14
update : MonthRequest
Duskafka Feb 19, 2023
700f32e
update : 다양한 검색기능 추가
Duskafka Feb 20, 2023
d9917b3
update : id
Duskafka Feb 20, 2023
c89f25c
fix : feeling id 추가에 따른 변경
Duskafka Feb 20, 2023
b4f3ac0
fix : search 객체 패키징
Duskafka Feb 20, 2023
c400005
update : 쿼리문으로 월별 삭제 기능 추가
Duskafka Feb 20, 2023
0f0e229
fix : 사용하지 없는 변수 삭제
Duskafka Feb 20, 2023
d16cb02
fix : 중복 메소드 삭제
Duskafka Feb 20, 2023
f31e595
fix : url 수정
Duskafka Feb 20, 2023
bdccfdd
fix : ApiOperation 수정
Duskafka Feb 20, 2023
9847235
fix : url 대문자 변경
Duskafka Feb 22, 2023
23e1bda
fix : 원시타입 참조타입으로 변경
Duskafka Feb 22, 2023
4470800
update : persistence 연결을 위한 xml
Duskafka Feb 25, 2023
3abb773
fix : cleanCode
Duskafka Feb 25, 2023
bb14106
fix : 변수형 변경
Duskafka Feb 25, 2023
4783817
update : Persistence DB 연동 성공
Duskafka Feb 25, 2023
cb0b484
none
Duskafka Feb 25, 2023
e2f77e9
fix : GenerateValue
Duskafka Feb 25, 2023
0108538
fix : Entity name
Duskafka Feb 25, 2023
067294b
update : feelingSearch
Duskafka Feb 25, 2023
98c0374
update : feelingSearch
Duskafka Feb 25, 2023
9f94913
delete
Duskafka Feb 25, 2023
e8f6a51
fix : cleancode
Duskafka Feb 27, 2023
d5a4661
fix : persistence name
Duskafka Feb 27, 2023
7be9377
fix : Entity 추가
Duskafka Mar 6, 2023
0976e81
update : JpaSpecificationExecutor
Duskafka Mar 6, 2023
ff93cf7
fix : cleancode
Duskafka Mar 6, 2023
178fd36
fix : cleancode
Duskafka Mar 6, 2023
59a7c6d
update : PersistenceService
Duskafka Oct 22, 2023
c05180b
update : 줄바꿈
Duskafka May 15, 2024
b9dc272
Merge remote-tracking branch 'origin/kihyun/diary-project' into kihyu…
Duskafka May 15, 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
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,72 @@
# SELAB-TODO
> basic todo with spring-mvc

# 요구명세서
> 일기 작성 서비스

## 목차
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


7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {

group = 'com.selab'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
sourceCompatibility = "11"

configurations {
compileOnly {
Expand All @@ -29,8 +29,13 @@ dependencies {
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'

// swagger
implementation "io.springfox:springfox-boot-starter:3.0.0"

}

tasks.named('test') {
useJUnitPlatform()
}
targetCompatibility = JavaVersion.VERSION_16
21 changes: 21 additions & 0 deletions src/main/java/com/selab/todo/common/BaseEntity.java
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;
}
28 changes: 28 additions & 0 deletions src/main/java/com/selab/todo/common/dto/PageDto.java
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);
}
}
30 changes: 30 additions & 0 deletions src/main/java/com/selab/todo/common/dto/ResponseDto.java
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();
}
}
9 changes: 9 additions & 0 deletions src/main/java/com/selab/todo/config/JpaConfig.java
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 {
}
39 changes: 39 additions & 0 deletions src/main/java/com/selab/todo/config/SwaggerConfig.java
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 Todo api info")
.description("SE TODO API")
.version("1.0.0")
.build();
}
}
29 changes: 29 additions & 0 deletions src/main/java/com/selab/todo/config/WebConfig.java
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;
}
}
65 changes: 59 additions & 6 deletions src/main/java/com/selab/todo/controller/TodoController.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,83 @@
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.TodoRegisterRequest;
import com.selab.todo.dto.response.TodoResponse;
import com.selab.todo.dto.request.TodoUpdateRequest;
import com.selab.todo.service.TodoService;
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 = {"TODO API"})
@RestController
@RequestMapping(value = "/api/v1/todos", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class TodoController {
private final TodoService todoService;

@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public TodoResponse register(@RequestBody TodoRegisterRequest request) {
return todoService.register(request);
@ApiOperation(value = "TODO 등록하기")
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, value = "/")
public ResponseEntity<?> register(@RequestBody TodoRegisterRequest request) {
var response = todoService.register(request);
return ResponseDto.created(response);
}

@ApiOperation(value = "TODO 단건 조회하기")
@GetMapping("/{id}")
public TodoResponse get(@PathVariable Long id) {
return todoService.get(id);
public ResponseEntity<?> get(@PathVariable Long id) {
var response = todoService.get(id);
return ResponseDto.ok(response);
}

@ApiOperation(value = "TODO 범위 조회")
@GetMapping("/month/{month}")
public ResponseEntity<?> getRange(
@PathVariable int month,
@PageableDefault Pageable pageable
) {
var response = todoService.getRange(pageable,month);
return PageDto.ok(response);
}

@ApiOperation(value = "TODO 전체 조회하기")
@GetMapping
public ResponseEntity<?> getAll(
@PageableDefault(sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable
) {
var response = todoService.getAll(pageable);
return PageDto.ok(response);
}

@ApiOperation(value = "TODO 수정하기")
@PutMapping("/{id}") // @PatchMapping
public ResponseEntity<?> update(
@PathVariable Long id,
@RequestBody TodoUpdateRequest request
) {
var response = todoService.update(id, request);
return ResponseDto.ok(response);
}

@ApiOperation(value = "TODO 삭제하기")
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(
@PathVariable Long id
) {
todoService.delete(id);
return ResponseDto.noContent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
public class TodoRegisterRequest {
private final String title;
private final String content;
private final String feel;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
public class TodoUpdateRequest {
private final String title;
private final String content;
private final String feel;
}
15 changes: 15 additions & 0 deletions src/main/java/com/selab/todo/dto/response/TodoResponse.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
package com.selab.todo.dto.response;

import com.selab.todo.entity.Todo;
import lombok.Data;

import java.time.LocalDateTime;

@Data
public class TodoResponse {
private final Long id;
private final String title;
private final String content;
private final LocalDateTime localDateTime;
private final String feel;

public static TodoResponse from(Todo todo) {
return new TodoResponse(
todo.getId(),
todo.getTitle(),
todo.getContent(),
todo.getCreatedAt(),
todo.getFeel()
);
}
}
Loading