반응형
01. 게시글(새글)을 저장하는 test프로그램 (board_test.jsp)
<%@page import="xyz.itwill.dao.BoardDAO"%>
<%@page import="xyz.itwill.dto.BoardDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//<%-- BOARD 테이블에 게시글(새글)을 500개 저장하는 JSP 문서 - 테스트 프로그램 --%>
//<%-- 이 프로그램을 먼저 실행해야 BoardDTO가 생성되어 삽입처리가 됨 --%>
<%
BoardDTO board=new BoardDTO();
for(int i=1;i<=500;i++) {
int num=BoardDAO.getDAO().selectNextNum();
board.setNum(num);
board.setId("abc123");
board.setSubject("테스트-"+i);
board.setRef(num);
board.setContent("게시글 연습-"+i);
board.setIp("192.168.13.31");
board.setStatus(1);
BoardDAO.getDAO().insertBoard(board);
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP</title>
</head>
<body>
<h1>500개의 테스트 게시글이 삽입 되었습니다.</h1>
</body>
</html>
02. 게시글목록 출력페이지 (board > board_list.jsp)
<%@page import="java.util.Date"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="xyz.itwill.dto.MemberDTO"%>
<%@page import="xyz.itwill.dto.BoardDTO"%>
<%@page import="java.util.List"%>
<%@page import="xyz.itwill.dao.BoardDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//<%-- BOARD 테이블에 저장된 게시글을 검색하여 게시글 목록을 클라이언트에게 전달하는 JSP 문서 --%>
//<%-- => 게시글 목록을 페이지로 구분 검색하여 응답처리 - 페이징 처리 --%>
//<%-- => [페이지번호]를 클릭한 경우 게시글목록 출력페이지(board_list.jsp)로 이동 - [페이징처리를 위한 : 페이지번호 ], [서칭을 위한 : 검색대상(컬럼명), 검색단어] 전달 --%>
//<%-- => [검색]을 클릭한 경우 게시글목록 출력페이지(board_list.jsp)로 이동 - 검색대상(컬럼명), 검색단어 전달 --%>
//<%-- => [글쓰기]를 클릭한 경우 게시글 입력페이지(board_wirte.jsp)로 이동 - 로그인 사용자에게만 링크 제공 --%>
//<%-- => [게시글의 제목]을 클릭한 경우 게시글 출력페이지(board_detail.jsp)로 이동 - 글번호(num), 페이지번호,검색대상(컬럼명), 검색단어 전달 --%>
<%
//검색대상과 검색단어를 반환받아 저장
String search=request.getParameter("search");
if(search==null){
search="";
}
String keyword=request.getParameter("keyword");
if(keyword==null){
keyword="";
}
//System.out.println("검색대상 = "+search+", 검색단어 = "+keyword);
//1.
//페이징 처리 관련 전달값(요청 페이지 번호)를 반환받아 저장
//=> 요청 페이지 번호에 대한 전달값이 없는 경우 첫번째 페이지의 게시글 목록을 검색하여 응답
int pageNum=1;//전달값이 없는 경우 1(첫번째페이지)로
if(request.getParameter("pageNum")!=null){//전달값이 있는 경우
pageNum=Integer.parseInt(request.getParameter("pageNum"));//pageNum(요청페이지번호)로
}
//2.
//하나의 페이지에 검색되어 출력될 게시글의 갯수 설정 - 전달값을 반환받아 저장 가능
int pageSize = 10;
/*
//2.
int pageSize=10;//전달값이 없는 경우 10개로
if(request.getParameter("pageSize")!=null){ //전달값이 있는 경우
pageNum=Integer.parseInt(request.getParameter("pageSize")); //pageSize(요청게시글갯수)로
}
*/
/*
//3.
//if문으로 다수의 메소드 호출해 제어하기 - 비권장
if(keyword.equals("")){
int totalBoard = BoardDAO.getDAO().selectBoardCount();
} else {
int totalBoard = BoardDAO.getDAO().selectBoardCount(search, keyword);
}
*/
//3.
//메소드 1개만 호출하지만, 메소드 내부에 선택적 SQL 명령 만들어 제어하기 - 권장
//BOARD 테이블에 저장된 전체 게시글의 갯수(일반글+삭제글+비밀글)를 검색하여 반환하는 DAO클래스의 메소드 호출 - 검색 기능 미구현시 호출하는 메소드
//int totalBoard = BoardDAO.getDAO().selectBoardCount(); //ex.totalBoard=99
//검색 관련 정보를 전달받아 BOARD 테이블에 저장된 특정 게시글의 갯수를 검색하여 반환하는 DAO클래스의 메소드 호출 - 검색 기능 구현시 호출하는 메소드
int totalBoard = BoardDAO.getDAO().selectBoardCount(search, keyword);
//4.
//전체 페이지의 갯수를 계산하여 저장 - 소숫점자리는 반드시 올림처리하여 전체페이지 갯수 저장하기
//int totalPage = (totalBoard/pageSize) + (totalBoard%pageSize==0 ? 0:1);
int totalPage = (int)Math.ceil((double)totalBoard/pageSize);
//전달되어 저장된 요청 페이지 번호에 대한 검증 - 원하는 페이지의 게시글들만 검색하기 위해
if(pageNum<=0 || pageNum>totalPage){ //비정상적인 요청 페이지 번호인 경우
pageNum=1; //첫번째 페이지의 게시글 목록이 검색되어 응답되도록 요청 페이지 번호 변경
}
//5.
//시작행과 종료행을 계산해 저장 (오라클 vs MYSQL:시작행+LIMIT절이용)
//=> SQL명령 전달하는 메소드 구현 시 사용하기 위해 필요
//요청 페이지 번호(pageNum)에 대한 [시작 게시글의 행번호(startRow)]를 계산하여 저장
//ex) 1 page : 1, 2 page : 11, 3 page : 21, 4 page : 31, ...
int startRow=(pageNum-1)*pageSize+1;
//요청 페이지 번호(pageNum)에 대한 [종료 게시글의 행번호(endRow)]를 계산하여 저장
//ex) 1 page : 10, 2 page : 20, 3 page : 30, 4 page : 40, ...
int endRow=pageNum*pageSize;
//마지막 페이지에 대한 종료 게시글의 행번호를 검색 게시글의 갯수로 변경
if(endRow>totalBoard){
endRow=totalBoard;
}
//6.
//요청 페이지에 대한 [시작 게시글의 행번호]와 [종료 게시글의 행번호]를 전달받아 BOARD 테이블에
//저장된 게시글에서 해당 범위의 게시글만을 검색하여 반환하는 DAO 클래스의 메소드 호출 - 검색 기능 미구현시 호출하는 메소드
//List<BoardDTO> boardList = BoardDAO.getDAO().selectBoardList(startRow, endRow);
//검색 관련 정보 및 요청 페이지에 대한 [시작 게시글의 행번호]와 [종료 게시글의 행번호]를 전달받아 BOARD 테이블에 저장된 게시글에서 해당 범위의 게시글만을 검색하여 반환하는 DAO 클래스의 메소드 호출 - 검색 기능 구현시 호출하는 메소드
List<BoardDTO> boardList = BoardDAO.getDAO().selectBoardList(startRow, endRow, search, keyword);
//7.
//세션에 저장된 [권한 관련 정보]를 반환받아 저장 - [로그인 사용자에게만] 글쓰기 권한을 제공하기 위해서 필요
//=> [비밀 게시글]인 경우 로그인 사용자가 [게시글 작성자]이거나 [관리자]인 경우에만 접근 권한을 제공하기 위해서 필요
MemberDTO loginMember = (MemberDTO) session.getAttribute("loginMember");
//8.
//서버 시스템에 현재 날짜를 반환받아 저장- 게시글의 작성날짜를 현재날짜와 비교하여 구분출력하기 위해 필요
//=> ex. [오늘작성날짜]: 시간만 출력, [과거작성날짜]: 날짜 + 시간 출력
String currentDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
//9.
//요청 페이지에 검색되어 출력될 게시글의 일련번호에 대한 시작값을 계산하여 저장
//=> printNum :게시글의 일련번호(출력될 글번호)
//=> VS BOARD테이블의 NUM(BoardDTO.num) : 게시글을 구분할 식별자
//ex) 전체 게시글의 갯수: 91 >> 1Page : 91~82, 2Page: 81~72, 3Page: 71~62, xPage:
int printNum = totalBoard-(pageNum-1)*pageSize ;
%>
<style type="text/css">
#board_list{ width: 1000px; margin: 0 auto; text-align: center; }
#board_title { font-size: 1.2em; font-weight: bold; }
table{ margin: 5px auto; border: 1px solid black; border-collapse: collapse; }
th { border: 1px solid black; background-color: black; color: white; }
td { border: 1px solid black; text-align: center; }
.subject { text-align: left; padding: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#board_list a:hover{ text-decoration: none; color: red; font-weight: bold; }
.secret, .remove { background-color: black; color: white; font-size: 14px; border: 1px solid black; border-radius: 4px; }
</style>
<div id="board_list">
<div id="board_title">게시글 목록(게시글 갯수 : <%=totalBoard %>)</div>
<% if(loginMember!=null) {//로그인 사용자가 JSP 문서를 요청한 경우 %>
<div style="text-align: right;">
<button type="button" onclick="location.href='<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_write';">글쓰기</button>
</div>
<% } %>
//<%-- 게시글 목록 출력 --%>
<table>
<tr>
<th width="100">번호</th>
<th width="500">제목</th>
<th width="100">작성자</th>
<th width="100">조회수</th>
<th width="200">작성일</th>
</tr>
<% if(totalBoard==0) { %>
<tr>
<td colspan="5">검색된 게시글이 없습니다.</td>
</tr>
<% } else { %>
//<%-- List 객체에서 요소(BoardDTO 객체)를 하나씩 제공받아 반복 처리 --%>
<% for(BoardDTO board:boardList) { %>
<tr>
//<%-- 일련번호 : BOARD 테이블에 저장된 게시글의 글번호가 아닌 일련번호로 응답 --%>
<td><%=pritnNum %></td>
<% pritnNum--; %><%-- 일련번호를 1씩 감소시켜 저장 --%>
//<%-- 제목 --%>
<td class="subject">
//<%-- 게시글이 답글인 경우에 대한 응답 처리 --%>
<% if(board.getReStep()!=0) {//게시글이 답글인 경우 %>
//<%-- 게시글의 깊이에 의해 왼쪽 여백을 다르게 설정하여 응답되도록 처리 --%>
<span style="margin-left: <%=board.getReLevel()*20%>px;">└[답글]</span>
<% } %>
//<%-- 게시글 상태를 구분하여 제목과 링크를 다르게 설정하여 응답되도록 처리 --%>
<% if(board.getStatus()==1) {//일반 게시글인 경우 %>
<a href="<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_detail&num=<%=board.getNum() %>&pageNum=<%=pageNum%>&search=<%=search%>&keyword=<%=keyword%>">
<%=board.getSubject() %>
</a>
<% } else if(board.getStatus()==2) {//비밀 게시글인 경우 %>
<span class="secret">비밀글</span>
//<%-- 로그인 사용자가 작성자이거나 관리자인 경우 --%>
<% if(loginMember!=null && (loginMember.getId().equals(board.getId())
|| loginMember.getStatus()==9)) { %>
<a href="<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_detail&num=<%=board.getNum() %>&pageNum=<%=pageNum%>&search=<%=search%>&keyword=<%=keyword%>">
<%=board.getSubject() %>
</a>
<% } else { %>
작성자 또는 관리자만 확인 가능합니다.
<% } %>
<% } else if(board.getStatus()==0) {//삭제 게시글인 경우 %>
<span class="remove">삭제글</span>
작성자 또는 관리자에 의해 삭제된 게시글입니다.
<% } %>
</td>
<% if(board.getStatus()!=0) {//삭제 게시글이 아닌 경우 %>
//<%-- 작성자 --%>
<td><%=board.getWriter() %></td>
//<%-- 조회수 --%>
<td><%=board.getReadcount() %></td>
//<%-- 작성일 : 오늘 작성된 게시글은 시간만 출력하고 오늘 작성된 게시글이 아닌 게시글은 날짜와 시간 출력 --%>
<td>
<% if(currentDate.equals(board.getRegDate().substring(0,10))) {//오늘 작성된 게시글인 경우 %>
<%=board.getRegDate().substring(11) %>
<% } else {//오늘 작성된 게시글이 아닌 경우 %>
<%=board.getRegDate() %>
<% } %>
</td>
<% } else {//삭제 게시글인 경우 %>
<td> </td>
<td> </td>
<td> </td>
<% } %>
</tr>
<% } %>
<% } %>
</table>
//<%-- 페이지 번호 출력 및 링크 설정 - 블럭화 처리 --%>
<%
//하나의 페이지 블럭에 출력될 페이지 번호의 갯수를 설정
int blockSize=5;
//페이지 블럭에 출력될 시작 페이지 번호를 계산하여 저장
//ex)1Block : 1, 2Block : 6, 3Block : 11, 4Block : 16,...
int startPage=(pageNum-1)/blockSize*blockSize+1;
//페이지 블럭에 출력될 종료 페이지 번호를 계산하여 저장
//ex)1Block : 5, 2Block : 10, 3Block : 15, 4Block : 20,...
int endPage=startPage+blockSize-1;
//마지막 페이지 블럭의 종료 페이지 번호 변경
if(endPage>totalPage) {
endPage=totalPage;
}
%>
<% if(startPage>blockSize) {//첫번째 페이지 블럭이 아닌 경우%>
<a href="<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_list&pageNum=<%=startPage-blockSize%>&search=<%=search%>&keyword=<%=keyword%>">[이전]</a>
<% } %>
<% for(int i=startPage;i<=endPage;i++) { %>
<% if(pageNum!=i) {//요청 페이지 번호와 이벤트 페이지 번호가 다른 경우 - 링크 제공 %>
<a href="<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_list&pageNum=<%=i%>&search=<%=search%>&keyword=<%=keyword%>">[<%=i %>]</a>
<% } else {//요청 페이지 번호와 이벤트 페이지 번호가 같은 경우 - 링크 미제공 %>
[<%=i %>]
<% } %>
<% } %>
<% if(endPage!=totalPage) {//마지막 페이지 블럭이 아닌 경우 %>
<a href="<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_list&pageNum=<%=startPage+blockSize%>&search=<%=search%>&keyword=<%=keyword%>">[다음]</a>
<% } %>
//<%-- 사용자로부터 검색어를 입력받아 게시글 검색 기능 구현 --%>
<form action="<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_list" method="post">
//<%-- select 태그에 의해 전달되는 값은 반드시 검색단어를 비교하기 위한 컬럼명과 같은 이름으로 전달되도록 설정 --%>
<select name="search">
<option value="name" selected="selected"> 작성자 </option>
<option value="subject"> 제목 </option>
<option value="content"> 내용 </option>
</select>
<input type="text" name="keyword">
<button type="submit">검색</button>
</form>
</div>
03. 게시글상세 입력페이지 (board > board_write.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//<%-- 사용자로부터 게시글(새글 또는 답글)을 입력받기 위한 JSP 문서 --%>
//<%-- => 로그인 사용자만 요청 가능한 JSP 문서 --%>
//<%-- => [글저장]을 클릭한 경우 게시글 삽입페이지(board_write_action.jsp)로 이동 - 입력값 전달 --%>
//<%-- 비로그인 사용자가 JSP 문서를 요청한 경우 에러페이지로 이동되로록 응답 처리 --%>
//<%-- => 비정상적인 요청에 대한 응답 처리 --%>
<%@include file="/security/login_check.jspf" %>
//<%-- 새글 : board_list.jsp 문서에 의해 요청한 경우 - 전달값 : X --%>
//<%-- 답글 : board_detail.jsp 문서에 의해 요청한 경우 - 전달값 : O --%>
//<%-- => 부모글 관련 정보(ref,reStep,reLevel,pageNum) 전달 --%>
<%
//전달만 하고, 액션이 데이타 처리할 것임(중개상역할)
//전달값을 반환받아 저장 - 전달값이 없는 경우(새글인 경우) 초기값 저장
String ref="0", reStep="0", reLevel="0", pageNum="1";
if(request.getParameter("ref")!=null){ //전달값이 있는 경우(답글인 경우)
ref = request.getParameter("ref");
reStep = request.getParameter("reStep");
reLevel = request.getParameter("reLevel");
pageNum = request.getParameter("pageNum");
}
%>
<style type="text/css">
table{ margin: 0 auto; }
th { width: 70px; font-weight: normal; }
td { text-align: left; }
</style>
//<%-- 새글인 경우 --%>
<% if(ref.equals("0")){ %>
<h2>새글쓰기</h2>
//<%-- 답글인 경우 --%>
<% } else { %>
<h2>답글쓰기</h2>
<% } %>
<form action="<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_write_action"
method="post" id="boardForm">
<input type="hidden" name="ref" value="<%=ref%>">
<input type="hidden" name="reStep" value="<%=reStep%>">
<input type="hidden" name="reLevel" value="<%=reLevel%>">
<input type="hidden" name="pageNum" value="<%=pageNum%>">
<table>
<tr>
<th>제목</th>
<td>
<input type="text" name="subject" id="subject" size="40">
<input type="checkbox" name="secret" value="2">비밀글
</td>
</tr>
<tr>
<th>내용</th>
<td>
<textarea rows="7" cols="60" name="content" id="board_content"></textarea>
</td>
</tr>
<tr>
<th colspan="2">
<button type="submit">글저장</button>
<button type="reset" id="resetBtn">다시쓰기</button>
</th>
</tr>
</table>
</form>
<div id="message" style="color:red;"></div>
<script type="text/javascript">
$("#subject").focus();
$("#boardForm").submit(function() {
if($("#subject").val()=="") {
$("#message").text("제목을 입력해 주세요.");
$("#subject").focus();
return false;
}
if($("#board_content").val()=="") {
$("#message").text("내용을 입력해 주세요.");
$("#content").focus();
return false;
}
});
$("#resetBtn").click(function() {
$("#subject").focus();
$("#message").text("");
});
</script>
04. 게시글상세 입력처리 (board > board_write_action.jsp)
<%@page import="xyz.itwill.dto.BoardDTO"%>
<%@page import="xyz.itwill.dao.BoardDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//<%-- 게시글(새글 또는 답글)을 전달받아 BOARD 테이블에 삽입하고 게시글목록 출력페이지로
//이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서 --%>
//<%-- => 로그인 사용자만 요청 가능한 JSP 문서 --%>
//<%-- 비로그인 사용자가 JSP 문서를 요청한 경우 에러페이지로 이동되로록 응답 처리 --%>
//<%-- => 비정상적인 요청에 대한 응답 처리 --%>
<%@include file="/security/login_check.jspf" %>
<%
//1.
//비정상적인 요청에 대한 응답 처리
if(request.getMethod().equals("GET")){
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
//2.
//전달값을 반환받아 저장 (7개 : ref,reStep,reLevel,pageNum,subject,secret,content)
int ref = Integer.parseInt(request.getParameter("ref"));
int reStep = Integer.parseInt(request.getParameter("reStep"));
int reLevel = Integer.parseInt(request.getParameter("reLevel"));
String pageNum = request.getParameter("pageNum");
//사용자로부터 입력받아 전달된 값에 태그 관련 문자가 존재할 경우 회피문자로 변경하여 저장
// => XSS 공격에 대한 방어
//String subject = request.getParameter("subject");
//String subject = Utility.stripTag(request.getParameter("subject"));
String subject = Utility.escapeTag(request.getParameter("subject"));
int status = 1;
if(request.getParameter("secret")!=null){
status = Integer.parseInt(request.getParameter("secret"));
}
//String content = request.getParameter("content");
//String content = Utility.stripTag(request.getParameter("content"));
String content = Utility.escapeTag(request.getParameter("content"));
//3.
//BOARD_SEQ 시퀀스의 다음값(자동 증가값)을 검색하여 반환하는 DAO 클래스의 메소드 호출
// => 게시글(새글 또는 답글)의 글번호(BOARD테이블의 NUM 컬럼값)로 저장하기 위해 필요
// => [새글인 경우]에는 게시글의 그룹번호(BOARD테이블의 REF 컬럼값)로 저장하기 위해 필요
int num = BoardDAO.getDAO().selectNextNum();
//4.
//게시글 작성자의 컴퓨터 IP 주소를 반환받아 저장 - BOARD테이블의 IP 컬럼값으로 저장
//request.getRemoteAddr() : JSP 문서를 요청한 클라이언트의 IP 주소를 반환하는 메소드
//=> 이클립스에 등록되어 동작되는 WAS 프로그램은 기본적으로 IPV6 프로토콜의 128Bit 형식의 IP 주소 제공
//IPV4 프로토콜의 32Bit 형식의 IP 주소를 제공받을 수 있도록 이클립스 실행 환경설정 변경
// Run >> Run Configrations... >> 사용중인 Apache Tomcat 선택 >>
// >> Arguments >> VM Arguments >> [-Djava.net.preferIPv4Stack=true]추가 >> Apply > 서버 restart하기
String ip = request.getRemoteAddr();
System.out.println("ip = "+ip);
//ip = 0:0:0:0:0:0:0:1
//ip = 127.0.0.1
//5.
//새글과 답글을 구분하여 BOARD 테이블의 컬럼값으로 저장될 변수값 변경
// => board_write.jsp 문서에서 hidden 타입으로 전달된 값이 저장된 ref, reStep, reLevel 변수값
//(새글 - 초기값, 답글 - 부모글) 변경
if(ref==0){ //새글인 경우
//BOARD 테이블에 REF 컬럼값으로 자동 증가값(num 변수값)이 저장되도록 ref 변수값을 변경하고
//RE_STEP 컬럼과 RE_LEVEL 컬럼에는 [0]이 저장되도록 reStep 변수와 reLevel 변수의 값 사용
ref=num;
} else{ //답글인 경우
//부모글의 정보(ref 변수값과 reStep 변수값)를 전달받아 BOARD 테이블에 저장된 게시글에서
//REF 컬럼값과 ref 변수값이 같은 게시글 중 RE_STEP 컬럼값이 reStep 변수값보다 커다란
//모든 게시글의 RE_STEP 컬럼값이 1씩 증가되도록 변경하는 DAO 클래스 메소드 호출
// => 답글의 검색 순서가 변경되어 다시 정렬되도록 RE_STEP 컬럼값 변경
BoardDAO.getDAO().updateRestep(ref, reStep);
//BOARD 테이블에 REF 컬럼값에는 부모글의 전달값이 저장되도록 ref 변수값을 사용하고
//RE_STEP 컬럼과 RE_LEVEL 컬럼에는 reStep 변수와 reLevel 변수의 값을 1 증가시켜 저장되도록 변경
reStep++;
reLevel++;
}
//6. 테이블에 삽입 처리
//BoardDTO 객체를 생성하여 변수값으로 필드값 변경
BoardDTO board = new BoardDTO();
board.setNum(num);
board.setId(loginMember.getId());
board.setSubject(subject);
board.setRef(ref);
board.setReStep(reStep);
board.setReLevel(reLevel);
board.setContent(content);
board.setIp(ip);
board.setStatus(status);
//게시글을 전달받아 BOARD 테이블에 삽입하는 DAO 클래스의 메소드 호출
BoardDAO.getDAO().insertBoard(board);
//7.
//페이지 이동
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=board&work=board_list&pageNum="+pageNum+"';");
out.println("</script>");
%>
05. 게시글상세 출력페이지 (board > board_detail.jsp)
<%@page import="xyz.itwill.dto.MemberDTO"%>
<%@page import="xyz.itwill.dto.BoardDTO"%>
<%@page import="xyz.itwill.dao.BoardDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//<%-- 글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 클라이언트에게 전달하는 JSP 문서 --%>
//<%-- [글변경]을 클릭한 경우 게시글 수정페이지(board_modify.jsp)로 이동 - 글번호, 페이지번호, 검색대상, 검색단어 전달 (변경 후 다시 되돌아오기 위해 페이지번호, 검색대상, 검색단어 필요 - 페이징과 서칭의 유지) --%>
//<%-- [글삭제]를 클릭한 경우 게시글 삭제 처리페이지(board_remove_action.jsp)로 이동 - 글번호 전달 --%>
//<%-- [답글쓰기]를 클릭한 경우 게시글 입력페이지(board_write.jsp)로 이동 - 그룹번호, 그룹답글순서, 답글깊이, 페이지번호, 검색대상, 검색단어 전달 --%>
//<%-- ,쿼리스트링으로 전달 ? 폼태그로 전달 ? --%>
//<%-- [글목록]을 클릭한 경우 게시글 목록 출력페이지(board_list.jsp)로 이동 - 값 전달 --%>
//<%-- 권한: [글변경]과 [글삭제]는 관리자 또는 작성자에게만 링크 제공 --%>
//<%-- 권한: [답글쓰기]는 로그인 사용자에게만 링크 제공 --%>
<%
//1.
//비정상적인 요청에 대한 응답 처리
if(request.getParameter("num")==null){
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
//2.
//전달값을 반환받아 저장
int num = Integer.parseInt(request.getParameter("num"));
//board_list의 서칭과 페이징을 유지하기 위해서 아래의 3개의 값도 전달받아야함
//즉, board_detail에서는 전달값을 사용하지 않지만,
//다시 board_list에 이동할 때는 가져가야하므로 전달받는 것 필수!!
String pageNum = request.getParameter("pageNum");
String search = request.getParameter("search");
String keyword = request.getParameter("keyword");
//3.
//글번호를 전달받아 BOARD테이블에 저장된 해당 글번호의 게시글을 검색하여 반환하는 DAO 클래스의 메소드 호출
BoardDTO board = BoardDAO.getDAO().selectBoard(num);
//4.
//검색된 게시글이 없거나 삭제 게시글인 경우 - 비정상적인 요청
if(board==null || board.getStatus()==0){
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
//5.
//세션에 저장된 권환 관련 정보(회원정보)를 반환받아 저장
MemberDTO loginMember = (MemberDTO)session.getAttribute("loginMember");
//6.
if(board.getStatus()==2){//비밀 게시글인 경우
//비로그인 사용자이거나 로그인 사용자가 게시글 작성자 또는 관리자가 아닌 경우 에러페이지로 이동
// => 권한이 없는 사용자가 JSP 문서를 요청한 경우 - 비정상적인 요청
if(loginMember==null || !loginMember.getId().equals(board.getId()) && loginMember.getStatus()!=9){
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
}
//7.
//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글의 조회수를 증가하는 DAO 클래스의 메소드 호출
BoardDAO.getDAO().updateReadCount(num);
//오늘본 게시글의 조회수는 더 이상 증가 안시키키게 하려면 Cookie나 Sesison 이용해 글번호 저장해서 만들기
%>
<style type="text/css">
#board_detail { width: 500px; margin: 0 auto; }
table { border: 1px solid black; border-collapse: collapse; }
th, td { border: 1px solid black; padding: 5px; }
th { width: 100px; background-color: black; color: white; }
td { width: 400px; }
.subject, .content { text-align: left; }
.content { height: 100px; vertical-align: middle; }
#board_menu { text-align: right; margin: 5px; }
</style>
<div id="board_detail">
<h2>게시글</h2>
<table>
<tr>
<th>작성자</th>
<td><%=board.getWriter() %> <%if(loginMember!=null && loginMember.getStatus()==9){//관리자인 경우 %>
[<%=board.getIp() %>] <%} %></td>
</tr>
<tr>
<th>작성일</th>
<td><%=board.getRegDate() %></td>
</tr>
<tr>
<th>조회수</th>
<td><%=board.getReadcount() + 1 %></td>
</tr>
<tr>
<th>제목</th>
<td class="subject">
<% if(board.getStatus()==2){//비밀 게시글인 경우 %> [비밀글] <%} %> <%=board.getSubject() %>
</td>
</tr>
<tr>
<th>내용</th>
<td class="content"><%=board.getContent().replace("\\\\n", "<br>")%>
</td>
</tr>
</table>
<div id="board_menu">
//<%-- 로그인 사용자 중 게시글 작성자이거나 관리자인 경우에만 태그를 이용하여 링크 제공 --%>
<%if(loginMember!=null && (loginMember.getId().equals(board.getId()) || loginMember.getStatus()==9)){%>
<button type="button" id="modifyBtn">글변경</button>
<button type="button" id="removeBtn">글삭제</button>
<%} %>
//<%-- 로그인 사용자인 경우에만 태그를 이용하여 링크 제공 --%>
<%if(loginMember!=null){%>
<button type="button" id="replyBtn">답글쓰기</button>
<%} %>
<button type="button" id="listBtn">글목록</button>
</div>
[POST]방식으로 값 전달
//<%-- 요청 페이지에 값을 전달하기 위한 form 태그 --%>
<form method="post" id="menuForm">
//<%-- [글변경] 및 [글삭제]를 클릭한 경우 전달되는 값 --%>
<input type="hidden" name="num" value="<%=board.getNum()%>">
//<%-- [글변경] 및 [글목록]를 클릭한 경우 전달되는 값 --%>
<input type="hidden" name="pageNum" value="<%=pageNum%>">
<input type="hidden" name="search" value="<%=search%>">
<input type="hidden" name="keyword" value="<%=keyword%>">
//<%-- [답글쓰기]를 클릭한 경우 전달되는 값 --%>
<input type="hidden" name="ref" value="<%=board.getRef()%>">
<input type="hidden" name="reStep" value="<%=board.getReStep()%>">
<input type="hidden" name="reLevel" value="<%=board.getReLevel()%>">
</form>
[GET]방식으로 값 전달
//<%-- 요청 페이지에 값을 전달하기 위한 form 태그 --%>
<form action="<%=request.getContextPath()%>/index.jsp" method="get" id="menuForm">
<input type="hidden" name="workgroup" value="board">
<input type="hidden" name="work" id="work">
//<%-- [글변경] 및 [글삭제]를 클릭한 경우 전달되는 값 --%>
<input type="hidden" name="num" value="<%=board.getNum()%>">
//<%-- [글변경] 및 [글목록]를 클릭한 경우 전달되는 값 --%>
<input type="hidden" name="pageNum" value="<%=pageNum%>">
<input type="hidden" name="search" value="<%=search%>">
<input type="hidden" name="keyword" value="<%=keyword%>">
//<%-- [답글쓰기]를 클릭한 경우 전달되는 값 --%>
<input type="hidden" name="ref" value="<%=board.getRef()%>">
<input type="hidden" name="reStep" value="<%=board.getReStep()%>">
<input type="hidden" name="reLevel" value="<%=board.getReLevel()%>">
</form>
</div>
[POST]방식일 경우 실행될 자바스크립트
<script type="text/javascript">
$("#modifyBtn").click(function() {
$("#menuForm").attr("action", "<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_modify");
$("#menuForm").submit();
})
$("#removeBtn").click(function() {
if(confirm("게시글을 삭제 하시겠습니까?")){
$("#menuForm").attr("action", "<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_remove_action");
$("#menuForm").submit();
}
})
$("#replyBtn").click(function() {
$("#menuForm").attr("action", "<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_write");
$("#menuForm").submit();
})
$("#listBtn").click(function() {
$("#menuForm").attr("action", "<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_list");
$("#menuForm").submit();
})
</script>
[GET]방식일 경우 실행될 자바스크립트
<script type="text/javascript">
$("#modifyBtn").click(function() {
$("#work").val("board_modify");
$("#menuForm").submit();
});
$("#removeBtn").click(function() {
if(confirm("게시글을 삭제 하시겠습니까?")) {
$("#work").val("board_remove_action");
$("#menuForm").submit();
}
});
$("#replyBtn").click(function() {
$("#work").val("board_write");
$("#menuForm").submit();
});
$("#listBtn").click(function() {
$("#work").val("board_list");
$("#menuForm").submit();
});
</script>
06. 게시글수정 출력페이지 (board > board_modify.jsp)
<%@page import="xyz.itwill.dao.BoardDAO"%>
<%@page import="xyz.itwill.dto.BoardDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//<%-- 글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 입력태그의
// 초기값으로 설정하고 사용자로부터 변경값을 입력받기 위한 JSP 문서 --%>
//<%-- => 로그인 사용자 중 게시글 작성자이거나 관리자인 경우에만 요청 가능한 JSP 문서 --%>
//<%-- [글변경]을 클릭한 경우 게시글 변경페이지(board_modify_action.jsp)로 이동 - 입력값 전달 --%>
//<%-- 비로그인 사용자가 JSP 문서를 요청한 경우 에러페이지로 이동하여 응답 처리 --%>
<%@include file="/security/login_check.jspf" %>
<%
//1.
//비정상적인 요청에 대한 응답 처리
if(request.getParameter("num")==null){
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
//2.
//전달값을 반환받아 저장
int num = Integer.parseInt(request.getParameter("num"));
String pageNum = request.getParameter("pageNum");
String search = request.getParameter("search");
String keyword = request.getParameter("keyword");
//3.
//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 반환하는 DAO 클래스의 메소드 호출
BoardDTO board = BoardDAO.getDAO().selectBoard(num);
//4.
//검색된 게시글이 없거나 삭제 게시글인 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
if(board==null || board.getStatus()==0){
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
//5.
//게시글 작성자가 아니거나 관리자도 아닌 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
if(!loginMember.getId().equals(board.getId()) && loginMember.getStatus()!=9){
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
%>
<style type="text/css">
table{ margin: 0 auto; }
th { width: 70px; font-weight: normal; }
td { text-align: left; }
</style>
<h2>글변경</h2>
<form action="<%=request.getContextPath()%>/index.jsp?workgroup=board&work=board_modify_action"
method="post" id="boardForm">
<input type="hidden" name="num" value="<%=num%>">
<input type="hidden" name="pageNum" value="<%=pageNum%>">
<input type="hidden" name="search" value="<%=search%>">
<input type="hidden" name="keyword" value="<%=keyword%>">
<table>
<tr>
<th>제목</th>
<td>
<input type="text" name="subject" id="subject" size="40" value="<%=board.getSubject()%>">
<input type="checkbox" name="secret" value="2" <%if(board.getStatus()==2){ %> checked="checked" <%} %>>비밀글
</td>
</tr>
<tr>
<th>내용</th>
<td>
<textarea rows="7" cols="60" name="content" id="board_content"><%=board.getContent()%></textarea>
</td>
</tr>
<tr>
<th colspan="2">
<button type="submit">글변경</button>
<button type="reset" id="resetBtn">다시쓰기</button>
</th>
</tr>
</table>
</form>
<div id="message" style="color:red;"></div>
<script type="text/javascript">
$("#subject").focus();
$("#boardForm").submit(function() {
if($("#subject").val()=="") {
$("#message").text("제목을 입력해 주세요.");
$("#subject").focus();
return false;
}
if($("#board_content").val()=="") {
$("#message").text("내용을 입력해 주세요.");
$("#content").focus();
return false;
}
});
$("#resetBtn").click(function() {
$("#subject").focus();
$("#message").text("");
});
</script>
07. 게시글수정 처리 (board > board_modify_action.jsp)
<%@page import="xyz.itwill.dao.BoardDAO"%>
<%@page import="xyz.itwill.dto.BoardDTO"%>
<%@page import="xyz.itwill.util.Utility"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//<%-- 게시글(변경글)을 전달받아 BOARD 테이블에 저장된 해당 게시글을 변경하고 게시글 출력페이지
//(board_detail.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서 --%>
//<%-- => 게시글 출력페이지(board_detail.jsp)로 글번호,페이지번호,검색대상,검색단어 전달 --%>
//<%-- => 로그인 사용자 중 게시글 작성자이거나 관리자인 경우에만 요청 가능한 JSP 문서 --%>
<%@include file="/security/login_check.jspf"%>
<%
//1.
//비정상적인 요청에 대한 응답 처리
if(request.getMethod().equals("GET")) {
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
//2.
//전달값을 반환받아 저장
int num=Integer.parseInt(request.getParameter("num"));
String pageNum=request.getParameter("pageNum");
String search=request.getParameter("search");
String keyword=request.getParameter("keyword");
String subject=Utility.escapeTag(request.getParameter("subject"));
int status=1;
if(request.getParameter("secret")!=null) {
status=Integer.parseInt(request.getParameter("secret"));
}
String content=Utility.escapeTag(request.getParameter("content"));
//3.
//BoardDTO 객체를 생성하여 전달값으로 필드값 변경
BoardDTO board=new BoardDTO();
board.setNum(num);
board.setSubject(subject);
board.setContent(content);
board.setStatus(status);
//4.
//게시글을 전달받아 BOARD 테이블에 저장된 해당 게시글을 변경하는 DAO 클래스의 메소드 호출
BoardDAO.getDAO().updateBoard(board);
//5.
//페이지 이동
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=board&work=board_detail"
+"&num="+num+"&pageNum="+pageNum+"&search="+search+"&keyword="+keyword+"';");
out.println("</script>");
%>
07. 게시글삭제 처리 (board > board_remove_action.jsp)
<%@page import="xyz.itwill.dao.BoardDAO"%>
<%@page import="xyz.itwill.dto.BoardDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//<%-- 글번호를 전달받아 BOARD 테이블의 저장된 게시글에서 해당 글번호의 게시글에 대한 STATUS
//컬럼값을 [0]으로 변경하여 삭제 처리하고 게시글목록 출력페이지(board_list.jsp)로 이동하는
//URL 주소를 클라이언트에게 전달하는 JSP 문서 --%>
//<%-- => 로그인 사용자 중 게시글 작성자이거나 관리자인 경우에만 요청 가능한 JSP 문서 --%>
<%@include file="/security/login_check.jspf" %>
<%
//1.
//전달값이 없는 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
if(request.getParameter("num")==null) {
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
//2.
//전달값을 반환받아 저장
int num=Integer.parseInt(request.getParameter("num"));
//3.
//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 반환하는 DAO 클래스의 메소드 호출
BoardDTO board=BoardDAO.getDAO().selectBoard(num);
//4.
//검색된 게시글이 없거나 삭제 게시글인 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
if(board==null || board.getStatus()==0) {
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
out.println("</script>");
return;
}
//5.
//게시글 작성자 및 관리자가 아닌 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
if(!loginMember.getId().equals(board.getId()) && loginMember.getStatus()!=9) {
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400");
out.println("</script>");
return;
}
//6.
//글번호와 글상태를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글에 대한 상태를 변경하는 DAO 클래스의 메소드 호출 - 삭제 처리
//BoardDAO.getDAO().updateStatus(num, 0);
//게시글을 전달받아 BOARD 테이블에 저장된 해당 게시글을 변경하는 DAO 클래스의 메소드 호출 - 삭제 처리
// => 메소드 만들지 않고, 상태 변경 후 기존 메소드 호출해도 됨
board.setStatus(0);
BoardDAO.getDAO().updateBoard(board);
//7.
//페이지 이동
out.println("<script type='text/javascript'>");
out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=board&work=board_list';");
out.println("</script>");
%>
반응형
'jsp' 카테고리의 다른 글
[jsp] 24. EL(Expression Language)의 개념 (0) | 2024.07.15 |
---|---|
[jsp] 23. 웹사이트 제작법9_ 회원 관리 페이지 제작 (feat. JSP) (0) | 2024.07.15 |
[jsp] 21. 웹사이트 제작법7_ 제품목록, 장바구니,구매목록 페이지 제작 (feat. JSP) (0) | 2024.07.14 |
[jsp] 20. 웹사이트 제작법6_ 마이페이지 제작 (feat. JSP) (0) | 2024.07.13 |
[jsp] 19. 웹사이트 제작법5_회원가입 페이지 제작 (feat. JSP) (0) | 2024.07.13 |