갈림길 이정표

[JSP] (최종 - Model Ⅰ방식) 간단한 쇼핑몰 게시판 만들어 보기 *갱신 필* 본문

Programming Language/Servlet & JSP

[JSP] (최종 - Model Ⅰ방식) 간단한 쇼핑몰 게시판 만들어 보기 *갱신 필*

이몽뇽 2020. 9. 2. 22:43

출처: cafe.daum.net/flowlife/HqLp/13

 

다음은 쇼핑몰 게시판을 만들기 위한 간단한 Mind Map이다. (나중에 Q&A로 활용 가능)

쇼핑몰 게시판 마이드 맵 (클릭하면 더 선명하게 볼 수 있다)

보통의 게시판이라면 위와 같이 간단하게 구조화 시킬 수 있다. 우리는 이런 기본적인 구조를 구현할 수 있으면 된다.

(추가적인 부분은 나중에 연구해서 구현해보도록 하자)

 

※ 이번 글은 각 기능 별 구현하는 방법에 대해 자세하게 다루기 위해 전반적인 코딩은 숨김으로 표시 해놓았다.

 


▽ web_myshop 사이드 바 목록

더보기
목록

▽구현을 위한 기본 java source 파일들

더보기

▼ DB 레코드에 대한 각 칼럼별 getter와 setter ( + jsp 액션 태그 中 setProperty를 쓰기 위함, INSERT용)
(※ setBdate 메소드 만큼은 Overloading 하였으니 주의)

[BoardBean.java]

package kr.shop.board;

import java.util.Calendar;

