2020년 01월 04일
업데이트:
공지사항
공지사항 상세 조회
행 어디를 클릭해도 해당 글의 상세페이지가 조회된다.
한 행은 tr로 이루어져있고, td가 형제관계로 존재하고 있다.
td중 한개를 선택했을 때, 맨 첫번째 형제인 글 번호(PK)를 선택하게 하기.
목록에 마우스를 올릴 경우 손가락 모양으로 커서 변경
/* 목록에 마우스를 올릴 경우 손가락 모양으로 변경 */
#list-table td:hover{
cursor : pointer;
}
공지사항 상세조회 초기 화면
noticeList.jsp
<h1>공지사항</h1>
<div class="list-wrapper">
<table class="table table-hover table-striped my-5" id="list-table">
<thead>
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>작성일</th>
</tr>
</thead>
<tbody>
<!-- 공지사항 목록 -->
<%-- 공지사항이 존재할 때와 존재하지 않을 때에 맞는 출력 형식을 지정해야 함. --%>
<c:choose>
<%-- 공지사항이 없을 때 --%>
<c:when test="${empty list}">
<tr>
<td colspan="5" align="center">존재하는 공지사항이 없습니다.</td>
</tr>
</c:when>
<%-- 공지사항이 존재할 때 --%>
<c:otherwise>
<c:forEach var="notice" items="${list}">
<tr>
<td>${ notice.noticeNo }</td>
<td>${notice.noticeTitle}</td>
<td>${notice.memberId}</td>
<td>${notice.readCount}</td>
<td>${notice.noticeCreateDate}</td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</tbody>
</table>
</div>
<script>
// 공지사항 상세보기 기능 (jquery를 통해 작업)
// id가 list-table인 요소의 후손 중에 td 하나가 클릭이 되면 해당 td의 첫번째 형제를 선택해라.
$("#list-table td").on("click", function(){
var noticeNo = $(this).parent().children().eq(0).text();
// 클릭 이벤트가 발생한 요소의 부모의 자식들 중의 제일 첫번째 자식.
// console.log(noticeNo);
// 얻어온 공지사항 글 번호를 쿼리스트링으로 작성하여 상세조회 요청
location.href = "${contextPath}/notice/view.do?no=" + noticeNo;
// ${contextPath}/notice/view.do : 상세조회를 위한 주소
});
</script>
로그인된 회원이 해당 글의 작성자일 경우에만 수정/삭제가 보인다.
noticeView.jsp
<%-- 로그인된 회원이 해당 글의 작성자인 경우 --%>
<!-- float-right 속성 : 오른쪽으로 정렬됨, 화면상에선 목록,수정,삭제 순서대로 보임. -->
<c:if test="${!empty loginMember && (loginMember.memberId == notice.memberId) }">
<button class="btn btn-primary float-right" id="deleteBtn">삭제</button>
<a href="updateForm.do?no=${param.no}" class="btn btn-primary float-right ml-1 mr-1">수정</a>
<!-- request 파라미터 중 no가 존재하고 있음.-->
</c:if>
NoticeController.java
// 공지사항 상세 조회 Controller **********
else if(command.equals("/view.do")) {
// command = 요청주소 가장 끝만 잘라내어 저장하는 변수
// 상세조회 요청이 왔다면
errorMsg = "공지사항 상세 조회 과정에서 오류 발생";
// 파라미터 얻어오기
// 쿼리스트링으로 전달된 공지사항 번호를 int형으로 파싱하여 저장
int noticeNo = Integer.parseInt(request.getParameter("no"));
// 상세조회 비즈니스 로직 수행 결과 반환
Notice notice = service.selectNotice(noticeNo);
// 조회 결과에 따른 view 연결 처리
if(notice != null) { // 조회 성공
// 경로 지정
path = "/WEB-INF/views/notice/noticeView.jsp";
// 요청 위임
request.setAttribute("notice", notice);
view = request.getRequestDispatcher(path);
view.forward(request, response);
}else { // 조회 실패
HttpSession session = request.getSession();
session.setAttribute("swalIcon", "error");
session.setAttribute("swalTitle", "공지사항 조회 실패");
// 이전 주소로 이동
response.sendRedirect(request.getHeader("referer"));
}
}
NoticeService.java
/** 공지사항 상세 조회 Service
* @param noticeNo
* @return notice
* @throws Exception
*/
public Notice selectNotice(int noticeNo) throws Exception {
// 1) 커넥션 얻어오기
Connection conn = getConnection();
// 2) dao 수행 후 결과 반환받기
Notice notice = dao.selectNotice(conn, noticeNo);
// 3) 공지사항 조회 성공 시 조회수 증가
if(notice !=null ) {
int result = dao.increaseReadCount(conn,noticeNo);
// 트랜잭션 처리
if(result>0) {
commit(conn);
// 이미 조회된 notice에서 readCount 값을 1 증가
notice.setReadCount(notice.getReadCount()+1);
}
else rollback(conn);
}
// 4) 커넥션 반환
close(conn);
// 5) 결과 반환
return notice;
}
NoticeDAO.java
/** 공지사항 상세조회 DAO
* @param conn
* @param noticeNo
* @return notice
* @throws Exception
*/
public Notice selectNotice(Connection conn, int noticeNo) throws Exception {
// 1) 결과를 저장할 변수 선언
Notice notice = null;
// 2) SQL 구문 얻어오기
String query = prop.getProperty("selectNotice");
// 3) SQL 수행 후 결과를 notice에 저장
try {
pstmt = conn.prepareStatement(query);
pstmt.setInt(1, noticeNo);
rset=pstmt.executeQuery();
if(rset.next()) {
notice = new Notice();
notice.setNoticeTitle(rset.getString("NOTICE_TITLE"));
notice.setNoticeContent(rset.getString("NOTICE_CONTENT"));
notice.setMemberId(rset.getString("MEMBER_ID"));
notice.setReadCount(rset.getInt("READ_COUNT"));
notice.setNoticeCreateDate(rset.getDate("NOTICE_CREATE_DT"));
}
}finally {
// 4) 사용한 JDBC 객체 반환
close(rset);
close(pstmt);
}
// 5) 결과 반환
return notice;
}
SQL
<!-- 공지사항 상세 조회 -->
<entry key="selectNotice">
SELECT NOTICE_TITLE, NOTICE_CONTENT, MEMBER_ID, READ_COUNT,NOTICE_CREATE_DT
FROM NOTICE
JOIN MEMBER ON(NOTICE_WRITER = MEMBER_NO)
WHERE NOTICE_NO=?
AND NOTICE_FL='Y'
</entry>
조회수 증가
조회수가 클릭 할 때마다 +1 씩 증가됨
NoticeDAO.java
/** 조회수 증가 DAO
* @param conn
* @param noticeNo
* @return result
* @throws Exception
*/
public int increaseReadCount(Connection conn, int noticeNo) throws Exception {
int result = 0;
String query = prop.getProperty("increaseReadCount");
try {
pstmt = conn.prepareStatement(query);
pstmt.setInt(1, noticeNo);
result = pstmt.executeUpdate();
}finally {
close(pstmt);
}
return result;
}
SQL
<!-- 조회수 증가 -->
<entry key="increaseReadCount">
UPDATE NOTICE SET
READ_COUNT = READ_COUNT+1
WHERE NOTICE_NO=?
</entry>
글쓰기 버튼
관리자로 로그인했을 때만 로그인 버튼이 보이게 설정하기
noticeList.jsp
<%-- 로그인된 계정이 관리자 등급인 경우 --%>
<c:if test="${!empty loginMember && loginMember.memberGrade=='A' }">
<button type="button" class="btn btn-primary float-right" id="insertBtn"
onclick="location.href = 'insertForm.do';">글쓰기</button>
</c:if>
공지사항 등록
공지사항 등록 초기 화면
noticeInsert.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공지사항</title>
<style>
#notice-area{ height: 700px;}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp"></jsp:include>
<div class="container my-5">
<h3>공지사항 등록</h3>
<hr>
<div class="bg-white rounded shadow-sm container py-3" id="notice-area">
<form method="POST" action="insert.do" role="form" onsubmit="return noticeValidate();">
<div class="form-inline mb-2">
<div class="input-group">
<label class="input-group-addon mr-3">제목</label>
<input type="text" class="form-control" id="noticeTitle" name="noticeTitle" size="70">
</div>
</div>
<div class="form-inline mb-2">
<div class="input-group">
<label class="input-group-addon mr-3">작성자</label>
<h5 class="my-0">${loginMember.memberId }</h5>
</div>
</div>
<div class="form-inline mb-2">
<div class="input-group">
<label class="input-group-addon mr-3">작성일</label>
<h5 class="my-0" id="today"></h5>
</div>
</div>
<hr>
<div class="form-group">
<div><label for="content">내용</label> </div>
<!-- textarea == input태근 -->
<textarea class="form-control" id="noticeContent" name="noticeContent" rows="15" style="resize: none;"></textarea>
</div>
<hr class="mb-4">
<div class="text-center">
<button type="submit" class="btn btn-primary">등록</button>
<a href="list" class="btn btn-primary">목록으로</a>
</div>
</form>
</div>
</div>
<jsp:include page="../common/footer.jsp"></jsp:include>
작성일에 오늘 날짜 출력
<script>
(function printToday(){
// 오늘 날짜 출력
var now = new Date(); // 현재 시간
var year = now.getFullYear(); // 201 Date라는 내장객체에 존재하는 함수
var month = now.getMonth() + 1; // 0~11중 하나가 반환
var date = now.getDate(); // 4
var str = year + "-" + (month<10? "0"+month : month) + "-" + (date<10 ? "0" +date : date);
$("#today").text(str);
})();
</script>
유효성 검사(제목/내용에 내용 필수적으로 작성해야 됨)
<script>
// 유효성 검사
function noticeValidate(){
// 제목에 아무것도 작성하지 않음
if( $("#noticeTitle").val().trim().length == 0){
alert("제목을 입력해 주세요.");
$("#title").focus();
return false;
}
// 내용에 아무것도 작성하지 않음
if( $("#noticeContent").val().trim().length == 0){
alert("내용을 입력해 주세요.");
$("#content").focus();
return false;
}
}
</script>
</body>
</html>
NoticeController.java
// 공지사항 작성 화면 전환 Controller **********
else if(command.contentEquals("/insertForm.do")) {
path = "/WEB-INF/views/notice/noticeInsert.jsp";
view = request.getRequestDispatcher(path);
view.forward(request, response);
}
*공지사항 등록 시 *
// 공지사항 등록 Controller **********
else if(command.contentEquals("/insert.do")) {
errorMsg = "공지사항 등록 과정에서 에러 발생.";
// 파라미터로 전달된 값 저장
String noticeTitle = request.getParameter("noticeTitle");
String noticeContent = request.getParameter("noticeContent");
// 세션에서 회원 번호 얻어오기
HttpSession session = request.getSession();
int noticeWriter = ((Member)session.getAttribute("loginMember")).getMemberNo();
// Map을 이용하여 데이터 전달(VO 대신 사용하는 경우가 많음)
Map<String, Object> map = new HashMap<String, Object>();
map.put("noticeTitle", noticeTitle);
map.put("noticeContent", noticeContent);
map.put("noticeWriter", noticeWriter);
// 공지사항 등록 비즈니스 로직 수행 후 결과 반환
int result = service.insertNotice(map);
if(result>0) { // 삽입 성공 시
// result에는 삽입된 공지사항 번호가 저장되어 있음.
path = "view.do?no="+result; // 쿼리스트링을 이용하여 상세조회 요청
swalIcon = "success";
swalTitle = "공지사항이 등록되었습니다.";
}else {
path = "list.do"; // 목록으로 돌아감
swalIcon = "error";
swalTitle = "공지사항 등록 실패";
}
session.setAttribute("swalIcon",swalIcon);
session.setAttribute("swalTitle", swalTitle);
response.sendRedirect(path);
}
NoticeService.java
/** 공지사항 등록 Service
* @param map
* @return result
* @throws Exception
*/
public int insertNotice(Map<String, Object> map) throws Exception {
Connection conn = getConnection();
// 1) 작성될 글 번호를 먼저 얻어오는 DAO 메소드 수행
// 이유 1) 글 작성 성공 후 해당 글 상세 조회 페이지로 redirect 하기 위해 필요.
// 이유 2) 글 작성 + 파일 첨부 시 발생하는 시퀀스 번호 밀림 현상을 제거하기 위해
int noticeNo = dao.selectNextNo(conn);
int result = 0;
if(noticeNo >0) { // 다음 글 번호를 얻어오는데 성공한 경우
// 2. 실제 공지글 등록 DAO 메소드 수행
// map에 얻어온 다음 글 번호를 세팅
map.put("noticeNo", noticeNo);
result = dao.insertNotice(conn,map);
// 트랜잭션 처리
if(result>0) {
commit(conn);
// 삽입 성공 시 result에 작성한 글 번호를 대입
result = noticeNo; // 글번호가 최종적으로 반환됨
}
else rollback(conn);
}
close(conn);
return result;
}
NoticeDAO.java
공지사항 등록 시 사용될 번호 반환
/** 공지사항 등록 시 사용될 번호 반환 DAO
* @param conn
* @return noticeNo
* @throws Exception
*/
public int selectNextNo(Connection conn) throws Exception {
int noticeNo = 0;
String query = prop.getProperty("selectNextNo");
try {
stmt = conn.createStatement();
rset = stmt.executeQuery(query);
if(rset.next()) {
noticeNo = rset.getInt(1);
}
}finally {
close(rset);
close(stmt);
}
return noticeNo;
}
SQL
<!-- 공지사항 등록 시 사용될 번호 반환 : 다음 시원스 조회 -->
<entry key="selectNextNo">
SELECT SEQ_NNO.NEXTVAL FROM DUAL
</entry>
공지사항 등록
/** 공지사항 등록 DAO
* @param conn
* @param map
* @return result
* @throws Exception
*/
public int insertNotice(Connection conn, Map<String, Object> map) throws Exception{
int result =0;
String query = prop.getProperty("insertNotice");
try {
pstmt = conn.prepareStatement(query);
pstmt.setInt(1, (int)map.get("noticeNo"));
pstmt.setString(2, (String)map.get("noticeTitle"));
pstmt.setString(3, (String)map.get("noticeContent"));
pstmt.setInt(4, (int)map.get("noticeWriter"));
result = pstmt.executeUpdate();
}finally {
close(pstmt);
}
return result;
}
SQL
<!-- 공지사항 등록 -->
<entry key="insertNotice">
INSERT INTO NOTICE(NOTICE_NO, NOTICE_TITLE, NOTICE_CONTENT, NOTICE_WRITER)
VALUES (?,?,?,?)
</entry>
크로스 사이트 스크립팅
웹 애플리케이션에서 많이 나타나는 보안 취약점 중 하나로,
웹 사이트 관리자가 아닌 사용자가 웹 페이지에 악성 스크립트를 삽입할 수 있는 취약점이 있다.
크로스 사이트 스크립팅 방지 전 (태그 적용 됨)
크로스 사이트 스크립팅 방지 후 (태그 사용 불가)
NoticeService.java
// 크로스 사이트 스크립팅 방지 메소드
private String replaceParameter(String param) {
String result = param;
if(result != null) {
result = result.replaceAll("&", "&");
result = result.replaceAll("<", "<");
result = result.replaceAll(">", ">");
result = result.replaceAll("\"", """);
}
return result;
}
공지사항 등록 Service에 스크립팅 방지 처리를 해준다.
// 크로스 사이트 스크립팅 방지 처리
map.put("noticeTitle", replaceParameter((String)map.get("noticeTitle")));
// <script> -> <script>
map.put("noticeContent", replaceParameter((String)map.get("noticeContent")));
// 개행문자 변경 처리
// textarea의 개행문자는 \r\n 이지만
// 상세조회에서 사용되는 div태그의 개행문자는 <br>이기 때문에 변경이 필요함
map.put("noticeContent", ((String)map.get("noticeContent")).replaceAll("\r\n", "<br>"));
공지사항 수정
공지사항 수정 전
공지사항 수정 후
noticeView.jsp
<a href="updateForm.do?no=${param.no}" class="btn btn-primary float-right ml-1 mr-1">수정</a>
<!-- request 파라미터 중 no가 존재하고 있음.-->
NoticeController.java
// 공지사항 수정 화면 출력용 Controller **********
else if(command.equals("/updateForm.do")) {
errorMsg = "공지사항 수정 화면 전환 과정에서 오류 발생.";
int noticeNo = Integer.parseInt(request.getParameter("no"));
Notice notice = service.updateView(noticeNo);
if(notice !=null) {
path = "/WEB-INF/views/notice/noticeUpdate.jsp";
request.setAttribute("notice",notice);
view = request.getRequestDispatcher(path);
view.forward(request, response);
}else {
request.getSession().setAttribute("swalIcon", "error");
request.getSession().setAttribute("swalText", "공지사항 수정을 위한 조회 실패");
response.sendRedirect("view.do?no=" + noticeNo);
}
}
NoticeService.java
/** 공지사항 수정 화면 Service
* @param noticeNo
* @return notice
* @throws Exception
*/
public Notice updateView(int noticeNo) throws Exception {
Connection conn = getConnection();
// 공지사항 상세조회 DAO 호출
Notice notice = dao.selectNotice(conn, noticeNo);
// textarea에 출력하기 위해 개행문자 변경
if(notice !=null) {
notice.setNoticeContent(notice.getNoticeContent().replaceAll("<br>", "\r\n"));
}
close(conn);
return notice;
}
NoticeController.java
// 공지사항 수정 Controller
else if(command.contentEquals("/update.do")) {
errorMsg = "공지사항 수정에서 오류 발생";
// 파라미터 얻어오기
int noticeNo = Integer.parseInt(request.getParameter("no"));
String noticeTitle = request.getParameter("noticeTitle");
String noticeContent = request.getParameter("noticeContent");
// 비즈니스 로직 수행
Map<String, Object> map = new HashMap<String, Object>();
map.put("noticeNo", noticeNo);
map.put("noticeTitle", noticeTitle);
map.put("noticeContent", noticeContent);
int result = service.updateNotice(map);
// 로직 수행 성공 시 "공지사항이 수정되었습니다." swal 출력
if (result>0) {
path = "view.do?no="+noticeNo; // 쿼리스트링을 이용하여 상세조회 요청
swalIcon = "success";
swalTitle = "공지사항 수정 성공 ";
}
// 로직 수행 실패 시 " 공지사항 수정 실패" swal 출력
else {
path = "list.do"; // 목록으로 돌아감
swalIcon = "error";
swalTitle = "공지사항 등록 실패";
}
request.getSession().setAttribute("swalIcon", swalIcon);
request.getSession().setAttribute("swalTitle", swalTitle);
// 수정된 공지사항 상세조회로 redirect
response.sendRedirect(path);
}
NoticeService.java
/** 공지사항 수정 Service
* @param map
* @return result
* @throws Exception
*/
public int updateNotice(Map<String, Object> map) throws Exception {
Connection conn = getConnection();
// 크로스 사이트 스크립팅 방지
map.put("noticeTitle", replaceParameter((String)map.get("noticeTitle")));
map.put("noticeContent", replaceParameter((String)map.get("noticeContent")));
map.put("noticeContent", ((String)map.get("noticeContent")).replaceAll("\r\n", "<br>"));
int result = dao.updateNotice(conn,map);
if(result>0) commit(conn);
else rollback(conn);
close(conn);
return result;
}
NoticeDAO.java
/** 공지사항 수정 DAO
* @param conn
* @param map
* @return result
* @throws Exception
*/
public int updateNotice(Connection conn, Map<String, Object> map) throws Exception {
int result =0;
String query = prop.getProperty("updateNotice");
try {
pstmt = conn.prepareStatement(query);
pstmt.setString(1, (String)map.get("noticeTitle"));
pstmt.setString(2, (String)map.get("noticeContent"));
pstmt.setInt(3, (int)map.get("noticeNo"));
result = pstmt.executeUpdate();
}finally {
close(pstmt);
}
return result;
}
SQL
<!-- 공지사항 수정 -->
<entry key="updateNotice">
UPDATE NOTICE SET
NOTICE_TITLE =?,
NOTICE_CONTENT = ?
WHERE NOTICE_NO = ?
</entry>
공지사항 삭제
삭제 버튼을 클릭했을 때 이벤트 발생(confirm)
noticeView.jsp
<button class="btn btn-primary float-right" id="deleteBtn">삭제</button>
<!-- 삭제버튼 클릭 시 -->
<script>
$("#deleteBtn").on("click",function(){
if (confirm("정말 삭제 하시겠습니까?")){
location.href ="delete.do?no=${param.no}"
}
});
</script>
삭제 완료 후
NoticeController.java
// 공지사항 삭체 Controller **********
else if (command.contentEquals("/delete.do")){
errorMsg ="공지사항 삭제 과정에서 오류 발생";
int noticeNo = Integer.parseInt(request.getParameter("no"));
// 비즈니스 로직 수행
int result = service.updateNoticeFl(noticeNo);
if(result>0) {
swalIcon = "success";
swalTitle = "공지사항이 삭제되었습니다.";
path = "list.do";
}else {
swalIcon = "error";
swalTitle = "공지사항 삭제 실패";
path = request.getHeader("referer");
}
request.getSession().setAttribute("swalIcon", swalIcon);
request.getSession().setAttribute("swalTitle", swalTitle);
response.sendRedirect(path);
}
NoticeService.java
/** 공지사항 삭제 service
* @param noticeNo
* @return result
* @throws Exception
*/
public int updateNoticeFl(int noticeNo) throws Exception {
Connection conn = getConnection();
int result = dao.updateNoticeFl(conn,noticeNo);
if(result>0) commit(conn);
else rollback(conn);
close(conn);
return result;
}
NoticeDAO.java
/** 공지사항 삭제 DAO
* @param conn
* @param noticeNo
* @return result
* @throws Exception
*/
public int updateNoticeFl(Connection conn, int noticeNo) throws Exception {
int result =0;
String query = prop.getProperty("updateNoticeFl");
try {
pstmt = conn.prepareStatement(query);
pstmt.setInt(1, noticeNo);
result = pstmt.executeUpdate();
}finally {
close(pstmt);
}
return result;
}
SQL
<!-- 공지사항 삭제 -->
<entry key="updateNoticeFl">
UPDATE NOTICE SET
NOTICE_FL= 'N'
WHERE NOTICE_NO=?
</entry>
전체 noticeList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL core Tag 사용 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공지사항</title>
<style>
.pagination {
justify-content: center;
}
/* 검색창 스타일 */
#searchForm > * {
top: 0;
vertical-align: top;
}
select[name='searchKey']{
width: 100px;
display: inline-block;
}
input[name='searchValue']{
width: 25%;
display: inline-block;
}
#searchBtn{
width: 100px;
display: inline-block;
}
.list-wrapper{
height: 540px;
}
/* 목록에 마우스를 올릴 경우 손가락 모양으로 변경 */
#list-table td:hover{
cursor : pointer;
}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp"></jsp:include>
<div class="container my-5 ">
<h1>공지사항</h1>
<div class="list-wrapper">
<table class="table table-hover table-striped my-5" id="list-table">
<thead>
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>작성일</th>
</tr>
</thead>
<tbody>
<!-- 공지사항 목록 -->
<%-- 공지사항이 존재할 때와 존재하지 않을 때에 맞는 출력 형식을 지정해야 함. --%>
<c:choose>
<%-- 공지사항이 없을 때 --%>
<c:when test="${empty list}">
<tr>
<td colspan="5" align="center">존재하는 공지사항이 없습니다.</td>
</tr>
</c:when>
<%-- 공지사항이 존재할 때 --%>
<c:otherwise>
<c:forEach var="notice" items="${list}">
<tr>
<td>${ notice.noticeNo }</td>
<td>${notice.noticeTitle}</td>
<td>${notice.memberId}</td>
<td>${notice.readCount}</td>
<td>${notice.noticeCreateDate}</td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</tbody>
</table>
</div>
<%-- 로그인된 계정이 관리자 등급인 경우 --%>
<c:if test="${!empty loginMember && loginMember.memberGrade=='A' }">
<button type="button" class="btn btn-primary float-right" id="insertBtn"
onclick="location.href = 'insertForm.do';">글쓰기</button>
</c:if>
<div class="my-5">
<ul class="pagination">
<li><a class="page-link" href="#"><</a></li>
<li><a class="page-link" href="#">1</a></li>
<li><a class="page-link" href="#">2</a></li>
<li><a class="page-link" href="#">3</a></li>
<li><a class="page-link" href="#">4</a></li>
<li><a class="page-link" href="#">5</a></li>
<li><a class="page-link" href="#">></a></li>
</ul>
</div>
<div class="mb-5">
<form action="search" method="GET" class="text-center" id="searchForm">
<select name="searchKey" class="form-control">
<option value="title">글제목</option>
<option value="content">내용</option>
<option value="titcont">제목+내용</option>
</select>
<input type="text" name="searchValue" class="form-control">
<button class="form-control btn btn-primary" id="searchBtn">검색</button>
</form>
</div>
</div>
<jsp:include page="../common/footer.jsp"></jsp:include>
<script>
// 공지사항 상세보기 기능 (jquery를 통해 작업)
// id가 list-table인 요소의 후손 중에 td 하나가 클릭이 되면 해당 td의 첫번째 형제를 선택해라.
$("#list-table td").on("click", function(){
var noticeNo = $(this).parent().children().eq(0).text();
// 클릭 이벤트가 발생한 요소의 부모의 자식들 중의 제일 첫번째 자식.
// console.log(noticeNo);
// 얻어온 공지사항 글 번호를 쿼리스트링으로 작성하여 상세조회 요청
location.href = "${contextPath}/notice/view.do?no=" + noticeNo;
// ${contextPath}/notice/view.do : 상세조회를 위한 주소
});
</script>
</body>
</html>
전체 noticeView.jsp
<%@ 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>
<style>
#notice-area{ height: 700px;}
#notice-content{ padding-bottom:150px;}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp"></jsp:include>
<div class="container my-5">
<div id="notice-area">
<!-- Title -->
<h1 class="mt-4">${notice.noticeTitle }</h1>
<!-- Writer -->
<p class="lead">
작성자 : <a class="idSelect">${notice.memberId }</a>
</p>
<hr>
<!-- Date -->
<p>
${notice.noticeCreateDate }
<span class="float-right">조회수 ${notice.readCount }</span>
</p>
<hr>
<!-- Content -->
<div id="notice-content">${notice.noticeContent }</div>
<hr>
<div>
<%-- 로그인된 회원이 해당 글의 작성자인 경우 --%>
<!-- float-right 속성 : 오른쪽으로 정렬됨, 화면상에선 목록,수정,삭제 순서대로 보임. -->
<c:if test="${!empty loginMember && (loginMember.memberId == notice.memberId) }">
<button class="btn btn-primary float-right" id="deleteBtn">삭제</button>
<a href="updateForm.do?no=${param.no}" class="btn btn-primary float-right ml-1 mr-1">수정</a>
<!-- request 파라미터 중 no가 존재하고 있음.-->
</c:if>
<a href="list.do" class="btn btn-primary float-right">목록으로</a>
</div>
</div>
</div>
<jsp:include page="../common/footer.jsp"></jsp:include>
<!-- 삭제버튼 클릭 시 -->
<script>
$("#deleteBtn").on("click",function(){
if (confirm("정말 삭제 하시겠습니까?")){
location.href ="delete.do?no=${param.no}"
}
});
</script>
</body>
</html>
전체 noticeInsert.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공지사항</title>
<style>
#notice-area{ height: 700px;}
</style>
</head>
<body>
<jsp:include page="../common/header.jsp"></jsp:include>
<div class="container my-5">
<h3>공지사항 등록</h3>
<hr>
<div class="bg-white rounded shadow-sm container py-3" id="notice-area">
<form method="POST" action="insert.do" role="form" onsubmit="return noticeValidate();">
<div class="form-inline mb-2">
<div class="input-group">
<label class="input-group-addon mr-3">제목</label>
<input type="text" class="form-control" id="noticeTitle" name="noticeTitle" size="70">
</div>
</div>
<div class="form-inline mb-2">
<div class="input-group">
<label class="input-group-addon mr-3">작성자</label>
<h5 class="my-0">${loginMember.memberId }</h5>
</div>
</div>
<div class="form-inline mb-2">
<div class="input-group">
<label class="input-group-addon mr-3">작성일</label>
<h5 class="my-0" id="today"></h5>
</div>
</div>
<hr>
<div class="form-group">
<div><label for="content">내용</label> </div>
<!-- textarea == input태근 -->
<textarea class="form-control" id="noticeContent" name="noticeContent" rows="15" style="resize: none;"></textarea>
</div>
<hr class="mb-4">
<div class="text-center">
<button type="submit" class="btn btn-primary">등록</button>
<a href="list" class="btn btn-primary">목록으로</a>
</div>
</form>
</div>
</div>
<jsp:include page="../common/footer.jsp"></jsp:include>
<script>
(function printToday(){
// 오늘 날짜 출력
var now = new Date(); // 현재 시간
var year = now.getFullYear(); // 201 Date라는 내장객체에 존재하는 함수
var month = now.getMonth() + 1; // 0~11중 하나가 반환
var date = now.getDate(); // 4
var str = year + "-" + (month<10? "0"+month : month) + "-" + (date<10 ? "0" +date : date);
$("#today").text(str);
})();
// 유효성 검사
function noticeValidate(){
// 제목에 아무것도 작성하지 않음
if( $("#noticeTitle").val().trim().length == 0){
alert("제목을 입력해 주세요.");
$("#title").focus();
return false;
}
// 내용에 아무것도 작성하지 않음
if( $("#noticeContent").val().trim().length == 0){
alert("내용을 입력해 주세요.");
$("#content").focus();
return false;
}
}
</script>
</body>
</html>
전체 NoticeController
package com.kh.wsp.notice.controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.RequestDispatcher;
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 javax.servlet.http.HttpSession;
import com.kh.wsp.member.model.vo.Member;
import com.kh.wsp.notice.model.service.NoticeService;
import com.kh.wsp.notice.model.vo.Notice;
// 모든 notice 관련 요청을 받아들임
@WebServlet("/notice/*")
public class NoticeController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Front Controller 패턴
// - 클라이언트의 요청을 한 곳으로 집중시켜 개발하는 패턴
// - 요청마다 Servlet을 생성하는 것이 아닌 하나의 Servlet에 작성하여 관리가 용이해짐.
// Controller의 역할 : 요청에 맞는 Service를 호출, 응답을 위한 View 선택
String uri = request.getRequestURI(); // 전체 요청 주소
// ex) /wsp/notice/list.do
String contextPath = request.getContextPath();
// ex) /wsp
String command = uri.substring((contextPath + "/notice").length() );
// System.out.println(uri);
// System.out.println(contextPath);
// System.out.println(command);
// 컨트롤러 내에서 공용으로 사용할 변수 미리 선언
String path = null; // forward 또는 redirect 경로를 저장할 변수
RequestDispatcher view = null; // 요청 위임 객체
// sweet alert 메세지 전달하는 용도
String swalIcon = null;
String swalTitle = null;
String swalText = null;
String errorMsg = null;
try {
NoticeService service = new NoticeService();
// 공지사항 목록 조회 Controller **********
if(command.equals("/list.do")) {
errorMsg = "공지사항 목록 조회 중 오류 발생";
// 비즈니스 로직 처리 후 결과 반환받기
List<Notice> list = service.selectList();
// list를 jsp로 가져가서 화면에 출력해야함
// 요청을 위임할 jsp 경로 지정
path ="/WEB-INF/views/notice/noticeList.jsp";
// 요청 위임 시 전달할 값 세팅
request.setAttribute("list", list);
// 요청 위임 객체 생성 후 위임 진행
view = request.getRequestDispatcher(path);
view.forward(request, response);
}
// 공지사항 상세 조회 Controller **********
else if(command.equals("/view.do")) {
// command = 요청주소 가장 끝만 잘라내어 저장하는 변수
// 상세조회 요청이 왔다면
errorMsg = "공지사항 상세 조회 과정에서 오류 발생";
// 파라미터 얻어오기
// 쿼리스트링으로 전달된 공지사항 번호를 int형으로 파싱하여 저장
int noticeNo = Integer.parseInt(request.getParameter("no"));
// 상세조회 비즈니스 로직 수행 결과 반환
Notice notice = service.selectNotice(noticeNo);
// 조회 결과에 따른 view 연결 처리
if(notice != null) { // 조회 성공
// 경로 지정
path = "/WEB-INF/views/notice/noticeView.jsp";
// 요청 위임
request.setAttribute("notice", notice);
view = request.getRequestDispatcher(path);
view.forward(request, response);
}else { // 조회 실패
HttpSession session = request.getSession();
session.setAttribute("swalIcon", "error");
session.setAttribute("swalTitle", "공지사항 조회 실패");
// 이전 주소로 이동
response.sendRedirect(request.getHeader("referer"));
}
}
// 공지사항 작성 화면 전환 Controller **********
else if(command.contentEquals("/insertForm.do")) {
path = "/WEB-INF/views/notice/noticeInsert.jsp";
view = request.getRequestDispatcher(path);
view.forward(request, response);
}
// 공지사항 등록 Controller **********
else if(command.contentEquals("/insert.do")) {
errorMsg = "공지사항 등록 과정에서 에러 발생.";
// 파라미터로 전달된 값 저장
String noticeTitle = request.getParameter("noticeTitle");
String noticeContent = request.getParameter("noticeContent");
// 세션에서 회원 번호 얻어오기
HttpSession session = request.getSession();
int noticeWriter = ((Member)session.getAttribute("loginMember")).getMemberNo();
// Map을 이용하여 데이터 전달(VO 대신 사용하는 경우가 많음)
Map<String, Object> map = new HashMap<String, Object>();
map.put("noticeTitle", noticeTitle);
map.put("noticeContent", noticeContent);
map.put("noticeWriter", noticeWriter);
// 공지사항 등록 비즈니스 로직 수행 후 결과 반환
int result = service.insertNotice(map);
if(result>0) { // 삽입 성공 시
// result에는 삽입된 공지사항 번호가 저장되어 있음.
path = "view.do?no="+result; // 쿼리스트링을 이용하여 상세조회 요청
swalIcon = "success";
swalTitle = "공지사항이 등록되었습니다.";
}else {
path = "list.do"; // 목록으로 돌아감
swalIcon = "error";
swalTitle = "공지사항 등록 실패";
}
session.setAttribute("swalIcon",swalIcon);
session.setAttribute("swalTitle", swalTitle);
response.sendRedirect(path);
}
// 공지사항 수정 화면 출력용 Controller **********
else if(command.equals("/updateForm.do")) {
errorMsg = "공지사항 수정 화면 전환 과정에서 오류 발생.";
int noticeNo = Integer.parseInt(request.getParameter("no"));
Notice notice = service.updateView(noticeNo);
if(notice !=null) {
path = "/WEB-INF/views/notice/noticeUpdate.jsp";
request.setAttribute("notice",notice);
view = request.getRequestDispatcher(path);
view.forward(request, response);
}else {
request.getSession().setAttribute("swalIcon", "error");
request.getSession().setAttribute("swalText", "공지사항 수정을 위한 조회 실패");
response.sendRedirect("view.do?no=" + noticeNo);
}
}
// 공지사항 수정 Controller
else if(command.contentEquals("/update.do")) {
errorMsg = "공지사항 수정에서 오류 발생";
// 파라미터 얻어오기
int noticeNo = Integer.parseInt(request.getParameter("no"));
String noticeTitle = request.getParameter("noticeTitle");
String noticeContent = request.getParameter("noticeContent");
// 비즈니스 로직 수행
Map<String, Object> map = new HashMap<String, Object>();
map.put("noticeNo", noticeNo);
map.put("noticeTitle", noticeTitle);
map.put("noticeContent", noticeContent);
int result = service.updateNotice(map);
// 로직 수행 성공 시 "공지사항이 수정되었습니다." swal 출력
if (result>0) {
path = "view.do?no="+noticeNo; // 쿼리스트링을 이용하여 상세조회 요청
swalIcon = "success";
swalTitle = "공지사항 수정 성공 ";
}
// 로직 수행 실패 시 " 공지사항 수정 실패" swal 출력
else {
path = "list.do"; // 목록으로 돌아감
swalIcon = "error";
swalTitle = "공지사항 등록 실패";
}
request.getSession().setAttribute("swalIcon", swalIcon);
request.getSession().setAttribute("swalTitle", swalTitle);
// 수정된 공지사항 상세조회로 redirect
response.sendRedirect(path);
}
// 공지사항 삭체 Controller **********
else if (command.contentEquals("/delete.do")){
errorMsg ="공지사항 삭제 과정에서 오류 발생";
int noticeNo = Integer.parseInt(request.getParameter("no"));
// 비즈니스 로직 수행
int result = service.updateNoticeFl(noticeNo);
if(result>0) {
swalIcon = "success";
swalTitle = "공지사항이 삭제되었습니다.";
path = "list.do";
}else {
swalIcon = "error";
swalTitle = "공지사항 삭제 실패";
path = request.getHeader("referer");
}
request.getSession().setAttribute("swalIcon", swalIcon);
request.getSession().setAttribute("swalTitle", swalTitle);
response.sendRedirect(path);
}
}catch(Exception e) {
e.printStackTrace();
path = "/WEB-INF/views/common/errorPage.jsp";
request.setAttribute("errorMsg", errorMsg);
view = request.getRequestDispatcher(path);
view.forward(request, response);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
전체 NoticeService
package com.kh.wsp.notice.model.service;
import static com.kh.wsp.common.JDBCTemplate.*;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import com.kh.wsp.notice.model.dao.NoticeDAO;
import com.kh.wsp.notice.model.vo.Notice;
public class NoticeService {
private NoticeDAO dao = new NoticeDAO();
/** 공지사항 목록 조회 Service
* @return list
* @throws Exception
*/
public List<Notice> selectList() throws Exception {
Connection conn = getConnection();
List<Notice> list = dao.selectList(conn);
close(conn);
return list;
}
/** 공지사항 상세 조회 Service
* @param noticeNo
* @return notice
* @throws Exception
*/
public Notice selectNotice(int noticeNo) throws Exception {
// 1) 커넥션 얻어오기
Connection conn = getConnection();
// 2) dao 수행 후 결과 반환받기
Notice notice = dao.selectNotice(conn, noticeNo);
// 3) 공지사항 조회 성공 시 조회수 증가
if(notice !=null ) {
int result = dao.increaseReadCount(conn,noticeNo);
// 트랜잭션 처리
if(result>0) {
commit(conn);
// 이미 조회된 notice에서 readCount 값을 1 증가
notice.setReadCount(notice.getReadCount()+1);
}
else rollback(conn);
}
// 4) 커넥션 반환
close(conn);
// 5) 결과 반환
return notice;
}
/** 공지사항 등록 Service
* @param map
* @return result
* @throws Exception
*/
public int insertNotice(Map<String, Object> map) throws Exception {
Connection conn = getConnection();
// 1) 작성될 글 번호를 먼저 얻어오는 DAO 메소드 수행
// 이유 1) 글 작성 성공 후 해당 글 상세 조회 페이지로 redirect 하기 위해 필요.
// 이유 2) 글 작성 + 파일 첨부 시 발생하는 시퀀스 번호 밀림 현상을 제거하기 위해
int noticeNo = dao.selectNextNo(conn);
int result = 0;
if(noticeNo >0) { // 다음 글 번호를 얻어오는데 성공한 경우
// 2. 실제 공지글 등록 DAO 메소드 수행
// map에 얻어온 다음 글 번호를 세팅
map.put("noticeNo", noticeNo);
// 크로스 사이트 스크립팅 방지 처리
map.put("noticeTitle", replaceParameter((String)map.get("noticeTitle")));
// <script> -> <script>
map.put("noticeContent", replaceParameter((String)map.get("noticeContent")));
// 개행문자 변경 처리
// textarea의 개행문자는 \r\n 이지만
// 상세조회에서 사용되는 div태그의 개행문자는 <br>이기 때문에 변경이 필요함
map.put("noticeContent", ((String)map.get("noticeContent")).replaceAll("\r\n", "<br>"));
result = dao.insertNotice(conn,map);
// 트랜잭션 처리
if(result>0) {
commit(conn);
// 삽입 성공 시 result에 작성한 글 번호를 대입
result = noticeNo; // 글번호가 최종적으로 반환됨
}
else rollback(conn);
}
close(conn);
return result;
}
// 크로스 사이트 스크립팅
// 웹 애플리케이션에서 많이 나타나는 보안 취약점 중 하나로
// 웹 사이트 관리자가 아닌 사용자가 웹 페이지에 악성 스크립트를 삽입할 수 있는 취약점
// 크로스 사이트 스크립팅 방지 메소드
private String replaceParameter(String param) {
String result = param;
if(result != null) {
result = result.replaceAll("&", "&");
result = result.replaceAll("<", "<");
result = result.replaceAll(">", ">");
result = result.replaceAll("\"", """);
}
return result;
}
/** 공지사항 수정 화면 Service
* @param noticeNo
* @return notice
* @throws Exception
*/
public Notice updateView(int noticeNo) throws Exception {
Connection conn = getConnection();
// 공지사항 상세조회 DAO 호출
Notice notice = dao.selectNotice(conn, noticeNo);
// textarea에 출력하기 위해 개행문자 변경
if(notice !=null) {
notice.setNoticeContent(notice.getNoticeContent().replaceAll("<br>", "\r\n"));
}
close(conn);
return notice;
}
/** 공지사항 수정 Service
* @param map
* @return result
* @throws Exception
*/
public int updateNotice(Map<String, Object> map) throws Exception {
Connection conn = getConnection();
// 크로스 사이트 스크립팅 방지
map.put("noticeTitle", replaceParameter((String)map.get("noticeTitle")));
map.put("noticeContent", replaceParameter((String)map.get("noticeContent")));
map.put("noticeContent", ((String)map.get("noticeContent")).replaceAll("\r\n", "<br>"));
int result = dao.updateNotice(conn,map);
if(result>0) commit(conn);
else rollback(conn);
close(conn);
return result;
}
/** 공지사항 삭제 service
* @param noticeNo
* @return result
* @throws Exception
*/
public int updateNoticeFl(int noticeNo) throws Exception {
Connection conn = getConnection();
int result = dao.updateNoticeFl(conn,noticeNo);
if(result>0) commit(conn);
else rollback(conn);
close(conn);
return result;
}
}
전체 NoticeDAO
package com.kh.wsp.notice.model.dao;
import static com.kh.wsp.common.JDBCTemplate.*;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.kh.wsp.notice.model.vo.Notice;
public class NoticeDAO {
// 자주 사용하는 JDBC 참조 변수 미리 선언
private Statement stmt = null;
private PreparedStatement pstmt = null;
private ResultSet rset = null;
// 외부 XML 파일에 작성된 sql을 읽어올 변수 선언
Properties prop = null;
// 기본 생성자로 NoticeDAO 객체 생성 시 SQL이 작성된 xml 파일 얻어오기
public NoticeDAO() {
String fileName = NoticeDAO.class.getResource("/com/kh/wsp/sql/notice/notice-query.xml").getPath();
try {
prop = new Properties();
prop.loadFromXML(new FileInputStream(fileName));
} catch (Exception e) {
e.printStackTrace();
}
}
/** 공지사항 목록 조회 DAO
* @param conn
* @return list
* @throws Exception
*/
public List<Notice> selectList(Connection conn) throws Exception {
List<Notice> list = null;
String query = prop.getProperty("selectList");
try {
stmt = conn.createStatement();
rset = stmt.executeQuery(query);
// sql 수행 후 DB관련 문제가 발생하지 않으면
// 조회 내용을 저장할 수 있는 ArrayList 생성
list = new ArrayList<Notice>();
while(rset.next()) {
Notice notice = new Notice();
notice.setNoticeNo(rset.getInt("NOTICE_NO"));
notice.setNoticeTitle(rset.getString("NOTICE_TITLE"));
notice.setMemberId(rset.getString("MEMBER_ID"));
notice.setReadCount(rset.getInt("READ_COUNT"));
notice.setNoticeCreateDate(rset.getDate("NOTICE_CREATE_DT"));
list.add(notice);
}
}finally {
close(rset);
close(stmt);
}
return list;
}
/** 공지사항 상세조회 DAO
* @param conn
* @param noticeNo
* @return notice
* @throws Exception
*/
public Notice selectNotice(Connection conn, int noticeNo) throws Exception {
// 1) 결과를 저장할 변수 선언
Notice notice = null;
// 2) SQL 구문 얻어오기
String query = prop.getProperty("selectNotice");
// 3) SQL 수행 후 결과를 notice에 저장
try {
pstmt = conn.prepareStatement(query);
pstmt.setInt(1, noticeNo);
rset=pstmt.executeQuery();
if(rset.next()) {
notice = new Notice();
notice.setNoticeTitle(rset.getString("NOTICE_TITLE"));
notice.setNoticeContent(rset.getString("NOTICE_CONTENT"));
notice.setMemberId(rset.getString("MEMBER_ID"));
notice.setReadCount(rset.getInt("READ_COUNT"));
notice.setNoticeCreateDate(rset.getDate("NOTICE_CREATE_DT"));
}
}finally {
// 4) 사용한 JDBC 객체 반환
close(rset);
close(pstmt);
}
// 5) 결과 반환
return notice;
}
/** 조회수 증가 DAO
* @param conn
* @param noticeNo
* @return result
* @throws Exception
*/
public int increaseReadCount(Connection conn, int noticeNo) throws Exception {
int result = 0;
String query = prop.getProperty("increaseReadCount");
try {
pstmt = conn.prepareStatement(query);
pstmt.setInt(1, noticeNo);
result = pstmt.executeUpdate();
}finally {
close(pstmt);
}
return result;
}
/** 공지사항 등록 시 사용될 번호 반환 DAO
* @param conn
* @return noticeNo
* @throws Exception
*/
public int selectNextNo(Connection conn) throws Exception {
int noticeNo = 0;
String query = prop.getProperty("selectNextNo");
try {
stmt = conn.createStatement();
rset = stmt.executeQuery(query);
if(rset.next()) {
noticeNo = rset.getInt(1);
}
}finally {
close(rset);
close(stmt);
}
return noticeNo;
}
/** 공지사항 등록 DAO
* @param conn
* @param map
* @return result
* @throws Exception
*/
public int insertNotice(Connection conn, Map<String, Object> map) throws Exception{
int result =0;
String query = prop.getProperty("insertNotice");
try {
pstmt = conn.prepareStatement(query);
pstmt.setInt(1, (int)map.get("noticeNo"));
pstmt.setString(2, (String)map.get("noticeTitle"));
pstmt.setString(3, (String)map.get("noticeContent"));
pstmt.setInt(4, (int)map.get("noticeWriter"));
result = pstmt.executeUpdate();
}finally {
close(pstmt);
}
return result;
}
/** 공지사항 수정 DAO
* @param conn
* @param map
* @return result
* @throws Exception
*/
public int updateNotice(Connection conn, Map<String, Object> map) throws Exception {
int result =0;
String query = prop.getProperty("updateNotice");
try {
pstmt = conn.prepareStatement(query);
pstmt.setString(1, (String)map.get("noticeTitle"));
pstmt.setString(2, (String)map.get("noticeContent"));
pstmt.setInt(3, (int)map.get("noticeNo"));
result = pstmt.executeUpdate();
}finally {
close(pstmt);
}
return result;
}
/** 공지사항 삭제 DAO
* @param conn
* @param noticeNo
* @return result
* @throws Exception
*/
public int updateNoticeFl(Connection conn, int noticeNo) throws Exception {
int result =0;
String query = prop.getProperty("updateNoticeFl");
try {
pstmt = conn.prepareStatement(query);
pstmt.setInt(1, noticeNo);
result = pstmt.executeUpdate();
}finally {
close(pstmt);
}
return result;
}
}
전체 SQL
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<!-- 공지사항 목록 조회 -->
<entry key="selectList">
SELECT * FROM V_NOTICE_LIST
WHERE NOTICE_FL='Y'
</entry>
<!-- 공지사항 상세 조회 -->
<entry key="selectNotice">
SELECT NOTICE_TITLE, NOTICE_CONTENT, MEMBER_ID, READ_COUNT,NOTICE_CREATE_DT
FROM NOTICE
JOIN MEMBER ON(NOTICE_WRITER = MEMBER_NO)
WHERE NOTICE_NO=?
AND NOTICE_FL='Y'
</entry>
<!-- 조회수 증가 -->
<entry key="increaseReadCount">
UPDATE NOTICE SET
READ_COUNT = READ_COUNT+1
WHERE NOTICE_NO=?
</entry>
<!-- 공지사항 등록 시 사용될 번호 반환 : 다음 시원스 조회 -->
<entry key="selectNextNo">
SELECT SEQ_NNO.NEXTVAL FROM DUAL
</entry>
<!-- 공지사항 등록 -->
<entry key="insertNotice">
INSERT INTO NOTICE(NOTICE_NO, NOTICE_TITLE, NOTICE_CONTENT, NOTICE_WRITER)
VALUES (?,?,?,?)
</entry>
<!-- 공지사항 수정 -->
<entry key="updateNotice">
UPDATE NOTICE SET
NOTICE_TITLE =?,
NOTICE_CONTENT = ?
WHERE NOTICE_NO = ?
</entry>
<!-- 공지사항 삭제 -->
<entry key="updateNoticeFl">
UPDATE NOTICE SET
NOTICE_FL= 'N'
WHERE NOTICE_NO=?
</entry>
</properties>
공유하기
Twitter Google+ LinkedIn
댓글남기기