간단한 웹페이지 만들기 - 게시판

임승현·2022년 12월 20일
0

JSP

목록 보기
18/20

🌈Part 1 - 테이블 생성

◈ SQL Develope 실행 후 아래코드 작성

create table board(num number(4) primary key,id varchar2(20)
	,subject varchar2(500),reg_date date,readcount number(4),
	ref number(4),re_step number(4),re_level number(4),
	content varchar2(4000),ip varchar2(20),status number(1));

create sequence board_seq;

desc board;

🌈Part 2 - DTO 클래스 생성

🌟 writer는 join 기능을 사용
1. xyz.itwill.dto 패키지에 BoardDTO 클래스 생성

📃BoardDTO.java

package xyz.itwill.dto;
//
/*
이름        널?       유형             
--------- -------- -------------- 
NUM       NOT NULL NUMBER(4)       - 글번호      
ID                 VARCHAR2(20)    - 작성자(아이디)
SUBJECT            VARCHAR2(500)   - 제목
REG_DATE           DATE            - 작성날짜
READCOUNT          NUMBER(4)       - 조회수
REF                NUMBER(4)       - 게시글 그룹 번호
RE_STEP            NUMBER(4)       - 게시글 그룹 내부의 글순서
RE_LEVEL           NUMBER(4)       - 게시글의 깊이
CONTENT            VARCHAR2(4000)  - 내용 
IP                 VARCHAR2(20)    - 작성자 컴퓨터의 IP 주소
STATUS             NUMBER(1)       - 상태 : 0(삭제글), 1(일반글), 2(비밀글)       
*/
//
public class BoardDTO {
	private int num;
	private String id;
	private String writer;//작성자(이름) - MEMBER 테이블의 name 컬럼값을 저장하기 위한 필드
	private String subject;
	private String regDate;
	private int readcount;
	private int ref;
	private int reStep;
	private int reLevel;
	private String content;
	private String ip;
	private int status;
	//
	public BoardDTO() {
		// TODO Auto-generated constructor stub
	}
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getRegDate() {
		return regDate;
	}
	public void setRegDate(String regDate) {
		this.regDate = regDate;
	}
	public int getReadcount() {
		return readcount;
	}
	public void setReadcount(int readcount) {
		this.readcount = readcount;
	}
	public int getRef() {
		return ref;
	}
	public void setRef(int ref) {
		this.ref = ref;
	}
	public int getReStep() {
		return reStep;
	}
	public void setReStep(int reStep) {
		this.reStep = reStep;
	}
	public int getReLevel() {
		return reLevel;
	}
	public void setReLevel(int reLevel) {
		this.reLevel = reLevel;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getIp() {
		return ip;
	}
	public void setIp(String ip) {
		this.ip = ip;
	}
	public int getStatus() {
		return status;
	}
	public void setStatus(int status) {
		this.status = status;
	}
}

🌈Part 3 - DAO 클래스 생성

1. xyz.itwill.dao 패키지에 BoardDAO 클래스 생성

📃BoardDAO.java

package xyz.itwill.dao;
//
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
//
import xyz.itwill.dto.BoardDTO;
//
public class BoardDAO extends JdbcDAO {
	private static BoardDAO _dao;
	//
	private BoardDAO() {
		// TODO Auto-generated constructor stub
	}
	//
	static {
		_dao = new BoardDAO();
	}
	//
	public static BoardDAO getDAO() {
		return _dao;
	}
	//
	/*
	//BOARD 테이블에 저장된 전체 게시글의 갯수를 검색하여 반환하는 메소드
	public int selectBoardCount() {
		Connection con=null;
		PreparedStatement pstmt=null;
		ResultSet rs=null;
		int count=0;
		try {
			con=getConnection();
			//
			String sql="select count(*) from board";
			pstmt=con.prepareStatement(sql);
			//
			rs=pstmt.executeQuery();
			//
			if(rs.next()) {
				count=rs.getInt(1);
			}
		} catch (SQLException e) {
			System.out.println("[에러]selectBoardCount() 메서드의 SQL 오류 = "+e.getMessage());
		} finally {
			close(con, pstmt, rs);
		}
		return count;
	}
	*/
	// 검색 관련 정보를 전달받아 BOARD 테이블에 저장된 특정 게시글의 갯수를 검색하여 반환하는 메소드
	public int selectBoardCount(String search, String keyword) {
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		int count = 0;
		try {
			con = getConnection();
			//
			// 매개변수에 저장된 값을 비교하여 다른 SQL 명령을 전달하여 실행되도록 작성
			// => 동적 SQL(Dynamic SQL) 기능 사용
			if (keyword.equals("")) {// 검색 기능을 사용하지 않은 경우
				String sql = "select count(*) from board";
				pstmt = con.prepareStatement(sql);
			} else {// 검색 기능을 사용한 경우
				// 검색대상(컬럼명)은 값이 아니므로 ?(InParameter)로 사용 불가능
				String sql = "select count(*) from board join member on board.id=member.id" + " where " + search
						+ " like '%'||?||'%'";
				pstmt = con.prepareStatement(sql);
				pstmt.setString(1, keyword);
			}
			//
			rs = pstmt.executeQuery();
			//
			if (rs.next()) {
				count = rs.getInt(1);
			}
		} catch (SQLException e) {
			System.out.println("[에러]selectBoardCount() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt, rs);
		}
		return count;
	}
	//
	// 검색 관련 정보 및 요청 페이지에 대한 시작 게시글의 행번호와 종료 게시글의 행번호를 전달
	// 받아 BAORD 테이블에 저장된 특정 게시글에서 해당 범위의 게시글만을 검색하여 반환하는 메소드
	// public List<BoardDTO> selectBoardList(int startRow, int endRow) {
	public List<BoardDTO> selectBoardList(int startRow, int endRow, String search, String keyword) {
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		List<BoardDTO> boardList = new ArrayList<>();
		try {
			con = getConnection();
			//
			if (keyword.equals("")) {
				String sql = "select * from (select rownum rn,temp.* from (select num,member.id"
						+ ",name,subject,reg_date,readcount,ref,re_step,re_level,content,ip"
						+ ",board.status from board join member on board.id=member.id"
						+ " order by ref desc, re_step) temp) where rn between ? and ?";
				pstmt = con.prepareStatement(sql);
				pstmt.setInt(1, startRow);
				pstmt.setInt(2, endRow);
			} else {
				String sql = "select * from (select rownum rn,temp.* from (select num,member.id"
						+ ",name,subject,reg_date,readcount,ref,re_step,re_level,content,ip"
						+ ",board.status from board join member on board.id=member.id" + " where " + search
						+ " like '%'||?||'%' and board.status=1 order by"
						+ " ref desc, re_step) temp) where rn between ? and ?";
				pstmt = con.prepareStatement(sql);
				pstmt.setString(1, keyword);
				pstmt.setInt(2, startRow);
				pstmt.setInt(3, endRow);
			}
			//
			rs = pstmt.executeQuery();
			//
			while (rs.next()) {
				BoardDTO board = new BoardDTO();
				board.setNum(rs.getInt("num"));
				board.setId(rs.getString("id"));
				board.setWriter(rs.getString("name"));
				board.setSubject(rs.getString("subject"));
				board.setRegDate(rs.getString("reg_date"));
				board.setReadcount(rs.getInt("readcount"));
				board.setRef(rs.getInt("ref"));
				board.setReStep(rs.getInt("re_step"));
				board.setReLevel(rs.getInt("re_level"));
				board.setContent(rs.getString("content"));
				board.setIp(rs.getString("ip"));
				board.setStatus(rs.getInt("status"));
				boardList.add(board);
			}
		} catch (SQLException e) {
			System.out.println("[에러]selectBoardList() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt, rs);
		}
		return boardList;
	}
	//
	// BOARD_SEQ 시퀸스의 다음값을 검색하여 반환하는 메소드
	public int selectNextNum() {
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		int nextNum = 0;
		try {
			con = getConnection();
			//
			String sql = "select board_seq.nextval from dual";
			pstmt = con.prepareStatement(sql);
			//
			rs = pstmt.executeQuery();
			//
			if (rs.next()) {
				nextNum = rs.getInt(1);
			}
		} catch (SQLException e) {
			System.out.println("[에러]selectNextNum() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt, rs);
		}
		return nextNum;
	}
	//
	// 게시글을 전달받아 BOARD 테이블에 삽입하고 삽입행의 갯수를 반환하는 메소드
	public int insertBoard(BoardDTO board) {
		Connection con = null;
		PreparedStatement pstmt = null;
		int rows = 0;
		try {
			con = getConnection();
			//
			String sql = "insert into board values(?,?,?,sysdate,0,?,?,?,?,?,?)";
			pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, board.getNum());
			pstmt.setString(2, board.getId());
			pstmt.setString(3, board.getSubject());
			pstmt.setInt(4, board.getRef());
			pstmt.setInt(5, board.getReStep());
			pstmt.setInt(6, board.getReLevel());
			pstmt.setString(7, board.getContent());
			pstmt.setString(8, board.getIp());
			pstmt.setInt(9, board.getStatus());
			//
			rows = pstmt.executeUpdate();
		} catch (SQLException e) {
			System.out.println("[에러]insertBoard() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt);
		}
		return rows;
	}
	//
	// 부모글의 정보를 전달받아 BOARD 테이블에 저장된 게시글에서 그룹이 같은 게시글 중
	// 부모글보다 순서가 높이 모든 게시글의 RE_STEP 컬럼값이 1씩 증가되도록 변경하고
	// 변경행의 갯수를 반환하는 메소드
	public int updateReStep(int ref, int reStep) {
		Connection con = null;
		PreparedStatement pstmt = null;
		int rows = 0;
		try {
			con = getConnection();
			//
			String sql = "update board set re_step=re_step+1 where ref=? and re_step>?";
			pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, ref);
			pstmt.setInt(2, reStep);
			//
			rows = pstmt.executeUpdate();
		} catch (SQLException e) {
			System.out.println("[에러]updateReStep() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt);
		}
		return rows;
	}
	//
	//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 반환하는 메소드
	public BoardDTO selectBoard(int num) {
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		BoardDTO board = null;
		try {
			con = getConnection();
			//
			String sql = "select num,member.id,name,subject,reg_date,readcount,ref,re_step"
					+ ",re_level,content,ip,board.status from board join member" + " on board.id=member.id where num=?";
			pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, num);
			//
			rs = pstmt.executeQuery();
			//
			if (rs.next()) {
				board = new BoardDTO();
				board.setNum(rs.getInt("num"));
				board.setId(rs.getString("id"));
				board.setWriter(rs.getString("name"));
				board.setSubject(rs.getString("subject"));
				board.setRegDate(rs.getString("reg_date"));
				board.setReadcount(rs.getInt("readcount"));
				board.setRef(rs.getInt("ref"));
				board.setReStep(rs.getInt("re_step"));
				board.setReLevel(rs.getInt("re_level"));
				board.setContent(rs.getString("content"));
				board.setIp(rs.getString("ip"));
				board.setStatus(rs.getInt("status"));
			}
		} catch (SQLException e) {
			System.out.println("[에러]selectBoard() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt, rs);
		}
		return board;
	}
	//
	//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글 조회수가 1 증가되도록 변경하고 변경행의 갯수를 반환하는 메소드
	public int updateReadCount(int num) {
		Connection con=null;
		PreparedStatement pstmt=null;
		int rows=0;
		try {
			con=getConnection();
			//
			String sql="update board set readcount=readcount+1 where num=?";
			pstmt=con.prepareStatement(sql);
			pstmt.setInt(1, num);
			//
			rows=pstmt.executeUpdate();
		} catch (SQLException e) {
			System.out.println("[에러]selectBoard() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt);
		}
		return rows;
	}
	//
	///게시글을 전달받아 BOARD 테이블에 저장된 해당 게시글을 변경하고 변경행의 갯수를 반환하는 메소드
	public int updateBoard(BoardDTO board) {
		Connection con=null;
		PreparedStatement pstmt=null;
		int rows=0;
		try {
			con=getConnection();
			//
			String sql="update board set subject=?,content=?,status=?, where num=?";
			pstmt=con.prepareStatement(sql);
			pstmt.setString(1, board.getSubject());
			pstmt.setString(2, board.getContent());
			pstmt.setInt(3, board.getStatus());
			pstmt.setInt(4, board.getNum());
			//
			rows=pstmt.executeUpdate();
		} catch (SQLException e) {
			System.out.println("[에러]selectBoard() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt);
		}
		return rows;
	}
	//
	// 글번호와 글상태를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글에 대한 상태를 변경하고 변경행의 갯수를 반환하는 메소드
	public int updateStatus(int num, int status) {
		Connection con = null;
		PreparedStatement pstmt = null;
		int rows = 0;
		try {
			con = getConnection();
			//
			String sql = "update board set status=? where num=?";
			pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, status);
			pstmt.setInt(2, num);
			//
			rows = pstmt.executeUpdate();
		} catch (SQLException e) {
			System.out.println("[에러]updateStatus() 메서드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt);
		}
		return rows;
	}
}

🌈Part 4 - 게시글 목록 관련

1. board_list.jsp
→BOARD 테이블에 저장된 게시글을 검색하여 게시글 목록을 클라이언트에게 전달하는 JSP 문서

📃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_write.jsp)로 이동 - 로그인 사용자에게만 링크 제공 --%>
<%-- → 게시글의 [제목]을 클릭한 경우 게시글 출력페이지(board_detail.jsp)로 이동 - 글번호,페이지번호,검색대상,검색단어 전달 --%>
<%
	//검색대상과 검색단어를 반환받아 저장
	String search=request.getParameter("search");
	if(search==null) {
		search="";
	}
	String keyword=request.getParameter("keyword");
	if(keyword==null) {
		keyword="";
	}
	System.out.println("검색대상 = "+search+", 검색단어 = "+keyword)
	//
	//페이징 처리 관련 전달값(요청 페이지 번호)를 반환받아 저장
	// => 요청 페이지 번호에 대한 전달값이 없는 경우 첫번째 페이지의 게시글 목록을 검색하여 응답
	int pageNum=1;
	if(request.getParameter("pageNum")!=null) {//전달값이 있는 경우
		pageNum=Integer.parseInt(request.getParameter("pageNum"));
	}
	//
	//하나의 페이지에 검색되어 출력될 게시글의 갯수 설정 - 전달값을 반환받아 저장 가능
	int pageSize=10;
	//
	//BOARD 테이블에 저장된 전체 게시글의 갯수를 검색하여 반환하는 DAO 클래스의 메소드 호출
	// => 검색 기능 미구현시 호출하는 메소드
	//int totalBoard=BoardDAO.getDAO().selectBoardCount();
	//↑↑↑↑↑=↓↓↓↓↓
	//검색 관련 정보를 전달받아 BOARD 테이블에 저장된 특정 게시글의 갯수를 검색하여 반환하는 DAO 클래스의 메소드 호출
	// => 검색 기능 구현시 호출하는 메소드
	int totalBoard=BoardDAO.getDAO().selectBoardCount(search, keyword);
	//            
	//전체 페이지의 갯수를 계산하여 저장
	//int totalPage=totalBoard/pageSize+totalBoard%pageSize==0?0:1;
	int totalPage=(int)Math.ceil((double)totalBoard/pageSize);
	//
	//요청 페이지 번호에 대한 검증
	if(pageNum<=0 || pageNum>totalPage) {//비정상적인 요청 페이지 번호인 경우
		pageNum=1;//첫번째 페이지의 게시글 목록이 검색되어 응답되도록 요청 페이지 번호 변경
	}
	//
	//요청 페이지 번호에 대한 시작 게시글의 행번호를 계산하여 저장
	//ex) 1Page : 1, 2Page : 11, 3Page : 21, 4Page : 31, ...
	int startRow=(pageNum-1)*pageSize+1;
    //              
	//요청 페이지 번호에 대한 종료 게시글의 행번호를 계산하여 저장
	//ex) 1Page : 10, 2Page : 20, 3Page : 30, 4Page : 40, ...
	int endRow=pageNum*pageSize;
	//
	//마지막 페이지에 대한 종료 게시글의 행번호를 검색 게시글의 갯수로 변경
	if(endRow>totalBoard) {
		endRow=totalBoard;
	}
	//
	//요청 페이지에 대한 시작 게시글의 행번호와 종료 게시글의 행번호를 전달받아 BAORD 테이블에
	//저장된 게시글에서 해당 범위의 게시글만을 검색하여 반환하는 DAO 클래스의 메소드 호출
	// => 검색 기능 미구현시 호출하는 메소드
	List<BoardDTO> boardList=BoardDAO.getDAO().selectBoardList(startRow, endRow);
	//↑↑↑↑↑=↓↓↓↓↓
	//검색 관련 정보 및 요청페이지에 대한 시작 게시글의 행번호와 종료 게시글의 행번호를
	//전달받아 BAORD 테이블에 저장된 특정 게시글에서 해당 범위의 게시글만을 검색하여 반환하는
	//DAO 클래스의 메소드 호출 - 검색 기능 구현시 호출하는 메소드
	List<BoardDTO> boardList=BoardDAO.getDAO().selectBoardList(startRow, endRow, search, keyword);
	//
	//세션에 저장된 권한 관련 정보를 반환받아 저장
	// => 로그인 사용자에게만 글쓰기 권한 제공
	// => 비밀 게시글인 경우 로그인 사용자가 게시글 작성자이거나 관리자인 경우에만 접근 권한 제공
	MemberDTO loginMember=(MemberDTO)session.getAttribute("loginMember");
	//
	//서버 시스템의 현재 날짜를 반환받아 저장
	// => 게시글의 작성날짜를 현재 날짜와 비교하여 구분 출력
	String currentDate=new SimpleDateFormat("yyyy-MM-dd").format(new Date());
	//
	//요청 페이지에 검색되어 출력될 게시글의 일련번호에 대한 시작값을 계산하여 저장
	//ex)전체 게시글의 갯수 : 91 >> 1Page : 91~82, 2Page : 81~72, 3Page : 71~62,...
	int pritnNum=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>&nbsp;</td>
				<td>&nbsp;</td>
				<td>&nbsp;</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%>">[<%=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">&nbsp;작성자&nbsp;</option>
			<option value="subject">&nbsp;제목&nbsp;</option>
			<option value="subject">&nbsp;내용&nbsp;</option>
		</select>
		<input type="text" name="keyword">
		<button type="submit">검색</button>
	</form>
</div>

🌈Part 5 - 게시글 작성(테스트 프로그램)

1. board_test.jsp
→BOARD 테이블에 게시글(새글)을 500개 저장하는 JSP 문서 - 테스트 프로그램

📃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 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>Insert title here</title>
</head>
<body>
	<h1>500개의 테스트 게시글이 삽입 되었습니다.</h1>
</body>
</html>

🌈Part 6 - 새글 또는 답글 관련

1. board_write.jsp
→사용자로부터 게시글(새글 또는 답글)을 입력받기 위한 JSP 문서

📃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("내용을 입력해 주세요.");
		$("#board_content").focus();
		return false;
	}
});
$("#resetBtn").click(function() {
	$("#subject").focus();
	$("#message").text("");
});
</script>

2. board_write_action.jsp
→게시글(새글 또는 답글)을 전달받아 BOARD 테이블에 삽입하고 게시글목록 출력페이지(board_list.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서

📃board_write_action.jsp

<%@page import="xyz.itwill.util.Utility"%>
<%@page import="xyz.itwill.dao.BoardDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 게시글(새글 또는 답글)을 전달받아 BOARD 테이블에 삽입하고 게시글목록 출력페이지(board_list.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서 --%>
<%-- → 로그인 사용자만 요청 가능한 JSP 문서 --%>
<%-- --%>
<%-- 비정상적인 요청에 대한 응답 처리 --%>
<%@include file="/security/login_check.jspf" %>
<%-- --%>
<%
	//비정상적인 요청에 대한 응답 처리
	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;		
	}
	//
	//전달값을 반환받아 저장
	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=Utility.escapeTag(request.getParameter("content"));
	//
	//BOARD_SEQ 시퀸스의 다음값(자동 증가값)을 검색하여 반환하는 DAO 클래스의 메소드 호출
	//→ 게시글(새글 또는 답글)의 글번호(NUM 컬럼값)로 저장
	//→ 새글인 경우에는 게시글의 그룹번호(REF 컬럼값)로 저장
	int num=BoardDAO.getDAO().selectNextNum();
	//
	//게시글 작성자의 컴퓨터 IP 주소를 반환받아 저장 - IP 컬럼값으로 저장
	//request.getRemoteAddr() : JSP 문서를 요청한 클라이언트의 IP 주소를 반환하는 메소드
	//→ 이클립스에 등록되어 동작되는 WAS 프로그램은 기본적으로 IPV6프로토콜의 128Bit 형식에IP 주소 제공
	//IPV4 프로토콜의 32Bit 형식에 IP 주소를 제공받을 수 있도록 이클립스 실행 환경설정 변경
	//→ Run >> Run Configurations... >> Apache Tomcat >> 사용중인 Apache Tomcat 선택 >> Arguments >> VM Arguments >> [-Djava.net.preferIPv4Stack=true] 추가 >> Apply
	String ip=request.getRemoteAddr();
	//
	//새글과 답글을 구분하여 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++;
	}
	//
	//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);
	//
	//페이지 이동
	out.println("<script type='text/javascript'>");
	out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=board&work=board_list&pageNum="+pageNum+"';");
	out.println("</script>");
%>   

🌈Part 7 - 게시판 검색 관련

1. board_detail.jsp

📃board_detail.jsp

<%@page import="xyz.itwill.dto.MemberDTO"%>
<%@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 문서 --%>
<%-- → [글변경]을 클릭한 경우 게시글 입력페이지(board_modify.jsp)로 이동 - 글번호,페이지번호,검색대상,검색단어 전달 --%>
<%-- → [글삭제]을 클릭한 경우 게시글 삭제페이지(board_remove_action.jsp)로 이동 - 글번호 전달 --%>
<%-- → [답글쓰기]을 클릭한 경우 게시글 입력페이지(board_write.jsp)로 이동 - 그룹번호,그룹답글순서,답글깊이,페이지번호 전달 --%>
<%-- → [글목록]을 클릭한 경우 게시글 목록 출력페이지(board_list.jsp)로 이동 - 페이지번호,검색대상,검색단어 전달 전달 --%>
<%-- → [글변경]과 [글삭제]는 관리자 또는 게시글 작성자에게만 링크를 제공하고 [답글쓰기]는 로그인 사용자에게만 링크 제공 --%>
<%
	//비정상적인 요청에 대한 응답 처리
	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;	
	}
	//
	//전달값을 반환받아 저장
	int num=Integer.parseInt(request.getParameter("num"));
	String pageNum=request.getParameter("pageNum");
	String search=request.getParameter("search");
	String keyword=request.getParameter("keyword");
	//
	//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 반환하는 DAO 클래스의 메소드 호출
	BoardDTO board=BoardDAO.getDAO().selectBoard(num);
	//
	//검색된 게시글이 없거나 삭제 게시글인 경우 - 비정상적인 요청
	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;	
	}
	//
	//세션에 저장된 권한 관련 정보(회원정보)를 반환받아 저장
	MemberDTO loginMember=(MemberDTO)session.getAttribute("loginMember");
	//
	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;
		}
	}
	//
	//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글 조회수를 증가하는 DAO 클래스의 메소드 호출
	BoardDAO.getDAO().updateReadCount(num);
