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.test.service.TestMapper">
<!--게시글 목록 조회 -->
<select id="selectTest" resultType="TestVO">
SELECT
*
FROM test
<trim prefix="WHERE" prefixOverrides="AND|OR">
<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>
</trim>
ORDER BY
testId DESC
LIMIT #{startList}, #{listSize}
</select>
<!-- 전체 글의 개수를 읽어 오는 SQL문 -->
<select id="getBoardListCnt" resultType="int">
SELECT
count(*) as
listCnt
FROM
test
<trim prefix="WHERE" prefixOverrides="AND|OR">
<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>
</trim>
</select>
<!--게시글 삽입 -->
<insert id="insertTest" parameterType="TestVO">
<![CDATA[
INSERT INTO test(testTitle, testContent, testName, testDate)
VALUES(#{testTitle}, #{testContent}, '밥샵', now())
]]>
</insert>
<!--게시글 클릭시 detailView -->
<select id="selectDetail"
parameterType="egovframework.example.test.domain.TestVO"
resultType="egovframework.example.test.domain.TestVO">
<![CDATA[
SELECT *
FROM test
WHERE testId = #{testId}
]]>
</select>
<!--게시글 업데이트 -->
<update id="updateTest">
update test set
testTitle = #{testTitle}
,testContent =
#{testContent}
where
testId = #{testId}
</update>
<!--게시글 삭제 -->
<delete id="deleteTest">
delete from test
where
testId = #{testId}
</delete>
</mapper>
Pagination
package egovframework.example.test.domain;
public class Pagination {
private int listSize = 10; // 초기값으로 목록개수를 10으로 셋팅 한 페이지당 보여질 리스트의 개수
private int rangeSize = 5; // 초기값으로 페이지범위를 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 getRangeSize() {
return 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 getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
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 int getListSize() {
return listSize;
}
public void setListSize(int listSize) {
this.listSize = listSize;
}
public int getListCnt() {
return listCnt;
}
public void setListCnt(int listCnt) {
this.listCnt = listCnt;
}
public int getStartList() {
return startList;
}
// 첫번째 인자 page 는 현재 페이지 정보, 두번째 인자 range 는 현재 페이지 범위 정보, 세번째 인자 listCnt는 게시물의 총 개수
public void pageInfo(int page, int range, int listCnt) {
this.page = page;
this.range = range;
this.listCnt = listCnt;
// 전체 페이지수
this.pageCnt = (int) Math.ceil((double) 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;
}
}
}
Search
package egovframework.example.test.domain;
//Search 클래스가 Pagination 클래스를 상속 받았으므로 기존 Pagination의 특성을 그대로 사용 할 수 있다.
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;
}
}
TestController
package egovframework.example.test.web;
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 org.springframework.web.servlet.mvc.support.RedirectAttributes;
import egovframework.example.test.domain.Search;
import egovframework.example.test.domain.TestVO;
import egovframework.example.test.service.TestService;
@Controller
public class TestController {
@Autowired
private TestService testServiceImpl;
// 글 목록 리스트, 페이징, 검색
@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);
// 전체 게시글 개수를 얻어와 listCnt에 저장
int listCnt = testServiceImpl.getBoardListCnt(search);
//검색
search.pageInfo(page, range, listCnt);
//페이징
model.addAttribute("pagination", search);
//게시글 화면 출력
model.addAttribute("list", testServiceImpl.selectTest(search));
return "test/testList";
}
// 글 작성 클릭시 글 작성 페이지로 이동
@RequestMapping(value = "/testRegister.do")
public String testRegister() {
return "test/testRegister";
}
// 글 작성 버튼 구현
@RequestMapping(value = "/insertTest.do")
public String write(@ModelAttribute("testVO") TestVO testVO, RedirectAttributes rttr) throws Exception {
testServiceImpl.insertTest(testVO);
return "redirect:testList.do";
}
// HttpServletRequest 객체안에 모든 데이터들이 들어가는데 getParameter메소드로 testId 원하는 데이터 가져옴
// 제목 클릭 시 상세보기
@RequestMapping(value = "/testDetail.do")
public String viewForm(@ModelAttribute("testVO") TestVO testVO, Model model, HttpServletRequest request)
throws Exception {
int testId = Integer.parseInt(request.getParameter("testId"));
testVO.setTestId(testId);
TestVO resultVO = testServiceImpl.selectDetail(testVO);
model.addAttribute("result", resultVO);
return "test/testDetail";
}
// 수정하기
@RequestMapping(value = "/updateTest.do")
public String updateTest(@ModelAttribute("testVO") TestVO testVO, HttpServletRequest request) throws Exception {
testServiceImpl.updateTest(testVO);
return "redirect:testList.do";
}
// 삭제하기
@RequestMapping(value = "/deleteTest.do")
public String deleteTest(@ModelAttribute("testVO") TestVO testVO) throws Exception {
testServiceImpl.deleteTest(testVO);
return "redirect:testList.do";
}
}
TestService
package egovframework.example.test.service;
import java.util.List;
import egovframework.example.test.domain.Search;
import egovframework.example.test.domain.TestVO;
public interface TestService {
public List<TestVO> selectTest(Search search) throws Exception;
public void insertTest(TestVO testVO)throws Exception;
public TestVO selectDetail(TestVO testVO) throws Exception;
public void updateTest(TestVO testVO) throws Exception;
public void deleteTest(TestVO testVO) throws Exception;
//총 게시글 개수 확인
public int getBoardListCnt(Search search) throws Exception;
}
TestServiceImpl
package egovframework.example.test.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import egovframework.example.test.dao.TestDAO;
import egovframework.example.test.domain.Search;
import egovframework.example.test.domain.TestVO;
import egovframework.example.test.service.TestService;
@Service("testServiceImpl")
public class TestServiceImpl implements TestService {
@Autowired
private TestDAO testDAOService;
@Override
public List<TestVO> selectTest(Search search) throws Exception {
return testDAOService.selectTest(search);
}
@Override
public void insertTest(TestVO testVO) throws Exception {
testDAOService.insertTest(testVO);
}
@Override
public TestVO selectDetail(TestVO testVO) throws Exception {
/*
* TestVO resultVO = testDAOService.selectDetail(testVO); return resultVO;
*/
return testDAOService.selectDetail(testVO);
}
@Override
public void updateTest(TestVO testVO) throws Exception {
testDAOService.updateTest(testVO);
}
@Override
public void deleteTest(TestVO testVO) throws Exception {
testDAOService.deleteTest(testVO);
}
// 총 게시글 개수 확인
@Override
public int getBoardListCnt(Search search) throws Exception {
return testDAOService.getBoardListCnt(search);
}
}
TestDAO
package egovframework.example.test.dao;
import java.util.List;
import egovframework.example.test.domain.Search;
import egovframework.example.test.domain.TestVO;
public interface TestDAO {
List<TestVO> selectTest(Search search) throws Exception;
void insertTest(TestVO testVO) throws Exception;
TestVO selectDetail(TestVO testVO) throws Exception;
void updateTest(TestVO testVO) throws Exception;
void deleteTest(TestVO testVO) throws Exception;
//총 게시글 개수 확인
public int getBoardListCnt(Search search) throws Exception;
}
TestDAOService
package egovframework.example.test.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import egovframework.example.test.domain.Search;
import egovframework.example.test.domain.TestVO;
import egovframework.example.test.service.TestMapper;
@Service("testDAOService")
public class TestDAOService implements TestDAO {
@Autowired
private SqlSession sqlSession;
@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(TestVO testVO) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
return mapper.selectDetail(testVO);
}
@Override
public void updateTest(TestVO testVO) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
mapper.updateTest(testVO);
}
@Override
public void deleteTest(TestVO testVO) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
mapper.deleteTest(testVO);
}
// 총 게시글 개수 확인
@Override
public int getBoardListCnt(Search search) throws Exception {
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
return mapper.getBoardListCnt(search);
}
}
TestMapper.java
package egovframework.example.test.service;
import java.util.List;
import egovframework.example.test.domain.Search;
import egovframework.example.test.domain.TestVO;
public interface TestMapper {
// 게시물 리스트 조회
public List<TestVO> selectTest(Search search) throws Exception;
// 게시물 작성
public void insertTest(TestVO testVO) throws Exception;
// 게시물 조회
public TestVO selectDetail(TestVO testVO) throws Exception;
// 게시물 수정
public void updateTest(TestVO testVO) throws Exception;
// 게시물 삭제
public void deleteTest(TestVO testVO) throws Exception;
// 총 게시글 개수 확인
public int getBoardListCnt(Search search) throws Exception;
}
testList.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<html>
<head>
<!-- Bootstrap CSS -->
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
crossorigin="anonymous">
<link href="/css/test/test.css" rel="stylesheet" type="text/css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
</head>
<body>
<h1>게시판List</h1>
<div class="testlist">
<form id="boardForm" name="boardForm" method="post">
<table class="list_table">
<colgroup>
<col width="20%" />
<col width="50%" />
<col width="15%" />
<col width="15%" />
</colgroup>
<tbody>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>등록일자</th>
</tr>
</thead>
<!-- jstl 데이터베이스를 검색해 넘겨 받은 list 를 result 라는 이름으로 순차적으로 실행을 시키게 됨 java의 for문같이 순차적으로 실행시킴-->
<c:forEach items="${list}" var="result">
<tr>
<td><c:out value="${result.testId}" /></td>
<td><a href='#' onClick='fn_view(${result.testId})'><c:out
value="${result.testTitle }" /></a></td>
<td><c:out value="${result.testName}" /></td>
<td><c:out value="${result.testDate}" /></td>
</tr>
</c:forEach>
</tbody>
</table>
</form>
</div>
<div>
<button id="btn_write" type="button" class="btn_write">글작성</button>
</div>
<br>
<!-- pagination{s} -->
<div id="paginationBox" class="pagination1">
<ul class="pagination">
<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{e} -->
<!-- search{s} -->
<div class="form-group row justify-content-center">
<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"
<%-- value="${pagination.keyword}" --%> 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{e} -->
<!-- 페이지 목록 갯수 -->
<div class="form-group row justify-content-center">
<p>게시판 목록 갯수</p>
<div class="w100" style="padding-right: 10px">
<select class="form-control form-control-sm" name="searchType"
id="listSize" onchange="page(1)">
<option value="10"
<c:if test="${pagination.getListSize() == 10 }">selected="selected"</c:if>>10개</option>
<option value="15"
<c:if test="${pagination.getListSize() == 15 }">selected="selected"</c:if>>15개</option>
<option value="20"
<c:if test="${pagination.getListSize() == 20 }">selected="selected"</c:if>>20개</option>
</select>
</div>
</div>
</body>
<script type="text/javascript">
//글 작성 버튼 클릭 시 testRegister로 이동
$("#btn_write").click(function javascript_onclikc() {
$(location).attr('href', 'testRegister.do');
});
//글조회
// 어떤 게시물을 클릭했는지 게시물의 번호(testId)를 넘겨 줘야 함 따라서 게시물 클릭 이벤트에서 게시물의 번호를 인자 값으로 받습니다.
// get 방식으로 데이터를 전송합니다. 따라서 ? 연산자를 사용해 testId를 주소 뒤에 붙여 줍니다
function fn_view(testId){
var form = document.getElementById("boardForm");
var url = "<c:url value='/testDetail.do'/>";
url = url + "?testId=" + testId;
form.action = url;
form.submit();
}
//이전 버튼 이벤트
//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 = url + "?page=" + page;
url = url + "&range=" + range;
url = url + "&listSize=" + listSize;
url = url + "&searchType=" + searchType;
url = url + "&keyword=" + keyword;
location.href = url;
}
//페이지 번호 클릭
function fn_pagination(page, range, rangeSize, listSize, searchType, keyword) {
var url = "/testList.do";
url = url + "?page=" + page;
url = url + "&range=" + range;
url = url + "&listSize=" + listSize;
url = url + "&searchType=" + searchType;
url = 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 = url + "?page=" + page;
url = url + "&range=" + range;
url = url + "&listSize=" + listSize;
url = url + "&searchType=" + searchType;
url = url + "&keyword=" + keyword;
location.href = url;
}
/* $는 jQuery를 시작하는 명령어로
$(DOM요소) 와 같은 명령어로 각 요소에 접근 할 수 있다.
e.preventDefault(); 는 버튼 고유의 기능을 막는 명령어 */
// 검색
$(document).on('click', '#btnSearch', function(e){
e.preventDefault();
var url = "/testList.do";
url = url + "?searchType=" + $('#searchType').val();
url = url + "&keyword=" + $('#keyword').val();
url = url + "&listSize=" + $('#listSize').val();
location.href = url;
console.log(url);
});
/*한페이지당 게시물 */
function page(testId){
var startPage = testId;
var listSize = $("#listSize option:selected").val();
if(listSize == 10){
var url="/testList.do?startPage="+startPage+"&listSize="+listSize
}else if(listSize == 15){
var url ="/testList.do?startPage="+startPage+"&listSize="+listSize
}else if(listSize == 20){
var url="/testList.do?startPage="+startPage+"&listSize="+listSize
}
location.href = url;
}
</script>
</html>
페이징과 검색 selectbox가 다 기능하는 모습입니다. 목록 갯수 변경 후 검색, 페이징 등
'Spring Framework > 게시판 연습' 카테고리의 다른 글
6. ajax게시판 만들기(list,페이징,검색,selectbox)(JSON형태로 AJAX비동기 통신) (0) | 2020.10.19 |
---|---|
5. 게시판 만들기(파일 업로드 다운로드) (1) | 2020.09.25 |
3. 게시판 만들기 CRUD 게시물 작성 수정 삭제 (2) | 2020.09.24 |
2. 게시판 만들기 maria DB 연결 (0) | 2020.09.22 |
1. 게시판 만들기 환경설정 egovframework(전자정부프레임워크) springframework(스프링프레임워크) (0) | 2020.09.21 |