사전 준비물
1. 개발툴(이클립스, 인텔리제이 등)
2. oracle DB
3. jdk 및 각종 lib(jstl, cos, ojdbc) !
JSTL 이란 ?
=> JSP에서 빈번하게 사용되는 여러가지 처리문들을 편하게 처리해주는 태그를 모아
표준으로 만들어 놓은 라이브러리 이다. JSTL을 사용하면 스크립틀릿 없이 태그만으로 작성할 수 있다.
(MVC 패턴에서는 스크립틀릿 태그를 사용하지 않기 때문에 필요 !)
jstl 다운로드 링크 : https://mvnrepository.com/artifact/javax.servlet/jstl/1.2
COS 란 ?
=> 파일 다운로드 및 다운로드에 도움을 주는 라이브러리 이다.
cos 다운로드 링크 : http://servlets.com/cos/
ojdbc : 다운받은 오라클의 폴더에 들어가서 찾는다 !
내 컴퓨터에서의 위치는 C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib !
모두 다운받고 프레젝트의 WebContent/WEB-INF/lib 폴더에 넣어주면 된다.
프로젝트 구상
1. 게시판 목록보기
2. 게시판 글쓰기
3. 게시물 상세보기 (제목 클릭 시)
4. 파일 다운로드(파일 첨부 및 다운로드 기능 )
5. 게시물삭제하기
6. 게시물 수정하기
게시판의 프로세스
· MVP 패턴을 철저하게 지키는 비 회원제 게시판 구현
· 파일 다운로드 기능 및 비밀번호 검증 기능구현
MVC 패턴의 Model 부분
테이블 생성하기
--모델2 방식의 파일첨부형 게시판 테이블 생성
create table mvcboard (
idx number primary key, -- 일련번호
name varchar2(50) not null, -- 작성자 이름
title varchar2(200) not null, -- 제목
content varchar2(2000) not null, -- 내용
postdate date default sysdate not null, -- 작성일
ofile varchar2(200), -- 원본 파일명
sfile varchar2(30), -- 저장된 파일명 (파일명이 겹치면 에러가 날 수 있기때문에 이런식으로 처리)
downcount number(5) default 0 not null, -- 다운로드 횟수
pass varchar2(50) not null, -- 비밀번호
visitcount number default 0 not null -- 조회수
);
더미 데이터 입력하기
--더미 데이터 입력 (디버깅을 위해)
insert into mvcboard (idx, name, title, content, pass)
values (seq_board_num.nextval, '김유신', '자료실 제목1 입니다.','내용','1234');
insert into mvcboard (idx, name, title, content, pass)
values (seq_board_num.nextval, '장보고', '자료실 제목2 입니다.','내용','1234');
insert into mvcboard (idx, name, title, content, pass)
values (seq_board_num.nextval, '이순신', '자료실 제목3 입니다.','내용','1234');
insert into mvcboard (idx, name, title, content, pass)
values (seq_board_num.nextval, '강감찬', '자료실 제목4 입니다.','내용','1234');
insert into mvcboard (idx, name, title, content, pass)
values (seq_board_num.nextval, '대조영', '자료실 제목5 입니다.','내용','1234');
commit;
DTO(Data Transfer Object) 생성
· 계층 간 데이터 교환을 하기위해 사용하는 객체이다
· DTO는 로직을 가지지 않는 순수한 데이터 객체(getter & setter) 만 가진 클래스이다.
· 유저가 입력한 데이터를 DB에 넣는 과정
1 => 유저가 자신의 브라우저에서 데이터를 입력하여 form에 있는 데이터를 DTO에 넣어서 전송한다.
2 => 해당 DTO를 받은 서버가 DAO를 이용하여 DB로 데이터를 집어넣는다.
package model2.mvcboard;
import java.sql.Date;
public class MVCBoardDTO {
private String idx;
private String name;
private String title;
private String content;
private Date postdate;
private String ofile;
private String sfile;
private int downcount;
private String pass;
private int visitcount;
public String getIdx() {
return idx;
}
public void setIdx(String idx) {
this.idx = idx;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getPostdate() {
return postdate;
}
public void setPostdate(Date postdate) {
this.postdate = postdate;
}
public String getOfile() {
return ofile;
}
public void setOfile(String ofile) {
this.ofile = ofile;
}
public String getSfile() {
return sfile;
}
public void setSfile(String sfile) {
this.sfile = sfile;
}
public int getDowncount() {
return downcount;
}
public void setDowncount(int downcount) {
this.downcount = downcount;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public int getVisitcount() {
return visitcount;
}
public void setVisitcount(int visitcount) {
this.visitcount = visitcount;
}
}
Java Resources/src/model2/mvcboard/MVCBoardDTO.java
DAO(Data Access Object) 생성
· DAO는 DB에 data에 접근하기 위한 객체이다.
· DB에 접근하기 위한 Logic & Business Logic 을 분리하기 위해 사용한다.
package model2.mvcboard;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import common.DBConnPool;
public class MVCBoardDAO extends DBConnPool{
public MVCBoardDAO() {
super();
}
// 검색 조건에 맞는 게시물의 개수를 반환합니다.
public int selectCount(Map<String, Object> map) {
int totalCount = 0;
String query = "SELECT COUNT(*) FROM mvcboard";
if (map.get("searchWord") != null) {
query += " WHERE " + map.get("searchField") + " "
+ " LIKE '%" + map.get("searchWord") + "%'";
}
try {
stmt = con.createStatement();
rs = stmt.executeQuery(query);
rs.next();
totalCount = rs.getInt(1);
}
catch (Exception e) {
System.out.println("게시물 카운트 중 예외 발생");
e.printStackTrace();
}
return totalCount;
}
// 검색 조건에 맞는 게시물 목록을 반환합니다(페이징 기능 지원).
public List<MVCBoardDTO> selectListPage(Map<String,Object> map) {
List<MVCBoardDTO> board = new Vector<MVCBoardDTO>();
String query = " "
+ "SELECT * FROM ( "
+ " SELECT Tb.*, ROWNUM rNum FROM ( "
+ " SELECT * FROM mvcboard ";
if (map.get("searchWord") != null)
{
query += " WHERE " + map.get("searchField")
+ " LIKE '%" + map.get("searchWord") + "%' ";
}
query += " ORDER BY idx DESC "
+ " ) Tb "
+ " ) "
+ " WHERE rNum BETWEEN ? AND ?";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, map.get("start").toString());
psmt.setString(2, map.get("end").toString());
rs = psmt.executeQuery();
while (rs.next()) {
MVCBoardDTO dto = new MVCBoardDTO();
dto.setIdx(rs.getString(1));
dto.setName(rs.getString(2));
dto.setTitle(rs.getString(3));
dto.setContent(rs.getString(4));
dto.setPostdate(rs.getDate(5));
dto.setOfile(rs.getString(6));
dto.setSfile(rs.getString(7));
dto.setDowncount(rs.getInt(8));
dto.setPass(rs.getString(9));
dto.setVisitcount(rs.getInt(10));
board.add(dto);
}
}
catch (Exception e) {
System.out.println("게시물 조회 중 예외 발생");
e.printStackTrace();
}
return board;
}
Java Resources/src/model2/mvcboard/MVCBoardDAO.java
MVC 패턴의 Controller 부분
Index.jsp 작성
· 서블릿은 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>
<h2>파일 첨부형 게시판</h2>
<a href="../mvcboard/list.do"> 게시판 목록 바로가기</a> <!-- ../ 상위 디렉토리를 의미한다. -->
</body>
</html>
WebContent/Index.jsp
ListController 서블릿 클래스 작성 ( 컨트롤러)
package model2.mvcboard;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import utils.BoardPage;
@WebServlet("/mvcboard/view.do") // 어노테이션 매핑
public class ListController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//DAO 생성
MVCBoardDAO dao = new MVCBoardDAO();
//뷰에 전달할 매개변수 저장용 맵 생성
Map<String, Object> map = new HashMap<String, Object>();
String searchField = request.getParameter("searchField");
String searchWord = request.getParameter("searchWord");
if(searchWord != null) {
// 쿼리스트링으로 전달받은 매개변수 중 검색어가 있다면 map에 저장
map.put("searchField", searchField);
map.put("searchWord", searchWord);
}
int totalCount = dao.selectCount(map); // 게시물 개수
/* 페이지 처리 start */
ServletContext application = getServletContext();
int pageSize = Integer.parseInt(application.getInitParameter("POSTS_PER_PAGE"));
int blockPage = Integer.parseInt(application.getInitParameter("PAGES_PER_BLOCK"));
//현재 페이지 확인
int pageNum = 1; // 기본값
String pageTemp = request.getParameter("pageNum");
if(pageTemp != null && !pageTemp.equals(""))
pageNum = Integer.parseInt(pageTemp); //요청받은 페이지로 수정
// 목록에 출력할 게시물 범위 계산
int start = (pageNum -1 ) * pageSize + 1; // 첫 게시물 번호
int end = pageNum * pageSize; // 마지막 게시물 번호
map.put("start", start);
map.put("end", end);
/* 페이지처리 end */
List<MVCBoardDTO> boardLists = dao.selectListPage(map);
// 게시물 목록 받기
dao.close();
// 뷰에 전달할 매개변수 추가
String pagingImg = BoardPage.pagingStr(totalCount, pageSize, blockPage, pageNum, "../mvcboard/list.do");
map.put("pagingImg", pagingImg);
map.put("totalCount", totalCount);
map.put("pageSize", pageSize);
map.put("pageNum", pageNum);
// 전달할 데이터를 request 영역에 저장 후 List.jsp로 포워드
request.setAttribute("boardLists",boardLists);
request.setAttribute("map",map);
request.getRequestDispatcher("/List.jsp").forward(request,response);
}
}
Java Resources/src/model2/mvcboard/ListController.java
MVC 패턴의 View 부분
목록 보기 (View)
<%@ 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>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/css/style.css">
<script type="text/javascript">
</script>
</head>
<body>
<div class="container">
<h2>파일 첨부형 게시판 - 목록보기(List)</h2>
<!-- 검색 폼 -->
<form method ="get">
<table width="100%">
<tr align="center">
<td>
<select name="searchField" class="custom-select" style="width:10%; display:inline-block;">
<option value="title">제목</option>
<option value="content">내용</option>
</select>
<input type="text" name="searchWord" class="form-control" style="width:30%; display:inline-block;"/>
<input type="submit" value="검색하기" class="btn btn-primary" style="width:10%; display:inline-block;"/>
</td>
</tr>
</table>
</form>
<!-- 목록 테이블 -->
<table class ="table">
<tr class= "bg-color2">
<th width ="10%">번호</th>
<th width ="*"> 제목 </th>
<th width ="15%"> 작성자 </th>
<th width ="10%"> 조회수 </th>
<th width ="15%"> 작성일 </th>
<th width ="8%"> 첨부 </th>
</tr>
<c:choose>
<c:when test="${empty boardLists }"> <!-- 게시물이 없을때 -->
<tr>
<td colspan="6" align="center"> 등록된 게시물이 없습니다 ! </td>
</tr>
</c:when>
<c:otherwise> <!-- 게시물이 있을때 -->
<c:forEach items="${ boardLists }" var ="row" varStatus="loop">
<tr align="center" class="bg-color4">
<td> ${map.totalCount - (((map.pageNum-1) * map.pageSize) + loop.index)} </td>
<td align="left">
<a href="../mvcboard/view.do?idx=${row.idx }">${row.title }</a>
</td>
<td> ${row.name} </td>
<td> ${row.visitcount} </td>
<td> ${row.postdate} </td>
<td>
<c:if test="${not empty row.ofile }">
<c:set var="fileNm" value="${row.ofile}" />
<c:forTokens var="token" items="${fileNm }" delims="." varStatus="status">
<c:if test="${status.last }">
<c:choose>
<c:when test="${token eq 'html' }">
<img src="/img/html.png" width="40px" height="40px">
</c:when>
<c:when test="${token eq 'txt'}">
<img src="/img/txt.png" width="40px" height="34px">
</c:when>
<c:when test="${token eq 'pdf'}">
<img src="/img/pdf.png" width="40px" height="40px">
</c:when>
<c:when test="${token eq 'css'}">
<img src="/img/css.png" width="40px" height="40px">
</c:when>
<c:when test="${token eq 'png'}">
<img src="/img/png.png" width="40px" height="40px">
</c:when>
<c:when test="${token eq 'jpg'}">
<img src="/img/jpg.png" width="40px" height="40px">
</c:when>
</c:choose>
</c:if>
</c:forTokens>
</c:if>
</td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</table>
<!-- 하단메뉴(바로가기, 글쓰기) -->
<table>
<tr align="center">
<td>
${map.pagingImg }
</td>
<td width="100"> <button type="button" onclick="location.href='../mvcboard/write.do';"> 글쓰기 </button> </td>
</tr>
</table>
</div>
</body>
</html>
WebContent/List.jsp
'Back-End' 카테고리의 다른 글
[rabbitMQ] M2칩 환경 SpringBoot + rabbitMQ 연동 (0) | 2022.08.23 |
---|---|
[팀프로젝트] - ERD 제작 (0) | 2022.06.17 |
[jsp] HTTP 에러 코드 모음 (번호) (0) | 2022.04.15 |
[jsp] requestParameter를 이용한 post방식 데이터 받기 (0) | 2022.04.14 |
[jsp] include를 이용한 간단한 홈페이지 레이아웃 나누기 (0) | 2022.04.13 |