Java Spring JSP웹페이지 만들기4(게시글 목록 페이지)

호연지기·2023년 5월 24일
1
post-thumbnail

🪐 게시글 목록 (paging)

로그인 성공 후 → 게시글 목록 페이지로 이동하기 위해 게시글 목록 페이지를 만들어준다.

✏ 작업 순서

css와 데이터베이스 자료는 생성되어 있던 것 사용

  1. 게시글 목록 페이지가 될 jsp 파일을 생성(boardList.jsp)
  2. paging 처리(PagingUtil, BoardService, BoardDao, BoardController, SearchDto, BoardDto)
  3. 글쓰기 버튼 생성(boardList.jsp)
  4. 접속자(회원 정보) 출력(boardList.jsp)
  5. 제목, 내용 검색(boardList.jsp)

게시글 목록 화면의 페이징 처리

Pagination(or Paging)
다수의 정보를 한 화면에 출력할 때, 출력할 내용의 개수를 제한하고 책의 페이지처럼 여러 화면으로 분리하는 방식.

DB(MySQL)에 SQL의 LIMIT 구문을 사용하여 한 화면에 출력할 데이터를 나눠서 가져오는 방식을 사용한다.

페이지의 번호에 pageNum 값을 다르게 링크하는 형식의 HTML 태그 코드를 작성.
전체 데이터의 양과 한 페이지에 보여질 개수 등의 정보를 가지고, 간단한 수식을 사용하여 자동으로 계산하는 객체를
사용하여 처리.

생성자를 활용하자!
Lombok의 @AllArgsConstructor 어노테이션
생성자란? 객체를 생성할 때 new 키워드 뒤에 호출하는 멤버변수(또는 인스턴스) 초기화 메소드

⚡ 게시글 목록 페이지 생성(JSP)

💻 boardList 소스(header&footer)

header와 footer는 jsp:include 코드로 import 해온다.

<header>
  <jsp:include page="header.jsp"></jsp:include>
</header>
<footer>
  <jsp:include page="footer.jsp"></jsp:include>
</footer>

💻 boardList 소스(게시글 영역)

<section>
    <div class="content">
        <div class="board-form">
            <div class="user-info">
                <div class="user-info-sub">
                    <p>등급 [${mb.g_name}]</p>
                    <p>POINT [${mb.m_point}]</p>
                </div>
            </div>
            <h2 class="login-header">게시글 목록</h2>
            <div class="search-area">
                <select id="sel">
                    <option value="b_title" selected>
                        제목
                    </option>
                    <option value="b_contents">
                        내용
                    </option>
                </select>
                <input type="text" id="keyword">
                <button id="search">검색</button>
            </div>
            <div class="data-area">
                <div class="title-row">
                    <div class="t-no p-10">번호</div>
                    <div class="t-title p-30">제목</div>
                    <div class="t-name p-15">작성자</div>
                    <div class="t-data p-30">작성일</div>
                    <div class="t-view p-15">조회수</div>
                </div>
                <div class="data-row">
                    <c:if test="${empty bList}">
                        <div style="width: 100%">
                            게시글이 없습니다.
                        </div>
                    </c:if>
                    <c:if test="${!empty bList}">
                        <c:forEach var="bitem" items="${bList}">
                            <div class="t-no p-10">${bitem.b_num}</div>
                            <div class="t-title p-30">
                                <a href="/contents?b_num=${bitem.b_num}">${bitem.b_title}</a>
                            </div>
                            <div class="t-name p-15">${bitem.m_name}</div>
                            <div class="t-date p-30">
                                <fmt:formatDate value="${bitem.b_date}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate>
                            </div>
                            <div class="t-views p-15">${bitem.b_views}</div>
                        </c:forEach>
                    </c:if>
                </div>
            </div>
        </div>
    </div>
</section>

⚡ Paging 처리

위 그럼처럼 게시글을 분리하기 위한 페이징 작업
다음 버튼을 누르면 6페이지부터 게시글을 다시 불러온다.

💻 BoardDto 소스

@Data
public class BoardDto {
    private int b_num;
    private String b_title;
    private String b_contents;
    private String b_id;
    private String m_name;
    private Timestamp b_date;
    private int b_views;
}

게시글 작성에 필요한 제목, 내용, 작성자 등 데이터

💻 PagingUtil 소스

