• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java EE 정리 18

22 Mar 2019

Reading time ~8 minutes

Java EE 정리 18 - 일정관리 만들기(3)


일정관리 만들기(3)

  • 진행중인 프로젝트 패키지

01

  • 일정을 클릭했을 때 상세 일정 보여주기
    • 코드가 길어질 때 줄바꿈은 태그 안에서만 수행한다.
    • 공백또한 태그 안에서만 수행한다.
<!-- 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>

02

  • 일정 수정 이벤트처리
// 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>

03

  • 일정 삭제 이벤트 처리
// 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>

04

  • 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>    

05

  • 게시판 형태 디자인
<!-- 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&copy; all right reserved.  class4 </div>
      </div>
</div>
</body>
</html>

06

게시판 만들기

  • 게시글을 뽑아오기 위해선 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;

07

  • 총 게시물의 수를 알아야 한다.
    • 검색을 한다면 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;


Java EEJSP