반응형
contents/board.html
<!DOCTYPE html>
<html
lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{common/layout}"
>
<section layout:fragment="content">
<h1>게시판</h1>
<div class="container">
<div id="post__list">
<table class="table">
<thead>
<tr>
<th>id</th>
<th>제목</th>
<th>작성자</th>
<th>날짜</th>
</tr>
</thead>
<tbody>
<tr th:each="post : ${post}">
<td th:text="${post.id}"></td>
<td>
<a th:href="@{'/board/' + ${post.id}}"> <span th:text="${post.title}"> </span></a>
</td>
<td th:text="${post.author.userName}"></td>
<td th:text="${#temporals.format(post.createdDate, 'yyyy-MM-dd HH:mm')}"></td>
</tr>
</tbody>
</table>
</div>
<div>
<nav aria-label="Page navigation example">
<ul class="pagination">
<th:block th:each="page : ${#numbers.sequence(page.startPage, page.totalPage)}">
<li class="page-item">
<a class="page-link" th:href="@{'/board?page=' + ${page}}"><span th:text="${page}"></span></a>
</li>
</th:block>
</ul>
</nav>
<!-- <th:block th:each="page : ${#numbers.sequence(page.startPage, page.totalPage)}">
<a th:href="@{'/board?page=' + ${page}}">
<button th:text="${page}"></button>
</a>
</th:block> -->
</div>
<!-- <span th:text="${page}"> </span> -->
</div>
<div align="right" class="col-md-12 left">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#savePostsModal">글 등록</button>
</div>
<div class="modal fade" id="savePostsModal" tabindex="-1" role="dialog" aria-labelledby="savePostsLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="savePostsLabel">게시글 등록</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form th:action="@{/post/save}" method="post">
<div class="form-group">
<label for="title">제목</label>
<input type="text" class="form-control" name="title" id="title" placeholder="제목을 입력하세요" />
</div>
<div class="form-group">
<label for="content"> 내용 </label>
<textarea class="form-control" name="content" id="content" placeholder="내용을 입력하세요" style="resize: none; height: 300px"></textarea>
</div>
</form>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">취소</button>
<button type="button" class="btn btn-primary" id="btn-write">등록</button>
</div>
</div>
</div>
</div>
</div>
<script src="/js/lib/jquery.min.js"></script>
<script>
const board = {
init: function () {
$("#btn-write").on("click", () => {
this.clickWriteBtn();
});
},
csrf: {
token: $("meta[name='_csrf']").attr("content"),
header: $("meta[name='_csrf_header']").attr("content"),
},
clickWriteBtn: function () {
const data = {
title: $("#title").val(),
content: $("#content").val(),
};
const { token, header } = this.csrf;
$.ajax({
type: "POST",
url: "/post/save",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
beforeSend: function (xhr) {
xhr.setRequestHeader(header, token);
},
})
.done(function (result) {
if (result.msg === "save") {
alert("게시글이 등록되었습니다.");
location.reload();
} else {
alert("게시글 등록에 실패했습니다. 다시 작성해주세요");
location.reload();
}
})
.fail(function (error) {
alert("error");
console.log(error);
});
},
};
board.init();
</script>
</section>
</html>
WebRestController.java
save 메소드로 Boards 객체를 전달받고 글 등록 구현
package com.cos.web01.controller;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.cos.web01.domain.boards.Boards;
import com.cos.web01.dto.user.UserSaveRequestDto;
import com.cos.web01.service.BoardService;
import com.cos.web01.service.UserSecurityService;
import lombok.AllArgsConstructor;
@RestController
@AllArgsConstructor
public class WebRestController {
@Autowired
private UserSecurityService userSecurityService;
@Autowired
private BoardService boardService;
@PostMapping("/users/signup")
public ResponseEntity<Map<String, Object>> saveUsers(@RequestBody UserSaveRequestDto dto) {
userSecurityService.accountUser(dto);
Map<String, Object> map = new HashMap<>();
map.put("msg", "save");
return new ResponseEntity<>(map, HttpStatus.OK);
}
@GetMapping("/user/userName")
public ResponseEntity<Map<String, Object>> getUserName(Principal principal) {
Map<String, Object> map = new HashMap<String, Object>();
// UserSecurityService에서 laodUserByUsername 메소드에
// 리턴 값으로 전달한 User 객체에서 설정한 Id 값을 가져옴
map.put("userName", principal.getName());
return new ResponseEntity<Map<String, Object>>(map, HttpStatus.OK);
}
@PostMapping("/user/changeName")
public ResponseEntity<Map<String, Object>> changeUserName(@RequestBody Map<String, Object> map,
Principal principal) {
String changeName = map.get("changeName").toString();
String userId = principal.getName();
userSecurityService.changeUserName(userId, changeName);
Map<String, Object> responseMap = new HashMap<String, Object>();
responseMap.put("msg", "success");
return new ResponseEntity<Map<String, Object>>(responseMap, HttpStatus.OK);
}
@DeleteMapping("/user")
public ResponseEntity<Map<String, Object>> deleteUser(Principal principal) {
String userId = principal.getName();
userSecurityService.deleteUser(userId);
Map<String, Object> responseMap = new HashMap<String, Object>();
return new ResponseEntity<Map<String, Object>>(responseMap, HttpStatus.OK);
}
@PostMapping("/post/save")
public ResponseEntity<Map<String, Object>> save(@RequestBody Boards boards, Principal principal) {
String userId = principal.getName();
System.out.println(boards);
boardService.savePost(boards, userId);
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("msg", "save");
return new ResponseEntity<>(responseMap, HttpStatus.OK);
}
}
BoardService.java - savePost 메소드, JPA의 save 메소드로 글 등록 실행
postList 메소드에서는 JPA의 findAll 메소드로 글 목록 불러오기, Pageable 객체를 파라미터로 넣어서 페이징 처리
getPost 메소드에서는 findById 메소드로 Boards 객체 불러오기
package com.cos.web01.service;
import com.cos.web01.domain.boards.Boards;
import com.cos.web01.domain.boards.BoardsRepository;
import com.cos.web01.domain.user.UserRepository;
import com.cos.web01.domain.user.Users;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.AllArgsConstructor;
@Service
@AllArgsConstructor
public class BoardService {
private BoardsRepository boardsRepository;
private UserRepository userRepository;
@Transactional
public void savePost(Boards boards, String userId) {
Users users = userRepository.findByUserId(userId).get();
boards.setAuthor(users);
boardsRepository.save(boards);
}
@Transactional(readOnly = true)
public Page<Boards> postList(Pageable pageable) {
return boardsRepository.findAll(pageable);
}
@Transactional(readOnly = true)
public Boards getPost(Long id) {
Boards boards = boardsRepository.findById(id).get();
return boards;
}
}
WebController.java
board 메소드에서 페이징 관련 작업, 페이징을 그냥 넘기게 되면 페이지의 첫 번째가 1이 아닌 0부터 시작하기 때문에, /boards?page=0이 첫번째 페이지가 된다
view에서는 일반적으로 페이지를 1부터 시작하기때문에, 내부적으로도 이를 맞춰줘야하고, 맞춰주는 다양한 방법들 중에서,
html에서는 그대로 [1][2][3] 이런 식으로 보이게 하고, 내부에서 처리될 때는 [0][1][2] 이런식으로 맞춰주는 방법으로,
Service로 넘어가는 boardSerivce.postList() 메소드의 파라미터에 view로부터 넘어온 페이지의 숫자 값에 -1을 해주는 식으로 하였다
나중에 10페이지 이상의 분량이 쌓일 경우에 대한 페이징 처리 작업이 필요하다
boardById 메소드는 글 상세 페이지를 불러오는 기능으로 만든 메소드
package com.cos.web01.controller;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import com.cos.web01.domain.boards.Boards;
import com.cos.web01.domain.user.UserRepository;
import com.cos.web01.domain.user.Users;
import com.cos.web01.service.BoardService;
import lombok.AllArgsConstructor;
@Controller
@AllArgsConstructor
public class WebController {
private UserRepository userRepository;
@Autowired
private BoardService boardService;
@GetMapping({ "", "/" })
public String index() {
return "contents/index";
}
@GetMapping("/board")
public String board(ModelMap model,
@PageableDefault(size = 3, sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
// System.out.println("데이터 - pageable " + pageable);
// System.out.println("데이터 - 받아온 페이지 넘버 : " + pageable.getPageNumber());
// System.out.println("데이터 - pageable.withPage : " +
// pageable.withPage(pageable.getPageNumber() - 1));
// Page<Boards> boards = boardService.postList(pageable);
// dto로 넘겨야하는 작업 필요
Page<Boards> boards = boardService.postList(pageable.withPage(pageable.getPageNumber() - 1));
int totalPage = boards.getTotalPages();
int startPage = totalPage - 10;
if (startPage < 1) {
startPage = 1;
}
Map<String, Object> page = new HashMap<String, Object>();
page.put("pageNumber", pageable.getPageNumber());
page.put("startPage", startPage);
page.put("totalPage", totalPage);
model.addAttribute("post", boards);
model.addAttribute("page", page);
return "contents/board";
}
@GetMapping("/board/{id}")
public String boardById(@PathVariable Long id, Model model) {
// System.out.println("param id : " + id);
// dto로 넘겨야하는 작업 필요
Boards post = boardService.getPost(id);
model.addAttribute("post", post);
return "contents/postDetail";
}
@GetMapping("/login/error")
public String error() {
return "contents/error";
}
@PostMapping("/login/fail")
public String initPost() {
return "contents/index";
}
@GetMapping("/info")
public String info(Principal principal, Model model) {
Optional<Users> users = userRepository.findByUserId(principal.getName());
Users user = users.get();
model.addAttribute("userName", user.getUserName());
return "contents/info";
}
}
반응형
'스프링 부트 > 웹MVC' 카테고리의 다른 글
업데이트, 더티 체킹 (0) | 2021.12.03 |
---|---|
스프링 시큐리티 적용 (0) | 2021.12.03 |
thymeleaf 적용 (0) | 2021.12.01 |
User 생성 작업 (0) | 2021.12.01 |
셋업 (0) | 2021.12.01 |