public class BoardBean {	//form bean
	private String name, pass, mail, title, cont, bip, bdate;
	private int num, readcnt, gnum, onum, nested;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPass() {
		return pass;
	}
	public void setPass(String pass) {
		this.pass = pass;
	}
	public String getMail() {
		return mail;
	}
	public void setMail(String mail) {
		this.mail = mail;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getCont() {
		return cont;
	}
	public void setCont(String cont) {
		this.cont = cont;
	}
	public String getBip() {
		return bip;
	}
	public void setBip(String bip) {
		this.bip = bip;
	}
	public String getBdate() {
		return bdate;
	}
	public void setBdate(String bdate) {
		this.bdate = bdate;
	}
	public void setBdate() {	//Overloading
		Calendar cal = Calendar.getInstance();	//Singleton 패턴
		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		int day = cal.get(Calendar.DATE);
		this.bdate = year + "-" + month + "-" + day;	//int로 받았지만 hyphen(-) 때문에 String으로 [Promotion]
	}
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public int getReadcnt() {
		return readcnt;
	}
	public void setReadcnt(int readcnt) {
		this.readcnt = readcnt;
	}
	public int getGnum() {
		return gnum;
	}
	public void setGnum(int gnum) {
		this.gnum = gnum;
	}
	public int getOnum() {
		return onum;
	}
	public void setOnum(int onum) {
		this.onum = onum;
	}
	public int getNested() {
		return nested;
	}
	public void setNested(int nested) {
		this.nested = nested;
	}
}

DB 레코드에 대한 각 칼럼별 getter와 setter (SELECT, UPDATE, DELETE용)

[BoardDTO.java]

package kr.shop.board;

public class BoardDTO {
	private String name, pass, mail, title, cont, bip, bdate;
	private int num, readcnt, gnum, onum, nested;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPass() {
		return pass;
	}
	public void setPass(String pass) {
		this.pass = pass;
	}
	public String getMail() {
		return mail;
	}
	public void setMail(String mail) {
		this.mail = mail;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getCont() {
		return cont;
	}
	public void setCont(String cont) {
		this.cont = cont;
	}
	public String getBip() {
		return bip;
	}
	public void setBip(String bip) {
		this.bip = bip;
	}
	public String getBdate() {
		return bdate;
	}
	public void setBdate(String bdate) {
		this.bdate = bdate;
	}
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public int getReadcnt() {
		return readcnt;
	}
	public void setReadcnt(int readcnt) {
		this.readcnt = readcnt;
	}
	public int getGnum() {
		return gnum;
	}
	public void setGnum(int gnum) {
		this.gnum = gnum;
	}
	public int getOnum() {
		return onum;
	}
	public void setOnum(int onum) {
		this.onum = onum;
	}
	public int getNested() {
		return nested;
	}
	public void setNested(int nested) {
		this.nested = nested;
	}
}

 

 

Q. 왜 javaBeans파일과 DTO파일은 비슷한데 따로 만드나요?

A. 공통점: <jsp:useBean/> 액션태그로 각각의 파일들이 DB connection 파일 (dbcp 또는 Driver연결 파일)과 연결하여 사용.

차이점:

javaBeans파일: <jsp:setProperty/>액션태그를 위해 사용.(post 방식의 넘겨받은 <form> tag정보들을 바로 javaBeans파일의 setter로 적용시키는 기법). 보통 사용자(User)로 부터 얻은 데이터 레코드를 DB에 저장해야 할 때, 오직 Business Logic을 위한 JSP 파일 (<HTML> tag 없음)에서만 사용됨. DAO(Data Access Object) 中 INSERT 작업을 위함. (∴ 사용자 입력 자료 DB 저장할 때, dbcp에서 Bean클래스 argument 필요.)

DTO(Data Transfer Object) 파일: <jsp:setProperty/> 액션 태그를 사용할 수 없으므로 따로 request.getParameter( )으로 필요 정보를 받아와야 되며, setter보단 getter를 많이 사용함. DAO(Data Access Object) 中 SELECT, UPDATE, DELETE 작업을 위함.(∴ DB로 부터 데이터를 읽어와야 될 때)


▽DAO(Data Access Object)를 위한 자바 클래스 파일 (ing...)

더보기
[BoardMgr.java]

package kr.shop.board;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class BoardMgr {	//Business logic
	private Connection conn;
	private PreparedStatement pstmt;
	private ResultSet rs;
	private DataSource ds;
	
	private int tot; // 전체 레코드 수
	private int pList = 10; //한 페이지 당 출력 행 수 (여기서 나중에 page당 몇 개씩 보기 옵션을 설정할 수 도 있음)
	private int pageSu;	// 전체 페이지 수
	
	public BoardMgr() {
		try {
			Context context = new InitialContext();
			ds = (DataSource)context.lookup("java:comp/env/jdbc_maria");	//JDBC Pooling
		} catch (Exception e) {
			System.out.println("BoardMgr err: " + e);
		}
	}
	
	public ArrayList<BoardDTO> getDataAll(int page, String stype, String sword){
		ArrayList<BoardDTO> list = new ArrayList<BoardDTO>();
		//String sql = "SELECT * FROM shopboard ORDER BY gnum DESC, onum ASC";
		
		String sql = "SELECT * FROM shopboard";	//검색이 있는 경우를 위해
		
		try {
			conn = ds.getConnection();
			if(sword == null) {	//검색이 없는 경우
				sql += " ORDER BY gnum DESC, onum ASC";
				pstmt = conn.prepareStatement(sql);
			}else {	//검색이 있는 경우
				sql += " WHERE " + stype + " like ?";	//띄어 쓰기 주의
				sql += " ORDER BY gnum DESC, onum ASC";
				pstmt = conn.prepareStatement(sql);
				pstmt.setString(1, "%" + sword + "%");
			}
			rs = pstmt.executeQuery();
			
			//5행씩 paging 처리
			for (int i = 0; i < (page - 1) * pList; i++) {
				rs.next();	//레코드 포인터 위치 (1 page → pointer: 0, 2 page → pointer: 4, 3 page → pointer: 9, ...)
				//0이 첫번째 레코드, 4는 5번째 레코드
			}
			
			int k = 0; //임의 변수 (여기서 나중에 page당 몇 개씩 보기 옵션을 설정할 수 도 있음)
			while(rs.next() && k < pList) {
				BoardDTO dto = new BoardDTO();
				dto.setNum(rs.getInt("num"));
				dto.setName(rs.getString("name"));
				dto.setTitle(rs.getString("title"));
				dto.setBdate(rs.getString("bdate"));
				dto.setReadcnt(rs.getInt("readcnt"));
				dto.setNested(rs.getInt("nested"));
				list.add(dto);
				k++;	//← 이게 추가됨
			}
		} catch (Exception e) {
			System.out.println("getDataAll() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
		return list;
	}
	
	public int currentGetNum() {	//새 글 최대번호 구하기
		String sql = "SELECT MAX(num) FROM shopboard";
		int cnt = 0;
		
		try {
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			rs = pstmt.executeQuery();
			if(rs.next()) cnt = rs.getInt(1); 	//결과 값이 하나 이므로 if (없으면 0 값으로  return 하도록)
		} catch (Exception e) {
			System.out.println("currentGetNum() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
		return cnt;
	}
	
	public void saveData(BoardBean bean) {
		String sql = "INSERT INTO shopboard VALUES(?,?,?,?,?,?,?,?,?,?,?,?)";
		try {
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, bean.getNum());
			pstmt.setString(2, bean.getName());
			pstmt.setString(3, bean.getPass());
			pstmt.setString(4, bean.getMail());
			pstmt.setString(5, bean.getTitle());
			pstmt.setString(6, bean.getCont());
			pstmt.setString(7, bean.getBip());
			pstmt.setString(8, bean.getBdate());
			pstmt.setInt(9, 0);		//readcnt
			pstmt.setInt(10, bean.getGnum());
			pstmt.setInt(11, 0);	//onum (원글 이므로 0)
			pstmt.setInt(12, 0);	//nested (원글 이므로 0)
			pstmt.executeUpdate();
			
			rs = pstmt.executeQuery();
		} catch (Exception e) {
			System.out.println("saveData() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
	}
	
	public void totalList() {
		String sql = "SELECT COUNT(*) FROM shopboard";
		
		try {
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			rs = pstmt.executeQuery();
			rs.next();
			tot = rs.getInt(1);
			
			//System.out.println("전체 건수 : " + tot);
			
		} catch (Exception e) {
			System.out.println("totalList() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
	}
	
	public int getPageSu() {
		pageSu = tot / pList;	//몫 정수값이 나옴
		if(tot % pList > 0) pageSu++;	//자투리 행 계산	 (Ex. tot = 12행 일 때 (pList=5로 나누면) pageSu = 몫:2 나머지 2) 
		
		return pageSu;	//pageSu: 몫 + (나머지) :3
	}
	
	public void updateReadcnt(String num) {	//(글 내용 보기전) 조회수 증가
		String sql = "UPDATE shopboard SET readcnt=readcnt +1 WHERE num = ?";
		try {
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, num);
			pstmt.executeQuery();	//(값을 받아올 필요가 없어서) rs 필요 없음
		} catch (Exception e) {
			System.out.println("updateReadcnt() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
	}
	
	public BoardDTO getData(String num) {
		String sql = "SELECT * FROM shopboard WHERE num =?";
		BoardDTO dto = null;
		try {
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, num);
			rs = pstmt.executeQuery();
			if(rs.next()) {	//있다 없다 여부
				dto = new BoardDTO();
				dto.setNum(Integer.parseInt(num));
				dto.setName(rs.getString("name"));
				dto.setPass(rs.getString("pass"));
				dto.setMail(rs.getString("mail"));
				dto.setTitle(rs.getString("title"));
				dto.setCont(rs.getString("cont"));
				dto.setBip(rs.getString("bip"));
				dto.setBdate(rs.getString("bdate"));
				dto.setReadcnt(rs.getInt("readcnt"));
			}
		} catch (Exception e) {
			System.out.println("getData() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
		return dto;
	}
	
	public BoardDTO getReplyData(String num) {	//댓글용
		BoardDTO dto = null;
		String sql = "SELECT * FROM shopboard WHERE num = ?";
		try {
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, num);
			rs = pstmt.executeQuery();
			if(rs.next()) {
				dto = new BoardDTO();
				dto.setTitle(rs.getString("title"));
				dto.setGnum(rs.getInt("gnum"));		//group number
				dto.setOnum(rs.getInt("onum"));		//order number
				dto.setNested(rs.getInt("nested"));	//공백
			}
			
		} catch (Exception e) {
			System.out.println("getReplyData() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
		return dto;
	}
	
	public void updateOnum(int gnum, int onum) {	//댓글용 - onum갱신
		//같은 그룹의 레코드는 모두 작업에 참여 - 같은 그룹의 onum 값 변경
		
		String sql = "UPDATE shopboard SET onum = onum +1 WHERE onum >= ? and gnum = ?";
		try {
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, onum);
			pstmt.setInt(2, gnum);
			pstmt.executeQuery();	//(값을 받아올 필요가 없어서) rs 필요 없음
		} catch (Exception e) {
			System.out.println("updateOnum() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
	}
	
	public void saveReplyData(BoardBean bean) {	//댓글용 - DB 저장
		String sql = "INSERT INTO shopboard VALUES(?,?,?,?,?,?,?,?,?,?,?,?)";
		try {
			conn = ds.getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, bean.getNum());
			pstmt.setString(2, bean.getName());
			pstmt.setString(3, bean.getPass());
			pstmt.setString(4, bean.getMail());
			pstmt.setString(5, bean.getTitle());
			pstmt.setString(6, bean.getCont());
			pstmt.setString(7, bean.getBip());
			pstmt.setString(8, bean.getBdate());
			pstmt.setInt(9, 0);		//readcnt
			pstmt.setInt(10, bean.getGnum());
			pstmt.setInt(11, bean.getOnum());	//onum
			pstmt.setInt(12, bean.getNested());	//nested
			pstmt.executeUpdate();
		} catch (Exception e) {
			System.out.println("saveReplyData() err: " + e);
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e2) {
		
			}
		}
	}
}

 

더보기
[index.html]

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
HOME<p/>
메뉴1 메뉴2 <a href="board/boardlist.jsp">게시판</a>

</body>
</html>

▽ ing...

[boardlist.jsp]

<%@page import="kr.shop.board.BoardDTO"%>
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
int pageBlock, start, end;	//페이징 처리를 위한 작업 (블럭단위)
int pageSu, spage = 1;		//페이징 처리를 위한 작업 (페이지단위)
%>

<jsp:useBean id="boardMgr" class="kr.shop.board.BoardMgr"/>
<jsp:useBean id="dto" class="kr.shop.board.BoardDTO"/>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판</title>
<link rel="stylesheet" type="text/css" href="../css/board.css">
<script type="text/javascript">
window.onload = function(){
	document.getElementById("btnSearch").onclick = function(){
		if(frm.sword.value === ""){
			frm.sword.focus();
			alert("검색어를 입력하시오.");
			return;
		}
		frm.submit();
	}
}
</script>
</head>
<body>
<table>
	<tr>
		<td>
			[<a href="../index.html">메인으로 돌아가기</a>] &nbsp;
			[<a href="boardlist.jsp?page=1">최근 목록 보기</a>] &nbsp;	<!-- page=1 고정 -->
			[<a href="boardwrite.jsp">새로 글쓰기</a>] &nbsp;
			[<a href="#" onclick="window.open('admin.jsp','','width=300,height=150,top=300,left=300')">관리자용</a>] &nbsp;
		</td>
	</tr>
</table>
<table>
	<tr style="background-color: silver;">
		<th>번호</th><th>제 목</th><th>작성자</th><th>작성일</th><th>조회</th>
	</tr>
	<%
	request.setCharacterEncoding("utf-8");
	
	try{
		spage = Integer.parseInt(request.getParameter("page"));
	}catch(Exception e){
		spage = 1;	//아무것도 안했을 때 (페이지 정보를 넘겨주지 않을 때)는  첫 페이지로..
	}
	if(spage <= 0 ) spage = 1;
	
	String stype = request.getParameter("stype");	//검색인 경우
	String sword = request.getParameter("sword");
	
	//paging
	//전체 레코드 수를 알아야 함
	boardMgr.totalList();
	pageSu = boardMgr.getPageSu();
	//out.print("페이지 수:" + pageSu); → 12행 기준 pageSu=3
	
	ArrayList<BoardDTO> list = boardMgr.getDataAll(spage, stype, sword);
	for(int i = 0; i < list.size(); i++){
		dto = (BoardDTO)list.get(i);
		//댓글 들여 쓰기 준비(nested 하나당 공백 4개씩)--------
		int nst = dto.getNested();
		String tab = "";
		//String icon = ""; 으로 이미지로 공백 분간 가능
		
		for(int k = 0; k < nst; k++){
			tab += "&nbsp;&nbsp;&nbsp;&nbsp;";
			//icon = "<img src=""...>"
		}
		
	%>
	<tr>
		<td><%=dto.getNum() %></td>
		<td>
			<%=tab %><a href="boardcontent.jsp?num=<%=dto.getNum()%>&page=<%=spage%>"><%=dto.getTitle() %></a>
			<!-- page=: 돌아가기 했을 때 작업하고 있던 현재 페이지로 돌아오기 위해 -->
		</td>
		<td><%=dto.getName() %></td>
		<td><%=dto.getBdate() %></td>
		<td><%=dto.getReadcnt() %></td>
	</tr>
	<%} %>
</table>
<table>
	<tr style="text-align: center;">	<!-- 가운데 정렬 -->
		<td>
		<%
		for(int i = 1; i <= pageSu; i++){
			if(i == spage){
				out.print("<b style='font-size: 12pt; color: red;'>[" + i + "]</b>");
			}else{
				out.print("<a href=boardlist.jsp?page=" + i + ">[" + i + "]</a>");
			}
		}
		%>
		<br><br>
		<form action="boardlist.jsp" name="frm" method="post">
			<select name="stype">
				<option value="title" selected="selected">글 제목</option>
				<option value="name">작성자</option>
			</select>
			<input type="text" name="sword">
			<input type="button" value="검색" id="btnSearch">
		</form>
		</td>
	</tr>
</table>
</body>
</html>
[boardwrite.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판</title>
<link rel="stylesheet" type="text/css" href="../css/board.css">
<script>
function check(){
	if(frm.name.value==""){
		alert("이름을 입력하세요");
		frm.name.focus();
	}else if(frm.pass.value ==""){
		alert("비밀번호를 입력하세요");
		frm.pass.focus();
	}else if(frm.mail.value ==""){
		alert("이메일을 입력하세요");
		frm.mail.focus();
	}else if(frm.title.value ==""){
		alert("제목을 입력하세요");
		frm.title.focus();
	}else if(frm.cont.value ==""){
		alert("내용을 입력하세요");
		frm.cont.focus();
	}else
		frm.submit();
}
</script>
</head>
<body>
<form name="frm" method="post" action="boardsave.jsp">
	<table border="1">
		<tr>
			<td colspan="2"><h2>*** 글쓰기 ***</h2></td>
		</tr>
		<tr>
			<td align="center" width="100">이 름</td>
			<td width="430"><input name="name" size="15"></td>
		</tr>
		<tr>
			<td align="center">암 호</td>
			<td><input type="password" name="pass" size="15"></td>
		</tr>
		<tr>
			<td align="center">메 일</td>
			<td><input name="mail" size="25"></td>
		</tr>
		<tr>
			<td align="center">제 목</td>
			<td><input name="title" size="50"></td>
		</tr>
		<tr>
			<td align="center">내 용</td>
			<td><textarea name="cont" cols="50" rows="10"></textarea></td>
		</tr>
		<tr>
			<td colspan="2" align="center" height="30">
			    <input type="button"
				 value="메  인" onClick="location.href='../index.html'">&nbsp;
				<input type="button" value="작  성" onClick="check()">&nbsp;
				<input type="button" value="목  록"
				  onClick="location.href='boardlist.jsp'"></td>
		</tr>
	</table>
</form>
</body>
</html>
[boardsave.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
request.setCharacterEncoding("utf-8");
%>

<jsp:useBean id="boardMgr" class="kr.shop.board.BoardMgr"/>
<jsp:useBean id="bean" class="kr.shop.board.BoardBean"/>
<jsp:setProperty property="*" name="bean" />

<%
bean.setBip(request.getRemoteAddr());		//ip
bean.setBdate();	//overriding 함			//등록일
int maxNum = boardMgr.currentGetNum() + 1;	
bean.setNum(maxNum);						//글 번호
bean.setGnum(maxNum);						//글 그룹 번호

boardMgr.saveData(bean);

response.sendRedirect("boardlist.jsp?page=1");	//저장 후 목록 보기
%>

[boardcontent.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:useBean id="boardMgr" class="kr.shop.board.BoardMgr"></jsp:useBean>
<jsp:useBean id="dto" class="kr.shop.board.BoardDTO"></jsp:useBean>
<%
//http://localhost/web_myshop/board/boardcontent.jsp?num=ㅇ&page=ㅁ
String num = request.getParameter("num");	//int X → String 으로 받음
String spage = request.getParameter("page");
//out.print(num + " " + spage);

boardMgr.updateReadcnt(num);	//조회수 증가
dto = boardMgr.getData(num);	//상세보기 레코드 얻기

/* 확인용
out.println(dto.getName() + "/");
out.println(dto.getTitle() + "/");
out.println(dto.getCont() + "/");
out.println(dto.getBdate()); */
 
String name = dto.getName();
String pass = dto.getPass();
String mail = dto.getMail();
String title = dto.getTitle();
String cont = dto.getCont();
String bip = dto.getBip();
String bdate = dto.getBdate();
int cnt = dto.getReadcnt();

String apass = "*****";//관리자 모드 (일반인은 비밀번호를 숨김)
String adminOk = (String)session.getAttribute("adminOk");
if(adminOk != null){
	if(adminOk.equalsIgnoreCase("admin")) apass = pass;
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 상세 보기</title>
<link rel="stylesheet" type="text/css" href="../css/board.css">
</head>
<body>
<table>
	<tr>
		<td><b>비밀번호: <%=apass %></b></td>
		<td colspan="2" style="text-align: right;">
			<a href="reply.jsp?num=<%=num %>&page=<%=spage %>">
				<img src="../images/reply.gif">
			</a>
			<a href="edit.jsp?num=<%=num %>&page=<%=spage %>">
				<img src="../images/edit.gif">
			</a>
			<a href="delete.jsp?num=<%=num %>&page=<%=spage %>">
				<img src="../images/del.gif">
			</a>
			<a href="boardlist.jsp?page=<%=spage %>">
				<img src="../images/list.gif">
			</a>
		</td>
	</tr>
	<tr>
		<td>
		작성자: <a href="mailto:<%=mail %>"><%=name %> (ip: <%=bip %>)
		</td>
		<td>작성일: <%=bdate %></td>
		<td>조회수: <%=cnt %></td>
	</tr>
	<tr>
		<td colspan="3" style="background-color:cyan">제목: <%=title %></td>
	</tr>
	<tr>
		<td colspan="3">
			<textarea rows="10" style="width:99%" readonly="readonly"><%=cont %></textarea>
		</td>
	</tr>
</table>
</body>
</html>

[reply.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:useBean id="boardMgr" class="kr.shop.board.BoardMgr"/>
<jsp:useBean id="dto" class="kr.shop.board.BoardDTO"/>

<%
String num = request.getParameter("num"); 
String spage = request.getParameter("page");
dto = boardMgr.getReplyData(num);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>댓글</title>
<link rel="stylesheet" type="text/css" href="../css/board.css">
<script type="text/javascript">
function check(){
	if(frm.name.value==""){
		alert("이름을 입력하세요");
		frm.name.focus();
	}else if(frm.pass.value ==""){
		alert("비밀번호를 입력하세요");
		frm.pass.focus();
	}else if(frm.mail.value ==""){
		alert("이메일을 입력하세요");
		frm.mail.focus();
	}else if(frm.title.value ==""){
		alert("제목을 입력하세요");
		frm.title.focus();
	}else if(frm.cont.value ==""){
		alert("내용을 입력하세요");
		frm.cont.focus();
	}else
		frm.submit();
}
</script>
</head>
<body>
<form action="replysave.jsp" name="frm" method="post">
<!-- 댓글에 대한 정보를 들고 가야 list 에서 정확한 여백을 주며 보여줄 수 있음 (단, hidden으로 user 눈에는 보이지 않음) -->
<input type="hidden" name="num" value="<%=num %>">
<input type="hidden" name="page" value="<%=spage %>">
<input type="hidden" name="gnum" value="<%=dto.getGnum() %>">
<input type="hidden" name="onum" value="<%=dto.getOnum() %>">
<input type="hidden" name="nested" value="<%=dto.getNested()%>">
	<table border="1">
		<tr>
			<td colspan="2"><h2>*** 댓글쓰기 ***</h2></td>
		</tr>
		<tr>
			<td align="center" width="100">이 름</td>
			<td width="430"><input name="name" size="15"></td>
		</tr>
		<tr>
			<td align="center">암 호</td>
			<td><input type="password" name="pass" size="15"></td>
		</tr>
		<tr>
			<td align="center">메 일</td>
			<td><input name="mail" size="25"></td>
		</tr>
		<tr>
			<td align="center">제 목</td>
			<td><input name="title" size="50" value="[RE]:<%=dto.getTitle() %>"></td>
		</tr>
		<tr>
			<td align="center">내 용</td>
			<td><textarea name="cont" rows="10" style="width: 100%"></textarea></td>
		</tr>
		<tr>
			<td colspan="2" align="center" height="30">
				<input type="button" value="작  성" onClick="check()">&nbsp;
				<input type="button" value="목  록"
				  onClick="location.href='boardlist.jsp?page=<%=spage%>'"></td>
		</tr>
	</table>
</form>
</body>
</html>
[replysave.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
request.setCharacterEncoding("utf-8");
%>
<jsp:useBean id="bean" class="kr.shop.board.BoardBean"/>
<jsp:setProperty property="*" name="bean"/>	<%-- 두줄로 setter기능 적용 됨. --%>
<jsp:useBean id="boardMgr" class="kr.shop.board.BoardMgr"/>
<%
String spage = request.getParameter("page");	//boardBean에는 page번호 멤버가 없다

int num = bean.getNum();
int gnum = bean.getGnum();
int onum = bean.getOnum() + 1;	//댓글이므로 1증가
int nested = bean.getNested() + 1;//댓글이므로 1증가	

//같은 그룹 내에서 새로운 댓글의 onum보다 크거나 같은 값을 댓글 입력 전에 먼저 수정하기. (작으면 수정 안함.)
boardMgr.updateOnum(gnum, onum);	//새로운 onum 갱신

//댓글 자료 저장
bean.setOnum(onum);
bean.setNested(nested);
bean.setBip(request.getRemoteAddr());
bean.setBdate();	//overloading으로 argument없이 호출 가능
bean.setNum(boardMgr.currentGetNum() + 1);	// 새 댓글의 레코드 번호 값 부여 (가장 큰 값을 가져옴)

boardMgr.saveReplyData(bean);
response.sendRedirect("boardlist.jsp?page=" + spage);	//댓글 저장 후 목록 보기
%>
<%-- <!DOCTYPE html> 비즈니스 로직 jsp 파일 이므로 생략--%>

아직 edit, editsave, delete 업로드 안함

▽ 그 외 부수적인 코딩 자료들

더보기
WebContent > css > [board.css]

@charset "UTF-8";
table{
	width: 80%; margin-left: auto; margin-right: auto;
}

a{
	text-decoration: none;
}

body {
	margin: 10px;
}

WebContent > WEB-INF > [context.xml]

<?xml version="1.0" encoding="UTF-8"?>
<Context>
	<Resource name="jdbc_maria" auth="Container" type="javax.sql.DataSource"
		driverClassName="org.mariadb.jdbc.Driver" loginTimeout="10" maxWait="5000"
		username="root" password="369369" testOnBorrow="true"
		maxActive="500" maxIdle="100"
		url="jdbc:mysql://localhost:3306/test" />
</Context>

[admin.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
관리자용
</body>
</html>

 

 

Q. 왜 저장을 할 때 boardsave, replysave, editsave 라는 파일을 따로 만들까?

A. Business logic

 

※ 주의 

rs = pstmt.executeQuery(); → 

pstmt.executeUdate(); → 

 

 

※페이지 이동

history.back(); → js

response.sendRedirect(); → jsp

Comments