전자정부 프레임워크 게시판 만들기 연습 (5) 페이징, 검색

Pagination과 Search 클래스 추가

 

1. vo/Pagination.java

===================================

 

package egovframework.example.ivory.vo;

public class Pagination {

private int listSize = 10; //초기값으로 한 페이지당 보여질 게시글 개수
private int rangeSize = 5; //초기값으로 페이지 범위에 보여질 페이지 개수

private int page; //현재 페이지 번호
private int range; //현재 페이지 범위
private int listCnt; //전체 게시글의 개수
private int pageCnt; //전체 페이지 범위의 개수
private int startPage; //각 페이지 범위 시작 번호
private int startList; //게시판 시작번호
private int endPage; //각 페이지 범위 끝 번호

private boolean prev; //이전페이지
private boolean next; //다음페이지

public int getListSize() {
return listSize;
}

public void setListSize(int listSize) {
this.listSize = listSize;
}

public int getRangeSize() {
return rangeSize;
}

public void setRangeSize(int rangeSize) {
this.rangeSize = rangeSize;
}

public int getPage() {
return page;
}

public void setPage(int page) {
this.page = page;
}

public int getRange() {
return range;
}

public void setRange(int range) {
this.range = range;
}

public int getListCnt() {
return listCnt;
}

public void setListCnt(int listCnt) {
this.listCnt = listCnt;
}

public int getPageCnt() {
return pageCnt;
}

public void setPageCnt(int pageCnt) {
this.pageCnt = pageCnt;
}

public int getStartPage() {
return startPage;
}

public void setStartPage(int startPage) {
this.startPage = startPage;
}

public int getStartList() {
return startList;
}

public void setStartList(int startList) {
this.startList = startList;
}

public int getEndPage() {
return endPage;
}


public void setEndPage(int endPage) {
this.endPage = endPage;
}


public boolean isPrev() {
return prev;
}

public void setPrev(boolean prev) {
this.prev = prev;

}

public boolean isNext() {
return next;
}


public void setNext(boolean next) {
this.next = next;
}


public void pageInfo(int page, int range, int listCnt){
//현재페이지
this.page = page;

//현재페이지 범위
this.range = range;

//게시글 개수
this.listCnt = listCnt;

//전체 페이지 개수
this.pageCnt = (int)Math.ceil(listCnt/listSize);

//시작페이지
this.startPage = (range - 1) * rangeSize + 1;

//끝페이지
this.endPage = range * rangeSize;

//게시판 시작 번호
this.startList = (page - 1) * listSize;

//이전 버튼 상태
this.prev = range == 1 ? false : true;

//다음 버튼 상태
this.next = endPage > pageCnt ? false : true;

if(this.endPage > this.pageCnt) {
this.endPage = this.pageCnt;
this.next = false;
}
}
}

 

==================================

 

 

2. vo/Search.java

====================================

 

package egovframework.example.ivory.vo;

public class Search extends Pagination {

private String searchType;
private String keyword;

public String getSearchType() {
return searchType;
}
public void setSearchType(String searchType) {
this.searchType = searchType;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}

}

====================================

 

 

3. testMapper.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="egovframework.example.ivory.service.TestMapper">

