1. 게시판 검색
① 동적쿼리 필요
② 페이지 이동처리 필요
③ page, pageSize 뿐만아니라 + option, keyword 필요
2. MyBatis의 동적쿼리(1) - <sql>, <include> < include refid="...">
MyBatis의 동적쿼리(2) - <if>
와일드카드 |
||
Oracle | % (여러글자 0 <= ) | ? ( +1 자리인것 ) |
MySQL | % (여러글자 0 <= ) | _ ( +1 자리인것 ) |
% 는 0글자 이상 가능 / ?, _ 는 0자리는 인식못함. |
예시) title% 으로 검색시, title ( o )
title1 ( o )
title_ 으로 검색시, title ( x )
title1 ( o )
MyBatis의 동적쿼리(3) - <choose>, <when>
choose는 when이 여러개있을때 하나만 선택.
처음나오는 when 이 true 라면 2~번째꺼는 판단안함.
MyBatis의 동적쿼리(3) - <foreach>
<c:out value='~'> 태그 ( 해커로부터 보호)
Log4Jdbc Log4j2 JDBC 4 1 라이브러리 ( 인텔리제이 로그 확인가능)
log4jdbc.log4j2.properties
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<!-- log4jdbc-log4j2 -->
<logger name="jdbc.sqlonly" level="INFO"/>
<logger name="jdbc.sqltiming" level="INFO"/>
<logger name="jdbc.audit" level="WARN"/>
<logger name="jdbc.resultset" level="INFO"/>
<logger name="jdbc.resultsettable" level="INFO"/>
<logger name="jdbc.connection" level="INFO"/>
</configuration>
boardList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %> <%--core_rt or corert 버전때문에 사용--%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>
<%@ page session="true"%>
<c:set var="loginId" value="${sessionScope.id}"/>
<c:set var="loginOutLink" value="${loginId=='' ? '/login/login' : '/login/logout'}"/>
<c:set var="loginOut" value="${loginId=='' ? 'Login' : 'ID='+=loginId}"/>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>fastcampus</title>
<link rel="stylesheet" href="<c:url value='/css/menu.css'/>">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: "Noto Sans KR", sans-serif;
}
a {
text-decoration: none;
color: black;
}
button,
input {
border: none;
outline: none;
}
.board-container {
width: 60%;
height: 1200px;
margin: 0 auto;
/* border: 1px solid black; */
}
.search-container {
background-color: rgb(253, 253, 250);
width: 100%;
height: 110px;
border: 1px solid #ddd;
margin-top : 10px;
margin-bottom: 30px;
display: flex;
justify-content: center;
align-items: center;
}
.search-form {
height: 37px;
display: flex;
}
.search-option {
width: 100px;
height: 100%;
outline: none;
margin-right: 5px;
border: 1px solid #ccc;
color: gray;
}
.search-option > option {
text-align: center;
}
.search-input {
color: gray;
background-color: white;
border: 1px solid #ccc;
height: 100%;
width: 300px;
font-size: 15px;
padding: 5px 7px;
}
.search-input::placeholder {
color: gray;
}
.search-button {
/* 메뉴바의 검색 버튼 아이콘 */
width: 20%;
height: 100%;
background-color: rgb(22, 22, 22);
color: rgb(209, 209, 209);
display: flex;
align-items: center;
justify-content: center;
font-size: 15px;
}
.search-button:hover {
color: rgb(165, 165, 165);
}
table {
border-collapse: collapse;
width: 100%;
border-top: 2px solid rgb(39, 39, 39);
}
tr:nth-child(even) {
background-color: #f0f0f070;
}
th,
td {
width:300px;
text-align: center;
padding: 10px 12px;
border-bottom: 1px solid #ddd;
}
td {
color: rgb(53, 53, 53);
}
.no { width:150px;}
.title { width:50%; }
td.title { text-align: left; }
td.writer { text-align: left; }
td.viewcnt { text-align: right; }
td.title:hover {
text-decoration: underline;
}
.paging {
color: black;
width: 100%;
align-items: center;
}
.page {
color: black;
padding: 6px;
margin-right: 10px;
}
.paging-active {
background-color: rgb(216, 216, 216);
border-radius: 5px;
color: rgb(24, 24, 24);
}
.paging-container {
width:100%;
height: 70px;
display: flex;
margin-top: 50px;
margin : auto;
}
.btn-write {
background-color: rgb(236, 236, 236); /* Blue background */
border: none; /* Remove borders */
color: black; /* White text */
padding: 6px 12px; /* Some padding */
font-size: 16px; /* Set a font size */
cursor: pointer; /* Mouse pointer on hover */
border-radius: 5px;
margin-left: 30px;
}
.btn-write:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div id="menu">
<ul>
<li id="logo">fastcampus</li>
<li><a href="<c:url value='/'/>">Home</a></li>
<li><a href="<c:url value='/board/list'/>">Board</a></li>
<li><a href="<c:url value='${loginOutLink}'/>">${loginOut}</a></li>
<li><a href="<c:url value='/register/add'/>">Sign in</a></li>
<li><a href=""><i class="fa fa-search"></i></a></li>
</ul>
</div>
<script>
let msg = "${msg}";
if(msg=="LIST_ERR") alert("게시물 목록을 가져오는데 실패했습니다. 다시 시도해 주세요.");
if(msg=="READ_ERR") alert("삭제되었거나 없는 게시물입니다.");
if(msg=="DEL_ERR") alert("삭제되었거나 없는 게시물입니다.");
if(msg=="DEL_OK") alert("성공적으로 삭제되었습니다.");
if(msg=="WRT_OK") alert("성공적으로 등록되었습니다.");
if(msg=="MOD_OK") alert("성공적으로 수정되었습니다.");
</script>
<div style="text-align:center">
<div class="board-container">
<div class="search-container">
<form action="<c:url value="/board/list"/>" class="search-form" method="get">
<select class="search-option" name="option">
<option value="A" ${ph.sc.option=='A' || ph.sc.option=='' ? "selected" : ""}>제목+내용</option>
<option value="T" ${ph.sc.option=='T' ? "selected" : ""}>제목만</option>
<option value="W" ${ph.sc.option=='W' ? "selected" : ""}>작성자</option>
</select>
<input type="text" name="keyword" class="search-input" type="text" value="${ph.sc.keyword}" placeholder="검색어를 입력해주세요">
<input type="submit" class="search-button" value="검색">
</form>
<button id="writeBtn" class="btn-write" onclick="location.href='<c:url value="/board/write"/>'"><i class="fa fa-pencil"></i> 글쓰기</button>
</div>
<table>
<tr>
<th class="no">번호</th>
<th class="title">제목</th>
<th class="writer">이름</th>
<th class="regdate">등록일</th>
<th class="viewcnt">조회수</th>
</tr>
<c:forEach var="boardDto" items="${list}">
<tr>
<td class="no">${boardDto.bno}</td>
<td class="title"><a href="<c:url value="/board/read${ph.sc.queryString}&bno=${boardDto.bno}"/>"><c:out value='${boardDto.title}'/></a></td>
<td class="writer">${boardDto.writer}</td>
<c:choose>
<c:when test="${boardDto.reg_date.time >= startOfToday}">
<td class="regdate"><fmt:formatDate value="${boardDto.reg_date}" pattern="HH:mm" type="time"/></td>
</c:when>
<c:otherwise>
<td class="regdate"><fmt:formatDate value="${boardDto.reg_date}" pattern="yyyy-MM-dd" type="date"/></td>
</c:otherwise>
</c:choose>
<td class="viewcnt">${boardDto.view_cnt}</td>
</tr>
</c:forEach>
</table>
<br>
<div class="paging-container">
<div class="paging">
<c:if test="${totalCnt==null || totalCnt==0}">
<div> 게시물이 없습니다. </div>
</c:if>
<c:if test="${totalCnt!=null && totalCnt!=0}">
<c:if test="${ph.showPrev}">
<a class="page" href="<c:url value="/board/list${ph.sc.getQueryString(ph.beginPage-1)}"/>"><</a>
</c:if>
<c:forEach var="i" begin="${ph.beginPage}" end="${ph.endPage}">
<a class="page ${i==ph.sc.page? "paging-active" : ""}" href="<c:url value="/board/list${ph.sc.getQueryString(i)}"/>">${i}</a>
</c:forEach>
<c:if test="${ph.showNext}">
<a class="page" href="<c:url value="/board/list${ph.sc.getQueryString(ph.endPage+1)}"/>">></a>
</c:if>
</c:if>
</div>
</div>
</div>
</div>
</body>
</html>
board.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %> <%--core_rt or corert 버전때문에 사용--%>
<%@ page session="true"%>
<c:set var="loginId" value="${sessionScope.id}"/>
<c:set var="loginOutLink" value="${loginId=='' ? '/login/login' : '/login/logout'}"/>
<c:set var="loginOut" value="${loginId=='' ? 'Login' : 'ID='+=loginId}"/>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>fastcampus</title>
<link rel="stylesheet" href="<c:url value='/css/menu.css'/>">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: "Noto Sans KR", sans-serif;
}
.container {
width : 50%;
margin : auto;
}
.writing-header {
position: relative;
margin: 20px 0 0 0;
padding-bottom: 10px;
border-bottom: 1px solid #323232;
}
input {
width: 100%;
height: 35px;
margin: 5px 0px 10px 0px;
border: 1px solid #e9e8e8;
padding: 8px;
background: #f8f8f8;
outline-color: #e6e6e6;
}
textarea {
width: 100%;
background: #f8f8f8;
margin: 5px 0px 10px 0px;
border: 1px solid #e9e8e8;
resize: none;
padding: 8px;
outline-color: #e6e6e6;
}
.frm {
width:100%;
}
.btn {
background-color: rgb(236, 236, 236); /* Blue background */
border: none; /* Remove borders */
color: black; /* White text */
padding: 6px 12px; /* Some padding */
font-size: 16px; /* Set a font size */
cursor: pointer; /* Mouse pointer on hover */
border-radius: 5px;
}
.btn:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div id="menu">
<ul>
<li id="logo">fastcampus</li>
<li><a href="<c:url value='/'/>">Home</a></li>
<li><a href="<c:url value='/board/list'/>">Board</a></li>
<li><a href="<c:url value='${loginOutLink}'/>">${loginOut}</a></li>
<li><a href="<c:url value='/register/add'/>">Sign in</a></li>
<li><a href=""><i class="fa fa-search"></i></a></li>
</ul>
</div>
<script>
let msg = "${msg}";
if(msg=="WRT_ERR") alert("게시물 등록에 실패하였습니다. 다시 시도해 주세요.");
if(msg=="MOD_ERR") alert("게시물 수정에 실패하였습니다. 다시 시도해 주세요.");
</script>
<div class="container">
<h2 class="writing-header">게시판 ${mode=="new" ? "글쓰기" : "읽기"}</h2>
<form id="form" class="frm" action="" method="post">
<input type="hidden" name="bno" value="${boardDto.bno}">
<%--out태그로 감사주면, out태그 내의 내용들을 자동으로 변환해주어 내용을 스크립트 적어도 막을수 있다.--%>
<%-- <input name="title" type="text" value="${boardDto.title}" placeholder=" 제목을 입력해 주세요." ${mode=="new" ? "" : "readonly='readonly'"}><br>--%>
<%-- <textarea name="content" rows="20" placeholder=" 내용을 입력해 주세요." ${mode=="new" ? "" : "readonly='readonly'"}>${boardDto.content}</textarea><br>--%>
<input name="title" type="text" value="<c:out value='${boardDto.title}'/>" placeholder=" 제목을 입력해 주세요." ${mode=="new" ? "" : "readonly='readonly'"}><br>
<textarea name="content" rows="20" placeholder=" 내용을 입력해 주세요." ${mode=="new" ? "" : "readonly='readonly'"}><c:out value='${boardDto.content}'/></textarea><br>
<c:if test="${mode eq 'new'}">
<button type="button" id="writeBtn" class="btn btn-write"><i class="fa fa-pencil"></i> 등록</button>
</c:if>
<c:if test="${mode ne 'new'}">
<button type="button" id="writeNewBtn" class="btn btn-write"><i class="fa fa-pencil"></i> 글쓰기</button>
</c:if>
<c:if test="${boardDto.writer eq loginId}">
<button type="button" id="modifyBtn" class="btn btn-modify"><i class="fa fa-edit"></i> 수정</button>
<button type="button" id="removeBtn" class="btn btn-remove"><i class="fa fa-trash"></i> 삭제</button>
</c:if>
<button type="button" id="listBtn" class="btn btn-list"><i class="fa fa-bars"></i> 목록</button>
</form>
</div>
<script>
$(document).ready(function(){
let formCheck = function() {
let form = document.getElementById("form");
if(form.title.value=="") {
alert("제목을 입력해 주세요.");
form.title.focus();
return false;
}
if(form.content.value=="") {
alert("내용을 입력해 주세요.");
form.content.focus();
return false;
}
return true;
}
$("#writeNewBtn").on("click", function(){
location.href="<c:url value='/board/write'/>";
});
$("#writeBtn").on("click", function(){
let form = $("#form");
form.attr("action", "<c:url value='/board/write'/>");
form.attr("method", "post");
if(formCheck())
form.submit();
});
$("#modifyBtn").on("click", function(){
let form = $("#form");
let isReadonly = $("input[name=title]").attr('readonly');
// 1. 읽기 상태이면, 수정 상태로 변경
if(isReadonly=='readonly') {
$(".writing-header").html("게시판 수정");
$("input[name=title]").attr('readonly', false);
$("textarea").attr('readonly', false);
$("#modifyBtn").html("<i class='fa fa-pencil'></i> 등록");
return;
}
// 2. 수정 상태이면, 수정된 내용을 서버로 전송
form.attr("action", "<c:url value='/board/modify${searchCondition.queryString}'/>");
form.attr("method", "post");
if(formCheck())
form.submit();
});
$("#removeBtn").on("click", function(){
if(!confirm("정말로 삭제하시겠습니까?")) return;
let form = $("#form");
form.attr("action", "<c:url value='/board/remove${searchCondition.queryString}'/>");
form.attr("method", "post");
form.submit();
});
$("#listBtn").on("click", function(){
location.href="<c:url value='/board/list${searchCondition.queryString}'/>";
});
});
</script>
</body>
</html>
pageHandler.java
package com.fastcampus.ch4.domain;
import org.springframework.web.util.*;
public class PageHandler {
// private int page; // 현재페이지
// private int pageSize; // 한 페이지의 크기(한화면에 몇개의 행을보여줄건지)
// private String option;
// private String keyword;
// ↑ 위4개 멤버를 SearchCondtion 객체로 묶음
private SearchCondition sc;
private int totalCnt; // 총개시물개수
private int naviSize=10; // 페이지 네비게이션의 크기 ( 표아래 1.2.3...버튼 )
private int totalPage; // 전체페이지의 갯수
private int beginPage; // 네비게이션의 첫번째 페이지
private int endPage; // 네비게이션의 마지막 페이지
private boolean showPrev; // 이전페이지로 이동하는 링크 여부
private boolean showNext; // 다음페이지로 이동하는 링크 여부
public PageHandler(){}
public PageHandler(int totalCnt, SearchCondition sc) {
this.totalCnt = totalCnt;
this.sc = sc;
doPaging(totalCnt, sc);
}
// public PageHandler(int totalCnt, int page){
// this(totalCnt, page, 10);
// }
public void doPaging(int totalCnt, SearchCondition sc) {
this.totalCnt = totalCnt;
totalPage = (int) Math.ceil(totalCnt / (double)sc.getPageSize()); // 총게시물 구하기 ( 소수점으로 떨어지면 +1페이지더하기위해 올림)
beginPage = (sc.getPage()-1) / naviSize * naviSize + 1; // 네비게이션의 첫번째 버튼 구하기 ( 1.2.3.4.5.6.7.8.9.10 네비버튼들이 있을때를 가정)
endPage = Math.min(beginPage + naviSize - 1, totalPage); //마지막페이지 첫 페이지에 + 네비버튼사이즈10 -1,
// 그런데 게시물개수가 10페이지도 안된다면? 전체페이로 보여주게끔 (3항연산자나, min 함수 사용)
showPrev = beginPage != 1; // showPrev 는 현재페이지가 첫페이지라면 보여주면 안됨.
showNext = endPage != totalPage; // showNext 는 현재페이지가 마지막 페이지라면 보여주면 안됨.
}
void print(){ // page navi 버튼을 print하는 메서드
// System.out.println("page = " + page);
System.out.print(showPrev ? "[Prev] " : "");
for (int i = beginPage; i <= endPage; i++) {
System.out.print(i + " ");
}
System.out.println(showNext ? " [Next]" : "");
}
@Override
public String toString() {
return "PageHandler{" +
"sc=" + sc +
", totalCnt=" + totalCnt +
", naviSize=" + naviSize +
", totalPage=" + totalPage +
", beginPage=" + beginPage +
", endPage=" + endPage +
", showPrev=" + showPrev +
", showNext=" + showNext +
'}';
}
public SearchCondition getSc() {
return sc;
}
public void setSc(SearchCondition sc) {
this.sc = sc;
}
public int getTotalCnt() {
return totalCnt;
}
public void setTotalCnt(int totalCnt) {
this.totalCnt = totalCnt;
}
public int getNaviSize() {
return naviSize;
}
public void setNaviSize(int naviSize) {
this.naviSize = naviSize;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getBeginPage() {
return beginPage;
}
public void setBeginPage(int beginPage) {
this.beginPage = beginPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public boolean isShowPrev() {
return showPrev;
}
public void setShowPrev(boolean showPrev) {
this.showPrev = showPrev;
}
public boolean isShowNext() {
return showNext;
}
public void setShowNext(boolean showNext) {
this.showNext = showNext;
}
}
searchCondition.java
package com.fastcampus.ch4.domain;
// 검색조건
import org.springframework.web.util.UriComponentsBuilder;
public class SearchCondition {
private Integer page=1;
private Integer pageSize=10;
// private Integer offset=0;
private String keyword="";
private String option="";
public String getQueryString(Integer page) {
return UriComponentsBuilder.newInstance()
.queryParam("page", page)
.queryParam("pageSize", pageSize)
.queryParam("option", option)
.queryParam("keyword", keyword)
.build().toString();
}
public String getQueryString(){
// 쿼리스트링으로 줘야함. 예처럼 반환하려는게 이 메서드 목적. // 예) page=1&pageSize=10&option=T&keyword="title"
// UriComponentsBuilder가 컴포넌츠를 예시처럼 만들어준다.
return getQueryString(getPage());
}
public SearchCondition(){}
public SearchCondition(Integer page, Integer pageSize, String keyword, String option) {
this.page = page;
this.pageSize = pageSize;
this.keyword = keyword;
this.option = option;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getOffset() {
return (page-1)*pageSize;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getOption() {
return option;
}
public void setOption(String option) {
this.option = option;
}
@Override
public String toString() {
return "SearchCondition{" +
"page=" + page +
", pageSize=" + pageSize +
", offset=" + getOffset() +
", keyword='" + keyword + '\'' +
", option='" + option + '\'' +
'}';
}
}
boardController.java
package com.fastcampus.ch4.controller;
import com.fastcampus.ch4.domain.BoardDto;
import com.fastcampus.ch4.domain.PageHandler;
import com.fastcampus.ch4.domain.SearchCondition;
import com.fastcampus.ch4.service.BoardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowired
BoardService boardService;
@PostMapping("/modify")
public String modify(BoardDto boardDto, HttpSession session, Model m, RedirectAttributes rattr, Integer page, Integer pageSize){
String writer = (String) session.getAttribute("id");
boardDto.setWriter(writer);
try {
int rowCnt = boardService.modify(boardDto); // 등록실패시 0
m.addAttribute("page", page);
m.addAttribute("pageSize", pageSize);
if (rowCnt != 1) {
throw new Exception("modify failed");
}
// m.addAttribute("msg", "Write_OK"); // 이렇게 작성시 계속 주소창에 남음 ↓ 이렇게 작성 추천
rattr.addFlashAttribute("msg", "modify_ok"); // 세션을 이용한 1회성 저장
return "redirect:/board/list";
} catch (Exception e) {
e.printStackTrace();
m.addAttribute(boardDto);
m.addAttribute("msg", "modify_error"); // 이렇게 작성시 계속 주소창에 남음 ↓ 이렇게 작성 추천
// rattr.addFlashAttribute("msg", "write_error"); // 세션을 이용한 1회성 저장
return "board"; // 등록 실패시, 입력했던 내용 다시 보여줄수 있도록
}
}
@PostMapping("/write")
public String write(BoardDto boardDto, HttpSession session, Model m, RedirectAttributes rattr){
String writer = (String) session.getAttribute("id");
boardDto.setWriter(writer);
try {
int rowCnt = boardService.write(boardDto); // 등록실패시 0
if (rowCnt != 1) {
throw new Exception("Write failed");
}
// m.addAttribute("msg", "Write_OK"); // 이렇게 작성시 계속 주소창에 남음 ↓ 이렇게 작성 추천
rattr.addFlashAttribute("msg", "write_ok"); // 세션을 이용한 1회성 저장
return "redirect:/board/list";
} catch (Exception e) {
e.printStackTrace();
m.addAttribute(boardDto);
m.addAttribute("msg", "write_error"); // 이렇게 작성시 계속 주소창에 남음 ↓ 이렇게 작성 추천
// rattr.addFlashAttribute("msg", "write_error"); // 세션을 이용한 1회성 저장
return "board"; // 등록 실패시, 입력했던 내용 다시 보여줄수 있도록
}
}
@GetMapping("/write")
public String write(Model m) {
m.addAttribute("mode", "new");
return "board"; // board.jsp 를 읽기와 쓰기에 사용 ( 쓰기 사용시 mode=new , mode가 new가 아니라면 읽기)
}
@PostMapping("/remove")
public String remove(Integer bno, Integer page, Integer pageSize, Model m, HttpSession session, RedirectAttributes rattr) {
String writer = (String) session.getAttribute("id");
try {
m.addAttribute("page",page);
m.addAttribute("pageSize",pageSize);
int rowCnt = boardService.remove(bno, writer); // writer은 어디에서 가져오는지? 세션에서
if(rowCnt != 1)
throw new Exception("board remove error");
rattr.addFlashAttribute("msg", "del_ok"); // rattr.addFlashAttribute 사용시,
// error, ok가 한번만 나오게된다.(1회성) 세션을 이용함
} catch (Exception e) {
e.printStackTrace();
rattr.addAttribute("msg", "del_error");
}
return "redirect:/board/list";
}
@GetMapping("/read")
public String read(Integer bno, Integer page, Integer pageSize, Model m){
try {
BoardDto boardDto = boardService.read(bno);
//m.addAttribute("boardDto",boardDto); // 이름생략가능 ↓ (아랫문장과 동일)
m.addAttribute(boardDto); // 생략시 이름의 첫글자를 소문자로한걸 이름으로 저장
m.addAttribute("page",page);
m.addAttribute("pageSize",pageSize);
} catch (Exception e) {
e.printStackTrace();
}
return "board";
}
@GetMapping("/list")
public String list(SearchCondition sc, Model m, HttpServletRequest request) {
if(!loginCheck(request))
return "redirect:/login/login?toURL="+request.getRequestURL(); // 로그인을 안했으면 로그인 화면으로 이동
try {
int totalCnt = boardService.getSearchResultCnt(sc);
m.addAttribute("totalCnt", totalCnt);
PageHandler pageHandler = new PageHandler(totalCnt, sc);
List<BoardDto> list = boardService.getSearchResultPage(sc);
m.addAttribute("list", list);
m.addAttribute("ph", pageHandler);
} catch (Exception e) {
e.printStackTrace();
}
return "boardList"; // 로그인을 한 상태이면, 게시판 화면으로 이동
}
// @GetMapping("/list")
// public String list(Integer page, Integer pageSize, Model m, HttpServletRequest request) {
// if(!loginCheck(request))
// return "redirect:/login/login?toURL="+request.getRequestURL(); // 로그인을 안했으면 로그인 화면으로 이동
//
// if(page==null) page =1;
// if(pageSize==null) pageSize =10;
//
// try {
// int totalCnt = boardService.getCount();
// PageHandler pageHandler = new PageHandler(totalCnt, page, pageSize);
//
// Map map = new HashMap();
// map.put("offset", (page-1)*pageSize);
// map.put("pageSize", pageSize);
//
// List<BoardDto> list = boardService.getPage(map);
// m.addAttribute("list", list);
// m.addAttribute("ph", pageHandler);
// m.addAttribute("page",page);
// m.addAttribute("pageSize",pageSize);
//
// } catch (Exception e) {
// e.printStackTrace();
// }
// return "boardList"; // 로그인을 한 상태이면, 게시판 화면으로 이동
// }
private boolean loginCheck(HttpServletRequest request) {
// 1. 세션을 얻어서
HttpSession session = request.getSession();
// 2. 세션에 id가 있는지 확인, 있으면 true를 반환
return session.getAttribute("id")!=null;
}
}
참고 :
남궁성, 스프링의 정석
'Spring의 정석' 카테고리의 다른 글
게시판만들기 (댓글2, 대댓글)11~13 (0) | 2023.04.01 |
---|---|
게시판만들기 (REST API와 Ajax, 댓글1)9~10 (0) | 2023.04.01 |
게시판만들기 (읽기,쓰기, 수정, 삭제)5~6 (0) | 2023.03.30 |
게시판만들기 ( 목록, 페이징 )3~4 (0) | 2023.03.30 |
게시판만들기 ( MyBatis 소개와 설정 )1~2 (0) | 2023.03.27 |