JSP

부트캠프53일차(게시판생성,writeForm , list , info)

동곤일상 2025. 4. 17. 17:50
반응형

1)게시판생성

1-1)board테이블 생성

1-2) Controller , Mapper (SQL가짐), Dao(DB와의연결,sql실행)생성

1-3) Board클래스

 

2)WriteForm(작성하는곳)

2-1)layout적용

2-2)BoardController(write매핑부분)

2-3) BoardDao(write관련 메서드)

2-4) BoardMapper (sql을 가지는 인터페이스 Mapper)

 

3)list

3-1)  list.jsp (view)

3-2) list매핑부분(Controller)

3-3) BoardDao ( boardCount , list 메서드)

3-4) BoardMapper

 

4)info

4-1)  Controller(info매핑부분)

4-2) BoardDao의 numSearch , readCntAdd메서드

4-3) BoardMapper인터페이스


1) 게시판생성

1-1) board 테이블 생성

create table board(
	num int auto_increment primary key ,-- 게시글 번호(기본키)
	writer varchar(30), -- 작성자
	pass varchar(20), -- 비밀번호
	title varchar(100), --게시글 제목
	content varchar(2000), --게시글 내용
	file1 varchar(200), --첨부파일명
	boardid varchar(2), --게시판 종류 (1.공지사항 , 2.자유게시판)
	regdate datetime, -- 게시글등록일자
	readcnt int(10), --조회수(상세보기 시 증가)
	grp int,		--답글 작성시 원글의 게시글 번호
	grplevel int(3), -- 답글의레벨(0:원글 1:원글의답글 2:답글의답글...)
	grpstep int(5) --그룹의 출력 순서
);

 

1-2) Controller , Mapper , Dao 생성

1-3) Board클래스(Bean)

package model.board;

import java.util.Date;

public class Board {
	private int num;
	private String writer;
	private String pass;
	private String title;
	private String content;
	private String file1;
	private String boardid;
	private Date regdate;
	private int readcnt;
	private int grp;
	private int grplevel;
	private int grpstep;
	
	//getter , setter , toString 생성	
}

2) writeForm

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<!-- /webapp/view/board/writeForm.jsp -->
<!DOCTYPE html>
<html>
<head>

<meta charset="UTF-8">
<title>게시글등록</title>
</head>
<body>
	<form action="write" method="post" enctype="multipart/form-data"
		name="f">
		<h2 class="text-center">게시판 글쓰기</h2>
		<table class="table">
			<tr>
				<td>글쓴이</td>
				<td><input type="text" name="writer" class="form-control"></td>
			</tr>
			<tr>
				<td>비밀번호</td>
				<td><input type="password" name="pass" class="form-control"></td>
			</tr>
			<tr>
				<td>제목</td>
				<td><input type="text" name="title" class="form-control"></td>
			</tr>
			<tr>
				<td>내용</td>
				<td><textarea rows="15" name="content" id="content"
						class="form-control"></textarea></td>
			</tr>
			<tr>
				<td>첨부파일</td>
				<td><input type="file" name="file1"></td>
			</tr>
			<tr>
				<td colspan="2"><a href="javascript:inputcheck()" class="btn btn-outline-secondary">[게시물등록]</a></td>
			</tr>
		</table>

	</form>
	<script type="text/javascript">
		function inputcheck() {
			f = document.f;
			if (f.writer.value == "") {
				alert("글쓴이 입력");
				f.writer.focus();
				return;
			}
			if (f.pass.value == "") {
				alert("비밀번호입력");
				f.pass.focus();
				return;
			}
			if (f.title.value == "") {
				alert("제목입력");
				f.title.focus();
				return;
			}
			f.submit(); //submit발생 
		}
	</script>

</body>
</html>

 

2-1) layout적용

/java/sitemesh/SiteMeshFilter.java

에 다음과같은 문장을 맨 아래에 넣어준다.

builder.addDecoratorPath("/board/*", "/layout/layout.jsp");

 

2-2) BoardController(write매핑부분)

package controller;

import java.io.File;

import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.oreilly.servlet.MultipartRequest;

import gdu.mskim.MskimRequestMapping;
import gdu.mskim.RequestMapping;
import model.board.Board;
import model.board.BoardDao;

@WebServlet(urlPatterns = {"/board/*"},
	initParams = {@WebInitParam(name="view",value="/view/")}
		)
public class BoardController extends MskimRequestMapping {
	private BoardDao dao =  new BoardDao();

