성실한 사람이 되자

성실하게 글쓰자

This is spear

JAVA_SPRING/SPRING BOOT

SPRING BOOT)스프링 부트를 이용한 간단한 게시글 페이지 설계 - 2

Imaspear 2020. 11. 13. 21:01
728x90

 

오늘은 저번에 만들었던 블로그 객체들을 이용해 데이터 출력하는 것을 해볼 겁니다. 간단하게 REST API를 사용하여 웹페이지 상에 URI로 받아 데이터를 삭제, 추가, 출력을 해보도록 하겠습니다. 

 

 

컨트롤러는 웹페이지 상에서 데이터를 받아오거나 프로젝트에서 데이터를 웹 페이지로 출력하는 역할을 해줄 겁니다. 특별한 기능 없이 설계했습니다. 

controller 설계


 

블로그 전체 데이터를 뽑기

전에 만든 프로젝트를 실행해보면 LoadedDatabase.class에서 생성된 객체들을 log에서 보실 수 있습니다. 우리가 log에서 볼 수 있도록 짰으니깐요 ^^ 

 

 

밑에 저장되었던 블로그 리스트를 출력합니다. 

 

아래 패키지에 적힌대로 컨트롤러를 만들겠습니다. 

package com.thisisspear.ThisIsBlog.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.thisisspear.ThisIsBlog.domain.Blog;
import com.thisisspear.ThisIsBlog.repository.BlogRepository;

import java.util.List;


@RestController
public class BlogController {

	@Autowired
	BlogRepository blogRepository;
	
	BlogController(BlogRepository blogRepository){
		this.blogRepository = blogRepository;
	}
	
}

 

이후에 나오는 메서드들은 모두 컨트롤러에 계속 붙여주시면 됩니다. 

 

 

모든 리스트 출력 


 

아래의 매서드는 블로그들을 모두 출력하는 메서드입니다. GetMapping을 이용해 URI을 작성하여 웹 주소창에서 실행할 수 있습니다. 

	@GetMapping("/blog")
	public List<Blog> all(){
		return blogRepository.findAll(); 
	}

 

 

http://localhost:8080/blog

위와 같이 출력됩니다. 

 

 

하나의 리스트 출력


전체 리스트 출력하는 기능을 만들었지만 하나씩은 볼 수 없습니다. 그래서 하나의 블로그만 출력하는 기능을 만들겠습니다. 우선 하나의 블로그를 가져오는데 없는 블로그를 가져오려 할 때를 대비해 예외 처리를 합니다. 

 

 

패키지 생성

 

 

BlogNotFoundException.class 

package com.thisisspear.ThisIsBlog;

public class BlogNotFoundException extends RuntimeException{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public BlogNotFoundException(Long id) {
		super("Could not find Blog "+ id);
	}
}

 

이런 식으로 warning message를 출력합니다. 

 

BlogNotFoundAdvice.class

package com.thisisspear.ThisIsBlog;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;


public class BlogNotFoundAdvice {
	
	@ResponseBody
	@ExceptionHandler(BlogNotFoundException.class)
	@ResponseStatus(HttpStatus.NOT_FOUND)
	String blogNotFoundHandler(BlogNotFoundException exception) {
		return exception.getMessage();
	}
}

 

 

 

blogController에 추가 

	@GetMapping("/blog/{id}")
	Blog one(@PathVariable Long id) {
		return blogRepository.findById(id).orElseThrow(() -> new com.thisisspear.ThisIsBlog.BlogNotFoundException(id));
	}

 

 

 

주소창에 URI를 입력해 출력할 수 있습니다. 

 

추가된 모습 

 

 

 

삽입 기능


 

PostMapping을 이용해 블로그 객체를 생성해보도록 하겠습니다.  PostMapping과 같은 경우는 주소창에 URI를 쓰는 방식이 아닌 JSON과 같은 형식으로 데이터를 보내야 합니다. 그렇기에 HTTPie라는 HTTP 클라이언트를 사용해 데이터를 보내보도록 하겠습니다. 

 

	
	@PostMapping("/blog")
	Blog newBlog(@RequestBody Blog newBlog) {
		return blogRepository.save(newBlog);
	}

 

 

 

HTTPied를 이용한 데이터 확인

아래의 게시글을 이용하여 Httpie를 사용할 수 있습니다. 

 

imspear.tistory.com/87

 

Httpie 다운로드 및 환경변수 설정하기

