쌓고 쌓다
[스프링 부트] 게시글 작성 및 전체 출력 - 1 본문
코드를 작성해보면 컨트롤러, 서비스, 리포지토리의 차이가 긴가민가하다.
- 컨트롤러: 웹 MVC의 컨트롤러 역할. 서비스의 제어를 담당하는 느낌 같다. (서비스를 이용해)
- 서비스: 핵심 비즈니스 로직 구현. 게시글을 작성하고 찾는 기능을 제공. (리포지토리를 이용해)
- 리포지토리: DB에 접근하여 도메인 객체를 DB에 저장하고 관리한다.
아직 차이가 긴가민가하다... 많이 경험해봐야할듯!
HomeController
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
}
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>home 페이지입니당~!</h1>
<a href="/poster/write">게시글 작성</a>
<a href="/posters">게시글 보기</a>
</body>
</html>
/poster/write : 게시글 작성 페이지
/posters : 게시글 조회 페이지
Poster
public class Poster {
private Long id;
private String title;
private String writer;
private String content;
// 추후에 작성일도 해보자.
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
... Getter, Setter들
}
게시글 ID, 제목, 작성자, 내용으로 구성.
추후에 작성일 추가 계획.
PosterRepository (Interface)
public interface PosterRepository {
Poster save(Poster poster);
Optional<Poster> findById(Long id);
Optional<Poster> findByTitle(String title);
List<Poster> findAll();
}
인터페이스로 만들어 놓으면
DB를 연결할때 간단히 가능하다는데
나중에 DB 연결할때 한번 그 장점을 느껴보자...
MemoryPosterRepository (구현체)
package com.example.board.repository;
import com.example.board.domain.Poster;
import org.springframework.stereotype.Repository;
import java.util.*;
@Repository
public class MemoryPosterRepository implements PosterRepository{
private Map<Long, Poster> store = new HashMap<>();
private Long sequence = 0L;
@Override
public Poster save(Poster poster) {
poster.setId(++sequence);
store.put(poster.getId(), poster);
return poster;
}
@Override
public Optional<Poster> findById(Long id) {
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Poster> findByTitle(String title) {
return store.values().stream()
.filter(member -> member.getTitle().equals(title))
.findAny(); // 추후에 중복 제목 불가도 해보고 중복 제목 검색 작업 해보자.
}
@Override
public List<Poster> findAll() {
return new ArrayList<>(store.values());
}
}
Null이 반환될 수 있는 부분에 Optional로 감싸는걸로 배웠었고 앞전의 학습 코드들을 참고하여 작성했다.
findByTitle에서 title 가지고 게시글을 찾는 과정이 있는데
이 부분도 추후에 여러 게시글을 조회 가능하게 수정할 필요가 있다.
PosterController
@Controller
public class PosterController {
private final PosterService posterService;
@Autowired
public PosterController(PosterService posterService) {
this.posterService = posterService;
}
@GetMapping("/poster/write")
public String writeForm() {
return "posters/createPosterForm";
}
@PostMapping("/poster/write")
public String write(Poster poster) {
posterService.write(poster);
return "redirect:/";
}
@GetMapping("/posters")
public String list(Model model) {
List<Poster> posters = posterService.findPosters();
model.addAttribute("posters", posters);
return "posters/posterList";
}
}
(1) 게시글 작성 (/poster/write)
GET 요청으로 /poster/write 들어오면
posters/createPosterForm.html을 반환한다.
이 html에서 게시글 내용에 대한 입력을 받고
<form action="/poster/write" method="post">
<label>제목</label>
<input type="text" name="title"><br>
...
<button type="submit">제출</button>
</form>
제출시 /poster/write로 Poster 클래스에 담아 POST 요청을 보낸다.
input 태그에 작성되어있는 name="title"처럼 name 값에 매핑되어
POST요청을 처리하는 메소드에 있는 매개변수에 담겨진다.
(2) 게시글 조회 (/posters)
게시글들에 대한 출력을 posters에 있는 posterList.html을 통해 출력을 한다.
Controller의 메서드는 Model이라는 타입의 객체를 파라미터로 받을 수 있다.
model.addAttribute로 (키, 값)으로 키에 값을 매핑하여 postList.html. 뷰에 데이터를 넘길 수 있다.
템플릿 엔진 타임리프로 받은 데이터를 출력할 예정.
PosterService
@Service
public class PosterService {
private PosterRepository posterRepository;
@Autowired
public PosterService(PosterRepository posterRepository) {
this.posterRepository = posterRepository;
}
public Long write(Poster poster) {
posterRepository.save(poster);
return poster.getId();
}
public List<Poster> findPosters() {
return posterRepository.findAll();
}
public Optional<Poster> findByOne(Long posterId) {
return posterRepository.findById(posterId);
}
}
createPosterForm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/poster/write" method="post">
<label>제목</label>
<input type="text" name="title"><br>
<label>작성자</label>
<input type="text" name="writer"><br>
<label>내용</label>
<textarea type="text" name="content"></textarea><br>
<button type="submit">제출</button>
</form>
</body>
</html>
posterList.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
<th>ID</th>
<th>title</th>
<th>writer</th>
<th>content</th>
<tr th:each="poster : ${posters}">
<td th:text="${poster.id}"></td>
<td th:text="${poster.title}"></td>
<td th:text="${poster.writer}"></td>
<td th:text="${poster.content}"></td>
</tr>
</table>
</body>
</html>
"http://www.thymeleaf.org"에 www를 빼면 타임리프 문법에 빨간줄이 뜨는걸 없앨수 있다.
결과
다음 목표: 게시글 상세 조회, 게시글 작성일, DB 연결
'프로그래밍 > spring' 카테고리의 다른 글
[스프링 부트] MySQL 연결 및 JPA - 2 (0) | 2023.06.24 |
---|---|
[스프링 부트] MySQL 연결 com.mysql.cj.jdbc.driver 에러(빨간줄) (0) | 2023.06.24 |
[스프링 부트] 인텔리제이 프로젝트 세팅 및 실행 (0) | 2023.06.21 |
회원 웹 기능 - 조회 (0) | 2023.06.21 |
회원 웹 기능 - 홈 화면 추가, 등록 (0) | 2023.05.16 |