Java EE 정리 18
22 Mar 2019
Reading time ~8 minutes
Java EE 정리 18 - 일정관리 만들기(3)
일정관리 만들기(3)
- 일정을 클릭했을 때 상세 일정 보여주기
- 코드가 길어질 때 줄바꿈은 태그 안에서만 수행한다.
- 공백또한 태그 안에서만 수행한다.
<!-- diary.jsp -->
<style text="text/css">
...
#readFrm {
background-color: #FFFFFF;
border:1px solid #333;
box-shadow: 5px 5px 5px #333;
padding:10px;
}
...
</style>
<script type="text/javascript">
function readEvt(num, year, month, date) {
$("[name='param_year']").val(year);
$("[name='param_month']").val(month);
$("[name='param_date']").val(date);
$("[name='num']").val(num);
$("[name='pageFlag']").val("read_form");
$("[name='diaryFrm']").submit();
}
</script>
...
<form action="diary.jsp" name="diaryFrm" method="post" >
<input type="hidden" name="param_month"/>
<input type="hidden" name="param_year"/>
<input type="hidden" name="param_date"/>
<input type="hidden" name="pageFlag"/>
<input type="hidden" name="num"/>
</form>
...
<a href="#void" onclick="readEvt(<%=dayEvt[i].getNum()
%>, ${ nowYear }, ${ nowMonth }, <%=tempDay %>)">
<img src="images/evtflag.png" title="<%=tempSubject %>"/>
</a>
- 번호에 따른 이벤트 조회 구현
// DiaryDAO
public DiaryDetailVO selectDetailEvent(int num) throws SQLException {
DiaryDetailVO ddvo = null;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConn();
StringBuilder selectOneEvt = new StringBuilder();
selectOneEvt
.append(" SELECT WRITER, SUBJECT, CONTENT, W_DATE, IP ")
.append(" FROM DIARY ")
.append(" WHERE NUM=? ");
pstmt = con.prepareStatement(selectOneEvt.toString());
pstmt.setInt(1, num);
rs = pstmt.executeQuery();
if(rs.next()) {
ddvo = new DiaryDetailVO(rs.getString("writer"),
rs.getString("subject"), rs.getString("content"),
rs.getString("w_date"), rs.getString("ip"));
}
} finally {
if (rs != null) { rs.close(); }
if (pstmt != null) { pstmt.close(); }
if (con != null) { con.close(); }
}
return ddvo;
}
<!-- read_form, write_form과 거의 동일(복붙 후 수정) -->
<%@page import="kr.co.sist.vo.DiaryDetailVO"%>
<%@page import="java.sql.SQLException"%>
<%@page import="kr.co.sist.diary.dao.DiaryDAO"%>
<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<div id="readFrm">
<%
DiaryDAO d_dao = DiaryDAO.getInstance();
try{
int num = Integer.parseInt(request.getParameter("num"));
DiaryDetailVO ddvo = d_dao.selectDetailEvent(num);
%>
<form action="diary.jsp" method="post" name="readFrm">
<!-- pageFlag값은 수정,삭제에 따라 바뀜 -->
<input type="hidden" name="pageFlag"/>
<!-- 다른 년월에서 유지하기 위한 Form Control -->
<input type="hidden" name="param_year" value="${ param.param_year }"/>
<input type="hidden" name="param_month" value="${ param.param_month }"/>
<!-- 수정 삭제 시 사용될 num -->
<input type="hidden" name="num" value="<%= num %>"/>
<table id="writeTab">
<tr>
<th colspan="2" style="text-align: center;">
<span style="font-size: 20px;">이벤트 읽기</span>
<span style="float:right; padding:5px;">
<a href="#void" id="btnCloseFrm"><img src="images/btn_close.png"/></a>
</span>
</th>
</tr>
<tr>
<td style="width:80px;">제목</td>
<td style="width:400px">
<div id="subject" ><%= ddvo.getSubject() %></div>
</td>
</tr>
<tr>
<td style="width:80px;">내용</td>
<td style="width:400px">
<textarea name="content" id="summernote"><%= ddvo.getContent() %></textarea>
</td>
</tr>
<tr>
<td style="width:80px;">이벤트 일</td>
<td style="width:400px">
<div id="evtDate">${ param.param_year }-${ param.param_month
}-${ param.param_date }</div>
</td>
</tr>
<tr>
<td style="width:80px;">작성자</td>
<td style="width:400px">
<div id="writer"><%= ddvo.getWriter() %></div>
</td>
</tr>
<tr>
<td style="width:80px;">비밀번호</td>
<td style="width:400px">
<input type="password" name="pass" id="pass" class="inputBox"
style="width:200px;"/>
</td>
</tr>
<tr>
<td style="width:80px;">작성일</td>
<td style="width:400px">
<div id="wDate"><%= ddvo.getW_date() %></div>
</td>
</tr>
<tr>
<td style="width:80px;">작성IP</td>
<td style="width:400px">
<div id="ip"><%=ddvo.getIp() %></i></div>(작성시 ip : <%= request.getRemoteAddr() %>)
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" value="이벤트 수정" class="btn" id="btnUpdate"/>
<input type="button" value="이벤트 삭제" class="btn" id="btnRemove"/>
<input type="button" value="닫기" class="btn" id="btnWriteClose"/>
</td>
</tr>
</table>
</form>
<%
} catch (SQLException se) {
%>
<img src="images/construction.jpg" title="죄송합니다."/>
<%
}
%>
</div>
- 일정 수정 이벤트처리
// diary.jsp
$("#btnUpdate").click(function() {
if($("#summernote").val() == "") {
alert("이벤트 내용은 필수입력 항목입니다.");
return;
}
if($("#pass").val() == "") {
alert("비밀번호는 필수입력 항목입니다.");
$("#pass").focus();
return;
}
$("[name='pageFlag']").val("update_process");
$("[name='readFrm']").submit();
});
- 업데이트, 삭제 DAO 메소드 구현
// DiaryDAO
public int updateEvent(DiaryUpdateVO duvo) throws SQLException {
int cnt = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConn();
StringBuilder updateEvt = new StringBuilder();
updateEvt
.append(" UPDATE diary ")
.append(" SET content=? and pass=? ")
.append(" WHERE num=? ");
pstmt = con.prepareStatement(updateEvt.toString());
pstmt.setString(1, duvo.getContent());
pstmt.setInt(2, duvo.getNum());
pstmt.setString(3, duvo.getPass());
cnt = pstmt.executeUpdate();
} finally {
if (pstmt != null) { pstmt.close(); }
if (con != null) { con.close(); }
}
return cnt;
}
public int deleteEvent(DiaryRemoveVO drvo) throws SQLException {
int cnt = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConn();
StringBuilder updateEvt = new StringBuilder();
updateEvt
.append(" DELETE FROM diary ")
.append(" WHERE num=? and pass=? ");
pstmt = con.prepareStatement(updateEvt.toString());
pstmt.setInt(1, drvo.getNum());
pstmt.setString(2, drvo.getPass());
cnt = pstmt.executeUpdate();
} finally {
if (pstmt != null) { pstmt.close(); }
if (con != null) { con.close(); }
}
return cnt;
}
- 일정 수정
- useBean을 쓸려면 VO 인자없는 생성자, setter필수
<!-- update_process.jsp -->
<%@page import="kr.co.sist.vo.DiaryUpdateVO"%>
<%@page import="kr.co.sist.diary.dao.DiaryDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="duvo" class="kr.co.sist.vo.DiaryUpdateVO" scope="page"></jsp:useBean>
<jsp:setProperty name="duvo" property="*"/>
<div id="readFrm">
<%
duvo.setPass(ShaUtil.shaEncoding(duvo.getPass())); // 암호화
DiaryDAO d_dao = DiaryDAO.getInstance();
String img = "", msg = "";
try {
int cnt = d_dao.updateEvent(duvo);
if (cnt == 0) { // 변경된 행이 없음 : 글번호 조작 | 비밀번호 틀린 경우
img = "pass_fail.png";
msg = "비밀번호를 확인해주세요.";
} else {
img = "success_update.png";
msg = "글을 변경 하였습니다..";
}
} catch(SQLException se) {
img = "construction.png";
msg = "죄송합니다. 장애처리에 최선을 다하고 있습니다.";
}
%>
<img src="images/<%= img %>"/><br/>
<%= msg %>
<input type="button" value="닫기" class="btn" id="btnCloseFrm"/>
</div>
- 일정 삭제 이벤트 처리
// diary.jsp
$("#btnRemove").click(function() {
if($("#pass").val() == "") {
alert("비밀번호는 필수입력 항목입니다.");
$("#pass").focus();
return;
}
$("[name='pageFlag']").val("delete_process");
$("[name='readFrm']").submit();
});
- 일정 삭제
<!-- delete_process.jsp -->
<%@page import="java.sql.SQLException"%>
<%@page import="kr.co.sist.util.ShaUtil"%>
<%@page import="kr.co.sist.vo.DiaryUpdateVO"%>
<%@page import="kr.co.sist.diary.dao.DiaryDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="drvo" class="kr.co.sist.vo.DiaryRemoveVO" scope="page"></jsp:useBean>
<jsp:setProperty name="drvo" property="*"/>
<div id="deleteFrm">
<%
drvo.setPass(ShaUtil.shaEncoding(drvo.getPass())); // 암호화
DiaryDAO d_dao = DiaryDAO.getInstance();
String img = "", msg = "";
try {
int cnt = d_dao.deleteEvent(drvo);
if (cnt == 0) { // 변경된 행이 없음 : 글번호 조작 | 비밀번호 틀린 경우
img = "pass_fail.png";
msg = "비밀번호를 확인해주세요.";
} else {
img = "success_update.png";
msg = "이벤트를 삭제 하였습니다.";
}
} catch(SQLException se) {
img = "construction.png";
msg = "죄송합니다. 장애처리에 최선을 다하고 있습니다.";
}
%>
<img src="images/<%= img %>"/><br/>
<%= msg %>
<a href="#void" id="btnCloseFrm">닫기</a>
</div>
- Smartmenus jQuery 플러그인으로 메뉴 추가
- Smartmenus
- 플러그인 다운 후 데모를 참고해서 필요한 css, html, js 추가
<!-- diary.jsp -->
...
<div id="wrap">
<div id="header">
<div id="headerTitle">SIST Class4</div>
<c:import url="main_menu.jsp"></c:import>
</div>
...
<!-- main_menu.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- SmartMenus 시작 -->
<!-- include 될 곳에 jQuery가 존재, 따로 추가 안해도 됨(추가하면 에러) -->
<!-- SmartMenus core CSS (required) -->
<link href="http://localhost:8080/jsp_prj/common/smartmenus/css/sm-core-css.css" rel="stylesheet" type="text/css" />
<!-- "sm-mint" menu theme (optional, you can use your own CSS, too) -->
<link href="http://localhost:8080/jsp_prj/common/smartmenus/css/sm-simple/sm-simple.css" rel="stylesheet" type="text/css" />
<!-- SmartMenus jQuery plugin -->
<script type="text/javascript" src="http://localhost:8080/jsp_prj/common/smartmenus/jquery.smartmenus.js"></script>
<!-- SmartMenus jQuery init -->
<script type="text/javascript">
$(function() {
$('#main-menu').smartmenus({
subMenusSubOffsetX: 6,
subMenusSubOffsetY: -8
});
});
</script>
<!-- SmartMenus 끝 -->
<nav id="main-nav">
<ul id="main-menu" class="sm sm-simple">
<li><a href="#void">홈으로</a></li>
<li><a href="#void">일정관리</a>
<ul>
<li><a href="http://localhost:8080/jsp_prj/diary/diary.jsp">캘린더</a></li>
<li><a href="http://localhost:8080/jsp_prj/diary/list.jsp">게시판</a></li>
<li><a href="http://sist.co.kr">쌍용교육센터</a></li>
<li><a href="#void">1조</a>
<ul>
<li><a href="http://youtube.com">이재찬</a></li>
<li><a href="http://comic.naver.com">김민정</a></li>
<li><a href="http://google.com">김정운</a></li>
<li><a href="http://naver.com">정택성</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="http://localhost:8080/jsp_prj/date0319/file_list.jsp">다운로드</a></li>
<li><a href="http://localhost:8080/jsp_prj/date0320/mr_upload_form.jsp">당신도 김본좌!!</a></li>
</ul>
</nav>
- 게시판 형태 디자인
<!-- list.jsp -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<style type="text/css">
...
/* 게시판 CSS */
#diary { margin-top: 20px; }
#diaryHeader { font-size: 20px; font-weight: bold; text-align: center; height: 40px; }
#diaryContent { height: 400px; }
#diarySearch { height: 100px; text-align:center; }
#diaryIndexList { height: 30px; }
#listTab {
border-top:3px solid #333;
margin:0px auto;
border-spacing: 0px;
}
#numTitle{ width:50px; height:25px; background-color: #F3F3F3; }
#subjectTitle { width:350px; height:25px; background-color: #F3F3F3; }
#writerTitle { width:120px; height:25px; background-color: #F3F3F3; }
#eDateTitle { width:150px; height:25px; background-color: #F3F3F3; }
#wDateTitle { width:150px; height:25px; background-color: #F3F3F3; }
th,td { border-bottom:1px solid #EEEEEE }
td { height:27px; }
tr:HOVER { background-color: #F3F3F3; }
.center { text-align: center; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<div id="wrap">
<div id="header">
<div id="headerTitle">SIST Class4</div>
<div style="padding-top:100px;">
<c:import url="http://localhost:8080/jsp_prj/diary/main_menu.jsp"></c:import>
</div>
</div>
<div id="container">
<div id="diary">
<div id="diaryHeader">이벤트 목록</div>
<div id="diaryContent">
<table id="listTab">
<tr>
<th id="numTitle">번호</th>
<th id="subjectTitle">이벤트 제목</th>
<th id="writerTitle">작성자</th>
<th id="eDateTitle">이벤트일자</th>
<th id="wDateTitle">작성일자</th>
</tr>
<tr>
<td class="center">1</td>
<td>오늘은 금요일입니다.</td>
<td class="center">노진경</td>
<td class="center">2019-03-22</td>
<td class="center">2019-03-22</td>
</tr>
<tr>
<td class="center">1</td>
<td>내일은 금요일 나는야 주 5일제 월화수목금금금</td>
<td class="center" \>주 52시간의 사나이</td>
<td class="center">2019-03-23</td>
<td class="center">2019-03-22</td>
</tr>
</table>
</div>
<div id="diarySearch">
<form action="list.jsp" method="post" id="searchFrm" name="searchFrm">
<select name="fieldName" class="inputBox" id="fieldName">
<option value="subject">제목</option>
<option value="content">내용</option>
<option value="writer">작성자</option>
</select>
<input type="text" name="keyword" class="inputBox" style="width:150px" id="keyword"/>
<input type="button" value="검색" class="btn" style="width:30px;"/>
</form>
</div>
</div>
<div id="diaryIndexList">
</div>
<div id="footer">
<div id="footerTitle">copyright© all right reserved. class4 </div>
</div>
</div>
</body>
</html>
게시판 만들기
- 게시글을 뽑아오기 위해선 diary table에서 가장 마지막에 입력된 글부터 10건까지를 조회할 줄 알아야 한다.
- 번호, 제목, 작성자, 이벤트일, 입력일 컬럼 조회
- 먼저 작성일 순으로 조회를 하고
- rownum을 이용 10개의 데이터를 가져온다
- 서브쿼리(인라인 뷰) 사용해서 조회
select num, subject, writer, e_year, e_month, e_date, to_char(w_date,'yyyy-mm-dd') w_date, ip
from (select rownum r, num, subject, writer, e_year, e_month, e_date, w_date, ip
from (select num, subject, writer, e_year, e_month, e_date, w_date, ip
from diary
order by w_date desc))
where r between 1 and 10;
- 총 게시물의 수를 알아야 한다.
- 검색을 한다면 WHERE절이 추가됨, WHERE절에 대한 동적인 쿼리가 만들어져야 한다.
int totalCnt = "SELECT COUNT(*) FROM diary"; // 예로 17개가 등록됐다면
- 한 화면에 보여줄 게시물의 수를 설정
int pageScale = 10;
- 총 페이지 수를 계산한다
int pageCnt = 0;
if (totalCnt % pageScale == 0) { // 딱 떨어지면
pageCnt = totalCnt/pageScale;
} else { // 딱 떨어지지 않으면(나머지 존재)
pageCnt = totalCnt/pageScale+1;
}
// 줄여쓰는 방법 1.
pageCnt = Math.ceil(totalCnt/pageScale);
// 또 다른 방법 2.
pageCnt = totalCnt/pageScale; // 무조건 계산하고
if(totalCnt%pageScale != 0) { // 0이아니면
pageCnt = pageCnt+1; // 1추가
}
- 시작 게시글번호 구하기
- pageScale이 10일 때
- 1번 목록 페이지를 열었을 때 1-10의 글을 보여줘야 함
- list.jsp?currentPage=1 로 요청
- 2번 목록 페이지를 열었을 때 11-20의 글을 보여줘야 함
- list.jsp?currentPage=2 로 요청
- 3번 목록 페이지를 열었을 때 21-30의 글을 보여줘야 함…
- list.jsp?currentPage=3 로 요청 …
String currentPage = request.getParameter("currentPage");
int startNum = 1;
// 처음 페이지가 열렸다면 currentPage 파라미터가 없음
if (currentPage != null) { // 목록을 눌렀다.
int tempPage = Integer.parseInt(currentPage);
// 선택된 페이지*스케일 - 스케일 + 1
startNum = tempPage*pageScale - pageScale + 1;
}
- 끝 게시글 번호 구하기
int endNum = 0;
endNum = startNum + pageScale - 1;