Spring boot

스프링부트 블로그 만들기 테스트

H_u 2024. 8. 22. 12:04
728x90
반응형
SMALL

요구사항

  • 게시판을 구현하시오
  • 익명 게시판 사이트입니다. 로그인이 없습니다.
  • 제목과 내용은 20자를 넘어갈 수 없습니다.
  • 글쓰기, 글목록보기, 글수정하기, 글삭제하기
  • JSP,Mustache 선택 가능
  • JPA, 마이바티스 선택 가능

심화1

위 요구사항을 만족하였다면 아래 1가지를 해보시오.

  • 글목록보기를 5개씩 페이징하세요. prev, next 버튼 구현

심화2

위 요구사항을 만족하였다면 아래 1가지를 해보시오.

  • 전체 글 개수가 21개라면, prev [0][1][2][3][4] next
  • 예시) 3번을 클릭하면 ?page=3 페이지로 이동되면 됩니다.
  • 예시) 글 개수가 21개이기 때문에 0~4 까지 번호가 만들어집니다.

기술스택

  • Springboot 3.2.x
  • JDK 21, 17 선택
  • h2, MySQL 선택

의존성

  • Lombok
  • DevTools
  • Spring WEB
  • JPA
  • h2
  • Mustache

 

footer.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<div class="bg-light p-5 text-center">
    <h4>Created by Metacoding</h4>
    <h5>☎ 010-2222-7777</h5>
    <button class="btn btn-outline-primary">고객센터</button>
    <button class="btn btn-outline-primary">오시는길</button>
</div>

</body>
</html>

 

header.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
  <title>Blog</title>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
    <div class="container-fluid">
      <a class="navbar-brand" href="/">Metacoding</a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="collapsibleNavbar">
        <ul class="navbar-nav">
          <li class="nav-item">
            <a class="nav-link" href="/board/saveForm">글쓰기</a>
          </li>
        </ul>
      </div>
    </div>
  </nav>

 

list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!-- heafer.jsp -->
<%@ include file="/WEB-INF/views/layout/header.jsp"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<div class="container p-5">
	<c:choose>
		<c:when test="${posts != null && !empty posts}">
			<table class="table table-striped">
				<thead>
					<tr>
						<th>번호</th>
						<th>제목</th>
						<th>내용</th>
						<th>작성자</th>
						<th></th>
					</tr>
				</thead>
				<tbody>
					<c:forEach var="post" items="${posts}">
						<tr>
							<td>${post.id}</td>
							<td>${post.title}</td>
							<td>${post.content}</td>
							<td>${post.username}</td>
							<td>
								<div class="d-flex">

									<form action="/board/delete/${post.id}" method="post">
										<button class="btn btn-danger">삭제</button>
									</form>

									<form action="/board/update" method="get">
									<input type="hidden" id="id" name="id" value="${post.id}">
										<button class="btn btn-warning">수정</button>
									</form>
								</div>
							</td>
						</tr>
					</c:forEach>

				</tbody>
			</table>
		<div class="d-flex justify-content-center" >
			<ul class="pagination">
				<li class="page-item  <c:if test='${currentPage == 1}'>disabled</c:if>">
					<a class="page-link" href="?type=${type}&page=${currentPage - 1}&size=${size}" >Previous</a>
				</li>
				<c:forEach begin="1" end="${totalPages}"  var="page" >
				<li class="page-item  <c:if test='${page == currentPage}'>active </c:if>">
					<a class="page-link"  href="?type=${type}&page=${page}&size=${size}" >${page}</a>
				</li>
				</c:forEach>
				<li class="page-item <c:if test='${currentPage == totalPages}'>disabled</c:if>" >
					<a class="page-link" href="?type=${type}&page=${currentPage + 1}&size=${size}" >Next</a>
				</li>
			</ul>
			
		</div>
		</c:when>
		<c:otherwise>
			<div>
				<h5>아직 게시글이 없습니다</h5>
			</div>
		</c:otherwise>
	</c:choose>

</div>

<!-- foofer.jsp -->
<%@ include file="/WEB-INF/views/layout/footer.jsp"%>

 

saveForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
	<!-- header.jsp  -->
	<%@ include file="/WEB-INF/views/layout/header.jsp" %>	
	
	<div class="container p-5">
    <div class="card">
        <div class="card-header"><b>익명 글쓰기 화면입니다</b></div>
        <div class="card-body">
            <form action="/board/save" method="post">
                <div class="mb-3">
                  <label for="username">작성자:</label>
                    <input type="text" id="username" name="username" required>
                </div>
                <div class="mb-3">
                <label for="title">제목:</label>
                    <input type="text" class="form-control" id="title" placeholder="Enter title" name="title">
                </div>
                <div class="mb-3">
                <label for="content">내용:</label>
                    <textarea class="form-control" rows="5"  id="content" name="content"></textarea>
                </div>
                <button type="submit" class="btn btn-primary form-control">글쓰기완료</button>
                
            </form>
        </div>
    </div>