//변수 선언 영역
@AllArgsConstructor
public class PagingUtil {
    private int maxNum;//전체 글 개수.
    private int pageNum;//현재 보이는 페이지 번호.
    private int listCnt;//페이지 당 글 개수.
    private int pageCnt;//보여질 페이지 번호 개수.
    private String listName;//목록 페이지가 여러개인 경우
                            //페이징 처리할 목록 페이지 url.
//페이징용 html 코드를 만드는 메소드
public String makePaging(){
    String page = null;
    StringBuffer sb = new StringBuffer();

    //1. 전체 페이지 개수 구하기(페이지 당 listCnt만큼 출력)
    // 전체 데이터가 4개 : 1 페이지
    // 전체 데이터가 6개 : 2 페이지
    int totalPage = (maxNum % listCnt) > 0 ?
            maxNum / listCnt +1 :
            maxNum / listCnt;

    //2. 현재 페이지가 속해 있는 그룹 번호 구하기
    int curGroup = (pageNum % pageCnt) > 0 ?
            pageNum /pageCnt + 1 :
            pageNum / pageCnt;

    //3. 현재 보이는 페이지 그룹의 시작 번호 구하기
    int start = (curGroup * pageCnt) - (pageCnt - 1);
    //두번째 그룹의 시작번호 = (2 * 5) - (5 - 1) = 6

    //4. 현재 보이는 페이지 그룹의 마지막 번호 구하기
    int end = (curGroup * pageCnt) >= totalPage ?
            totalPage : curGroup * pageCnt;
    //totalPage 9, curGroup * pageCnt 10 -> totalPage가 마지막 번호

    //'이전' 버튼 처리. 시작번호가 1일 때는 버튼 생성 x.
    if(start != 1){
        sb.append("<a class='pno' href='/" + listName
        + "pageNum=" + (start -1) + "'>");
        sb.append("&nbsp;이전&nbsp;</a>");
    }
    //중간 페이지 번호 버튼 처리
    for(int i = start; i <= end; i++){
        if(pageNum != i){//현재 페이지가 아닌 번호
            sb.append("<a class='pno' href='/" + listName +
                    "pageNum=" + i + "'>");
            sb.append("&nbsp;" + i + "&nbsp;</a>");
        } else { //현재 페이지 번호(링크x)
            sb.append("<font class='pno' style='color: red;'>");
            sb.append("&nbsp;" + i + "&nbsp;</font>");
            //<font class='pno' style='color: red;'>&nbsp;1&nbsp;</font>
        }
    }//for end
    //'다음' 버튼 처리.
    if(end != totalPage){
        sb.append("<a class='pno' href='/" + listName
                + "pageNum=" + (end + 1) + "'>");
        sb.append("&nbsp;다음&nbsp;</a>");
        //<a class='pno' href='/list?pageNum=6'>&nbsp;다음&nbsp;</a>
    }

    //StringBuffer에 저장된 내용을 문자열로 변환.
    page = sb.toString();
    return page;
}

💻 SearchDto 소스

@Data
public class SearchDto {
    private String colname;
    private String keyword;
    private int pageNum;//보여질 페이지 번호
    private int listCnt;//페이지 당 출력할 게시글 개수
}

페이징과 검색에 필요한 데이터 타입 모음

💻 BoardService 소스

//Dao 객체
@Autowired
private BoardDao bDao;
@Autowired
private MemberDao mDao;

private ModelAndView mv;
private int lcnt = 5;//목록에 보여질 게시글 개수

Dao @Autowired 어노테이션하고 ModelAndView 사용

private String getPaging(SearchDto sdto) {
    String pageHtml = null;

    //전체 글개수 구하기.
    int maxNum = bDao.selectBoardCnt(sdto);
    //페이지에 보여질 번호 개수
    int pageCnt = 5;
    String listName = null;
    if(sdto.getColname() != null){
        listName = "list?colName" + sdto.getColname() + "&keyword=" + sdto.getKeyword() + "&";
    }//list?colname=b_title&keyword=4&
    else {
        listName = "list?";
    }

    PagingUtil paging = new PagingUtil(maxNum, sdto.getPageNum(), sdto.getListCnt(), pageCnt, listName);
    pageHtml = paging.makePaging();

    return pageHtml;
}

데이터베이스에 저장되어 있는 전체 글 개수를 구하고 게시글 목록 페이지에 보여질 개수를 pageCnt로 지정한다.
pageHtml로 리턴

public ModelAndView getBoardList(SearchDto sdto, HttpSession session){
    log.info("getBoardList()");
    mv = new ModelAndView();

    //SQL 쿼리문의 limit 부분 설정
    int num = sdto.getPageNum();
    //출력할 게시물 수가 설정되지 않으면 기본값(5)로 설정
    if(sdto.getListCnt() == 0){
        sdto.setListCnt(lcnt);
    }
    //페이지번호를 limit 시작 번호로 변경
    sdto.setPageNum((num - 1) * sdto.getListCnt());

    //Dao로 게시글 목록 가져오기
    List<BoardDto> bList = bDao.selectBoardList(sdto);

    mv.addObject("bList", bList);

    //페이징처리
    sdto.setPageNum(num);
    String pageHtml = getPaging(sdto);
    mv.addObject("paging", pageHtml);

    //세션에 필요 정보 저장(pageNum, 검색관련 정보)
    //페이지 번호 저장 - 글쓰기 또는 상세보기 화면에서
    //목록으로 돌아갈 때
    session.setAttribute("pageNum", num);
    //검색 결과 목록으로 돌아갈 때
    if(sdto.getColname() != null){
        //검색 결과 목록
        session.setAttribute("sdto", sdto);
    } else {
        //검색이 아닐 때는 searchDto를 제거
        //세션에 저장한 데이터 삭제 : removeAttribute()
        session.removeAttribute("sdto");
    }

    mv.setViewName("boardList");
    return mv;

}

getPaging 메소드에서 만든 페이징 정보와 Dao의 sql 명령어 결과를 가져오는 메소드

💻 BoardDao 소스(java)

@Mapper
public interface BoardDao {
    //게시글 목록 가져오는 메소드 선언
    List<BoardDto> selectBoardList(SearchDto sdto);
    //게시글 개수 가져오는 메소드 선언
    int selectBoardCnt(SearchDto sdto);
}

BoardDao.java에서 메소드를 먼저 선언한 후 generate로 BoardDao.xml에 쿼리를 만든다.

💻 BoardDao.xml 소스(mybatis)

<mapper namespace="com.raspberry.board.dao.BoardDao">

<select id="selectBoardList" resultType="BoardDto" parameterType="SearchDto">
    select * from blist <if test="colname != null and colname != ''">
    where ${colname} like concat('%', #{keyword}, '%')
</if>
    limit #{pageNum}, #{listCnt}
</select>

<select id="selectBoardCnt" resultType="java.lang.Integer" parameterType="SearchDto">
    select count(*) from blist
    <if test="colname != null and colname != ''">
        where ${colname} like concat('%',#{keyword},'%')
    </if>
</select>

⚡ 글쓰기 버튼 생성

글쓰기 버튼 생성 후 onclick="location.href='/writeForm'"에 대한 처리는 글쓰기 처리를 하면서 작업한다.

💻 boardList.jsp 소스

<%--data-area--%>
<div class="btn-area">
    <div class="paging">${paging}</div>
    <button class="wr-btn" onclick="location.href='/writeForm'">글쓰기</button>
</div> <%--btn-area--%>

⚡ 접속자(회원 정보) 출력

💻 boardList.jsp 소스

로그인 성공 여부나 글 작성 등 동작에 대한 결과를 나타내주는 메시지 출력 명령어와 사용자 정보를 출력하는 함수

<script>
    $(function(){
        //메시지 출력 부분
        let m = "${msg}";
        if(m != ""){
            alert(m);
        }

        //로그인한 회원 정보 및 로그아웃 출력
        let loginName = "${mb.m_name}";
        $("#mname").html(loginName + "님");
        $(".suc").css("display", "block");
        $(".bef").css("display", "none");
    });
</script>

⚡ 제목, 내용 검색

제목 또는 내용으로 게시글을 검색하는 스크립트

💻 boardList.jsp 소스

<script>
    //검색 기능
    $("#search").click(function () {
        let keyword = $("#keyword").val();
        if(keyword == ""){
            alert("검색어를 입력하세요.");
            return;
        }
        let select = $("#sel").val(); //제목 or 내용
        console.log(select, keyword);
        location.href = "/list?colname=" + select + "&keyword=" + keyword + "&pageNum=1";
        // localhost/list?colname=b_title&keyword=4&pageNum=1
    });
</script>

📅 DATE

2023.05.24 작성

profile
사람의 마음에 차 있는 너르고 크고 올바른 기운

0개의 댓글