자 저번글에서 로그인 , 회원가입 까지 했습니다!
이번에는 DB로 부터 글들을 불러와서 보여주는 부분을 만들어 보겠습니다!
레이아웃 작성하기
우선 완성된 레이아웃은 위에 메뉴가 있고 , 검색기능 , 페이징 기능까지 만들어 보겠습니다!
이번글에서 한번에 다루지는 않고
글 보여주기 -> 페이징 -> 검색기능 순으로 순차적으로 적어보도록 하겠습니다.
우선 위에 메뉴바는 index.jsp에서 nav부분을 그대로 가져왔습니다. 그럼 이 부분을 중복 코드가 되겟죠? 그래서~~
저부분을 저희가 전 글에서 사용했던 jspf를 만들어 include 하겠습니다.
nav.jspf
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">스프링 부트를 이용한 게시판 만들기</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<c:if test="${empty loginMember}">
<form class="navbar-form navbar-right" action="/member/login" method="post">
<div class="form-group">
<input autocomplete="off" name="id" type="text" placeholder="아아디를 입력해주세요" class="form-control">
</div>
<div class="form-group">
<input autocomplete="off" name="password" type="password" placeholder="비밀번호를 입력해주세요" class="form-control">
</div>
<button type="submit" class="btn btn-success" onclick="location.href ='/member/login'">로그인</button>
<button type="button" class="btn btn-success" onclick="location.href ='/member/register'">회원가입</button>
</form>
</c:if>
<c:if test="${!empty loginMember}">
<form class="navbar-form navbar-right" action="/member/logout" method="post">
<div class="form-group">
<label class="loginMember">${loginMember.mid}님 접속을 환영합니다</label>
</div>
<button type="submit" class="btn btn-success">로그아웃</button>
</form>
</c:if>
</div><!--/.navbar-collapse -->
</div>
</nav>
우선 list.jsp를 만들어서 include를 해줍니다!
우선 형태만 만들어 놓은거구요! 검색기능이랑 페이징기능은 차차 다루도록 하겠습니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
<%@include file="../part/head.jspf" %>
<link rel="stylesheet" href="/resource/list.css">
<title>게시판</title>
</head>
<body>
<div class="nav">
<%@include file="../part/nav.jspf" %>
</div>
<div class="jumbotron">
<div class="container">
<h2>게시판 리스트</h2>
<div class="header">
<select id="type" name="choice" class="selectpicker" data-style="btn-info">
<option value="">항목선택</option>
<option value="title">제목</option>
<option value="contents">내용</option>
<option value="mid">작성자</option>
</select>
<input class="form-control" id="search" onkeyup="search(1)" type="text" size="20" placeholder="검색어를 입력해주세요!">
<button class="btn btn-primary" onclick="search(1)" type="button">검색</button>
</div>
<form action="./add">
<table id="articleList" class="table table-hover tablestriped text-center" style="border: 1px solid;">
<thead>
<th>글 번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
<th>조회수</th>
</thead>
<c:forEach var="article" items="${list}" varStatus="st">
<tbody>
<tr>
<td>${st.index+1}</td>
<td><a href="./detail?aid=${article.aid}">${article.title}</a></td>
<td>${article.mid}</td>
<td>${article.regDate}</td>
<td>${article.hit}</td>
</tr>
</tbody>
</c:forEach>
</table>
<c:if test="${!empty loginMember}">
<button class="btn btn-primary">글 작성하기</button>
</c:if>
</form>
<ul class="pagination" id="pagination">
<li class="disabled">
<a href="#">
<span>«</span>
</a>
</li>
<c:forEach begin="1" end ="${article.paginationInfo.totalPageCount}" step="1" varStatus="status">
<li id="${status.count}">
<a href="/article/list?currentPageNo=${status.count}" >
${status.count}
</a>
</li>
</c:forEach>
<li>
<a href="#">
<span>»</span>
</a>
</li>
</ul>
<ul class="pagination" id="pagination1" style="display: none;">
</ul>
</div>
</div>
<script src="/js/list.js"></script>
</body>
</html>
뷰를 만들었으니 이제 Model(Dto)를 만들어볼까요
Article.java
롬북을 사용해서 setter,getter,생성자를 만들어줬구요!
package com.example.starter.dto;
import com.example.starter.pageing.CommonDto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Article extends CommonDto{
private long aid;
private String mid;
private String title;
private String contents;
private String regDate;
private int hit;
}
페이징에 필요한 클래스도 만들어줍니다!
Criteria.java - 페이징을 이용해 원하는 글 목록을 불러오기 위한 변수들을 모아놓은 클래스입니다.
package com.example.starter.pageing;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import lombok.Data;
@Data
public class Criteria {
/** 현재 페이지 번호 */
private int currentPageNo;
/** 페이지당 출력할 데이터 개수 */
private int recordsPerPage;
/** 화면 하단에 출력할 페이지 사이즈 */
private int pageSize;
/** 검색 키워드 */
private String searchKeyword;
/** 검색 유형 */
private String searchType;
public Criteria() {
this.currentPageNo = 1;
this.recordsPerPage = 10;
this.pageSize = 10;
}
public String makeQueryString(int pageNo) {
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.queryParam("currentPageNo", pageNo)
.queryParam("recordsPerPage", recordsPerPage)
.queryParam("pageSize", pageSize)
.queryParam("searchType", searchType)
.queryParam("searchKeyword", searchKeyword)
.build()
.encode();
return uriComponents.toUriString();
}
}
PaginationInfo.java - 페이징을 계산하는 클래스 입니다.
package com.example.starter.pageing;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
public class PaginationInfo {
/** 페이징 계산에 필요한 파라미터들이 담긴 클래스 */
private Criteria criteria;
/** 전체 데이터 개수 */
private int totalRecordCount;
/** 전체 페이지 개수 */
private int totalPageCount;
/** 페이지 리스트의 첫 페이지 번호 */
private int firstPage;
/** 페이지 리스트의 마지막 페이지 번호 */
private int lastPage;
/** SQL의 조건절에 사용되는 첫 RNUM */
private int firstRecordIndex;
/** SQL의 조건절에 사용되는 마지막 RNUM */
private int lastRecordIndex;
/** 이전 페이지 존재 여부 */
private boolean hasPreviousPage;
/** 다음 페이지 존재 여부 */
private boolean hasNextPage;
public PaginationInfo(Criteria criteria) {
if (criteria.getCurrentPageNo() < 1) {
criteria.setCurrentPageNo(1);
}
if (criteria.getRecordsPerPage() < 1 || criteria.getRecordsPerPage() > 100) {
criteria.setRecordsPerPage(10);
}
if (criteria.getPageSize() < 5 || criteria.getPageSize() > 20) {
criteria.setPageSize(10);
}
this.criteria = criteria;
}
public void setTotalRecordCount(int totalRecordCount) {
this.totalRecordCount = totalRecordCount;
if (totalRecordCount > 0) {
calculation();
}
}
private void calculation() {
/* 전체 페이지 수 (현재 페이지 번호가 전체 페이지 수보다 크면 현재 페이지 번호에 전체 페이지 수를 저장) */
totalPageCount = ((totalRecordCount - 1) / criteria.getRecordsPerPage()) + 1;
if (criteria.getCurrentPageNo() > totalPageCount) {
criteria.setCurrentPageNo(totalPageCount);
}
/* 페이지 리스트의 첫 페이지 번호 */
firstPage = ((criteria.getCurrentPageNo() - 1) / criteria.getPageSize()) * criteria.getPageSize() + 1;
/* 페이지 리스트의 마지막 페이지 번호 (마지막 페이지가 전체 페이지 수보다 크면 마지막 페이지에 전체 페이지 수를 저장) */
lastPage = firstPage + criteria.getPageSize() - 1;
if (lastPage > totalPageCount) {
lastPage = totalPageCount;
}
/* SQL의 조건절에 사용되는 첫 RNUM */
firstRecordIndex = (criteria.getCurrentPageNo() - 1) * criteria.getRecordsPerPage();
/* SQL의 조건절에 사용되는 마지막 RNUM */
lastRecordIndex = criteria.getCurrentPageNo() * criteria.getRecordsPerPage();
/* 이전 페이지 존재 여부 */
hasPreviousPage = firstPage != 1;
/* 다음 페이지 존재 여부 */
hasNextPage = (lastPage * criteria.getRecordsPerPage()) < totalRecordCount;
}
}
CommonDto.java - 이 클래스는 프로그램 소스를 좀 더 자바스럽게 하기 위한 클래스입니다. 자세한내용은 뒤에 작성하도록 하겠습니다!
package com.example.starter.pageing;
import lombok.Data;
@Data
public class CommonDto extends Criteria{
private PaginationInfo paginationInfo;
}
이제 이 뷰를 사용자에게 보여주기 위해 Controller를 만들어볼까요!
controller 패키지 밑에 ArticleController를 하나 만들어줬습니다!
ArticleController.java
@RequestMapping("/article/list")
public String showList(Article article, Model model) {
List<Article> articleList = articleService.selectArticleList(article);
model.addAttribute("list",articleList);
model.addAttribute("article",article);
return "article/list";
}
/article/list로 사용자가 접속하면 articleService.selectArticleList를 호출하여 게시물들을 list에 담아
model 객체에 담아 사용 할 수 있도록 했습니다.
article폴더 밑에 있는 list.jsp를 반환하도록 했습니다!
여기서 model.article 은 나중에 페이징 정보를 담을 객체입니다!
우선 Controller를 끝났구 Service를 작성해볼까요
ArticleService.java
package com.example.starter.service;
import java.util.List;
import java.util.Map;
import org.springframework.web.multipart.MultipartFile;
import com.example.starter.dto.Article;
import com.example.starter.pageing.Criteria;
public interface ArticleService {
public List<Article> selectArticleList(Article article);
}
인터페이스니 구현부가 있어야겠죠?
ArticleServiceImpl.java
package com.example.starter.service;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import com.example.starter.dao.ArticleDao;
import com.example.starter.dao.FileDao;
import com.example.starter.dto.Article;
import com.example.starter.pageing.Criteria;
import com.example.starter.dto.FileDto;
import com.example.starter.pageing.PaginationInfo;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class ArticleServiceImpl implements ArticleService{
@Autowired
ArticleDao articleDao;
@Override
public List<Article> selectArticleList(Article article) {
List<Article> articleList = Collections.emptyList();
int articleCount = articleDao.getTotalCount();
PaginationInfo paginationInfo = new PaginationInfo(article);
paginationInfo.setTotalRecordCount(articleCount);
article.setPaginationInfo(paginationInfo);
if(articleCount > 0 ) {
articleList = articleDao.selectArticleList(article);
}
return articleList;
}
}
이제 Dao를 작성해보겠습니다
ArticleDao.java
package com.example.starter.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import com.example.starter.dto.Article;
import com.example.starter.pageing.Criteria;
@Mapper // 이렇게 해주면 ArticleDao의 구현체를 마이바티스가 대신 구현해준다.
public interface ArticleDao {
public List<Article> selectArticleList(Article article);
public int getTotalCount(); //게시물 총 갯수를 가져와주는 메소드
}
ArticleDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace = "com.example.starter.dao.ArticleDao">
<!-- 페이징 구현 추가 부분 -->
<select id ="getTotalCount" resultType="int">
SELECT COUNT(*) FROM article
</select>
<select id="selectArticleList" parameterType="Article" resultType="Article">
SELECT
*
FROM
article
ORDER BY
aid DESC
LIMIT
#{paginationInfo.firstRecordIndex}, #{recordsPerPage}
</select>
</mapper>
자 View, Controller, Service , Dao 까지 다 작성했습니다! 이제 DB안에 20~30개의 데이터를 insert 하신 후 article/list로 접속하시면 페이징기능까지 구현되어 보이실 겁니다! 오늘은 일단 틀을 완성시켯고 다음 글에서
페이징에 대한 자세한 설명을 해보도록 하겠습니다
'자바 > 스프링부트 기초' 카테고리의 다른 글
스프링부트! 게시판 만들면서 배우기! 4. 게시물 작성하기 (0) | 2021.04.29 |
---|---|
스프링부트! 게시판 만들면서 배우기! 3-1 . 페이징! (0) | 2021.04.26 |
스프링부트! 게시판 만들면서 배우기! 3.로그인, 회원가입 구현하기 (0) | 2021.04.23 |
스프링부트! 게시판 만들면서 배우기! 2. 인덱스 페이지만들기 (0) | 2021.04.22 |
스프링부트! 게시판 만들면서 배우기! 1. 환경설정 (0) | 2021.04.22 |