HTTPie는 JSON 지원과 영구적인 세션, wget과 유사하며 플로그 등이 제공이 되기에 API 시대에서 사용자 친화적인 HTTP 클라이언트로서 사용이 편리합니다. 사용하기 좋은 이유 HTTPie는 API, HTTP 서버 및

imspear.tistory.com

 

 

imspear.tistory.com/79

 

HTTPie를 이용해보기(HTTPie 설치 및 실행하기)

설명 HTTPie는 JSON 지원과 영구적인 세션, wget과 유사하며 플로그 등이 제공이 되기에 API 시대에서 사용자 친화적인 HTTP 클라이언트로서 사용이 편리합니다. 사용하기 좋은 이유 HTTPie는 API, HTTP 서

imspear.tistory.com

 

 

 

 

HttPie를 이용해 데이터 산출하는 모습입니다. 

 

http localhost:8080/blog

 

 

아래는 POST 형식으로 데이터를 삽입하는 모습입니다. 

http POST localhost:8080/blog logoFile=thisislogo title=thisistitle

 

 

삽입 후 리스트 출력입니다. 

http localhost:8080/blog

 

 

 

위와 같은 리스트는 임시 데이터 베이스에 저장되므로 프로젝트를 재실행하면 없어지는 점 유의하길 바랍니다. 

 

삭제 기능


DeleteMapping을 이용해 데이터를 삭제하는 방법입니다. 

 

@DeleteMapping("/blog/{id}")
	void deleteBlog(@PathVariable Long id) {
		blogRepository.deleteById(id);
	}

 

HTTPie를 이용한 삭제 기능 사용입니다.

http DELETE localhost:8080/blog/1

 

 

 

삭제 후 리스트 출력입니다. 

 http localhost:8080/blog

 

 

 

수정하기


 

 

블로그 번호를 입력받아 블로그를 수정하는 기능입니다. 만약 해당 번호에 블로그 객체가 없으면 새로 만듭니다.

	@PutMapping("/blog/{id}")
	Blog replaceBlog(@RequestBody Blog newBlog, @PathVariable Long id) {
		return blogRepository.findById(id).map(blog -> 
			{
				blog.setTitle(newBlog.getTitle());
				blog.setLogoFile(newBlog.getLogoFile());
				return blogRepository.save(blog);
			}).orElseGet(() -> {
				newBlog.setId(id);
				return blogRepository.save(newBlog);
			});
	}

 

 

PutMapping을 하였기 때문에 PUT으로 데이터를 수정한다.

http PUT localhost:8080/blog/9 logoFile=thisislogo title=thisistitle

 

 

 

10번은 블로그가 아닌 포스트로 저장되어 있어서 수정하려 하면 수정되지 않고 새로운 블로그가 생성되는걸 볼 수 있습니다. 

 

 

마지막 전체적인 BlogController.class


 

package com.thisisspear.ThisIsBlog.controller;

import org.springframework.beans.factory.annotation.Autowired;
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.RestController;

import com.thisisspear.ThisIsBlog.domain.Blog;
import com.thisisspear.ThisIsBlog.repository.BlogRepository;

import java.util.List;


@RestController
public class BlogController {

	@Autowired
	BlogRepository blogRepository;
	
	BlogController(BlogRepository blogRepository){
		this.blogRepository = blogRepository;
	}
	
	@GetMapping("/blog")
	public List<Blog> all(){
		return blogRepository.findAll(); 
	}
	
	@GetMapping("/blog/{id}")
	Blog one(@PathVariable Long id) {
		return blogRepository.findById(id).orElseThrow(() -> new com.thisisspear.ThisIsBlog.blogexceptions.BlogNotFoundException(id));
	}
	
	@PostMapping("/blog")
	Blog newBlog(@RequestBody Blog newBlog) {
		return blogRepository.save(newBlog);
	}
	
	@DeleteMapping("/blog/{id}")
	void deleteBlog(@PathVariable Long id) {
		blogRepository.deleteById(id);
	}
	
	@PutMapping("/blog/{id}")
	Blog replaceBlog(@RequestBody Blog newBlog, @PathVariable Long id) {
		return blogRepository.findById(id).map(blog -> 
			{
				blog.setTitle(newBlog.getTitle());
				blog.setLogoFile(newBlog.getLogoFile());
				return blogRepository.save(blog);
			}).orElseGet(() -> {
				newBlog.setId(id);
				return blogRepository.save(newBlog);
			});
	}
}

 

 

 

전체적인 폴더 구조