이전에 사용했던 PageRequestDTO와 PageResultDTO를 이용하여 목록 페이지를 생성하겠습니다.
MovieRepository에서 목록을 출력하기 위한 데이터를 받아오는 메서드는 이미 설계를 했었는데, [movie, movieImage, 평점, 리뷰수]라는 객체배열 타입의 Page를 반환합니다.
이 Object[] 내의 모든 요소들이 MovieDTO를 통해 전달되어야 하므로 MovieDTO에 평점과 리뷰수를 추가합니다.
MovieDTO
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MovieDTO {
private Long mno;
private String title;
@Builder.Default
private List<MovieImageDTO> imageDTOList = new ArrayList<>();
private double avg;
private int reviewCnt;
private LocalDateTime regDate;
private LocalDateTime modDate;
}
또한 regDate와 modDate를 전달할 수 있도록 추가하였습니다.
다음으로 entity 객체들을 DTO로 변환하는 작업이 필요합니다. 서비스에 default로 구현합니다.
MovieService
default MovieDTO entitiesToDTO(Movie movie, List<MovieImage> movieImages, Double avg, Long reviewCnt) {
MovieDTO movieDTO = MovieDTO.builder()
.mno(movie.getMno())
.title(movie.getTitle())
.regDate(movie.getRegDate())
.modDate(movie.getModDate())
.build();
List<MovieImageDTO> movieImageDTOList = movieImages.stream().map(movieImage -> {
return MovieImageDTO.builder()
.imgName(movieImage.getImgName())
.path(movieImage.getPath())
.uuid(movieImage.getUuid())
.build();
}).collect(Collectors.toList());
movieDTO.setImageDTOList(movieImageDTOList);
movieDTO.setAvg(avg);
movieDTO.setReviewCnt(reviewCnt.intValue());
return movieDTO;
}
PageResult를 반환하는 서비스 계층 메서드도 생성하겠습니다.
MovieService
PageResultDTO<MovieDTO, Object[]> getList(PageRequestDTO pageRequestDTO);
MovieServiceImpl
@Override
public PageResultDTO<MovieDTO, Object[]> getList(PageRequestDTO requestDTO) {
Pageable pageable = requestDTO.getPageable(Sort.by("mno").descending());
Page<Object[]> result = movieRepository.getListPage(pageable);
Function<Object[], MovieDTO> fn = (arr -> entitiesToDTO(
(Movie) arr[0],
(List<MovieImage>) (Arrays.asList((MovieImage)arr[1])),
(Double) arr[2],
(Long) arr[3]
));
return new PageResultDTO<>(result, fn);
}
Controller에서 서비스의 결과를 받아 list 페이지에 반환합니다.
MovieController
@GetMapping("/list")
public void list(PageRequestDTO pageRequestDTO, Model model) {
log.info("pageRequestDTO: ", pageRequestDTO);
model.addAttribute("result", movieService.getList(pageRequestDTO));
}
list 페이지는 이전에 했던 예제들과 비슷한 구조로 작성합니다.
list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:replace="~{/layout/basic :: setContent(~{this::content})}">
<th:block th:fragment="content">
<h1 class="mt-4">Movie List Page
<span>
<a th:href="@{/movie/register}">
<button type="button" class="btn btn-outline-primary">REGISTER</button>
</a>
</span>
</h1>
<form action="/movie/list" method="get" id="searchForm">
<input type="hidden" name="page" value="1">
</form>
<table class="table table striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title & Picture</th>
<th scope="col">Review Count</th>
<th scope="col">AVG Rating</th>
<th scope="col">Regdate</th>
</tr>
</thead>
<tbody>
<tr th:each="dto : ${result.dtoList}">
<th scope="row">
<a th:href="@{/movie/read(mno = ${dto.mno}, page=${result.page})}">
[[${dto.mno}]]
</a>
</th>
<td>
<img th:if="${dto.imageDTOList.size() > 0 && dto.imageDTOList[0].path != null}" th:src="|/display?fileName=${dto.imageDTOList[0].getThumbnailURL()}|">
[[${dto.title}]]
</td>
<td>
[[${dto.reviewCnt}]]
</td>
<td>
<b>
[[${dto.avg}]]
</b>
</td>
<td>
[[${#temporals.format(dto.regDate, 'yyyy/MM/dd')}]]
</td>
</tr>
</tbody>
</table>
<ul class="pagination h-100 justify-content-center align-items-center">
<li class="page-item" th:if="${result.prev}">
<a class="page-link" th:href="@{/movie/list(page=${result.start - 1})}" tabindex="-1">Previous</a>
</li>
<li th:class=" 'page-item ' + ${result.page == page ? 'active' : ''} " th:each="page: ${result.pageList}">
<a class="page-link" th:href="@{/movie/list(page=${page})}">
[[${page}]]
</a>
</li>
<li class="page-item" th:if="${result.next}">
<a class="page-link" th:href="@{/movie/list(page=${result.end + 1})}">Next</a>
</li>
</ul>
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>등록되었습니다.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary close" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script th:inline="javascript">
var msg = [[${msg}]];
console.log(msg);
const $modal = $(".modal")
if(msg) {
$('.modal').show();
}
$(".close").on("click", () => {
$modal.hide()
});
</script>
</th:block>
</th:block>
등록 완료 후 목록 페이지로 돌아가면 모달창이 뜨는 부분까지 구현되어 있습니다. 다음 게시글에서는 조회 페이지 작성을 진행하겠습니다.