	@RequestMapping("write")
	public String write(HttpServletRequest request , 
			HttpServletResponse response) {
		String path = request.getServletContext().getRealPath("/")+"/upload/board/";
		//C:/java/workspace/.metadata/
		// .plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/model2Study/upload/board/
		File f = new File(path);
		if(!f.exists()) {
			f.mkdirs();
		}
		int size = 10*10*1024;//10M(업로드파일의 최대크기)
		MultipartRequest multi = null;
		try {
			multi = new MultipartRequest(request, path,size,"UTF-8");
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		Board board = new Board();
		board.setWriter(multi.getParameter("writer"));
		board.setPass(multi.getParameter("pass"));
		board.setTitle(multi.getParameter("title"));
		board.setContent(multi.getParameter("content"));
		board.setFile1(multi.getFilesystemName("file1")); //업로드된 파일명
		String boardid = (String)request.getSession().getAttribute("boardid");
		if(boardid==null) {
			boardid="1"; // 공지사항 기본게시판으로설정
		}
		board.setBoardid(boardid);//게시판종류 1:공지사항 , 2:자유게시판
		
		if(board.getFile1()==null) {
			board.setFile1("");
		}
		int num = dao.maxnum();
		board.setNum(++num); // 게시글 키값(게시글번호)
		board.setGrp(num); // 그룹번호
		String msg="게시물등록실패";
		String url = "writeForm";
		if(dao.insert(board)) {
			return "redirect:list?boardid="+boardid;
		}
		request.setAttribute("msg", msg);
		request.setAttribute("url", url);
		return "alert";
		
	}
}

 

 

2-3) BoardDao( DB와의 연결을 위한 파일)

package model.board;

import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;

import model.MyBatisConnection;
import model.mapper.BoardMapper;

public class BoardDao {

	private Class<BoardMapper> cls = BoardMapper.class;
	private Map<String, Object> map = new HashMap<>();
	
	
	public int maxnum() {
		SqlSession session = MyBatisConnection.getConnection();
		try {
			return session.getMapper(cls).maxnum();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			MyBatisConnection.close(session);
		}
		return 0;
	}


	public boolean insert(Board board) {
		SqlSession session = MyBatisConnection.getConnection();
		try {
			if(session.getMapper(cls).insert(board)) {
				return true;
			}
			return false;
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			MyBatisConnection.close(session);
		}
		return false;
	}

}

 

2-4) BoardMapper (sql을 설정하는 인터페이스 Mapper)

package model.mapper;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;

import model.board.Board;

public interface BoardMapper {

	//num이 null이라면 0을 반환해줌
	@Select("select ifnull(max(num),0) from board")
	int maxnum();

	@Insert("insert  into board(writer,pass,title,content,file1,regdate,"
			+ "readcnt, grp , grplevel , grpstep , boardid) "
			+ " values(#{writer},#{pass},#{title},#{content},#{file1},now(),"
			+ "0, #{grp} , #{grplevel} , #{grpstep} , #{boardid})")
	boolean insert(Board board);

}

 

 

3) list

3-1) list.jsp (view)

 

writeForm이 정상적으로 작성됐다면

그 데이터의 boardid를 파라미터로 갖는

list 실행

 

/view/board/list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<!-- 
첨부파일이 존재하는 게시물의 제목앞에 @ 표시
 -->
<head>
<meta charset="UTF-8">
<title>게시물목록</title>
</head>
<body>
<h2>${boardName}</h2>
<table class="table">
<c:if test="${boardcount == 0}">
	<tr><td colspan="5">등록된게시글이없어요</td></tr>
</c:if>
<c:if test="${boardcount > 0}">
	<tr><td colspan="5" style="text-align:right">글 갯수:${boardcount}</td></tr>
	<tr>
	<th width="8%">번호</th><th width="50%">제목</th>
	<th width="14%">작성자</th><th width="17%">등록일</th>
	<th width="11%">조회수</th>
	</tr>
	<c:set var="num" value="${num}" /> <!-- (controller에서만듬)num속성을 c:set으로 지정 -->
	<c:forEach var="b" items="${list}" >
		<tr><td>${num}</td>
	<c:set var="num" value="${num-1}" /> <!-- num을 -1해줌 -->
		<td style="text-align: left">
		
		<c:if test="${!empty b.file1}"><a href="../upload/board/${b.file1}">@</a></c:if>
		<c:if test="${empty b.file1}">&nbsp;&nbsp;&nbsp;</c:if>	
		<a href="info?num=${b.num}">${b.title}</a></td>
		<td>${b.writer}</td>
		<td>${b.regdate}</td>
		<td>${b.readcnt}</td>
	</c:forEach>
	<tr><td colspan="5" align="center">
		<c:if test="${pageNum <= 1}">[이전]</c:if>
		<c:if test="${pageNum > 1}">
		<a href="list?pageNum=${pageNum-1}">[이전]</a>
		</c:if>
		<c:forEach var="a" begin="${startpage}" end="${endpage}">
			<c:if test="${a == pageNum}"><a href="#">[${a}]</a></c:if><!-- 현재페이지를 누르면 아무일도일어나지않음 -->
			<c:if test="${a != pageNum}"><!-- 다른페이지클릭시 해당 pageNum으로넘어감 -->
				<a href="list?pageNum=${a}">[${a}]</a>
			</c:if>
		</c:forEach>
		<c:if test="${pageNum >= maxpage}">[다음]</c:if>
		<c:if test="${pageNum < maxpage}">
			<a href="list?pageNum=${pageNum+1}">[다음]</a>
		</c:if>
	</td></tr>
