관리자 글쓰기

 본 내용은 혼자 공부하기 위하여 다른 포스트를 보면서 저에게 필요한 부분과 궁금했던 부분을 추가하여 게시하는 곳입니다.


궁금한 것에 대한 것은 모르는 것이 많겠지만 함께 알아보도록 노력하겠습니다.


참조 게시 포스트 : http://addio3305.tistory.com/


-------------------------------------------------------------------------------------------------------------------------------------------

1. 게시글 상세보기 작성

마찬가지로 Controller - > Service - > ServiceImpl -> DAO -> SQL -> JSP 순으로 작성하겠습니다.

그 전에 먼저 게시글 리스트 보기 JSP를 수정할 부분이 있습니다.


1.0 boardList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>first</title>
<%@ include file="/WEB-INF/include/include-header.jspf" %>
</head>
<body>
<h2>게시판 목록</h2>
<table style="border:1px solid #ccc" class="board_list">
    <colgroup>
        <col width="10%"/>
        <col width="*"/>
        <col width="15%"/>
        <col width="20%"/>
    </colgroup>
    <thead>
        <tr>
            <th scope="col">글번호</th>
            <th scope="col">제목</th>
            <th scope="col">조회수</th>
            <th scope="col">작성일</th>
        </tr>
    </thead>
    <tbody>
        <c:choose>
            <c:when test="${fn:length(list) > 0}">
                <c:forEach items="${list }" var="row">
                    <tr>
                        <td>${row.IDX }</td>
                        <td><input type="hidden" id="IDX" value="${row.IDX }"/><a class="title" href="#this" name="title" >${row.TITLE }</a></td>
                        <td>${row.HIT_CNT }</td>
                        <td>${row.CREA_DTM }</td>
                    </tr>
                </c:forEach>
            </c:when>
            <c:otherwise>
                <tr>
                    <td colspan="4">조회된 결과가 없습니다.</td>
                </tr>
            </c:otherwise>
        </c:choose>
         
    </tbody>
</table>
<a href="#this" id="write" class="btn">글쓰기</a>

<%@ include file="/WEB-INF/include/include-body.jspf" %>
<script type="text/javascript">
	$(document).ready(function(){
		$("#write").on("click",function(e){
			e.preventDefault();
			fn_openBoardWrite();
		})
		$("a[name='title']").on("click",function(e){
			e.preventDefault();
			fn_openBoardDetail($(this));
		})
	})
	
	function fn_openBoardWrite(){
		var comSubmit = new ComSubmit();
		comSubmit.setUrl("<c:url value='/sample/openBoardWrite.do'/>");
		comSubmit.submit();
	}
	function fn_openBoardDetail(val){
		var comSubmit = new ComSubmit();
		comSubmit.addParam("IDX",val.parent().find("#IDX").val());
		comSubmit.setUrl("<c:url value='/sample/openBoardDetail.do'/>");
		comSubmit.submit();
	}
</script>

</body>
</html>

- 31줄과 55~71줄이 수정되었습니다.

먼저 31줄의 경우 해당 게시물의 게시글 번호를 알기 위하여 hidden type의 input을 만들어 놓았고 제목을 <a>태그로 감싸놓았다. 이것으로 jQuery에서 IDX를 참조할 수 있게 된다.

55~59줄의 경우는 글 등록 페이지로 갈 수 있는 단순한 처리를 바인딩 해놓았으며 60~63줄의 경우 31줄에서 만들어놓았던 <a>태그에 이벤트를 바인딩 해두었다. 그중 $(this)는 jQuery 객체로 해당 <a> 자체에 대한 객체이다. 66~70줄에서 특별한 것으로는 addParam 메서드로 여기서 아까 가져온 $(this) = val = <a>로 생각하면 쉽다.

즉, 선택한 <a>.parent().find("#IDX").val() =>  <td>.find("#IDX").val()  => <input id="IDX">.val()으로 해석하면 이해가 쉽다. 이 값을 새로운 Request의 파라미터로 추가하여 다시 컨트롤러에 도달할 예정이다. 이 부분부터 이제 상세 페이지가 시작된다.



1.1 Controller

SampleController.java 에 추가

	@RequestMapping(value="/sample/openBoardDetail.do")
	public ModelAndView openBoardDetail(CommandMap commandMap) throws Exception{
		ModelAndView mv = new ModelAndView("/sample/boardDetail");
		Map<String,Object> map = sampleService.selectBoard(commandMap.getMap());
		mv.addObject("map", map);
		return mv;
	}

- 4~5줄

게시글 리스트 보기 페이지에서 선택한 게시글의 IDX가 commandMap에 담겨있다. 왜 담겨 있는 지는 아까 위에서 설명했듯이 게시글 리스트 보기 페이지에서 글을 선택하면서 IDX를 파라미터로 추가하여 넘겨줬기 때문이다. 그 IDX값이 포함된 map 값으로 sampleService 메서드의 파라미터로 보낸다. 그리고 그 리턴값을 뷰 페이지에 추가하여 넘긴다.



1.2 Service, ServiceImpl

SampleService.java 에 추가

Map<String,Object> selectBoard(Map<String,Object> map)throws Exception;


SampleServiceImpl.java 에 추가

