본문 바로가기
Java/Servlet & JSP

JSP) 검색 페이징 처리

by 박채니 2022. 7. 1.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


검색 페이징 처리

 

Content 영역

 

Controller

AdminMemberFinder

@WebServlet("/admin/memberFinder")
public class AdminMemberFinder extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private MemberService memberService = new MemberService();
	
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			// 1. 사용자 입력값 처리
			int cPage = 1;
			int numPerPage = 10;
			try {
				cPage = Integer.parseInt(request.getParameter("cPage"));
			} catch(NumberFormatException e) {}
			
			String searchType = request.getParameter("searchType");
			String searchKeyword = request.getParameter("searchKeyword");
			int start = ((cPage - 1) * numPerPage) + 1;
			int end = cPage * numPerPage;
			Map<String, Object> param = new HashMap<>();
			param.put("searchType", searchType);
			param.put("searchKeyword", searchKeyword);
			param.put("start", start);
			param.put("end", end);
			
			// 2. 업무로직
			// a. content 영역
			List<Member> memberList = memberService.findMemberLike(param);
			
			// 3. view단 처리
			request.setAttribute("memberList", memberList);
			request.getRequestDispatcher("/WEB-INF/views/admin/memberList.jsp").forward(request, response);
			
		} catch(Exception e) {
			e.printStackTrace();
			throw e;
		}
	}
}

cPage는 현재페이지, numPerPage는 보여줄 정보의 수를 의미합니다.

이 값들을 이용하여 between ? and ? 으로 start, end값을 지정해주어 한 페이지에 보여지는 개수를 조정해주었습니다.

 

Service

MemberService

public List<Member> findMemberLike(Map<String, Object> param) {
    Connection conn = getConnection();
    List<Member> memberList = memberDao.findMemberLike(conn, param);
    close(conn);
    return memberList;
}

 

Dao

MemberDao

// findMemberLike = select * from (select row_number() over (order by enroll_date desc) rnum, m.* from member m where # like ?) m where rnum between ? and ?
public List<Member> findMemberLike(Connection conn, Map<String, Object> param) {
    PreparedStatement pstmt = null;
    ResultSet rset = null;
    List<Member> memberList = new ArrayList<>();
    String sql = prop.getProperty("findMemberLike");
    sql = sql.replace("#", (String)param.get("searchType"));

    try {
        pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, "%" + param.get("searchKeyword") + "%");
        pstmt.setInt(2, (int)param.get("start"));
        pstmt.setInt(3, (int)param.get("end"));
        rset = pstmt.executeQuery();
        while(rset.next()) {
            memberList.add(handleMemberResultSet(rset));
        }
    } catch (SQLException e) {
        throw new MemberException("관리자 회원 검색 오류!", e);
    } finally {
        close(rset);
        close(pstmt);
    }
    return memberList;
}

일반 페이징과 달리 검색어가 있는 페이징 처리이기 때문에 지정한 타입과 검색어를 where 조건으로 두어 필터링을 거치도록 하였습니다.

content영역이 지정한 10개씩 보여지는 것을 확인할 수 있으며, 링크가 걸려있지 않기 때문에 '&cPage='로 지정해주어 페이지를 이동해보았습니다.

 


pagebar 영역

 

Controller

AdminMemberFinder

// b. pagebar 영역
int totalContent = memberService.getTotalContentLike(param);
System.out.println("toatlaContent" + totalContent);
String url = request.getRequestURI();	// /mvc2/admin/memberFinder
String pagebar = HelloMvcUtils.getPagebar(cPage, numPerPage, totalContent, url);

// 3. view단 처리
request.setAttribute("memberList", memberList);
request.setAttribute("pagebar", pagebar);
request.getRequestDispatcher("/WEB-INF/views/admin/memberList.jsp").forward(request, response);

 

getPagebar()

public static String getPagebar(int cPage, int numPerPage, int totalContent, String url) {
    StringBuilder pagebar = new StringBuilder();
    url += "?cPage=";
    int totalPage = (int)Math.ceil((double)totalContent / numPerPage);
    int pagebarSize = 5;
    int pagebarStart = ((cPage - 1) / pagebarSize * pagebarSize) + 1;
    int pagebarEnd = pagebarStart + pagebarSize - 1;
    int pageNo = pagebarStart;

    // 이전영역
    if(pageNo == 1) {

    } else {
        pagebar.append("<a href='" + url + (pageNo -1) + "'>이전</a>\n");
    }

    // pageNo영역
    while(pageNo <= pagebarEnd && pageNo <= totalPage) {
        // 현재페이지
        if(pageNo == cPage) {
            pagebar.append("<span class='cPage'>" + pageNo + "</span>\n");
        }
        // 현재페이지가 아닌 경우
        else {
            pagebar.append("<a href='" + url + pageNo + "'>" + pageNo + "</a>\n");
        }
        pageNo++;
    }

    // 다음영역
    if(pageNo > totalPage) {

    } else {
        pagebar.append("<a href='" + url + pageNo + "'>다음</a>\n");
    }
    return pagebar.toString();
}

 

Service

MemberService

public int getTotalContentLike(Map<String, Object> param) {
    Connection conn = getConnection();
    int totalContentLike = memberDao.getTotalContentLike(conn, param);
    close(conn);
    return totalContentLike;
}

 

Dao

MemberDao

// getTotalContentLike = select count(*) from member where # like ?
public int getTotalContentLike(Connection conn, Map<String, Object> param) {
    PreparedStatement pstmt = null;
    ResultSet rset = null;
    String sql = prop.getProperty("getTotalContentLike");
    int totalContentLike = 0;
    sql = sql.replace("#", (String)param.get("searchType"));

    try {
        pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, "%" + (String)param.get("searchKeyword") + "%");
        rset = pstmt.executeQuery();
        if(rset.next()) {
            totalContentLike = rset.getInt(1);
        }
    } catch (SQLException e) {
        throw new MemberException("관리자 검색 회원 수 조회 오류!", e);
    } finally {
        close(rset);
        close(pstmt);
    }
    return totalContentLike;
}

pagebar가 잘 생성되었지만, 페이지 이동을 하면, 위와 같이 검색이 풀려버려 500오류가 발생하는 것을 확인할 수 있습니다.

현재 넘겨준 uri는 /mvc2/admin/memberFinder이기 때문에 해당 uri로 처리하면 풀려버리는 것이죠.

따라서 아래와 같이 수정해줍니다.

String url = request.getRequestURI() + "?searchType=" + searchType + "&searchKeyword=" + searchKeyword;

하지만 이렇게 uri를 변경해도 페이지 이동을 하면 위와 같이 검색이 이루어집니다.

기본적인 path와 queryString의 구분자는 '?'인데, '?cPage=2'가 또 나와버리기 때문에 규격에 맞지 않아 원하는 값들을 못 가져오는 것입니다.

 

getPagebar() 메소드의 url 값을 아래와 같이 수정해줍니다.

url += (url.indexOf("?") < 0 ) ? "?cPage=" : "&cPage=";

넘어온 url에 "?"가 없다면 url 뒤에 "?cPage="를 추가해주고, 있다면 url 뒤에 "&cPage="를 추가해주도록 하였습니다.