</c:if>
<tr><td colspan="5" style="text-align:right">
	<p align="right"><a href="writeForm">[글쓰기]</a></p>
</td></tr>
</table>

</body>
</html>

 

3-2) list매핑부분(Controller)

/*
	 * 1.한 페이지당 10건의 게시물을 출력하기. 
	 * pageNum이라는 파라미터값 => 없는경우는 1로설정
	 * boardid파라미터값 => 있는경우 session에등록
	 * 2.최근등록된 게시물이 가장 위쪽
	 * 3.db에서 해당페이지에 출력될 내용만 조회해 화면에출력
	 */
	@RequestMapping("list")
	public String list(HttpServletRequest request , 
			HttpServletResponse response) {
		//pageNum파라미터가존재하면 파라미터값을 pageNum변수에 저장
		//pageNum 파라미터가없으면 파라미터값을 pageNum변수는 1로저장
		int pageNum = 1;
		try {
			pageNum = Integer.parseInt(request.getParameter("pageNum"));
			
		} catch (NumberFormatException e) {}
		//boardid파라미터값 
		String boardid = request.getParameter("boardid");
		if(boardid==null || boardid.trim().equals("")) {
			boardid = "1";//boardid파라미터가 없는경우 '1'로설정
		}
		//board값을 session에 등록
		request.getSession().setAttribute("boardid", boardid);
		
		

		int limit = 10;//페이지당 출력되는 게시물의건수
		int boardcount = dao.boardCount(boardid);//현재등록된 게시물건수
		//pageNum에 해당하는 게시물목록을 최대10개 조회
		List<Board> list = dao.list(boardid,pageNum,limit);
		int maxpage = (int)((double)boardcount/limit + 0.95);
		/*
		 * maxpage : 필요한페이지 갯수 
		 * 	게시물건수    maxpage
		 *    10        10.0/10 +0.95 = (int)1.95 => 1
		 *    11        11.0/10 + 0.95  = (int)2.05 => 2
		 *    500       500.0/10 + 0.95 = (int)50.95 => 50
		 */
		int startpage = ((int)(pageNum/10.0 + 0.9) - 1) * 10 +1;
		/*
		 * startpage : 화면에출력되는 시작페이지
		 * 	현재페이지(pageNum)   startpage  endPage
		 *     1                   1        10
		 *     12                  11       20
		 *     43                  41       50 
		 */
		int endpage = startpage+ 9;//한화면에는 10개의 페이지번호만보임
		if(endpage>maxpage) { //maxpage보다 크다면 endpage는 maxpage로 바뀐다
			endpage = maxpage;
		}
		//ex) 11개의 게시물밖에없는데 10개의페이지가 필요할까? 2개의페이지(maxpage)만있으면된다!
		String boardName = "공지사항";
		
		if(boardid.equals("2")) {
			boardName = "자유게시판";
		}
		int num = boardcount - (pageNum-1)*limit; 
		
		/*
		 * num : 목록번호(boardid별로 다름)
		 * 	boardid=1 이 13개의 게시글을 가지고있고 1페이지인경우
		 *  13- 0*10 = 13    
		 *  2페이지인경우
		 *  13 - 10 =  3 
		 */
		
		request.setAttribute("boardName", boardName); //게시판이름
		request.setAttribute("boardcount", boardcount);//게시판종류별 등록된게시물
		request.setAttribute("boardid", boardid); //게시판코드
		request.setAttribute("num", num);
		request.setAttribute("pageNum", pageNum);//현재페이지
		request.setAttribute("list", list);//현재페이지에출력한 게시물목록
		request.setAttribute("startpage", startpage);//페이지시작번호
		request.setAttribute("endpage", endpage);//페이지마지막번호
		request.setAttribute("maxpage", maxpage);//페이지의 갯수
		return "board/list";
		
	}

 

 

