관리자 글쓰기

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

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


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


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


1. 설정

1.1. 전자정부 프레임워크 라이브러리

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<repositories>
        <repository>
            <id>egovframe</id>
            <url>http://maven.egovframe.kr:8080/maven/</url>
            <releases>
            <enabled>true</enabled>
            </releases>
            <snapshots>
            <enabled>false</enabled>
            </snapshots>
        </repository>
</repositories>
 
<dependency>
    <groupId>egovframework.rte</groupId>
    <artifactId>egovframework.rte.ptl.mvc</artifactId>
    <version>2.7.0</version>
</dependency>

전자정부 프레임워크 라이브러리는 별도로 repository로 다운 받아야 하기 때문에 위와 같은 형식을 pom.xml에 추가하여 준다.


1.2 Bean 설정

context-common.xml

1
2
3
4
5
6
7
8
<bean id="textRenderer" class="egovframework.rte.ptl.mvc.tags.ui.pagination.DefaultPaginationRenderer"/> 
<bean id="paginationManager" class="egovframework.rte.ptl.mvc.tags.ui.pagination.DefaultPaginationManager">
    <property name="rendererType">
        <map>
            <entry key="text" value-ref="textRenderer"/>
        </map>
    </property>
</bean>

전자정보 프레임워크의 페이지 렌더 방식 설정하는 부분으로 보다 자세한 설명은 해당 홈페이지에 있다.

(http://www.egovframe.org/wiki/doku.php?id=egovframework:rte:ptl:view:paginationtag)


1.3 SQL

sample_SQL.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<select id="sample.selectBoardList" resultType="hashmap" parameterType="hashmap" >
   <![CDATA[
       SELECT
           (
               SELECT
                   COUNT(*)
               FROM
                   TB_BOARD
               WHERE
                   DEL_GB = 'N'
           ) AS TOTAL_COUNT ,
           IDX,
           TITLE,
           HIT_CNT,
           CREA_DTM
       FROM
           TB_BOARD
       WHERE
           DEL_GB= 'N'
       ORDER BY
           IDX DESC
       LIMIT #{START} , #{END}
   ]]>
</select>

- LIMIT에 #{START}는 몇번 째부터 시작할 지를 나타내고, #{END}는 몇 개의 칼럼을 가져올 지 정한다. TOTAL_COUNT는 게시물 총 갯수를 구하기 위함이다.


- 게시물 추가하기(프로시저 생성)

1
2
3
4
5
6
7
8
9
10
DELIMITER $$
CREATE PROCEDURE myFunction()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE (i < 501) DO
INSERT INTO TB_BOARD(TITLE, CONTENTS, HIT_CNT, DEL_GB, CREA_DTM, CREA_ID) VALUES(concat('제목',i), concat('내용',i), 0, 'N', SYSDATE(), 'Admin');
SET i = i + 1;
END WHILE;
END$$
DELIMITER ;

- 프로시저 실행

1
CALL myFunction;

페이징 테스트를 위하여 많은 양의 게시물을 생성해 넣는다.



2. 코드 작성

2.1 AbstractDAO.java

해당 코드를 AbstractDAO.java 에 추가 작성하라.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@SuppressWarnings({ "rawtypes", "unchecked" })
public Map selectPagingList(String queryId, Object params){
    printQueryId(queryId);
      
    Map<String,Object> map = (Map<String,Object>)params;
    PaginationInfo paginationInfo = null;
      
    if(map.containsKey("currentPageNo") == false || StringUtils.isEmpty(map.get("currentPageNo")) == true)
        map.put("currentPageNo","1");
      
    paginationInfo = new PaginationInfo();
    paginationInfo.setCurrentPageNo(Integer.parseInt(map.get("currentPageNo").toString()));
    if(map.containsKey("PAGE_ROW") == false || StringUtils.isEmpty(map.get("PAGE_ROW")) == true){
        paginationInfo.setRecordCountPerPage(15);
    }
    else{
        paginationInfo.setRecordCountPerPage(Integer.parseInt(map.get("PAGE_ROW").toString()));
    }
    paginationInfo.setPageSize(10);
 
    int start = paginationInfo.getFirstRecordIndex();
    int end = paginationInfo.getRecordCountPerPage();
    map.put("START",start);
    map.put("END",end);
      
    params = map;
     
    Map<String,Object> returnMap = new HashMap<String,Object>();
    List<Map<String,Object>> list = sqlSession.selectList(queryId,params);
      
    if(list.size() == 0){
        map = new HashMap<String,Object>();
        map.put("TOTAL_COUNT",0);
        list.add(map);
          
        if(paginationInfo != null){
            paginationInfo.setTotalRecordCount(0);
            returnMap.put("paginationInfo", paginationInfo);
        }
    }
    else{
        if(paginationInfo != null){
            paginationInfo.setTotalRecordCount(Integer.parseInt(list.get(0).get("TOTAL_COUNT").toString()));
 
            returnMap.put("paginationInfo", paginationInfo);
        }
    }
    returnMap.put("result", list);
    return returnMap;
}

- 6줄

페이지 설정 정보를 담는 클래스 선언.

- 8~12줄

현재 페이지에 대한 값을 가지고 있는 지 확인하고 없을 시에는 1페이지를 위하여 1의 값을 설정 후 페이지 설정 변수에 세팅.

- 13~19줄

게시물 숫자가 설정되어 있지 않으면 15로 설정하고 페이지의 갯수 10으로 설정

- 21~24줄

페이지 설정 클래스의 첫번째 값의 인덱스 값과 게시물 숫자를 가져와 map에 값을 추가하여 준다.(SQL에서 사용)

- 29줄

쿼리의 결과 값을 가져온다.

- 31~47줄

쿼리의 결과값을 통해 TOTAL_COUNT 값을 가져오고 페이지 설정 클래스를 map에 추가한다.

- 48~49줄

페이시 설정 클래스와 쿼리 결과값을 포함한 map을 리턴한다.


2.2 JSP

- include-header.jspf

1
<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %>

해당 태그를 추가한다.


- boardList.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<%@ 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_list">
        <colgroup>
            <col width="5%">
            <col width="50%">
            <col width="5%">
            <col width="15%">
            <col width="15%">
        </colgroup>
        <caption>게시판</caption>
        <thead>
            <tr>
                <th>No.</th>
                <th>제목</th>
                <th>Hit</th>
                <th>작성자</th>
                <th>작성시간</th>
            </tr>
        </thead>
        <tbody>
            <c:choose>
                <c:when test="${fn:length(list)>0}">
                    <c:forEach items="${list }" var="con" >
                        <tr>
                            <td>${con.IDX }</td>
                            <td><input type="hidden" id="IDX" value="${con.IDX }"><a href="#this" name="TITLE">${con.TITLE }</a></td>
                            <td>${con.HIT_CNT }</td>
                            <td>${con.CREA_ID }</td>
                            <td>${con.CREA_DTM }</td>
                        </tr>
                    </c:forEach>
                </c:when>
                <c:otherwise>
                    <tr>
                        <td>게시물이 존재하지 않습니다.</td>
                    </tr>
                </c:otherwise>           
            </c:choose>
        </tbody>
    </table>
 
    <c:if test="${not empty paginationInfo}">
         <ui:pagination paginationInfo = "${paginationInfo}" type="text" jsFunction="fn_search"/>
    </c:if>
    <input type="hidden" id="currentPageNo" name="currentPageNo"/>
     
 
 
 
    <a href="#this" class="btn" id="write">글쓰기</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();
        }
        function fn_search(pageNo){
            var comSubmit = new ComSubmit();
            comSubmit.setUrl("<c:url value='/sample/openBoardList.do' />");
            comSubmit.addParam("currentPageNo", pageNo);
            comSubmit.submit();
        }
 
    </script>