%>
<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_datail">
	<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>
	<%-- 요청 페이지에 값을 전달하기 위한 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>
<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>

🌈Part 8 - 게시글 변경 관련

1. board_modify.jsp
→글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 입력태그의 초기값으로 설정하고 사용자로부터 변경값을 입력받기 위한 JSP 문서

📃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" %>
<%
	//비정상적인 요청에 대한 응답 처리
	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;
	}
	//
	//전달값을 반환받아 저장
	int num=Integer.parseInt(request.getParameter("num"));
	String pageNum=request.getParameter("pageNum");
	String search=request.getParameter("search");
	String keyword=request.getParameter("keyword");
	//
	//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 반환하는 DAO 클래스의 메소드 호출
	BoardDTO board=BoardDAO.getDAO().selectBoard(num);
	//
	//검색된 게시글이 없거나 삭제 게시글인 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
	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;
	}
	//
	//게시글 작성자 및 관리자가 아닌 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
	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("내용을 입력해 주세요.");
		$("#board_content").focus();
		return false;
	}
});
$("#resetBtn").click(function() {
	$("#subject").focus();
	$("#message").text("");
});
</script>

2. board_modify_action.jsp
→게시글(변경글)을 전달받아 BOARD 테이블에 저장된 해당 게시글을 변경하고 게시글 출력페이지(board_datail.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서

📃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_datail.jsp)로 이동하기 위한
URL 주소를 클라이언트에게 전달하는 JSP 문서 --%>
<%-- → 게시글 출력페이지(board_detail.jsp)로 글번호,페이지번호,검색대상,검색단어 전달 --%>
<%-- → 로그인 사용자 중 게시글 작성자이거나 관리자인 경우에만 요청 가능한 JSP 문서 --%>
<%@include file="security/login_check.jspf" %>
<%
	//비정상적인 요청에 대한 응답 처리
	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;
	}
	//
	//전달값을 반환받아 저장
	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"));
	//
	//BoardDTO 객체를 생성하여 전달값으로 필드값 변경
	BoardDTO board=new BoardDTO();
	board.setNum(num);
	board.setSubject(subject);
	board.setContent(content);
	board.setStatus(status);
	//
	//게시글을 전달받아 BOARD 테이블에 저장된 해당 게시글을 변경하는 DAO 클래스의 메소드 호출
	BoardDAO.getDAO().updateBoard(board);
	//
	//페이지 이동
	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>");