3-3) BoardDao ( boardCount , list 메서드)

DB를 연결하는 역할 , 인터페이스에서 쿼리를실행시킬거임

public int boardCount(String boardid) {
		
		SqlSession session = MyBatisConnection.getConnection();
		try {
			return session.getMapper(cls).boardCount(boardid);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			MyBatisConnection.close(session);
		}
		return 0;
	}


	
	public List<Board> list(String boardid, int pageNum, int limit) {
		SqlSession session = MyBatisConnection.getConnection();
		map.clear();
		map.put("boardid", boardid);
		map.put("start", (pageNum-1) * limit);
		map.put("limit", limit);
		try {
			return session.getMapper(cls).list(map);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			MyBatisConnection.close(session);
		}
		return null;
	}

 

3-4 ) BoardMapper

Mapper역할 (sql구문 실행)

	@Select("select count(*) from board where boardid=#{val}")
	int boardCount(String boardid);

	
	@Select("select * from board where boardid=#{boardid}"
			+ " order by grp desc , grpstep asc limit #{start},#{limit}")
// grp 를 내림차순으로 정렬해 가장 최신의 글이 맨 위로올라갈거임          
	//start번에서부터   limit개 조회해
	List<Board> list(Map<String, Object> map);


4) info ( list에서 제목을누르면 이동하는곳)

num을 파라미터로 가짐

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시물상세보기</title>
</head>
<body>
<h2 class="">${boardName}</h2>
<table class="table">
<tr><th width="20%">글쓴이</th> <!-- Controller에서 b속성(boarder객체)를 넘겼음 -->
<td width="80%" style="text-align:left">${b.writer}</td></tr>
<%-- ${b.xxx} : b(board)에 getxx프로퍼티 --%>
<tr><th>제목</th><td style="text-align:left">${b.title}</td></tr>
<tr><th>내용</th><td><table style="width:100%; height:250px;">
<tr><td style="border-width:0px; vertical-align:top; text-align:left; margin:0px; padding:0px;">
${b.content}</td></tr></table></td></tr>
<tr><th>첨부파일</th>
	<td><c:if test="${empty b.file1}">&nbsp;</c:if>
	<c:if test="${!empty b.file1}">
		<a href="../upload/board/${b.file1}">${b.file1}</a>
	</c:if></td></tr>
<tr><td colspan="2" class="w3-center">
	<a href="replyForm?num=${b.num}">[답변]</a>
	<a href="updateForm?num=${b.num}">[수정]</a>
	<a href="deleteForm?num=${b.num}">[삭제]</a>
	<a href="list?boardid=${b.boardid}">[목록]</a>
</td></tr>
</table>

</body>
</html>

 

4-1) Controller(info매핑부분)

@RequestMapping("info")
	public String info(HttpServletRequest request, HttpServletResponse response) {
		int num = Integer.parseInt(request.getParameter("num"));
		String readcnt = request.getParameter("readcnt");
//		String boardid = (String)request.getSession().getAttribute("boardid");
		// b : num 값의 게시물 데이터 저장
		Board b = dao.numSearch(num);
		// readcnt 파라미터의 값이 "f"인 경우 조회수 증가 안함.
		if(readcnt == null || !readcnt.trim().equals("f")) {
			dao.readcntAdd(num); // 조회수 증가
		}
		String boardid = b.getBoardid();
		String boardName = "공지사항";
		if(boardid.equals("2")) {
			boardName = "자유게시판";
		}
		request.setAttribute("b",b);
		request.setAttribute("boardName", boardName);
		request.setAttribute("boardid", boardid);
		return "board/info";
	}

 

4-2 ) BoardDao의 numSearch , readcntAdd메서드

public Board numSearch(int num) {
		SqlSession session = MyBatisConnection.getConnection();
		try {
			return session.getMapper(cls).numSearch(num);
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			MyBatisConnection.close(session);
		}
		return null;
	
	}


	public int readcntAdd(int num) {
		SqlSession session = MyBatisConnection.getConnection();
		try {
			return session.getMapper(cls).readcntAdd(num);
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			MyBatisConnection.close(session);
		}
		return 0;
	}

 

4-3 ) BoardMapper인터페이스

numSeach , readcntAdd메서드

(실행하고자하는 sql를 가지고있음)

	@Select("select * from board where num=#{num}")
	Board numSearch(int num);

	@Update("update board set readcnt=readcnt+1 where num=#{v}")
	int readcntAdd(int num);