</div>

<!-- footer.jsp  -->
<%@ include file="/WEB-INF/views/layout/footer.jsp" %>

 

updateForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- header.jsp  -->
<%@ include file="/WEB-INF/views/layout/header.jsp"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<div class="container p-5">
    <div class="card">
        <div class="card-header">
            <b>글수정 화면입니다</b>
        </div>
        <div class="card-body">
            <form action="/board/update" method="post">
                <input type="hidden" name="id" value="${post.id}">
                <label for="title">제목:</label>
                <input type="text" id="title" name="title" value="${post.title}" required>
                <br>
                <label for="content">내용:</label>
                <textarea id="content" name="content" required>${post.content}</textarea>
                <br>
                <label for="username">작성자:</label>
                <input type="text" id="username" name="username" value="${post.username}" required>
                <br>
                <button type="submit">수정</button>
            </form>
        </div>
    </div>
</div>

<!-- footer.jsp  -->
<%@ include file="/WEB-INF/views/layout/footer.jsp"%>

 

PostService.java
package com.tenco.main.util;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tenco.main.model.PostList;
import com.tenco.main.repository.PostRepository;

@Service
public class PostService {

	@Autowired
	 private PostRepository postRepository;

	
	
    public List<PostList> getAllPosts(int page, int size) {
    	
    	int offset = (page - 1) * size;
        return postRepository.findAll(offset, size);
    }
	
    public void savePost(PostList post) {
        postRepository.insert(post);
    }
    
    public PostList getPostById(Long id) {
        return postRepository.findById(id);
    }

    public void updatePost(PostList post) {
        postRepository.update(post);
    }

    public void deletePost(Long id) {
        postRepository.delete(id);
    }
    public int getTotalCount() {
        return postRepository.count();
    }

}

 

PostRepository.java
package com.tenco.main.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.tenco.main.model.PostList;

@Mapper
public interface PostRepository {
    void insert(PostList post);

    List<PostList> findAll(@Param("offset") int offset, @Param("limit") int limit);

    PostList findById(Long id);

    void update(PostList post);

    void delete(Long id);
   
    int count();
}

 

PostList.java
package com.tenco.main.model;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
public class PostList {
    private Long id;
    private String title;
    private String content;
    private String username;
    private Timestamp createdAt;
}

 

BoardController
package com.tenco.main.board;

import java.sql.Timestamp;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.tenco.main.model.PostList;
import com.tenco.main.util.PostService;

import lombok.RequiredArgsConstructor;

@Controller
@RequestMapping("/board")
@RequiredArgsConstructor
public class BoardController {

    @Autowired
    private final PostService postService;

    @GetMapping("/")
    public String index() {
        return "index";
    }

    @GetMapping("/saveForm")
    public String saveForm() {
        return "board/saveForm";
    }

    @PostMapping("/save")
    public String save(@RequestParam ("username") String username, 
    								@RequestParam ("title") String title, 
    								@RequestParam ("content") String content) {
        PostList post = PostList.builder()
        		.username(username)
                .title(title)
                .content(content)
                .createdAt(new Timestamp(System.currentTimeMillis()))
                .build();
        postService.savePost(post);
        return "redirect:/board/list";
    }

    @GetMapping("/update")
    public String updateForm(@RequestParam(name = "id")Long id, Model model) {
        model.addAttribute("id", id);
        PostList post = postService.getPostById(id);
        model.addAttribute("post", post);
        return "board/updateForm";
    }

    @PostMapping("/update")
    public String update(@RequestParam("id") Long id, 
    									@RequestParam("title") String title, 
    									@RequestParam("content") String content, 
    									@RequestParam("username") String username) {
    	System.out.println("업데이트");
        PostList post = PostList.builder()
                .id(id)
                .title(title)
                .content(content)
                .username(username)
                .build();
        postService.updatePost(post);
        return "redirect:/board/list";
    }

    @PostMapping("/delete/{id}")
    public String delete(@PathVariable("id") Long id) {
        postService.deletePost(id);
        return "redirect:/board/list";
    }

    @GetMapping("/list")
    public String list(@RequestParam(name = "page", defaultValue = "1") int page, 
    							@RequestParam(name = "size", defaultValue = "5") int size, 
    							Model model) {
        List<PostList> posts = postService.getAllPosts(page, size);
        int totalCount = postService.getTotalCount();
        int totalPages = (int) Math.ceil((double) totalCount / size);

        model.addAttribute("posts", posts);
        model.addAttribute("currentPage", page);
        model.addAttribute("totalPages", totalPages);
        model.addAttribute("totalItems", totalCount);

        return "board/list";
    }
}
728x90
반응형
SMALL