지금까지 API기능을 만들기 위한 모든 부분들을 간단하게 만들어봤다. 이제 이들을 조합해서 간단한 블로그 API를 만들어보자
Service
매개변수로 받은 변수들을 활용해서 상황에 맞는 응답의 데이터를 조작한다.
@Service
@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;
@Transactional(readOnly = true)
public List<PostDto> getPosts() {
return this.postRepository.findAll().stream()
.map(post -> new PostDto(post.getTitle(), post.getBody(), post.getViews()))
.collect(Collectors.toList());
}
@Transactional
public PostDto getPost(long postId) {
Post post = this.postRepository.findById(postId).orElseThrow(PostNotFoundException::new);
post.increaseViews();
return new PostDto(post.getTitle(), post.getBody(), post.getViews());
}
@Transactional
public PostDto addPost(String title, String body) {
Post post = this.postRepository.save(new Post(title, body));
return new PostDto(post.getTitle(), post.getBody(), post.getViews());
}
@Transactional
public PostDto updatePost(long postId, String title, String body) {
Post post = this.postRepository.findById(postId).orElseThrow(PostNotFoundException::new);
post.updatePost(title, body);
return new PostDto(post.getTitle(), post.getBody(), post.getViews());
}
@Transactional
public void deletePost(long postId) {
this.postRepository.deleteById(postId);
}
}
repository를 이용하여 데이터를 조회 한 후, 가공하여 DTO를 사용하여 반환한다. 데이터의 트랜잭션을 보장하기 위햐여 @Transactional
어노테이션을 붙여주고 상황에 맞게 옵션을 준다. 이부분은 JPA시리즈에서 자세히 설명하겠다.
Spring Data JPA를 사용해서 데이터를 조회할 때 기본으로 제공되는 기능은 Optional
자료형을 사용한다. Null체크를 일일이 하지 않고 제공되는 orElse~
구문을 사용해서 예외처리를 하면 된다. 자세한 내용은 따로 포스팅에서 설명하겠다.
Exception
> post/exception/exceptions/PostNotFoundException.java
public class PostNotFoundException extends RuntimeException{
public PostNotFoundException() {
super("존재하지 않는 게시글입니다.");
}
}
java에서 예외처리를 직접 구현하는거보다 예외를 던지고 handler에서 처리하는것이 훨씬 더 깔끔한 구현이니 위와같은 예외를 만들어서 문제가 생겼을 때 바로 던지자.
Response
> post/response/GetPostResponse.java
@Getter
public class GetPostResponse {
private String title;
private String body;
private Long views;
public GetPostResponse(PostDto postDto){
this.title = postDto.getTitle();
this.body = postDto.getBody();
this.views = postDto.getViews();
}
}
> post/response/GetPostsResponse.java
@Getter
@AllArgsConstructor
public class GetPostsResponse {
List<PostDto> posts;
}
서비스에서 받은 데이터를 컨트롤러에서 생성할 수 있도록 생성자를 만들어 주면 되고, 스프링이 responsebody를 구성할 수 있도록 Getter를 생성해 주어야 한다.
Controller
@RestController
@RequestMapping("/posts")
@RequiredArgsConstructor
public class PostController {
private final PostService postService;
@GetMapping
@ResponseStatus(HttpStatus.OK)
public GetPostsResponse getPosts() {
List<PostDto> posts = this.postService.getPosts();
return new GetPostsResponse(posts);
}
@GetMapping("/{postId}")
@ResponseStatus(HttpStatus.OK)
public GetPostResponse getPost(
@PathVariable long postId
) {
PostDto post = this.postService.getPost(postId);
return new GetPostResponse(post);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public GetPostResponse addPost(
@RequestBody updatePostRequest updatePostRequest
) {
PostDto post = this.postService.addPost(updatePostRequest.getTitle(), updatePostRequest.getBody());
return new GetPostResponse(post);
}
@PutMapping("/{postId}")
@ResponseStatus(HttpStatus.OK)
public GetPostResponse updatePost(
@PathVariable long postId,
@RequestBody updatePostRequest updatePostRequest
) {
PostDto post = this.postService.updatePost(postId, updatePostRequest.getTitle(), updatePostRequest.getBody());
return new GetPostResponse(post);
}
@DeleteMapping("/{postId}")
@ResponseStatus(HttpStatus.OK)
public void deletePost(
@PathVariable long postId
) {
this.postService.deletePost(postId);
}
}
서비스로부터 받은 데이터를 지정한 Response에 맞게 포장하여 반환한다.
현재까지의 패키지 구조
마무리
간단하다고 하면 간단하고, 복잡하다고 하면 복잡하다고 할 수 있는 Api 기능에 대한 구현은 우선 전부 마쳤다. 다음시간에는 예외처리에 대해서 알아보자
'springboot로 API만들어보기' 카테고리의 다른 글
[스프링부트로 API 만들기] Junit 으로 API 테스트 코드 작성하기 (2) | 2021.01.05 |
---|---|
[스프링부트로 API 만들기] ControllerAdvice를 사용하여 예외처리하기 (0) | 2021.01.03 |
[스프링부트로 API 만들기] 데이터를 관리해주는 모델 (0) | 2021.01.03 |
[스프링부트로 API 만들기]기능을 수행해주는 서비스 (0) | 2021.01.03 |
[스프링부트로 API 만들기]API 요청을 받아 처리하는 컨트롤러 (0) | 2021.01.03 |
댓글