*
어디까지는 확실히 됐었고, 어디서부터 안되는지 구분을 해야함
구분을 해서 개별적으로 테스트를 하고, 정확하게 어디까지 되는지 확인 후 안되는부분을 확인, 안되는부분을 수정해야함
※ 복습
※
1. 라이브러리 파일(JSTL)
https://mvnrepository.com/artifact/jstl/jstl/1.2
jar파일 다운
※ 게시글에 대한 반복처리
1. JSTL(표준 태그 라이브러리) 사용
예제) web-inf에 jstl.jsp 생성
- el을 대상
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>2023. 3. 9.오전 10:16:19</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
</body>
</html>
태그 라이브러리를 등록해야함. jsp/jstl/core가 들어간 uri를 사용하며 프리픽스는 자동완성으로 c가 붙음
주로 forEach와 if를 사용
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>2023. 3. 9.오전 10:16:19</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
<!-- scope의 기본값은 page -->
<c:set var="num" value="20" />
<c:set var="title" value="<script>alert()</script>" />
<h2>${num}</h2>
<!-- 조금 더 합리적인 방법의 호출
c:out은 xss의 공격을 방지함 -->
<h2><c:out value="안녕하세요" /></h2>
<h2><c:out value="${num}" /></h2>
<!-- xss차단 불가 스크립트로 해석 -->
<%-- <h2>${title}</h2> --%>
<!-- 문자열로 해석하여 xss를 원천차단함 -->
<h2><c:out value="${title}" /> </h2>
<c:if test="">
</c:if>
</body>
</html>
if는 else가 없는 if임
jstl 종합예제)
<%@page import="java.util.ArrayList"%>
<%@page import="com.chanyongyang.jsp.vo.Board"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>2023. 3. 9.오전 10:16:19</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
<%
List<Board> boards = new ArrayList<>();
boards.add(new Board("aaa", "bbb", "ccc"));
boards.add(new Board("aaa1", "bbb", "ccc"));
boards.add(new Board("aaa2", "bbb", "ccc"));
request.setAttribute("boards", boards);
%>
<!-- scope의 기본값은 page, set을 통한 지정, out을 통한 출력 -->
<c:set var="num" value="15" />
<c:set var="title" value="<script>alert()</script>" />
<h2>${num}</h2>
<!-- 조금 더 합리적인 방법의 호출
c:out은 xss의 공격을 방지함 -->
<h2><c:out value="안녕하세요" /></h2>
<h2><c:out value="${num}" /></h2>
<!-- xss차단 불가 스크립트로 해석 -->
<%-- <h2>${title}</h2> --%>
<!-- 문자열로 해석하여 xss를 원천차단함 -->
<h2><c:out value="${title}" /> </h2>
<!-- 조건문1 -->
<c:if test="${num == 20}">
<h2>20 입니다</h2>
</c:if>
<c:if test="${num != 20}" >
<h2>20이 아닙니다</h2>
</c:if>
<!-- 조건문2 복합적인 형태에 사용 -->
<c:choose>
<c:when test="${num == 20}">
<h3>20 입니다</h3>
</c:when>
<c:when test="${num == 30}">
<h3>30 입니다</h3>
</c:when>
<c:otherwise>
<h3>20도 30도 아닙니다</h3>
</c:otherwise>
</c:choose>
<!-- 반복문(for와 같음 일반포문, 향상포문) 필수속성 : 1.
begin(이상) end(이하) step(건너뜀)-->
<c:forEach var="i" begin="1" end="10" step="3">
<h4>반복문장 ${i}</h4>
</c:forEach>
<h2>forEach를 활용한 구구단</h2>
<c:forEach var="i" begin="2" end="9">
<c:forEach var="j" begin="1" end="9" >
<h4>${i}*${j} = ${i*j}</h4>
</c:forEach>
</c:forEach>
<!-- items는 향상포문을 쓰겠다는것이며, 순회대상이 된다.
step 사용가능
varStatus는 index와 count를 호출할 수 있음 -->
<c:forEach var="board" items="${boards}" varStatus="stat" step="2">
<h4>${stat.index}</h4>
<h4>${stat.count}</h4>
<h3>${board.title}</h3>
</c:forEach>
<!-- c:import(잘 안씀)는 인클루드랑 비슷함
인클루드의 대상에 추가 파라미터를 줄 때 사용 c:param이랑 같이 사용 -->
<!-- c:catch는 예외처리 (잘안씀) -->
</body>
</html>
실습) 게시판 구현 및 꾸미기
1. 게시판 소스를 긁어와서
2. webapp 에 boardlist.html 생성
3. 사전준비
https://cdnjs.com/libraries/font-awesome/5.15.4
font-awesome - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers
The iconic SVG, font, and CSS toolkit - Simple. Fast. Reliable. Content delivery at its finest. cdnjs is a free and open-source CDN service trusted by over 12.5% of all websites, serving over 200 billion requests each month, powered by Cloudflare. We make
cdnjs.com
https://fontawesome.com/v5/icons/search?s=solid&f=classic
Font Awesome
The internet's icon library + toolkit. Used by millions of designers, devs, & content creators. Open-source. Always free. Always awesome.
fontawesome.com
head.jsp에 링크 추가
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' href=' https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/js/all.min.js" integrity="sha512-Tn2m0TIpgVyTzzvmxLNuqbSJH3JP8jm+Cy3hvHrW7ndTDcJ1w5mBiksqDBb8GpE2ksktFvDB/ykZ0mDpsZj20w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
4. vs코드에서 경로 찾아 작업
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' href=' https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/js/all.min.js" integrity="sha512-Tn2m0TIpgVyTzzvmxLNuqbSJH3JP8jm+Cy3hvHrW7ndTDcJ1w5mBiksqDBb8GpE2ksktFvDB/ykZ0mDpsZj20w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<header class="container-fluid bg-warning">
<div class="container">
<div class="pt-3">
<a href="/member_board" class="text-decoration-none">
<h1><span class="fs-2">더조은 아카데미</span> <span class="fs-6">AWS 클라우드 기반 자바&스프링&리액트 풀스택 개발자 양성</span></h1>
</a>
</div>
<nav class="navbar navbar-expand-sm">
<!-- Links -->
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">홈</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">게시판</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">갤러리</a>
</li>
</ul>
</nav>
</div>
</header>
<main class="container p-3 pb-5">
<div class="card">
<div class="card-header p-5">
<h2>Board List</h2>
</div>
<div class="card-body">
<div class="clearfix mb-3">
<div class="float-start">
<select class="form-select">
<option>10개씩보기</option>
<option>25개씩보기</option>
<option>50개씩보기</option>
</select>
</div>
<div class="float-start mx-5">
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Search">
<button class="btn btn-success" type="submit"><i class="fas fa-search"></i></button>
</div>
</div>
<a href="write" class="float-end btn btn-primary">write</a>
</div>
<div class="card">
<a href="view?bno=20" class="text-decoration-none">
<div class="container card-body border-bottom">
<div class="mb-4 text-truncate">java dao에서 테스트</div>
<div class="row text-muted small">
<div class="col-7">id1</div>
<div class="col text-end small"><span class="mr-3">2023-03-08 16:18:56</span> <span>조회수 0</span></div>
</div>
</div>
</a>
<a href="view?bno=20" class="text-decoration-none">
<div class="container card-body ">
<div class="mb-4 text-truncate">java dao에서 테스트 java dao에서 테스트java dao에서 테스트java dao에서 테스트java dao에서 테스트java dao에서 테스트java dao에서 테스트java dao에서 테스트</div>
<div class="row text-muted small">
<div class="col-7">id1</div>
<div class="col text-end small"><span class="mr-3">2023-03-08 16:18:56</span> <span>조회수 0</span></div>
</div>
</div>
</a>
</div>
<ul class="pagination mt-3 justify-content-center">
<li class="page-item"><a class="page-link" href="#">Previous</a></li>
<li class="page-item"><a class="page-link active" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
</div>
</div>
</main>
<footer class="container-fluid bg-warning p-5 text-center">
<address>copyright @ TJ academy</address>
</footer>
</body>
</html>
5. vscode 작업을 토대로 이클립스에서 구현
5-1) html의 card-body클래스만 긁어서 list.jsp에 추가
5-2) card 클래스에 반복문(forEach) 추가
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@ include file="../common/head.jsp" %>
</head>
<body>
<%@ include file="../common/header.jsp" %>
<main class="container p-3 pb-5">
<div class="card">
<div class="card-header p-5">
<h2>Board List</h2>
</div>
<div class="card-body">
<div class="clearfix mb-3">
<div class="float-start">
<select class="form-select">
<option>10개씩보기</option>
<option>25개씩보기</option>
<option>50개씩보기</option>
</select>
</div>
<div class="float-start mx-5">
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Search">
<button class="btn btn-success" type="submit"><i class="fas fa-search"></i></button>
</div>
</div>
<a href="write" class="float-end btn btn-primary">write</a>
</div>
<div class="card">
<c:forEach var="board" items="${boards}">
<a href="view?bno=${board.bno}" class="text-decoration-none">
<div class="container card-body border-bottom">
<div class="mb-4 text-truncate">${board.title}</div>
<div class="row text-muted small">
<div class="col-7">${board.writer}</div>
<div class="col text-end small"><span class="mx-3">${board.regdate}</span> <span>조회수 ${board.hitcount}</span></div>
</div>
</div>
</a>
</c:forEach>
</div>
<ul class="pagination mt-3 justify-content-center">
<li class="page-item"><a class="page-link" href="#">Previous</a></li>
<li class="page-item"><a class="page-link active" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
</div>
</div>
</main>
<%@ include file="../common/footer.jsp" %>
</body>
</html>
<!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->
요청 & 응답
BoardListController 생성
package com.chanyongyang.jsp.board.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
@WebServlet("/board/list")
public class BoardListController extends HttpServlet {
private BoardService boardService = new BoardServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("boards", boardService.list(1));
req.getRequestDispatcher("/WEB-INF/jsp/board/list.jsp").forward(req, resp);
}
}
BoardWriteController 생성
package com.chanyongyang.jsp.board.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
import com.chanyongyang.jsp.vo.Board;
@WebServlet("/board/write")
public class BoardWriteController extends HttpServlet {
private BoardService boardService = new BoardServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if(req.getSession().getAttribute("member") == null) {
resp.sendRedirect(req.getContextPath() + "/member/login");
return;
}
req.getRequestDispatcher("/WEB-INF/jsp/board/write.jsp").forward(req, resp);
}
@Override //글작성 주로 나오는 오류는 네임값오류이다. 이름이 맞는지 getParameter에 네임값이 맞는지 꼭 확인하자!
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Board board = new Board(req.getParameter("title"), req.getParameter("content"), req.getParameter("writer"));
boardService.register(board);
resp.sendRedirect("list");
}
}
게시판 상세조회
a태그를 클릭햇을 때 다음페이지
Servlet이 필요
post할일은 없음 (doGet사용)
가져와야할 필수 정보는 글번호(bno)
화면형식
view.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@ include file="../common/head.jsp" %>
</head>
<body>
<%@ include file="../common/header.jsp" %>
<main class="container p-3 pb-5">
<div class="card">
<div class="card-header p-5">
<h2>Board Write</h2>
</div>
<div class="card-body">
<form method="post">
<div class="mb-3 mt-3">
<label for="title" class="form-label">title</label>
<input type="text" class="form-control" id="email" placeholder="Enter title" name="title" readonly value="${board.title}">
</div>
<div class="mb-3">
<label for="content" class="form-label">content</label>
<textarea class="form-control" id="content" placeholder="Enter content" name="content" rows="10" readonly>${board.content}</textarea>
</div>
<div class="mb-3">
<label for="writer" class="form-label">writer</label>
<input type="text" class="form-control" id="writer" placeholder="Enter writer" name="writer" value="${board.writer}" readonly>
</div>
<div class="text-center">
<a href="modify?bno=${board.bno}" class="btn btn-warning">수정</a>
<a href="remove?bno=${board.bno}" class="btn btn-danger">삭제</a>
<a href="javascript:history.back()" class="btn btn-outline-primary">목록으로</a>
</div>
</form>
</div>
</div>
</main>
<%@ include file="../common/footer.jsp" %>
</body>
</html>
<!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->
board.controller에 BoardViewController.java 생성
package com.chanyongyang.jsp.board.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
@WebServlet("/board/view")
public class BoardViewController extends HttpServlet {
private BoardService boardService = new BoardServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("board", boardService.get(Long.valueOf(req.getParameter("bno"))));
req.getRequestDispatcher("/WEB-INF/jsp/board/view.jsp").forward(req, resp);
}
}
* 경로에 관한 팁
getRequestDispatcher : 프로젝트 최상단(root)로 보냄
sendRedirect : 현재 경로
수정하기
1. modify.jsp 생성(view.jsp 복사 후 수정)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@ include file="../common/head.jsp" %>
</head>
<body>
<%@ include file="../common/header.jsp" %>
<main class="container p-3 pb-5">
<div class="card">
<div class="card-header p-5">
<h2>Board Modify</h2>
</div>
<div class="card-body">
<form method="post">
<div class="mb-3 mt-3">
<label for="title" class="form-label">title</label>
<input type="text" class="form-control" id="email" placeholder="Enter title" name="title" value="${board.title}">
</div>
<div class="mb-3">
<label for="content" class="form-label">content</label>
<textarea class="form-control" id="content" placeholder="Enter content" name="content" rows="10" >${board.content}</textarea>
</div>
<div class="mb-3">
<label for="writer" class="form-label">writer</label>
<input type="text" class="form-control" id="writer" placeholder="Enter writer" name="writer" value="${board.writer}" readonly>
</div>
<div class="text-center">
<input type="hidden" name="bno" value="${board.bno}">
<button class="btn btn-warning">수정</button>>
<a href="javascript:history.back()" class="btn btn-outline-warning">이전</a>
</div>
</form>
</div>
</div>
</main>
<%@ include file="../common/footer.jsp" %>
</body>
</html>
<!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->
2. BoardModifyController 생성 (BoardWriteController 복사 후 수정)
package com.chanyongyang.jsp.board.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
import com.chanyongyang.jsp.vo.Board;
@WebServlet("/board/modify")
public class BoardModifyController extends HttpServlet {
private BoardService boardService = new BoardServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if(req.getSession().getAttribute("member") == null) {
resp.sendRedirect(req.getContextPath() + "/member/login");
return;
}
req.setAttribute("board", boardService.get(Long.valueOf(req.getParameter("bno"))));
req.getRequestDispatcher("/WEB-INF/jsp/board/modify.jsp").forward(req, resp);
}
@Override //글작성 주로 나오는 오류는 네임값오류이다. 이름이 맞는지 getParameter에 네임값이 맞는지 꼭 확인하자!
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Board board = new Board(req.getParameter("title"), req.getParameter("content"), req.getParameter("writer"));
board.setBno(Long.valueOf(req.getParameter("bno")));
boardService.modify(board);
resp.sendRedirect("view?bno=" + board.getBno());
}
}
게시글 수정 후 목록으로 누르게 되면 동작이 이상하게 되는데
수정 후 목록으로 가는 a태그는 뒤로 가는 경로를 적어놨기 때문에 다시 수정하기가 나온다.
modify.jsp, view.jsp에 목록으로 가는 경로를 뒤로가기에서 list로 변경한다.
삭제하기
삭제하시겠습니까? 문구
boolean으로 처리
사전준비
jquery cnd js 복사해서 head에 붙여넣기
시작
view.jsp 하단에 script추가
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@ include file="../common/head.jsp" %>
</head>
<body>
<%@ include file="../common/header.jsp" %>
<main class="container p-3 pb-5">
<div class="card">
<div class="card-header p-5">
<h2>Board View</h2>
</div>
<div class="card-body">
<form method="post">
<div class="mb-3 mt-3">
<label for="title" class="form-label">title</label>
<input type="text" class="form-control" id="email" placeholder="Enter title" name="title" readonly value="${board.title}">
</div>
<div class="mb-3">
<label for="content" class="form-label">content</label>
<textarea class="form-control" id="content" placeholder="Enter content" name="content" rows="10" readonly>${board.content}</textarea>
</div>
<div class="mb-3">
<label for="writer" class="form-label">writer</label>
<input type="text" class="form-control" id="writer" placeholder="Enter writer" name="writer" value="${board.writer}" readonly>
</div>
<div class="text-center">
<a href="modify?bno=${board.bno}" class="btn btn-warning">수정</a>
<a href="remove?bno=${board.bno}" class="btn btn-danger btn-remove">삭제</a>
<a href="list" class="btn btn-outline-primary">목록으로</a>
</div>
</form>
</div>
</div>
</main>
<%@ include file="../common/footer.jsp" %>
<script>
$(".btn-remove").click(function() {
return confirm("정말 삭제 하시겠습니까?");
});
</script>
</body>
</html>
<!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->
removeController 생성 (뷰 컨트롤러 복사)
package com.chanyongyang.jsp.board.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
@WebServlet("/board/remove")
public class BoardRemoveController extends HttpServlet {
private BoardService boardService = new BoardServiceImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
boardService.remove(Long.valueOf(req.getParameter("bno")));
resp.sendRedirect("list");
}
}
* 페이지번호, 한페이지에 몇개 보여줄건지(카테고리)
※ 페이징
예전에 자바로 과일바구니 예제를 햇을때랑 똑같다.
올림연산 사용 1의 자리에서 10의 자리로 올림연산을 해야함. (우선 총 몇페이지를 해야하는가)
총갯수, 몇페이지씩 볼건지
db에서의 count로 가져옴
dao를 추가하고 controller로 활용
관리대상 : 페이지번호, 몇개씩 볼거냐
관리대상을 따로 객체로 만들어서 관리해야함
매순간 객체가 변경되기 때문에 DTO 형태로 만들어야함
1. vo패키지명 변경 -> domain
2. domain 패키지에 Criteria 클래스 생성
package com.chanyongyang.jsp.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Criteria {
// 초기값을 주는게 좋다.
private int pageNum = 1;
private int amount = 10;
}
3. PageDto 생성
글의 총 갯수를 알아야함
첫 시작페이지가 몇페이지인지 알아야함
package com.chanyongyang.jsp.domain;
import lombok.Data;
@Data
public class PageDto {
// 하단에 출력 될 페이지 사이즈
private int pageCount = 10;
// 시작 페이지 숫자
private int startPage;
// 종료 페이지 숫자
private int endPage;
// 게시글의 총 갯수
private int total;
// next, prev
private boolean prev;
private boolean next;
private boolean doublePrev;
private boolean doubleNext;
// criteria
private Criteria cri;
public PageDto(int total, Criteria cri) {
this(10, total, cri);
}
public PageDto(int pageCount, int total, Criteria cri) {
this.pageCount = pageCount;
this.total = total;
this.cri = cri;
endPage = (cri.getPageNum() + (pageCount-1)) / pageCount * pageCount;
startPage = endPage - (pageCount-1);
int realEnd = (total + (cri.getAmount() - 1)) / cri.getAmount();
System.out.println(realEnd);
if(endPage > realEnd) {
endPage = realEnd;
}
prev = cri.getPageNum() > 1;
next = cri.getPageNum() < endPage;
doublePrev = startPage > 1;
doubleNext = endPage < realEnd;
}
public static void main(String[] args) {
Criteria cri = new Criteria(11, 10);
PageDto page = new PageDto(223, cri);
System.out.println(page);
}
// 예정 <<, >>
}
4. BoardDao에 selectListCount 추가
package com.chanyongyang.jsp.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.chanyongyang.jsp.domain.Board;
import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.domain.Member;
import com.chanyongyang.jsp.util.DBConn;
public class BoardDao {
private Connection conn;
private PreparedStatement pstmt;
private ResultSet rs;
public int insert(Board board) {
conn = DBConn.getConnection();
int result = 0;
// 처리할 sql구문, 지정타입에 맞춰서 ? 로 바꿀수 있음
String sql = "insert into tbl_board (title, content, writer) values (?, ?, ?)";
System.out.println(sql);
try {
// 문장 생성
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, board.getTitle());
pstmt.setString(2, board.getContent());
pstmt.setString(3, board.getWriter());
// 문장 처리
result = pstmt.executeUpdate();
close();
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
public Board selectOne(Long bno) {
conn = DBConn.getConnection();
// 반환 예정 객체
Board board = null;
// 처리할 sql구문
String sql = "select * from tbl_board where bno = ?";
try {
// 문장 생성 conn으로부터 문장생성 객체를 만듬
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, bno);
// 결과집합 반환
rs = pstmt.executeQuery();
// 결과집합을 자바객체로 만듬
if(rs.next()) {
int idx = 1;
// 객체 생성 후 값 바인딩
board = new Board(
rs.getLong(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getDate(idx++),
rs.getString(idx++),
rs.getInt(idx++), rs.getInt(idx++));
}
close();
} catch (SQLException e) {
e.printStackTrace();
}
// 결과 반환
return board;
}
public List<Board> selectList(Criteria cri) {
conn = DBConn.getConnection();
// 반환 예정 객체
List<Board> boards = new ArrayList<Board>();
// 처리할 sql구문
String sql = "select * from tbl_board where category = ? order by bno desc limit ? offset ?";
try {
// 문장 생성 conn으로부터 문장생성 객체를 만듬
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, cri.getCategory());
pstmt.setInt(2, cri.getAmount());
pstmt.setInt(3, (cri.getPageNum() - 1) * cri.getAmount());
// 결과집합 반환
rs = pstmt.executeQuery();
// 결과집합을 자바객체로 만듬
while(rs.next()) {
int idx = 1;
// 객체 생성 후 값 바인딩
Board board = new Board(
rs.getLong(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getDate(idx++),
rs.getString(idx++),
rs.getInt(idx++), rs.getInt(idx++));
boards.add(board);
}
close();
} catch (SQLException e) {
e.printStackTrace();
}
// 결과 반환
return boards;
}
public int selectListCount(int category) {
conn = DBConn.getConnection();
// 반환 예정 객체
int count = 0;
// 처리할 sql구문
String sql = "select count(*) from tbl_board where category = ?";
try {
// 문장 생성 conn으로부터 문장생성 객체를 만듬
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, category);
// 결과집합 반환
rs = pstmt.executeQuery();
// 결과집합을 자바객체로 만듬
while(rs.next()) {
int idx = 1;
// 객체 생성 후 값 바인딩
count = rs.getInt(1);
}
close();
} catch (SQLException e) {
e.printStackTrace();
}
// 결과 반환
return count;
}
public void update(Board board) {
conn = DBConn.getConnection();
// 처리할 sql구문
String sql = "update tbl_board set\r\n"
+ " title = ?,\r\n"
+ " content = ?,\r\n"
+ " updatedate = now()\r\n"
+ "where bno = ?";
// System.out.println(sql);
try {
// 문장 생성
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, board.getTitle());
pstmt.setString(2, board.getContent());
pstmt.setLong(3, board.getBno());
// 문장 처리
pstmt.executeUpdate();
close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void delete(Long bno) {
conn = DBConn.getConnection();
// 처리할 sql구문
String sql = "delete from tbl_board where bno = ?";
// System.out.println(sql);
try {
// 문장 생성
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, bno);
// 문장 처리
pstmt.executeUpdate();
close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 자원반환
public void close() {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {}
}
}
public static void main(String[] args) {
// new BoardDao().selectList(1).forEach(System.out::println);
BoardDao dao = new BoardDao();
// Board board = dao.selectOne(5L);
System.out.println(dao.selectListCount(1));
// board.setTitle("java에서 수정한 내용");
// board.setContent("java에서 수정한 내용");
// dao.update(board);
// dao.delete(5L);
// System.out.println(dao.selectOne(5L));
}
}
5. BoardService 인터페이스에 listCount 추가
package com.chanyongyang.jsp.service;
import java.util.List;
import com.chanyongyang.jsp.domain.Board;
import com.chanyongyang.jsp.domain.Criteria;
public interface BoardService {
// CRUD
Long register(Board board);
Board get(Long bno);
List<Board> list(Criteria cri); // 파라미터 여하에 따라 추가처리
int listCount(int category);
void modify(Board board);
void remove(Long bno);
}
6. BoardServiceImpl(구현부) listCount오버라이드
package com.chanyongyang.jsp.service;
import java.util.List;
import com.chanyongyang.jsp.dao.BoardDao;
import com.chanyongyang.jsp.domain.Board;
import com.chanyongyang.jsp.domain.Criteria;
public class BoardServiceImpl implements BoardService {
private BoardDao dao = new BoardDao();
// 서비스의 존재의 의의 : 트랜젝션의 기준
@Override
public Long register(Board board) {
return (long)dao.insert(board);
}
@Override
public Board get(Long bno) {
return dao.selectOne(bno);
}
@Override
public List<Board> list(Criteria cri) {
return dao.selectList(cri);
}
@Override
public void modify(Board board) {
dao.update(board);
}
@Override
public void remove(Long bno) {
dao.delete(bno);
}
@Override
public int listCount(int category) {
return dao.selectListCount(category);
}
}
7. service 구현
굳이 criteria를 만든이유 : 페이징 처리를 했을 때 최소 정보 (기본값 1)
list 컨트롤러로 간다.
doGet부분 수정
package com.chanyongyang.jsp.board.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.domain.PageDto;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
@WebServlet("/board/list")
public class BoardListController extends HttpServlet {
private BoardService boardService = new BoardServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Criteria criteria = null;
try {
int pageNum = Integer.parseInt(req.getParameter("page"));
int amount = Integer.parseInt(req.getParameter("amount"));
criteria = new Criteria(pageNum, amount);
}
// numberformatexception 발생 방지
catch (Exception e) {
criteria = new Criteria();
}
System.out.println(criteria);
req.setAttribute("boards", boardService.list(criteria));
req.setAttribute("page", new PageDto(boardService.listCount(1), criteria));
req.getRequestDispatcher("/WEB-INF/jsp/board/list.jsp").forward(req, resp);
}
}
8. BoardDao list부분 수정
package com.chanyongyang.jsp.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.chanyongyang.jsp.domain.Board;
import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.domain.Member;
import com.chanyongyang.jsp.util.DBConn;
public class BoardDao {
private Connection conn;
private PreparedStatement pstmt;
private ResultSet rs;
public int insert(Board board) {
conn = DBConn.getConnection();
int result = 0;
// 처리할 sql구문, 지정타입에 맞춰서 ? 로 바꿀수 있음
String sql = "insert into tbl_board (title, content, writer) values (?, ?, ?)";
System.out.println(sql);
try {
// 문장 생성
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, board.getTitle());
pstmt.setString(2, board.getContent());
pstmt.setString(3, board.getWriter());
// 문장 처리
result = pstmt.executeUpdate();
close();
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
public Board selectOne(Long bno) {
conn = DBConn.getConnection();
// 반환 예정 객체
Board board = null;
// 처리할 sql구문
String sql = "select * from tbl_board where bno = ?";
try {
// 문장 생성 conn으로부터 문장생성 객체를 만듬
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, bno);
// 결과집합 반환
rs = pstmt.executeQuery();
// 결과집합을 자바객체로 만듬
if(rs.next()) {
int idx = 1;
// 객체 생성 후 값 바인딩
board = new Board(
rs.getLong(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getDate(idx++),
rs.getString(idx++),
rs.getInt(idx++), rs.getInt(idx++));
}
close();
} catch (SQLException e) {
e.printStackTrace();
}
// 결과 반환
return board;
}
public List<Board> selectList(Criteria cri) {
conn = DBConn.getConnection();
// 반환 예정 객체
List<Board> boards = new ArrayList<Board>();
// 처리할 sql구문
String sql = "select * from tbl_board where category = ? order by bno desc limit ? offset ?";
try {
// 문장 생성 conn으로부터 문장생성 객체를 만듬
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, cri.getCategory());
pstmt.setInt(2, cri.getAmount());
pstmt.setInt(3, (cri.getPageNum() - 1) * cri.getAmount());
// 결과집합 반환
rs = pstmt.executeQuery();
// 결과집합을 자바객체로 만듬
while(rs.next()) {
int idx = 1;
// 객체 생성 후 값 바인딩
Board board = new Board(
rs.getLong(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getDate(idx++),
rs.getString(idx++),
rs.getInt(idx++), rs.getInt(idx++));
boards.add(board);
}
close();
} catch (SQLException e) {
e.printStackTrace();
}
// 결과 반환
return boards;
}
public int selectListCount(int category) {
conn = DBConn.getConnection();
// 반환 예정 객체
int count = 0;
// 처리할 sql구문
String sql = "select count(*) from tbl_board where category = ?";
try {
// 문장 생성 conn으로부터 문장생성 객체를 만듬
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, category);
// 결과집합 반환
rs = pstmt.executeQuery();
// 결과집합을 자바객체로 만듬
while(rs.next()) {
int idx = 1;
// 객체 생성 후 값 바인딩
count = rs.getInt(1);
}
close();
} catch (SQLException e) {
e.printStackTrace();
}
// 결과 반환
return count;
}
public void update(Board board) {
conn = DBConn.getConnection();
// 처리할 sql구문
String sql = "update tbl_board set\r\n"
+ " title = ?,\r\n"
+ " content = ?,\r\n"
+ " updatedate = now()\r\n"
+ "where bno = ?";
// System.out.println(sql);
try {
// 문장 생성
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, board.getTitle());
pstmt.setString(2, board.getContent());
pstmt.setLong(3, board.getBno());
// 문장 처리
pstmt.executeUpdate();
close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void delete(Long bno) {
conn = DBConn.getConnection();
// 처리할 sql구문
String sql = "delete from tbl_board where bno = ?";
// System.out.println(sql);
try {
// 문장 생성
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, bno);
// 문장 처리
pstmt.executeUpdate();
close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 자원반환
public void close() {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {}
}
}
public static void main(String[] args) {
// new BoardDao().selectList(1).forEach(System.out::println);
BoardDao dao = new BoardDao();
// Board board = dao.selectOne(5L);
System.out.println(dao.selectListCount(1));
// board.setTitle("java에서 수정한 내용");
// board.setContent("java에서 수정한 내용");
// dao.update(board);
// dao.delete(5L);
// System.out.println(dao.selectOne(5L));
}
}
9. list컨트롤러 수정
package com.chanyongyang.jsp.board.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.domain.PageDto;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
@WebServlet("/board/list")
public class BoardListController extends HttpServlet {
private BoardService boardService = new BoardServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Criteria criteria = null;
try {
int pageNum = Integer.parseInt(req.getParameter("page"));
int amount = Integer.parseInt(req.getParameter("amount"));
criteria = new Criteria(pageNum, amount);
}
// numberformatexception 발생 방지
catch (Exception e) {
criteria = new Criteria();
}
System.out.println(criteria);
req.setAttribute("boards", boardService.list(criteria));
req.setAttribute("page", new PageDto(boardService.listCount(1), criteria));
req.getRequestDispatcher("/WEB-INF/jsp/board/list.jsp").forward(req, resp);
}
}
10. list.jsp 페이징부분 처리
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@ include file="../common/head.jsp" %>
</head>
<body>
<%@ include file="../common/header.jsp" %>
<main class="container p-3 pb-5">
<div class="card">
<div class="card-header p-5">
<h2>Board List</h2>
</div>
<div class="card-body">
<div class="clearfix mb-3">
<div class="float-start">
<select class="form-select">
<option>10개씩보기</option>
<option>25개씩보기</option>
<option>50개씩보기</option>
</select>
</div>
<div class="float-start mx-5">
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Search">
<button class="btn btn-success" type="submit"><i class="fas fa-search"></i></button>
</div>
</div>
<a href="write" class="float-end btn btn-primary">write</a>
</div>
<div class="card">
<c:forEach var="board" items="${boards}" varStatus="stat">
<a href="view?bno=${board.bno}" class="text-decoration-none">
<div class="container card-body ${stat.last ? '': 'border-bottom'}">
<div class="mb-4 text-truncate">${board.title}</div>
<div class="row text-muted small">
<div class="col-7">${board.writer}</div>
<div class="col text-end small"><span class="mx-3">${board.regdate}</span> <span>조회수 ${board.hitcount}</span></div>
</div>
</div>
</a>
</c:forEach>
</div>
<ul class="pagination mt-3 justify-content-center">
${page}
<li class="page-item"><a class="page-link" href="#">Previous</a></li>
<li class="page-item"><a class="page-link active" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
</div>
</div>
</main>
<%@ include file="../common/footer.jsp" %>
</body>
</html>
<!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->
* VO와 DTO
멤버들에 대한 불변성이 명확하면 VO, 가변적이면 DTO라고 함
VO :
DTO :
'Servlet, JSP > Servlet, JSP' 카테고리의 다른 글
23-03-15 Servlet, JSP (0) | 2023.03.15 |
---|---|
23-03-13 Servlet, JSP (0) | 2023.03.13 |
23-03-07(1) Servlet, JSP (0) | 2023.03.07 |
23-03-06 (1) servlet, jsp (0) | 2023.03.06 |