넘버링
1. listPage.jsp --> 추가
<bash />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/include/header.jsp" %>
<script>
var result = "${msg}";
if(result == "register"){ // alert 뜬 후 새로고침하면 없어지므로 다시 뜨진 않음
alert("작성 완료!");
}else if(result == "delete"){
alert("삭제 완료!");
}else if(result == "modify"){
alert("수정 완료!");
}
</script>
<center>
<h3>LIST PAGE</h3>
<table border=1 width=700>
<tr>
<th style="width:10px">BNO</th>
<th>TITLE</th>
<th>WRITER</th>
<th>REGDATE</th>
<th style="width: 40px">VIEWCNT</th>
</tr>
<c:set var="number" value="${pageMaker.totalCount - (pageMaker.cri.page - 1) * pageMaker.cri.perPageNum }" />
<c:forEach var="boardVO" items="${list}">
<tr>
<td>${number}</td>
<td> <!-- pageMaker.cri.page or cri.page -->
<%-- <a href="/board/readPage?bno=${boardVO.bno }&page=${pageMaker.cri.page}">${boardVO.title }</a> --%>
<a href="/board/readPage${pageMaker.makeQuery(pageMaker.cri.page)}&bno=${boardVO.bno }">${boardVO.title }</a> <!-- UriComponentsBuilder 이용한다면 -->
</td>
<td>${boardVO.writer }</td>
<!-- <td>${boardVO.regdate }</td> -->
<td><fmt:formatDate pattern="yyyy-MM-dd HH:mm:ss" value="${boardVO.regdate }"/></td>
<td>${boardVO.viewcnt }</td>
</tr>
<c:set var="number" value="${number - 1 }"/>
</c:forEach>
</table>
<br>
<table border=0 width=700>
<tr>
<td align=right><a href="register">[글쓰기]</a></td>
</tr>
</table>
<!-- 페이징 추가 -->
<table border=1 align=center>
<tr>
<c:if test="${pageMaker.prev}">
<td>
<%-- <a href="listPage?page=${pageMaker.startPage - 1 }">«</a> --%>
<a href="listPage${pageMaker.makeQuery(pageMaker.startPage - 1)}">«</a>
</td>
</c:if>
<c:forEach var="idx" begin="${pageMaker.startPage }" end="${pageMaker.endPage }">
<td>
<c:if test="${pageMaker.cri.page == idx}"><b></c:if>
<a href="listPage${pageMaker.makeQuery(idx)}">${idx}</a> <!-- <a href="listPage?page=${idx}">${idx}</a> -->
<c:if test="${pageMaker.cri.page == idx}"></b></c:if>
</td>
</c:forEach>
<c:if test="${pageMaker.next && pageMaker.endPage > 0}">
<td>
<%-- <a href="listPage?page=${pageMaker.endPage +1 }">»</a> --%>
<a href="listPage${pageMaker.makeQuery(pageMaker.endPage +1)}">»</a>
</td>
</c:if>
</tr>
</table>
</center>
<%@ include file="/WEB-INF/views/include/footer.jsp" %>
조회수
1. boardMapper.xml --> 추가
<bash />
<update id="updateViewCnt">
update tbl_board set viewcnt = viewcnt + 1 where bno = #{bno}
</update>
2. BoardDAOImpl.java --> 추가
<bash />
@Override
public BoardVO read(Integer bno) throws Exception { // 있다면
session.update(namespace+".updateViewCnt", bno); // 조회수 올린 다음
return session.selectOne(namespace+".read", bno); // 한건의 데이터 보여주기
}
검색
사용자가 게시물을 검색을 하고 난 후, 목록 페이지를 만들려면 적어도 다음과 같은 정보가 필요
ㄴ> page(현재페이지의 번호)
ㄴ> perPageNum(페이지당 보여지는 데이터의 수)
ㄴ> searchType(field)
ㄴ> keyword
1. SearchCriteria.java
<bash />package org.zerock.domain; import lombok.Data; @Data public class SearchCriteria extends Criteria { // 상속(Cri 대신 사용하면 됨) private String searchType; private String keyword; }
2. SearchBoardController.java
<bash />
package org.zerock.controller;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestMethod;
import org.zerock.domain.PageMaker;
import org.zerock.domain.SearchCriteria;
import org.zerock.service.BoardService;
@Controller
@RequestMapping("/sboard/*") // 부모
public class SearchBoardController {
private static final Logger logger = LoggerFactory.getLogger(SearchBoardController.class);
@Inject
private BoardService service; //인스턴스 변수의 선언으로 BoardService 객체를 주입 받을 수 있게 설계 처리
//@ModelAttribute("cri")를 사용함으로써 cri객체를 list.jsp에 자동 전달 처리된다.
@RequestMapping(value = "/list", method = RequestMethod.GET)
public void list(@ModelAttribute("cri") SearchCriteria cri, Model model) throws Exception {
logger.info(cri.toString());
model.addAttribute("list", service.listCriteria(cri));
PageMaker pageMaker = new PageMaker();
pageMaker.setCri(cri);
pageMaker.setTotalCount(service.listCountCriteria(cri));
model.addAttribute("pageMaker", pageMaker);
//위 @ModelAttribute("cri") 생략 한다면 아래 구문을 추가해 준다.
//model.addAttribute("cri", cri);
}
}
3. PageMaker.java --> 추가
<bash />
// search 추가
public String makeSearch(int page) {
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.queryParam("page", page)
.queryParam("perPageNum", cri.getPerPageNum())
.queryParam("searchType", ((SearchCriteria) cri).getSearchType())
.queryParam("keyword", ((SearchCriteria) cri).getKeyword())
//.queryParam("keyword", encoding(((SearchCriteria) cri).getKeyword())) //한글이 깨진다면 사용
.build();
return uriComponents.toUriString();
}
4. sboard 폴더 생성 --> views 에
5. sboard/list.jsp
<bash />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/include/header.jsp" %>
<script>
var result = "${msg}";
if(result == "register"){ // alert 뜬 후 새로고침하면 없어지므로 다시 뜨진 않음
alert("작성 완료!");
}else if(result == "delete"){
alert("삭제 완료!");
}else if(result == "modify"){
alert("수정 완료!");
}
</script>
<script>
function change(ppn){
/* location.href="list?page=1&perPageNum="+ppn; */
location.href="list?page=1&perPageNum="+ppn+"&searchType=${cri.searchType}&keyword=${cri.keyword}";
}
</script>
<center>
<h3>LIST PAGE</h3>
<table border=0 width=700>
<tr>
<td>
Total : ${pageMaker.totalCount } <!-- pageMaker가 가지고 있으므로 -->
<select name="perPageNum" onchange="change(this.value)">
<option value="1" <c:if test="${pageMaker.cri.perPageNum == 1}">selected</c:if>>1개</option>
<option value="2" <c:if test="${pageMaker.cri.perPageNum == 2}">selected</c:if>>2개</option>
<option value="4" <c:if test="${pageMaker.cri.perPageNum == 4}">selected</c:if>>4개</option>
<option value="5" <c:if test="${pageMaker.cri.perPageNum == 5}">selected</c:if>>5개</option>
<option value="10" <c:if test="${pageMaker.cri.perPageNum == 10}">selected</c:if>>10개</option>
</select>
</td>
<td align=right>
<!-- search 시작 -->
<form method="get">
<input type="hidden" name="perPageNum" value="${pageMaker.cri.perPageNum}">
<select name="searchType">
<option value="n" ${cri.searchType == null?'selected':''}>---</option>
<option value="t" ${cri.searchType eq 't'?'selected':''}>Title</option>
<option value="c" ${cri.searchType eq 'c'?'selected':''}>Content</option>
<option value="w" ${cri.searchType eq 'w'?'selected':''}>Writer</option>
<option value="tc" ${cri.searchType eq 'tc'?'selected':''}>Title OR Content</option>
<option value="cw" ${cri.searchType eq 'cw'?'selected':''}>Content OR Writer</option>
<option value="tcw" ${cri.searchType eq 'tcw'?'selected':''}>Title OR Content OR Writer</option>
</select>
<input type="text" name='keyword' id="keywordInput" value='${cri.keyword }'>
<input type="submit" value="Search">
</form>
<!-- search 끝 -->
</td>
</tr>
</table>
<table border=1 width=700>
<tr>
<th style="width:10px">BNO</th>
<th>TITLE</th>
<th>WRITER</th>
<th>REGDATE</th>
<th style="width: 40px">VIEWCNT</th>
</tr>
<c:set var="number" value="${pageMaker.totalCount - (pageMaker.cri.page - 1) * pageMaker.cri.perPageNum }" />
<c:forEach var="boardVO" items="${list}">
<tr>
<td>${number}</td>
<td> <!-- pageMaker.cri.page or cri.page -->
<%-- <a href="/board/readPage?bno=${boardVO.bno }&page=${pageMaker.cri.page}">${boardVO.title }</a> --%>
<a href="read${pageMaker.makeSearch(pageMaker.cri.page)}&bno=${boardVO.bno }">${boardVO.title }</a> <!-- UriComponentsBuilder 이용한다면 -->
</td>
<td>${boardVO.writer }</td>
<!-- <td>${boardVO.regdate }</td> -->
<td><fmt:formatDate pattern="yyyy-MM-dd HH:mm:ss" value="${boardVO.regdate }"/></td>
<td>${boardVO.viewcnt }</td>
</tr>
<c:set var="number" value="${number - 1 }"/>
</c:forEach>
</table>
<br>
<table border=0 width=700>
<tr>
<td align=right><a href="register${pageMaker.makeQuery(pageMaker.cri.page)}">[글쓰기]</a></td>
</tr>
</table>
<!-- 페이징 추가 -->
<table border=1 align=center>
<tr>
<c:if test="${pageMaker.prev}">
<td>
<%-- <a href="listPage?page=${pageMaker.startPage - 1 }">«</a> --%>
<a href="list${pageMaker.makeSearch(pageMaker.startPage - 1)}">«</a>
</td>
</c:if>
<c:forEach var="idx" begin="${pageMaker.startPage }" end="${pageMaker.endPage }">
<td>
<c:if test="${pageMaker.cri.page == idx}"><b></c:if>
<a href="list${pageMaker.makeSearch(idx)}">${idx}</a> <!-- <a href="listPage?page=${idx}">${idx}</a> -->
<c:if test="${pageMaker.cri.page == idx}"></b></c:if>
</td>
</c:forEach>
<c:if test="${pageMaker.next && pageMaker.endPage > 0}">
<td>
<%-- <a href="listPage?page=${pageMaker.endPage +1 }">»</a> --%>
<a href="list${pageMaker.makeSearch(pageMaker.endPage +1)}">»</a>
</td>
</c:if>
</tr>
</table>
</center>
<%@ include file="/WEB-INF/views/include/footer.jsp" %>
6. header.jsp --> 추가
<bash />
<a href="/sboard/list">[listSearch]</a>
7. BoardDAO.java --> 추가
<bash />public List<BoardVO> listSearch(SearchCriteria cri) throws Exception; public int listSearchCount(SearchCriteria cri) throws Exception;
8. BoardDAOImpl.java --> 추가
<bash />
@Override // 검색
public List<BoardVO> listSearch(SearchCriteria cri) throws Exception {
return session.selectList(namespace+".listSearch", cri);
}
@Override
public int listSearchCount(SearchCriteria cri) throws Exception {
return session.selectOne(namespace+".listSearchCount", cri);
}
9. boardMapper.xml --> 추가
<bash />
<!-- search -->
<select id="listSearch" resultType="BoardVO">
<![CDATA[
select * from tbl_board where bno > 0
]]>
<include refid="search"></include>
<![CDATA[
order by bno desc, regdate desc limit #{pageStart}, #{perPageNum}
]]>
</select>
<select id="listSearchCount" resultType="int">
<![CDATA[
select count(bno) from tbl_board where bno > 0
]]>
<include refid="search"></include>
</select>
<sql id="search">
<if test="searchType != null" >
<!--
MyBatis에서는 변수가 자바객체처럼 사용되므로
( OGNL (Object Graph Navigation Language)를 사용하여 속성 처리를 하고 있기 때문에 )
자바에서 사용되는 문자열 비교 메소드를 이용하면 된다.
단 비교할 문자를 먼저 쓴 경우도 에러 발생.
<if test="searchType == 't'.toString()"> (o)
<if test="searchType eq 't'.toString()"> (o)
<if test="searchType.toString() == 't'.toString()"> (o)
<if test="searchType.equalsIgnoreCase('t')"> (o)
<if test='searchType == "t"'> (o)
// 작은, 큰 따옴표 순서
<if test='"t".equals(searchType)'> (o) toString() 사용안하는 경우에
<if test="'t'.equals(searchType)"> (x)
<if test='searchType.equals("t")'> (o)
<if test="searchType.equals('t')"> (x)
-->
<!-- CONCAT 함수 필수(like 비교를 위해서) -->
<if test="searchType == 't'.toString()"> <!-- title이라면 -->
and title like CONCAT('%', #{keyword}, '%')
</if>
<if test="searchType == 'c'.toString()"> <!-- content라면 -->
and content like CONCAT('%', #{keyword}, '%')
</if>
<if test="searchType == 'w'.toString()"> <!-- writer이라면 -->
and writer like CONCAT('%', #{keyword}, '%')
</if>
<if test="searchType == 'tc'.toString()"> <!-- title, content라면 -->
and ( title like CONCAT('%', #{keyword}, '%') OR content like CONCAT('%', #{keyword}, '%'))
</if>
<if test="searchType == 'cw'.toString()"> <!-- content, writer이라면 -->
and ( content like CONCAT('%', #{keyword}, '%') OR writer like CONCAT('%', #{keyword}, '%'))
</if>
<if test="searchType == 'tcw'.toString()"> <!-- title, content, writer이라면 -->
and
( title like CONCAT('%', #{keyword}, '%')
OR content like CONCAT('%', #{keyword}, '%')
OR writer like CONCAT('%', #{keyword}, '%'))
</if>
</if>
</sql>
10. BoardDAOTest.java
<bash />
//@Test
public void testDynamic1() throws Exception {
SearchCriteria cri = new SearchCriteria();
cri.setKeyword("df");
cri.setSearchType("t"); //제목(title)
logger.info("-------------------------------------");
logger.info(cri.toString());
List<BoardVO> list = dao.listSearch(cri);
for (BoardVO boardVO : list) {
logger.info(boardVO.getBno() + ": " + boardVO.getTitle()); //목록 출력
}
logger.info("=====================================");
logger.info("COUNT: " + dao.listSearchCount(cri)); //검색된 총 개수
}

11. BoardService.java --> 추가
<bash />public List<BoardVO> listSearchCriteria(SearchCriteria cri) throws Exception; public int listSearchCount(SearchCriteria cri) throws Exception;
12. BoardServiceImpl.java --> 추가
<bash />
@Override
public List<BoardVO> listSearchCriteria(SearchCriteria cri) throws Exception {
return dao.listSearch(cri);
}
@Override
public int listSearchCount(SearchCriteria cri) throws Exception {
return dao.listSearchCount(cri);
}
13. SearchBoardController.java --> list 부분 수정 & 나머지 페이지들 추가
<bash />
package org.zerock.controller;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.zerock.domain.BoardVO;
import org.zerock.domain.PageMaker;
import org.zerock.domain.SearchCriteria;
import org.zerock.service.BoardService;
@Controller
@RequestMapping("/sboard/*") // 부모
public class SearchBoardController {
private static final Logger logger = LoggerFactory.getLogger(SearchBoardController.class);
@Inject
private BoardService service; //인스턴스 변수의 선언으로 BoardService 객체를 주입 받을 수 있게 설계 처리
//@ModelAttribute("cri")를 사용함으로써 cri객체를 list.jsp에 자동 전달 처리된다.
@RequestMapping(value = "/list", method = RequestMethod.GET)
public void list(@ModelAttribute("cri") SearchCriteria cri, Model model) throws Exception {
logger.info(cri.toString());
//model.addAttribute("list", service.listCriteria(cri));
model.addAttribute("list", service.listSearchCriteria(cri));
PageMaker pageMaker = new PageMaker();
pageMaker.setCri(cri);
//pageMaker.setTotalCount(service.listCountCriteria(cri));
pageMaker.setTotalCount(service.listSearchCount(cri));
model.addAttribute("pageMaker", pageMaker);
//위 @ModelAttribute("cri") 생략 한다면 아래 구문을 추가해 준다.
//model.addAttribute("cri", cri);
}
@RequestMapping(value = "/read", method = RequestMethod.GET)
public void read(@RequestParam("bno") int bno, @ModelAttribute("cri") SearchCriteria cri, Model model) throws Exception {
PageMaker pageMaker = new PageMaker();
pageMaker.setCri(cri);
model.addAttribute("pageMaker", pageMaker);
model.addAttribute(service.read(bno));
}
@RequestMapping(value = "/modify", method = RequestMethod.GET)
public void modifyGET(int bno, @ModelAttribute("cri") SearchCriteria cri, Model model) throws Exception {
model.addAttribute(service.read(bno));
}
@RequestMapping(value = "/modify", method = RequestMethod.POST)
public String modifyPOST(BoardVO board, SearchCriteria cri, RedirectAttributes rttr) throws Exception {
logger.info(cri.toString());
service.modify(board);
rttr.addAttribute("page", cri.getPage());
rttr.addAttribute("perPageNum", cri.getPerPageNum());
rttr.addAttribute("searchType", cri.getSearchType());
rttr.addAttribute("keyword", cri.getKeyword());
rttr.addFlashAttribute("msg", "modify");
logger.info(rttr.toString());
return "redirect:/sboard/list";
}
@RequestMapping(value = "/remove", method = RequestMethod.GET)
public String remove(@RequestParam("bno") int bno, SearchCriteria cri, RedirectAttributes rttr) throws Exception {
service.remove(bno);
rttr.addAttribute("page", cri.getPage());
rttr.addAttribute("perPageNum", cri.getPerPageNum());
rttr.addAttribute("searchType", cri.getSearchType());
rttr.addAttribute("keyword", cri.getKeyword());
rttr.addFlashAttribute("msg", "delete");
return "redirect:/sboard/list";
}
@RequestMapping(value = "/register", method = RequestMethod.GET)
public void registGET() throws Exception {
logger.info("regist get ...........");
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String registPOST(BoardVO board, RedirectAttributes rttr) throws Exception {
logger.info("regist post ...........");
logger.info(board.toString());
service.regist(board);
rttr.addFlashAttribute("msg", "register");
return "redirect:/sboard/list";
}
}
14. sboard/register.jsp
<bash />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/include/header.jsp" %>
<center>
<h3>WRITER PAGE</h3>
<form method="post">
<table>
<tr>
<td>제목</td>
<td><input name="title"></td>
</tr>
<tr>
<td>내용</td>
<td><textarea name="content" rows="3"></textarea></td>
</tr>
<tr>
<td>작성자</td>
<td><input name="writer"></td>
</tr>
<tr>
<td></td>
<td><button>Submit</button></td>
</tr>
</table>
</form>
</center>
<%@ include file="/WEB-INF/views/include/footer.jsp" %>
15. sboard/read.jsp
<bash />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/include/header.jsp" %>
<center>
<h3>READ PAGE</h3>
<table border=1 width=570>
<tr>
<td width=70>제목</td>
<td width=500>${boardVO.title }</td>
</tr>
<tr>
<td>내용</td>
<td>${boardVO.content }</td>
</tr>
<tr>
<td>작성자</td>
<td>${boardVO.writer }</td>
</tr>
</table>
<br>
<table border=0 width=570>
<tr>
<td width=50%>
<%-- <a href="list?&page=${param.page}">[리스트]</a> --%>
<a href="list${pageMaker.makeSearch(pageMaker.cri.page)}">[list]</a>
</td>
<td width=50% align="right">
<%-- <a href="modify?bno=${boardVO.bno }&page=${param.page}">[수정]</a> --%> <!-- pageMaker.cri.page or 주소창에 이미 불러와있으므로 param.page도 가능 -->
<a href="modify${pageMaker.makeSearch(pageMaker.cri.page)}&bno=${boardVO.bno }">수정</a>
<a href="remove?bno=${boardVO.bno }">[삭제]</a>
</td>
</tr>
</table>
<!-- ajax 이용 -->
<form role="pkt" name="pkt" method="get">
<input type="hidden" name="bno" value="${boardVO.bno }">
</form>
<button class="btn-modify">수정</button>
<button class="btn-delete">삭제</button>
<button class="btn-list">리스트</button>
</center>
<%@ include file="/WEB-INF/views/include/footer.jsp" %>
16. sboard/modify.jsp
<bash />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/include/header.jsp" %>
<center>
<h3>MODIFY PAGE</h3>
<form role="pkt" name="pkt" method="post">
<input type="hidden" name="bno" value="${boardVO.bno}">
<input type="hidden" name="page" value="${param.page}">
<table>
<tr>
<td>제목</td>
<td><input name="title" value="${boardVO.title}"></td>
</tr>
<tr>
<td>내용</td>
<td><textarea name="content" rows="3">${boardVO.content}</textarea></td>
</tr>
<tr>
<td>작성자</td>
<td><input name="writer" value="${boardVO.writer}" readonly></td>
</tr>
<tr>
<td></td>
<td><button type="submit">Submit</button></td>
</tr>
</table>
</form>
</center>
<%@ include file="/WEB-INF/views/include/footer.jsp" %>
'JAVA > spring' 카테고리의 다른 글
스프링 댓글 구현 (0) | 2023.05.04 |
---|---|
스프링 member 구현 (0) | 2023.05.03 |
스프링 Board 구현_예외처리, 페이징 (1) | 2023.05.02 |
스프링 Board 구현 (0) | 2023.04.28 |
스프링 페이지 이동(변수 전달) (0) | 2023.04.28 |