본문 바로가기

Spring

ch4 08. 게시판 검색 기능 추가하기(2)

- BoardServiceImpl클래스에 searchsSelectPage를 호출하는 메서드 생성  

BoardServiceImpl
BoardService
BoardController

[PageHandler] 수정

package com.fastcampus.ch4.domain;

public class PageHandler {
//    private int page; // 현재 페이지
//    private int pageSize; // 한 페이지의 크기
//    private String option;
//    private String keyword;
    private SearchCondition sc;

    private int totalCnt; // 총 게시물 갯수
    private int naviSize = 10; // 페이지 내비게이션의 크기
    private int totalPage; // 전체 페이지의 갯수
    private int beginPage; // 내비게이션의 첫번째 페이지
    private int endPage; // 내비게이션의 마지막 페이지
    private boolean showPrev; // 이전 페이지로 이동하는 링크를 보여줄 것인지의 여부
    private boolean showNext; // 다음 페이지로 이동하는 링크를 보여줄 것인지의 여부

    public PageHandler(int totalCnt, SearchCondition sc) {
        this.totalCnt = totalCnt;
        this.sc = sc;

        doPaging(totalCnt, sc);
    }


    public void doPaging(int totalCnt, SearchCondition sc) {
        this.totalCnt = totalCnt;


        totalPage = (int)Math.ceil(totalCnt / (double)sc.getPageSize()); // 남으면 페이지가 하나 더 필요해서 올림
        beginPage = (sc.getPage()-1) / naviSize * naviSize + 1;
        endPage = Math.min(beginPage + naviSize -1 , totalPage); // totalPage보다 작을 수 있으니 Math.min 사용해서 둘 중 작은 수 사용
        showPrev = beginPage != 1;
        showNext = endPage != totalPage;
    }

    public SearchCondition getSc() {
        return sc;
    }

    public void setSc(SearchCondition sc) {
        this.sc = sc;
    }

    public int getTotalCnt() {
        return totalCnt;
    }

    public void setTotalCnt(int totalCnt) {
        this.totalCnt = totalCnt;
    }

    public int getNaviSize() {
        return naviSize;
    }

    public void setNaviSize(int naviSize) {
        this.naviSize = naviSize;
    }

    public int getTotalPage() {
        return totalPage;
    }

    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }

    public int getBeginPage() {
        return beginPage;
    }

    public void setBeginPage(int beginPage) {
        this.beginPage = beginPage;
    }

    public int getEndPage() {
        return endPage;
    }

    public void setEndPage(int endPage) {
        this.endPage = endPage;
    }

    public boolean isShowPrev() {
        return showPrev;
    }

    public void setShowPrev(boolean showPrev) {
        this.showPrev = showPrev;
    }

    public boolean isShowNext() {
        return showNext;
    }

    public void setShowNext(boolean showNext) {
        this.showNext = showNext;
    }

    // 페이지 내비게이션을 print하는 메서드
    void print() {
        System.out.println("page = " + sc.getPage());
        System.out.print(showPrev ? "[PREV] " : ""); // 참이면 이전페이지 가는 링크

        for(int i = beginPage; i <= endPage; i++) {
            System.out.print(i + " ");
        }
        System.out.println(showPrev ? "[Next] " : "");
    }

    @Override
    public String toString() {
        return "PageHandler{" +
                "sc=" + sc +
                ", totalCnt=" + totalCnt +
                ", naviSize=" + naviSize +
                ", totalPage=" + totalPage +
                ", beginPage=" + beginPage +
                ", endPage=" + endPage +
                ", showPrev=" + showPrev +
                ", showNext=" + showNext +
                '}';
    }
}

 

[SearchCondition]

package com.fastcampus.ch4.domain;

import org.springframework.web.util.UriComponentsBuilder;

public class SearchCondition {
    private Integer page = 1;
    private Integer pageSize = 10;
    private Integer offset = 0;
    private String keyword = "";
    private String option = "";

    public SearchCondition(){}
    public SearchCondition(Integer page, Integer pageSize, String keyword, String option) {
        this.page = page;
        this.pageSize = pageSize;
        this.keyword = keyword;
        this.option = option;
    }

    // 매개변수 page로 지정된 페이지로 셋팅되도록 함.
    public String getQueryString(Integer page) {
        // ?page=1&pageSize=10&option=T&keyword="title"
        return UriComponentsBuilder.newInstance()
                .queryParam("page",page)
                .queryParam("pageSize", pageSize)
                .queryParam("option", option)
                .queryParam("keyword", keyword)
                .build().toString();

    }

    // 페이지를 지정해주지 않을 경우 searchCondition의 getPage()사용
    public String getQueryString() {
        return getQueryString(page);
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public Integer getOffset() {
        return offset;
    }

    public void setOffset(Integer offset) {
        this.offset = offset;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public String getOption() {
        return option;
    }

    public void setOption(String option) {
        this.option = option;
    }

    @Override
    public String toString() {
        return "SearchCondition{" +
                "page=" + page +
                ", pageSize=" + pageSize +
                ", offset=" + offset +
                ", keyword='" + keyword + '\'' +
                ", option='" + option + '\'' +
                '}';
    }
}

 

이후 서버를 실행하면 다음과 같은 게시물 목록을 볼 수 있다. 

 

 

검색 기능도 잘 동작하는 걸 확인할 수 있다. 

offset값을 읽을 때 page, pageSize 두 개의 값을 이용해서 계산하도록 해준다. 

SearchCondition의 offset 변수를 주석처리한 후 setOffset은 삭제하고 getOffset을 다음과 같이 수정한다. 

 

- boardMapper에서 쿼리 작성 - 동적 sql로 만들음<choose>

테스트를 돌려보면 잘 통과하는걸 확인할 수 있다. 

 

 

- boardMapper 별도 sql문으로 구성

수정 후 테스트를 돌려도 통과해야한다. (통과!)

 

 

- 스크립트 코드

글쓰기에 들어가서 제목과 내용에 스크립드 코드를 넣은 다음 등록을 누르게 되면 

해당 알림과 함께 게시물이 생성된다. 이렇게 스크립트 내용이 들어가게 하면 안되며, 보여줘서도 안된다. 

여기 악의적인 공격을 막아주기 위해 out 태그를 사용한다. 

board.jsp

이렇게 out 태그로 감싸면, 안에 있는 내용에 태그가 있으면 그걸 자동으로 변환해준다. 

board, boardList의 title과 board의 content를 해당 태그로 감싸준다. 

이후 보이는건 잘 보이지만 텍스트로 인식되어 실행되지 않아 해커들의 악의적인 공격으로부터 방어할 수 있다.