<!-- 게시글 목록 조회 -->
<select id="selectTest" resultType="egovframework.example.ivory.vo.TestVo">
SELECT * FROM test
<where>
<if test="searchType=='testTitle' and keyword != null and keyword !=''">
AND testTitle like CONCAT('%',#{keyword},'%')
</if>
<if test="searchType=='testContent' and keyword != null and keyword !=''">
AND testContent like CONCAT('%',#{keyword},'%')
</if>
<if test="searchType=='testName' and keyword != null and keyword !=''">
AND testName like CONCAT('%',#{keyword},'%')
</if>
</where>
ORDER BY testId DESC
LIMIT #{startList}, #{listSize}
</select>


<!-- 게시글 갯수 -->
<select id="getBoardListCnt" resultType="Integer">
SELECT count(*) as listCnt
FROM test
<where>
<if test="keyword != null and keyword != ''">
<if test="searchType=='testTitle'">
AND testTitle like CONCAT('%',#{keyword},'%')
</if>
<if test="searchType=='testContent'">
AND testContent like CONCAT('%',#{keyword},'%')
</if>
<if test="searchType=='testName'">
AND testName like CONCAT('%',#{keyword},'%')
</if>
</if>
</where>
</select>

<!-- 게시글 상세보기 -->
<select id="selectDetail" parameterType="Integer" resultType="egovframework.example.ivory.vo.TestVo">
SELECT * FROM test
WHERE testId = #{testId}
</select>

<!-- 게시글 삽입 -->
<insert id="insertTest" parameterType="egovframework.example.ivory.vo.TestVo">
INSERT INTO test(testTitle, testContent, testName, testDate)
VALUES(#{testTitle},#{testContent},'ivory',now())
</insert>

 

********************** 오라클 코드 *************************

<!-- 게시글 삽입 -->
<insert id="insertTest" parameterType="egovframework.example.ivory.vo.TestVo">
INSERT INTO test(testId, testTitle, testContent, testName, testDate)
VALUES(TESTID.NEXTVAL,#{testTitle},#{testContent},'ivory',SYSDATE)
</insert>

 

****************************************************************

<!-- 게시글 수정 -->
<update id="updateTest" parameterType="egovframework.example.ivory.vo.TestVo">
UPDATE test SET
testTitle = #{testTitle}, testContent = #{testContent}
WHERE testId = #{testId}
</update>


<!-- 게시글 삭제 -->
<delete id="deleteTest" parameterType="Integer">
DELETE FROM test
WHERE testId = #{testId}
    </delete>

</mapper>

==================================

 

4. testController.java

============================

package egovframework.example.ivory.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import egovframework.example.ivory.service.TestService;
import egovframework.example.ivory.vo.Search;
import egovframework.example.ivory.vo.TestVo;


@Controller
public class TestController {

@Autowired
private TestService testService;

//글보기 조회
/* @RequestMapping(value="/testList.do")
public String testListDo(TestVo testVo, Model model) throws Exception{

model.addAttribute("list", testService.selectTest(testVo));

return "test/testList";
}



//글목록페이지
@RequestMapping(value="/testList.do")
public String testListDo(TestVo testVo, Model model) throws Exception{
model.addAttribute("list", testService.selectTest(testVo));
return "test/testList";
}
*/





//글목록페이지,페이징,검색
@RequestMapping(value="/testList.do")
public String testListDo(Model model
,@RequestParam(required=false,defaultValue="1")int page
,@RequestParam(required=false,defaultValue="1")int range
,@RequestParam(required=false,defaultValue="testTitle")String searchType
,@RequestParam(required=false)String keyword
,@ModelAttribute("search")Search search) throws Exception{

//검색
model.addAttribute("search", search);
search.setSearchType(searchType);
search.setKeyword(keyword);

//전체 개시글 개수
int listCnt = testService.getBoardListCnt(search);

//검색 후 페이지
search.pageInfo(page, range, listCnt);
//페이징
model.addAttribute("pagination", search);
//게시글 화면 출력
model.addAttribute("list", testService.selectTest(search));

//model.addAttribute("list", testService.selectTest(testVo));

return "test/testList";
}






//글 상세페이지
@RequestMapping(value="testDetail.do")
public String viewForm(Model model, HttpServletRequest request) throws Exception{
int testId = Integer.parseInt(request.getParameter("testId"));
TestVo testVo = testService.selectDetail(testId);
model.addAttribute("vo", testVo);
return "test/testDetail";

}

//글작성페이지
@RequestMapping(value="/testRegister.do")
public String testRegister(){
return "test/testRegister";
}


//글쓰기
@RequestMapping(value="/insertTest.do")
public String write(@ModelAttribute("testVo") TestVo testVo) throws Exception {
testService.insertTest(testVo);
return "redirect:testList.do";
}

//글수정

@RequestMapping(value="/updateTest.do")
public String updateTest(@ModelAttribute("testVo") TestVo testVo) throws Exception {
testService.updateTest(testVo);
return "redirect:testDetail.do?testId="+testVo.getTestId();
}

//글삭제
@RequestMapping(value="/deleteTest.do")
public String deleteTest(HttpServletRequest request) throws Exception {
int testId = Integer.parseInt(request.getParameter("testId"));
testService.deleteTest(testId);
return "redirect:testList.do";
}

}

============================

selectTest에 보내주는 객체가 다르니 참고!! (service,serviceImpl,dao.... 에 있는 메서드도 바꿔주어야함)

 

5. testService.java

==============================

package egovframework.example.ivory.service;

import java.util.List;

import egovframework.example.ivory.vo.TestVo;

import egovframework.example.ivory.vo.Search;

public interface TestService {

public List<TestVo> selectTest(Search search) throws Exception;


//public List<TestVo> selectTest(TestVo testVo) throws Exception;

public void insertTest(TestVo testVo) throws Exception;

public TestVo selectDetail(int testId) throws Exception;

public void updateTest(TestVo testVo) throws Exception;

public void deleteTest(int testId) throws Exception;



public int getBoardListCnt(Search search) throws Exception;



}

=============================

 

6. testServiceImpl.java

=============================

package egovframework.example.ivory.service.impl;

import java.util.List;

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


import egovframework.example.ivory.dao.TestDao;
import egovframework.example.ivory.service.TestService;
import egovframework.example.ivory.vo.TestVo;

import egovframework.example.ivory.vo.Search;


@Service
public class TestServiceImpl implements TestService{


@Autowired
private TestDao testDao;


/* @Override
public List<TestVo> selectTest(TestVo testVo) throws Exception {

return testDao.selectTest(testVo);
}*/


@Override
public List<TestVo> selectTest(Search search) throws Exception {
return testDao.selectTest(search);
}

@Override
public int getBoardListCnt(Search search) throws Exception {
return testDao.getBoardListCnt(search);
}





@Override
public void insertTest(TestVo testVo) throws Exception {
testDao.insertTest(testVo);
}

@Override
public TestVo selectDetail(int testId) throws Exception {
return testDao.selectDetail(testId);
}

@Override
public void updateTest(TestVo testVo) throws Exception {
testDao.updateTest(testVo);
}

@Override
public void deleteTest(int testId) throws Exception {
testDao.deleteTest(testId);
}



}

=============================

 

 

7. testDao.java

===============================

package egovframework.example.ivory.dao;

import java.util.List;


import egovframework.example.ivory.vo.TestVo;

import egovframework.example.ivory.vo.Search;


public interface TestDao {


public List<TestVo> selectTest(Search search) throws Exception;
// public List<TestVo> selectTest(TestVo testVo) throws Exception;




public void insertTest(TestVo testVo) throws Exception;

public TestVo selectDetail(int testId)throws Exception;

public void updateTest(TestVo testVo) throws Exception;

public void deleteTest(int testId) throws Exception;




public int getBoardListCnt(Search search) throws Exception;

}



===============================

 

 

8. testDaoImpl.java

============================

package egovframework.example.ivory.dao.impl;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import egovframework.example.ivory.dao.TestDao;
import egovframework.example.ivory.service.TestMapper;
import egovframework.example.ivory.vo.TestVo;

import egovframework.example.ivory.vo.Search;

@Repository
public class TestDaoImpl implements TestDao {

@Autowired
private SqlSession sqlSession;

/* @Override
public List<TestVo> selectTest(TestVo testVo) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
return mapper.selectTest(testVo);
}*/

@Override
public List<TestVo> selectTest(Search search) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
return mapper.selectTest(search);
}




@Override
public void insertTest(TestVo testVo) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
mapper.insertTest(testVo);
}

@Override
public TestVo selectDetail(int testId) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
return mapper.selectDetail(testId);
}

@Override
public void updateTest(TestVo testVo) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
mapper.updateTest(testVo);
}

@Override
public void deleteTest(int testId) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
mapper.deleteTest(testId);
}


@Override
public int getBoardListCnt(Search search) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
return mapper.getBoardListCnt(search);
}



}

============================

 

9. TestMapper.java

============================

package egovframework.example.ivory.service;

import java.util.List;

import egovframework.example.ivory.vo.TestVo;

import egovframework.example.ivory.vo.Search;

//Mapper namespace 와 ID를 연결할 Interface 를 두어서 interface를 호출하는 방법.
//Mybatis 매핑XML에 기재된 SQL을 호출하기 위한 인터페이스이다.
//SQL id는 인터페이스에 정의된 메서드명과 동일하게 작성한다
public interface TestMapper {


//List<TestVo> selectTest(TestVo testVo) throws Exception;

public List<TestVo> selectTest(Search search) throws Exception;



public void insertTest(TestVo testVo) throws Exception;

public TestVo selectDetail(int testId) throws Exception;

public void updateTest(TestVo testVo) throws Exception;

public void deleteTest(int testId) throws Exception;



public int getBoardListCnt(Search search)throws Exception;

}

============================

 

10. testList.jsp

============================

<%@ 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 PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Board List</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<style type="text/css">
a {
    text-decoration: auto;
}
.row>*{
    width:auto;
}
</style>
</head>
<body>
<br />
<h1 class="text-center">Board List</h1>
<br />
<br />
<div class="container">
<table class="table table-hover table-striped text-center"
style="border: 1px solid;">
<colgroup>
<col width="10%" />
<col width="50%" />
<col width="20%" />
<col width="20%" />
</colgroup>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>등록일자</th>
</tr>
</thead>

<tbody>
<c:forEach items="${list }" var="result">
<tr>
<td>${result.testId}</td>
<td><a href="testDetail.do?testId=${result.testId}">${result.testTitle}</a></td>
<td>${result.testName}</td>
<td>${result.testDate}</td>
</tr>
</c:forEach>
</tbody>
</table>
<!-- pagination start -->
<div id="paginationBox" class="pagination1">
<ul class="pagination" style="justify-content: center;">

<c:if test="${pagination.prev}">
<li class="page-item"><a class="page-link" href="#"
onClick="fn_prev('${pagination.page}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.listSize}'
,'${search.searchType}', '${search.keyword}')">이전</a></li>
</c:if>

<c:forEach begin="${pagination.startPage}" end="${pagination.endPage}" var="testId">
<li class="page-item <c:out value="${pagination.page == testId ? 'active' : ''}"/> ">
<a class="page-link" href="#"
onClick="fn_pagination('${testId}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.listSize}'
,'${search.searchType}', '${search.keyword}')">
${testId}</a></li>
</c:forEach>