</body>
</html>

- 50~53줄

페이지 정보 클래스를 받아와서 페이징 태그 속성 값을 설정해주었다. jsFunction은 페이징 태그를 클릭하였을 때 실행시킬 함수를 지정한다.

- 83~88줄

페이징 태그 클릭 시 실행되는 함수를 설정해둔 것으로 pageNo라는 값은 페이징 태그를 클릭하는 값을 파라미터로 넘겨 줌으로써 currentPageNo 값으로  Controller로 파라미터를 추가하여 보낸다.


2.3 JAVA

게시물 리스트 관련 코드를 아래와 같이 수정하라.

- Controller

SampleController.java

1
2
3
4
5
6
7
8
9
10
@RequestMapping(value="/sample/openBoardList.do")
public ModelAndView openBoardList(CommandMap commandMap) throws Exception{
     
    ModelAndView mv = new ModelAndView("boardList");
    Map<String,Object> map = sampleService.selectBoardList(commandMap.getMap());
    mv.addObject("list", map.get("result"));
    mv.addObject("paginationInfo", (PaginationInfo)map.get("paginationInfo"));
     
    return mv;
}

- List 값을 리턴하던 것을 Map으로 바꾸고 쿼리 결과 값과 페이징 정보 값을 맵에서 가져와 뷰로 보내준다. 여기서 페징 정보 값은 위의 boardList.jsp 에서 작성할 때 보았던 ui:paginationInfo 에서 보았던 ${paginationInfo}로 사용 될 것이다.


- Service, ServiceImpl

SampleServiceImpl.java

1
2
3
4
@Override
public Map<String,Object> selectBoardList(Map<String, Object> map) throws Exception {
    return sampleDAO.selectBoardList(map);
}
- Map 형식으로 바꾼 것을 주의하면서 코드를 수정한다.


- DAO

SampleDAO.java

1
2
3
4
@SuppressWarnings("unchecked")
public Map<String,Object> selectBoardList(Map<String,Object> map) throws Exception{
    return (Map<String,Object>)selectPagingList("sample.selectBoardList",map);
}

- Map 형식으로 바꾼 것을 주의하면서 코드를 수정한다. 여기는 또한 selectBoardList를 selectPagingList로 수정하는 것을 주의한다.


3. 테스트


- 게시물 리스트 페이지를 열어보자.


- 다음 2 페이지로 넘어가보자.


- 다음 버튼을 눌러 11페이지로 넘어가보자.


- 마지막 버튼을 클릭하여 동작하는지 보자.


- 위 작업들에 대한 로그이다.


- 위의 이미지들처럼 동작을 완료했다면 전자정부 프레임워크 라이브러리를 이용한 페이징도 완료하였다.