[JSP] 글 리스트 Servlet 서블릿/DAO
by mini_min[JSP] 글 리스트 Servlet 서블릿/DAO
✔️ 글 리스트 출력하기 (DB)
: 먼저 숙지할 것!! 글 리스트만 출력하면 <전체 데이터 갯수 구하는 DAO / 리스트 출력 DAO> 이렇게 2가지만 있어도 되지만, 검색 기능이 가능한 게시판을 만들기 때문에 DAO 가 2개 더 필요하다.
- 전체 데이터 갯수 구하는 DAO
- 전체 데이터 리스트 출력 DAO
- 검색된 데이터 갯수 구하는 DAO (NEW)
- 검색된 데이터 리스트 출력 DAO (NEW)
💡 중요!!
데이터 리스트를 출력할 때, 페이징 처리하여 출력할거다.
인수로 건너뛸 수 offset 과 데이터를 가져올 수 size 2가지를 갖는다.
📓 전체 데이터 갯수 구하는 DAO
public int dataCount() {
//전체 데이터 갯수
int result = 0;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql;
try {
sql = " SELECT COUNT(*) FROM bbs ";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
if(rs.next()) {
result = rs.getInt(1);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(rs!=null) {
try {
rs.close();
} catch (Exception e2) {
}
}
if(pstmt!=null) {
try {
pstmt.close();
} catch (Exception e2) {
}
}
}
return result;
}
📓 전체 데이터 리스트 출력 DAO
public List<BoardDTO> listBoard(int offset, int size) {
List<BoardDTO> list = new ArrayList<>();
PreparedStatement pstmt = null;
ResultSet rs = null;
StringBuilder sb = new StringBuilder();
try {
sb.append(" SELECT num, name, subject, hitCount, ");
sb.append(" TO_CHAR(reg_date, 'YYYY-MM-DD') reg_date ");
sb.append(" FROM bbs ");
sb.append(" ORDER BY num DESC ");
sb.append(" OFFSET ? ROWS FETCH FIRST ? ROWS ONLY ");
pstmt = conn.prepareStatement(sb.toString());
pstmt.setInt(1, offset);
pstmt.setInt(2, size);
rs = pstmt.executeQuery();
while(rs.next()) {
BoardDTO dto = new BoardDTO();
dto.setNum(rs.getLong("num"));
dto.setName(rs.getString("name"));
dto.setSubject(rs.getString("subject"));
dto.setHitCount(rs.getInt("hitCount"));
dto.setReg_date(rs.getString("reg_date"));
list.add(dto);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(rs!=null) {
try {
rs.close();
} catch (Exception e2) {
}
}
if(pstmt!=null) {
try {
pstmt.close();
} catch (Exception e2) {
}
}
}
return list;
}
📓 검색된 데이터 갯수 구하는 DAO
: 검색한 데이터를 구하기 위해서는, select 박스의 조건과 검색어가 일치하는 부분을 가져와야한다.
- 1차로 볼 것 : select 박스의 조건 일치 여부
- 2차로 볼 것 : select 박스에 입력한 검색어와 조건 영역에 일치하는 것이 있는지 여부
👩💻 검색 케이스
• 제목, 내용에 일치하는게 있는지(조건: all) 확인하기 (2군데는 예외적인 케이스)
: WHERE INSTR(subject, ?) >= 1 OR INSTR(content, ?) >= 1
• 날짜에 일치하는게 있는지(조건: reg_date) 확인하기
이때, 날짜는 어떻게 입력될지 모르니까, 날짜로 입력되는 keyword 에 . / - 는 공백처리한다.(replaceAll)
: WHERE TO_CHAR(reg_date, 'YYYYMMDD')= ?
• 2군데 검색 / 날짜 검색 말고 다른 검색들은 들어오는 조건과 검색어가 일치하는지 else 구문으로 파악한다.
: WHERE INSTR(condition, ?) >= 1
👩💻 2군데 검색(제목+내용) 부분은 pstmt.set keyword 값이 2개가 필요하며, if 문으로 처리하고 나머지 부분은 pstmt.set 1개만 입력한다.
public int dataCount(String condition, String keyword) {
//검색할 때 데이터 갯수
int result = 0;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql;
try {
sql = " SELECT COUNT(*) cnt FROM bbs ";
if(condition.equals("all")) { //제목, 내용에 일치하는게 있는지 확인
sql += " WHERE INSTR(subject, ?) >= 1 OR INSTR(content, ?) >= 1 ";
}else if(condition.equals("reg_date")) { //날짜는 형식 다 제거하기
keyword = keyword.replaceAll("(\\-|\\/|\\.)", "");
sql += " WHERE TO_CHAR(reg_date, 'YYYYMMDD')= ? ";
}else { //name, subject, content
sql += " WHERE INSTR(" + condition + ", ?) >= 1 ";
}
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, keyword);
if(condition.equals("all")) {
pstmt.setString(2, keyword);
}
rs = pstmt.executeQuery();
if(rs.next()) {
result = rs.getInt("cnt");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(rs!=null) {
try {
rs.close();
} catch (Exception e2) {
}
}
if(pstmt!=null) {
try {
pstmt.close();
} catch (Exception e2) {
}
}
}
return result;
}
📓 검색된 데이터 리스트 출력
: 전체 리스트 출력 메소드와 윗부분은 동일하지만, <키워드, 조건>이 WHERE 절에 추가로 작성되어야한다.
마찬가지로 all 인 경우, reg_date 날짜 검색인 경우를 if 문으로 처리한다.
public List<BoardDTO> listBoard(int offset, int size, String condition, String keyword) {
List<BoardDTO> list = new ArrayList<>();
PreparedStatement pstmt = null;
ResultSet rs = null;
StringBuilder sb = new StringBuilder();
try {
sb.append(" SELECT num, name, subject, hitCount, ");
sb.append(" TO_CHAR(reg_date, 'YYYY-MM-DD') reg_date ");
sb.append(" FROM bbs ");
if(condition.equals("all")) {
sb.append(" WHERE INSTR(subject, ?) >= 1 OR INSTR(content, ?) >= 1");
}else if(condition.equals("reg_date")) {
keyword = keyword.replaceAll("(\\-|\\/|\\.)", "");
sb.append(" WHERE TO_CHAR(reg_date, 'YYYYMMDD') = ? ");
}else {
sb.append(" WHERE INSTR(" + condition + ", ? ) >= 1 ");
}
sb.append(" ORDER BY num DESC ");
sb.append(" OFFSET ? ROWS FETCH FIRST ? ROWS ONLY ");
pstmt = conn.prepareStatement(sb.toString());
if(condition.equals("all")) {
pstmt.setString(1, keyword);
pstmt.setString(2, keyword);
pstmt.setInt(3, offset);
pstmt.setInt(4, size);
}else {
pstmt.setString(1, keyword);
pstmt.setInt(2, offset);
pstmt.setInt(3, size);
}
rs = pstmt.executeQuery();
while(rs.next()) {
BoardDTO dto = new BoardDTO();
dto.setNum(rs.getLong("num"));
dto.setName(rs.getString("name"));
dto.setSubject(rs.getString("subject"));
dto.setHitCount(rs.getInt("hitCount"));
dto.setReg_date(rs.getString("reg_date"));
list.add(dto);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(rs!=null) {
try {
rs.close();
} catch (Exception e2) {
}
}
if(pstmt!=null) {
try {
pstmt.close();
} catch (Exception e2) {
}
}
}
return list;
}
✔️ 글 리스트 출력하기 (서블릿)
: 서블릿 부분은 더 복잡하다....
왜냐하면, 페이징 처리까지 들어가기 때문이다.
• dao 객체 / 페이징 처리해주는 메소드가 있는 MyUtil (이전에 미리 작성) 객체를 만들어준다.
+ 추가로 ContextPath 경로 값도 cp 변수에 저장한다.
✨ cp 변수는 페이징 처리할 때 필요하다. 검색했을 때 페이지에 따라 출력되는 데이터를 봐야하기 때문이다.
📓 필요한 것!!!!
1) 파라미터 구하기 (페이지 번호, 검색 조건, 검색어)
- 페이지 번호 파라미터 값 (전체 페이지 초과하는 것 막기)
- 검색 조건, 검색어(키워드) 파라미터 값
2) 디코딩
- GET 방식일 때, 검색어(키워드) 디코딩
3) 페이징 처리 - 데이터, 페이지 수 구하기
- 전체 데이터 수 (검색 or not)
- 전체 페이지 수 util 의 pageCount 이용
- offset 값 설정
4) 데이터 출력
- list DAO 실행 (검색 or not)
5) 페이징 처리 - query 값 설정
- 검색시 보여지는 url 를 query 값에 저장 (검색 or not)
6) 페이징 처리 - uri 설정
- 검색에 따른 url 를 설정하기 위해서 query 값 이용
query 가 url 가 되는 조건들을 설정하고 util 의 paging 메소드를 실행해서 페이징 처리한다.
이때, listUrl 이 query 가 url 가 되는 조건들이 설정되어서 생성된 url 이 되는 것이다.
7) 포워딩할 JSP 에 지금까지 작성한 모든 속성 전달하기~~
+ 포워딩하기, JSP 에서 사용하기만 하면 끝...ㅠㅠ
📓 아래 코드 순서대로 풀이함
protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//글 리스트
BoardDAO dao = new BoardDAO();
MyUtil_c util = new MyUtil_c();
String cp = req.getContextPath();
try {
//페이지 번호
String page = req.getParameter("page");
int current_page = 1;
//클라이언트가 전송한 페이지 번호가 있으면 그게 현재 페이지
if(page != null) {
current_page = Integer.parseInt(page);
}
//검색 (검색조건과 검색어 파라미터값 가져오기)
//따로 검색한게 없으면 all / 검색어x
String condition = req.getParameter("condition");
String keyword = req.getParameter("keyword");
if(condition == null) {
condition = "all";
keyword = "";
}
//GET 방식이면 디코딩
if(req.getMethod().equalsIgnoreCase("GET")) {
keyword = URLDecoder.decode(keyword, "utf-8");
}
//전체 데이터 개수
int dataCount;
if(keyword.length()==0) { //검색이 아닌경우 모두 출력
dataCount = dao.dataCount();
}else { //검색인 경우
dataCount = dao.dataCount(condition, keyword);
}
//전체 페이지 수?
int size = 10; //데이터 10개씩 출력
int total_page = util.pageCount(dataCount, size);
if(current_page>total_page) {
current_page = total_page;
}
//게시글 가져오기 0 10 20 30 이거!
int offset = (current_page - 1) * size;
if(offset < 0) offset = 0;
//검색어 1)무 2)유
List<BoardDTO> list;
if(keyword.length()==0) {
list = dao.listBoard(offset, size);
}else {
list = dao.listBoard(offset, size, condition, keyword);
}
String query = "";
if(keyword.length()!=0) {
query = "condition =" +condition+ "&keyword="+URLEncoder.encode(keyword, "utf-8");
}
//페이징 처리
String listUrl = cp + "/bbs/list.do";
String articleUrl = cp + "/bbs/article.do?page="+current_page;
if(query.length()!=0) {
listUrl += "?" + query;
articleUrl += "&" + query;
}
String paging = util.paging(current_page, total_page, listUrl);
//포워딩할 JSP 에 전달할 속성(attribute)
//포워딩할 곳 : list.jsp 입니다.
req.setAttribute("list", list);
req.setAttribute("page", current_page);
req.setAttribute("dataCount", dataCount);
req.setAttribute("size", size);
req.setAttribute("total_page", total_page);
req.setAttribute("articleUrl", articleUrl);
req.setAttribute("paging", paging);
req.setAttribute("condition", condition);
req.setAttribute("keyword", keyword);
} catch (Exception e) {
e.printStackTrace();
}
// 포워딩에서의 /는 cp까지
forward(req, resp, "/WEB-INF/views/bbs/list.jsp");
}
'JSP' 카테고리의 다른 글
[JSP] 쿠키 설정 / 가져오기 (Cookie) (0) | 2022.10.10 |
---|---|
[JSP] 글 수정,삭제 Servlet 서블릿/DAO (0) | 2022.10.06 |
[JSP] Servlet 서블릿 작성 + 글쓰기 Servlet 서블릿/DAO (0) | 2022.10.05 |
[JSP] Servlet 서블릿 게시판 만들기 (개요) (0) | 2022.10.05 |
[JSP] JSTL - fmt 태그 / function 태그 (0) | 2022.10.04 |
블로그의 정보
개발자 미니민의 개발로그
mini_min