Tech Blog of Pinomaker
Published 2022. 5. 30. 11:34
[Spring] Book Api Project B.E/Spring

1. Book Project

  • Create Book : 생성 요청 처리
  • Find Book : 조회 요청 처리
  • Find Books 전체 조회 요청 처리
API Method URL Request DATA Response DATA
Create Book POST "/api/book" {
  title : "String",
  authorId : "Long"
}
{
  id : "Long"
}
Find Books GET "/api/book" none [
  {
    id : "Long",
    title : "String",
    authodId : "Long"
  }
]
Find Book GET "/api/book/:id" none {
  id : "Long",
  title : "String",
  authodId : "Long"
}

 

2. 폴더 구조

Package Class
controller BookController
domain Book
dto BookResponse
CreateBookRequest
repository BookRepository (interface)
BookInMemoryRepository
service BookService

3.  

4. Domain

domain는 모델의 정보 처리의 파일이다.

<java />
//domain package com.example.demo.domain; public class Book { //Book 객체는 고유 id, title, autorId를 가지고 있음 private Long id; private String title; private Long authorId; //고유 ID Getter public Long getId() { return id; } //Title Getter public String getTitle() { return title; } //AuthorId Getter public Long getAuthorId() { return authorId; } //생성자 1 public Book(Long id, String title, Long authorId) { this.id = id; this.title = title; this.authorId = authorId; } //생성자 2 public Book(String title, Long authorId) { this.title = title; this.authorId = authorId; } }

5. Controller

controller는 유저의 요청을 처리해주는 파일이다.

<java />
//controller package com.example.demo.controller; import com.example.demo.domain.Book; import com.example.demo.dto.BookResponse; import com.example.demo.dto.CreateBookRequest; import com.example.demo.service.BookService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.stream.Collectors; @RestController public class BookController { private final BookService bookService; //생성자 public BookController(BookService bookService) { this.bookService = bookService; } //GET : "/api/book" @GetMapping("/api/book") public List<BookResponse> findAll(){ //bookService.findAll 값을 BookResponse 객체로 생성 return this.bookService.findAll().stream().map(book -> new BookResponse(book)).collect(Collectors.toList()); } //GET : "/api/book/:id" @GetMapping("/api/book/{id}") //PathVariable를 이용하여 {id} 값을 추출하여 매개 변수로 전달 public BookResponse findById(@PathVariable(name = "id") Long id) { //ID 값으로 Data를 찾아 book 객체 생성 후 저장 Book book = this.bookService.findById(id); //BookRespnse에 book을 넣어 생성 후 리턴 return new BookResponse(book); } @PostMapping("/api/book") //@RequestBody를 이용하여, 요청 값 읽기 public Long save(@RequestBody CreateBookRequest request) { return this.bookService.save(request); } }

6. Repository

인터페이스를 사용하여 만들어준다.

<java />
//interface : BookRepository package com.example.demo.repository; import java.util.*; import com.example.demo.domain.Book; public interface BookRepository { //Find Books List<Book> findAll(); //Find Book Optional<Book> findById(Long id); //Create Book Book save(Book book); }

 

BookRepository 인터페이스를 상속 받아 저장소를 생성한다.

<java />
//BookInMemoryRepository package com.example.demo.repository; import com.example.demo.domain.Book; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.List; import java.util.Optional; @Repository public class BookInMemoryRepository implements BookRepository { //Book 객체를 담은 ArrayList, bookList를 생성 private final List<Book> bookList = new ArrayList<>(); //Book 고유 ID 값 지정 private Long bookNextId = 1L; private Long bookNextId = 1L; //Book List 반환 기능 @Override public List<Book> findAll() { return this.bookList; } //ID 값을 받아 해당 ID의 Book 반환 @Override public Optional<Book> findById(Long id) { // stream을 이용하여, filter로 List를 돌리고, 입력 받은 ID와 List의 Book ID가 같으면 선택 후 첫 번째 값 반환 return this.bookList.stream() .filter(book -> book.getId().equals(id)) .findFirst(); } //Book 객체를 받아 저장 및 업데이트 @Override public Book save(Book book) { //Book 객체인, bookOptional에 입력 받은 book의 ID 값을 이용하여 List에 해당 ID 값 있는 지 여부 저장 Optional<Book> bookOptional = this.findById(book.getId()); //만약에 값이 있다면 => 중복 데이터 if (bookOptional.isPresent()) { //수정한 book 객체를 가져와서 targetBook에 저장 Book targetBook = bookOptional.get(); //updateInfo 사용하여, 타이틀과 ID 값 변경 targetBook.updateInfo(book.getTitle(), book.getAuthorId()); return targetBook; } //savedBook 객체 생성자 이용하여 생성, 고유 ID 값과 타이틀, ID 값을 가짐 Book savedBook = new Book(bookNextId++, book.getTitle(), book.getAuthorId()); //add를 이용하여 bookList에 추가 this.bookList.add(savedBook); //Return 해줌 return savedBook; } }

7. Service

서비스는 로직이 담긴 곳으로, controller와 연결된다.

<java />
//BookService package com.example.demo.service; import com.example.demo.domain.Book; import com.example.demo.dto.CreateBookRequest; import com.example.demo.repository.BookRepository; import org.springframework.stereotype.Service; import java.util.*; @Service public class BookService { private final BookRepository bookRepository; public BookService(BookRepository bookRepository) { this.bookRepository = bookRepository; } public List<Book> findAll(){ return this.bookRepository.findAll(); } public Book findById(Long id) { return this.bookRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("not exist book id : '" + id + "'")); } public Long save(CreateBookRequest request) { Book book = new Book(request.getTitle(), request.getAuthorId()); Book savedBook = this.bookRepository.save(book); return savedBook.getId(); } }

8. DTO

DTO(Data Transfer Object)는 계층 간 데이터 교환을 하기 위해 사용하는 객체로, 로직을 가지고 있지 않으며, getter, setter만 가지고 있는 클래스다.

 

요청 받을 때 데이터와 응답을 보낼 때 사용한다.

 

<java />
//Book Response package com.example.demo.dto; import com.example.demo.domain.Book; public class BookResponse { private Long id; private String title; private Long authorId; public BookResponse(Book book) { this.id = book.getId(); this.title = book.getTitle(); this.authorId = book.getAuthorId(); } public Long getId() { return id; } public String getTitle() { return title; } public Long getAuthorId() { return authorId; } }

 

<java />
//CreateBookRequest package com.example.demo.dto; import com.example.demo.domain.Book; public class CreateBookRequest { private String title; private Long authorId; public CreateBookRequest(String title, Long authorId) { this.title = title; this.authorId = authorId; } public String getTitle() { return title; } public Long getAuthorId() { return authorId; } }
profile

Tech Blog of Pinomaker

@pinomaker

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!