<c:if test="${pagination.next}">
<li class="page-item"><a class="page-link" href="#"
onClick="fn_next('${pagination.range}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.listSize}'
,'${search.searchType}', '${search.keyword}')">다음</a></li>
</c:if>
</ul>
</div>
<!-- pagination end -->
<hr />


<a class="btn btn-outline-info" style="float: right" href="testRegister.do">글쓰기</a>

<!-- search start -->
<div class="form-group row">
<div class="w100" style="padding-right: 10px">
<select class="form-control form-control-sm" name="searchType" id="searchType">
<option value="testTitle">제목</option>
<option value="testContent">내용</option>
<option value="testName">작성자</option>
</select>
</div>
<div class="w300" style="padding-right: 10px">
<input type="text" class="form-control form-control-sm" name="keyword" id="keyword">
</div>
<div>
<button class="btn btn-sm btn-primary" name="btnSearch" id="btnSearch">검색</button>
</div>

</div>
<!-- search end -->

</div>
<br>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
crossorigin="anonymous"></script>

<script
src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"
integrity="sha384-q2kxQ16AaE6UbzuKqyBE9/u/KzioAlnx2maXQHiDX9d4/zp8Ok3f+M7DPm+Ib6IU"
crossorigin="anonymous"></script>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js"
integrity="sha384-pQQkAEnwaBkjpqZ8RU1fF1AKtTcHJwFl3pblpTlHXybJjHpMYo79HY3hIi4NKxyj"
crossorigin="anonymous"></script>
</body>
<script type="text/javascript">