%>

🌈Part 9 - 게시글 삭제 관련

1. board_remove_action.jsp
→글번호를 전달받아 BOARD 테이블의 저장된 게시글에서 해당 글번호의 게시글에 대한 STATUS 컬럼값을 [0]으로 변경하여 삭제 처리하고 게시글목록 출력페이지(board_list.jsp)로 이동하는 URL 주소를 클라이언트에게 전달하는 JSP 문서

📃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" %>
<%
	//전달값이 없는 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
	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;
	}
	//전달값을 반환받아 저장
	int num=Integer.parseInt(request.getParameter("num"));
	//
	//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글을 검색하여 반환하는 DAO 클래스의 메소드 호출
	BoardDTO board=BoardDAO.getDAO().selectBoard(num);
	//
	//검색된 게시글이 없거나 삭제 게시글인 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
	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;
	}
	//
	//게시글 작성자 및 관리자가 아닌 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
	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;
	}
	//글번호를 전달받아 BOARD 테이블에 저장된 해당 글번호의 게시글에 대한 STATUS 컬럼값을 [0]으로 변경하는 DAO 클래스의 메소드 호출
	//BoardDAO.getDAO().updateStatus(num, 0);
	//→ 게시글을 전달받아 BOARD 테이블에 저장된 해당 게시글을 변경하는 DAO 클래스의 메소드 호출
	board.setStatus(0);
	BoardDAO.getDAO().updateBoard(board);
	//
	//페이지 이동
	out.println("<script type='text/javascript'>");
	out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=board&work=board_list';");
	out.println("</script>");
%>

0개의 댓글