@Override
	public Map<String, Object> selectBoard(Map<String, Object> map) throws Exception {
		sampleDAO.updateHitCnt(map);
		return sampleDAO.selectBoard(map); 
	}

여기서 설명할 것으로는 sampleDAO.updateHitCnt(map)의 부분이다. 이 부분은 게시판을 골랐을 때 조회수를 올리는 부분으로 DAO에서 처리하면 될 것이라고 생각할 수 있지만 DAO에서는 한 메서드당 하나의 처리를 맡아야한다. 따라서 서비스단에서 이 부분을 맡고 DAO에서는 처리를 따로 2번 해준다. 4줄의 경우는 게시글 리스트와 비슷한 형식이다.



1.3 DAO

sampleDAO.java에 추가

@SuppressWarnings("unchecked") public Map<String,Object> selectBoard(Map<String,Object> map){ return (Map<String,Object>)selectOne("sample.selectBoard",map); }

public void updateHitCnt(Map<String,Object> map) { update("sample.updateHitCnt",map); }


이 부분도 게시글 리스트를 작성할 때와 거의 유사하다. 여기서는 한 게시글의 정보만 가져오기 때문에 Map 형식이다.
똑같이 SQLID와 map을 파라미터로 selectOne을 호출한다. 밑의 메서드는 조회수를 올릴 때 사용되는 메서드이다.


1.4 SQL
sample_SQL.xml
     <select id="sample.selectBoard" parameterType="hashmap" resultType="hashmap">
     	<![CDATA[
     		SELECT
     			IDX,
     			TITLE,
     			CONTENTS,
     			HIT_CNT,
     			CREA_ID,
     			CREA_DTM
     		FROM
     			TB_BOARD1
     		WHERE
     			IDX=#{IDX}
     	]]>
     </select>
     
     <update id="sample.updateHitCnt" parameterType="hashmap">
     	<![CDATA[
     		UPDATE TB_BOARD1
     		SET
     			HIT_CNT = HIT_CNT+1
     		WHERE
     			IDX=#{IDX}
     	]]>
     </update>

두 쿼리 모두 #{IDX}를 사용하는 모습을 볼 수 있다. 그렇기 때문에 게시글 리스트 페이지에서부터 파라미터를 추가했던 것이다.



1.5 JSP

boardDetail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>상세보기</title>
<%@ include file="/WEB-INF/include/include-header.jspf" %>
</head>
<body>
	<table class="board_view">
		<caption>상세보기</caption>
		<colgroup>
			<col width="15%">
			<col width="35%">
			<col width="15%">
			<col width="*">
		</colgroup>
		
		<tbody>
			<tr>
				<th>제목</th>
				<td>${map.TITLE}</td>
				<th>조회수</th>
				<td>${map.HIT_CNT }</td>
			</tr>
			<tr>
				<th>작성자</th>
				<td>${map.CREA_ID }</td>
				<th>작성시간</th>
				<td>${map.CREA_DTM }</td>
			</tr>
			<tr>
				<th>내용</th>
				<td colspan="3">
					${map.CONTENTS }
				</td>
			</tr>
		</tbody>
	</table>
	<a href="#this" id="list" class="btn">목록으로</a>
	<a href="#this" id="modify" class="btn">수정하기</a>
	<%@ include file="/WEB-INF/include/include-body.jspf" %>
	
	<script type="text/javascript">
		$(document).ready(function(){
			$("#list").on("click",function(e){
				e.preventDefault();
				fn_openBoardList();
			})
			$("#modify").on("click",function(e){
				e.preventDefault();
				fn_openBoardModify();
			})
		})
		
		function fn_openBoardList(){
			var comSubmit = new ComSubmit();
			comSubmit.setUrl("<c:url value='/sample/openBoardList.do'/>");
			comSubmit.submit();
		}
		function fn_openBoardModify(){
			var idx = "${map.IDX}";
			var comSubmit = new ComSubmit();
			comSubmit.setUrl("<c:url value='/sample/openBoardModify.do'/>");
			comSubmit.addParam("IDX",idx);
			comSubmit.submit();
		}
	</script>	
</body>
</html>

- Controller에서 게시글의 정보를 받아왔기에 ${map.TITLE} 처럼 사용할 수 있다. 여기서 특별한 점은 따로 없고 게시글 리스트로 가는 바인딩과 수정하기로 가는 바인딩을 미리 만들어 줬다. 수정하기로 갈 때는 해당 게시글의 번호를 게시글 상세보기 페이지처럼 idx 값을 다시 할당하여 줬다. 이 부분이 아까처럼 사용하지 않는 이유는 아까 게시글 리스트 페이지에서는 게시글의 IDX가 하나가 아니라 게시글마다의 번호가 있으며 그 번호에 대한 처리를 하기 위하여 .parent()와 같은 메서드를 쓴 것이고 여기에서는 해당 IDX가 이 게시글의 IDX만 존재하기 때문에 이렇게 작성하였다.


1.6 테스트

여기까지 잘 따라왔으면 게시글 리스트 페이지에서 게시물의 제목을 클릭하면 밑과 같은 화면이 출력될 것이다.


조회수도 잘 오르는 지 확인하여라.


로그는 아래와 같이 뜬다.