//이전 버튼 이벤트
//5개의 인자값을 가지고 이동 testList.do
//무조건 이전페이지 범위의 가장 앞 페이지로 이동
function fn_prev(page, range, rangeSize, listSize, searchType, keyword) {

var page = ((range - 2) * rangeSize) + 1;
var range = range - 1;


var url = "/testList.do";
url += "?page=" + page;
url += "&range=" + range;
url += "&listSize=" + listSize;
url += "&searchType=" + searchType;
url += "&keyword=" + keyword;
location.href = url;
}


//페이지 번호 클릭
    function fn_pagination(page, range, rangeSize, listSize, searchType, keyword) {

var url = "/testList.do";
url += "?page=" + page;
url += "&range=" + range;
url += "&listSize=" + listSize;
url += "&searchType=" + searchType;
url += "&keyword=" + keyword;

location.href = url;
}

//다음 버튼 이벤트
//다음 페이지 범위의 가장 앞 페이지로 이동
function fn_next(page, range, rangeSize, listSize, searchType, keyword) {
var page = parseInt((range * rangeSize)) + 1;
var range = parseInt(range) + 1;
var url = "/testList.do";
url += "?page=" + page;
url += "&range=" + range;
url += "&listSize=" + listSize;
url += "&searchType=" + searchType;
url += "&keyword=" + keyword;
location.href = url;
}

// 검색
$(document).on('click', '#btnSearch', function(e){
e.preventDefault();
var url = "/testList.do";
url += "?searchType=" + $('#searchType').val();
url += "&keyword=" + $('#keyword').val();
location.href = url;
console.log(url);
});

</script>
</html>

=============================

 

서버 재실행

 

 

 

ㄴ testList.jsp 메인 화면

 

ㄴ 페이지 번호 이동

 

 

ㄴ 다음 버튼 눌렀을때

 

 

ㄴ 제목을 테스트로 검색 했을때

 

 

 

 

ㄴ 내용을 '검색어' 로 했을때

 

 

ㄴ 작성자를 'ddd' 로 검색 했을때

+ Recent posts