반응형
게시판 목록 페이지
- 페이지 개념 없이, 전체 게시물을 한꺼번에 출력하는 형태
- 목록 처리 프로세스와 담당 모듈(파일)
1. DTO와 DAO 준비 (오라클 연결을 위한 준비)
1) board 테이블에 데이터를 저장하거나 전송하기 위한 DTO 클래스 생성
- 프로젝트에서 Java Resources 폴더 → src 폴더 → model1폴더 → board 폴더 → BoardDTO.java 파일 생성
// Java Resources/src/model1/board/BoardDTO.java
package model1.board; //1.
public class BoardDTO {
//2.멤버 변수 선언
private String num;
private String title;
private String content;
private String id;
private java.sql.Date postdate;
private String visitcount;
private String name; //3.
//4.게터/세터
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public void getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public java.sql.Date getPostdate() {
return postdate;
}
public void setPostdate(java.sql.Date postdate) {
this.postdate = postdate;
}
public String getVisitcount() {
return visitcount;
}
public void setVisitcount(String visitcount) {
this.visitcount = visitcount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 패키지를 model1.board로 선언
- 멤버 변수를 board 테이블의 컬럼과 동일하게 작성, 자바빈즈 규약에 따라 접근 지정자는 private로 지정, 자료형은 특별한 이유는 없으므로 String으로 선언
- board 테이블에는 작성자의 아이디만 저장되므로, 목록 출력 시 이름 출력 불가→ DTO는 필요한 경우, 다른 테이블의 컬럼을 멤버 변수로 추가할 수 있음
→ 이름(name 컬럼) 출력 시 member 테이블과 조인(Join) 사용 - 멤버 변수를 선언하였다면, 게터와 세터 메서드는 [Source] → [Generate Getters and Setters..] 메뉴로 자동으로 생성할 수 있음
2) 데이터베이스에 접근하여 CRUD 작업을 수행하기 위해 DAO 클래스 생성
- 프로젝트에서 Java Resources 폴더 → src 폴더 → model1폴더 → board 폴더 → BoardDAO.java 파일 생성
// Java Resources/src/model1/board/BoardDAO.java
package model1.board; //1.
import javax.servlet.ServletContext;
import common.JDBConnect;
public class BoardDAO extends JDBConnect { //2.
public BoardDAO(ServletContext application) {
super(application); //3.
}
}
- BoardDTO 클래스와 같은 패키지
- 이전에 생성했던 JDBConnect 클래스를 상속함
- 생성자에서 부모 클래스의 생성자 호출→ 이 생성자는 매개 변수로 받은 application 내장 객체를 통해 web.xml에 정의해둔 오라클 접속 정보를 직접 가져와서 DB에 연결해줌
→ 부모 클래스인 JDBConnect에는 총 3개의 생성자를 정의했는데, 그 중 application 내장 객체를 받는 생성자를 이용함
2. JSP 페이지 구현
1) 게시물 개수 세기
- BoardDAO.java에 selectCount() 메소드 추가 → select count(*) from board; 를 실행한 결과를 반환
// Java Resources/src/model1/board/BoardDAO.java
...생략...
import java.util.Map; //1.
public class BoardDAO extends JDBConnect {
...생성자 생략...
//검색 조건에 맞는 게시물의 개수 반환
public int selectCount(Map<String, Object>map) { //2.
int totalCount = 0; //결과(게시물 수)를 담을 변수
//3.게시물 수를 얻어오는 쿼리문 작성
String query = "select count(*) from board";
if (map.get("searchWord") != null) { //4.
query += " where " + map.get("searchField") + " "
+ " like '%" + map.get("searchWord") + "%'";
}
try { //5.
stmt = con.createStatement(); //6.쿼리문 생성
rs = stmt.executeQuery(query); //7.쿼리 실행
rs.next(); //8.커서를 첫 번째 행으로 이동
totalCount = rs.getInt(1); //9.첫 번째 컬럼 값을 가져옴
}
catch (Exception e) {
System.out.println("게시물 수를 구하는 중 예외 발생");
e.printStackTrace();
}
return totalCount; //10.
}
}
- selectCount() 코드에서 사용하는 외부 클래스를 임포트함 (Ctrl + Shift + O로 자동으로 추가할 수 있음)
- 게시물 개수를 알려주는 메소드 정의 - 매개변수로 받은 Map<String, Object> 컬렉션에는 게시물 검색을 위한 조건(=검색어)이 담겨 있음
- 게시물의 개수를 얻어오는 쿼리문 작성 - SQL이 제공하는 count(*) 한수 사용
- if문을 써서 검색어가 있는 경우(Map 컬렉션에 “searchWord” 키로 저장된 값이 있을 때) where 절 추가
- try/catch문으로 감쌈 - JDBC 프로그래밍은 기본적으로 예외처리를 해야 하기 때문
- 정적 쿼리문 실행을 위해, Statement 객체를 생성
- 6.에서 생성한 객체의 쿼리문 실행 - 결과는 ResultSet 객체로 반환 (ResultSet 객체는 행 단위로 저장되며, 현재 행을 가리키는 커서를 통해 값을 읽어오는 구조)
- next()로 커서를 최초 행으로 이동시킴
- 게시물 개수 추출 - count(*) 함수가 반환하는 값은 정수이므로 getInt() 사용 (숫자 1은 select절에 명시된 컬럼의 인덱스를 의미)
- 추출한 값을 반환 (JSP로 반환)
*만약 사용자가 검색 항목으로 ‘제목’을 선택한 후 “홍길동”이라고 입력하고 [검색하기] 버튼을 누른다면, 쿼리문에는 where절이 추가되어야 함
→ select count(*) from board where title like ‘%홍길동%’; //like를 사용해, title 컬럼에서 검색어로 입력한 단어가 포함된 레코드를 찾게 됨
⇒ 이 쿼리문을 실행한 후 결과를 얻는 코드
stmt = con.createStatement(); //쿼리문을 실행하기 위해 Statement 객체 생성
rs = stmt.executeQuery(query); //select 쿼리문을 실행, 실행 결과는 ResultSet 객체로 반환
rs.next(); //커서를 이동시켜 결괏값이 있는지 확인
totalCount = rs.getInt(1); //ResultSet 객체의 1번 인덱스의 결과를 정수로 추출
2) 게시물 목록 가져오기
- BoardDAO.java에 selectList() 메소드 추가
// Java Resources/src/model1/board/BoardDAO.java
...생략...
public class BoardDAO extends JDBConnect {
...생략...
public int selectList(Map<String, Object>map) {...생략...}
//검색 조건에 맞는 게시물 목록 반환
public List<BoardDTO> selectList(Map<String, Object>map) { //1.
List<BoardDTO> bbs = new Vector<BoardDTO>(); //2.결과(게시물 목록)를 담을 변수
String query = "select * from board"; //3.
if (map.get("searchWord") != null) { //4.
query += " where " + map.get("searchField") + " "
+ " like '%" + map.get("searchWord") + "%' ";
}
query += " order by num desc "; //5.
try {
stmt = con.createStatement(); //6.쿼리문 생성
rs = stmt.executeQuery(query); //7.쿼리실행
while (rs.next()) //8.결과를 순회하며 한 행(게시물 하나)의 내용을 DTO에 저장
//9.(아래 코드 7줄)
BoardDTO dto = new BoardDTO();
dto.setNum(rs.getString("num")); //일련번호
dto.setTitle(rs.getString("title")); //제목
dto.setContent(rs.getString("content")); //내용
dto.setPostdate(rs.getDate("postdate")); //작성일
dto.setId(rs.getString("id")); //작성자 아이디
dto.setVisitcount(rs.getString("visitcount")); //조회수
bbs.add(dto); //10.결과 목록에 저장
}
}
catch (Exception e) {
System.out.println("게시물 조회 중 예외 발생");
e.printStackTrace();
}
return bbs; //11.
}
}
- 연결된 데이터베이스로부터 게시물 목록을 가져오는 메소드 정의 - ‘검색 조건’을 매개변수로 받음
- 테이블에서 레코드를 가져올 때는 항상 List 계열의 컬렉션에 저장함 (여기서는 Vector를 사용했지만, ArrayList/LinkedList 등 List 계열 컬렉션이면 모두 동일하게 사용 가능)
→ List 컬렉션에는 데이터가 순서대로 저장되어 인덱스를 통해 가져올 수 있기 때문 - 목록을 가져오기 위해 쿼리문 작성
- 검색어가 있다면 where절을 추가
- 게시물 정렬을 위한 order by절 - 게시판 목록은 항상 최근 게시물이 상단에 출력되므로, 일련번호 컬럼 num을 내림차순(desc)으로 정렬
- Statement 객체 생성
- 6.에서 생성한 객체로 쿼리문 실행 (결과는 ResultSet 객체에 저장되어 반환됨)
- next() 메소드 - ResultSet에 저장된 행이 있는지 확인 (있다면 true 반환+커서를 첫 번째 행으로 이동시킴)
→ while문과 함께 사용: 더 이상 행이 없을 때까지 중괄호 안의 작업 반복 - while문 안: 하나의 행(게시물 하나)의 내용을 DTO 객체에 저장
- 9.의 DTO를 List 컬렉션에 담음 - while 루프를 끝까지 돌고 나면, 쿼리문으로 받아온 게시물 목록이 모두 List 컬렉션인 bbs에 저장됨
- 쿼리 결과를 모두 담은 List 컬렉션을 JSP로 반환
3) 게시글 목록 출력하기
- 게시글 목록을 화면에 출력해주는 JSP 파일 생성
- 프로젝트의 WebContent 폴더 → Board 폴더에 List.jsp 파일 생성(코드 앞부분)
// WebContent/Board/List.jsp
<%@ page import="java.util.List"%>
<%@ page import="java.util.HashMap"%>
<%@ page import="java.util.Map"%>
<%@ page import="model1.board.BoardDAO"%>
<%@ page import="model1.board.BoardDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//1.DAO를 생성해 DB에 연결
BoardDAO dao = new BoardDAO(application);
//2.사용자가 입력한 검색 조건을 Map에 저장
Map<String, Object> param = new HashMap<String, Object>();
String searchField = request.getParameter("searchField");
String searchWord = request.getParameter("searchWord");
if (searchWord != null) {
param.put("searchField", searchField);
param.put("searchWord", searchWord);
}
int totalCount = dao.selectCount(param); //3.게시물 수 확인
List<BoardDTO> boardLists = dao.selectList(param); //4.게시물 목록 받기
dao.close(); //DB 연결 닫기
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원제 게시판</title>
</head>
<body>
...생략(코드 뒷부분)...
</body>
</html>
- BoardDAO 객체 생성 (DAO 생성 과정에서 DB와의 연결이 완료됨)
- 사용자가 검색폼에서 입력한 내용을 Map 컬렉션에 저장
→ DAO의 메소드를 호출할 때, 이 컬렉션을 매개변수로 전달할 것
*DAO가 제공하는 메소드 호출!
3. 게시물의 개수 (2.에서 만든 검색 조건을 매개변수로 전달)
4. 게시물 목록 (2.에서 만든 검색 조건을 매개변수로 전달)
- List.jsp 파일(코드 뒷부분)
// WebContent/Board/List.jsp
...생략...
<body>
<jsp:include page=".../Common/Link.jsp" /> <!-- 공통 링크 -->
<h2>목록 보기(List)</h2>
<!-- 1. 검색폼 -->
<form method="get"> <!-- 2 -->
<table border="1" width="90%">
<tr>
<td align="center">
<select name="searchField"> <!-- 3 -->
<option value="title">제목</option>
<option value="content">내용</option>
</select>
<input type="text" name="searchWord" />
<input type="submit" value="검색하기" />
</td>
</tr>
</table>
</form>
<!-- 4.게시물 목록 테이블(표) -->
<table border="1" width="90%">
<!-- 5.각 컬럼의 이름 -->
<tr>
<th width="10%">번호</th>
<th width="50%">제목</th>
<th width="15%">작성자</th>
<th width="10%">조회수</th>
<th width="15%">작성일</th>
</tr>
<!-- 6.목록의 내용 -->
<%
if (boardLists.isEmpty()) {
//7.게시물이 하나도 없을 때
%>
<tr>
<td colspan="5" align="center">
등록된 게시물이 없습니다.
</td>
</tr>
<%
}
else {
//8.게시물이 있을 때
int virtualNum = 0; //화면상에서의 게시물 번호
for (BoardDTO dto : boardLists)
{
virtualNum = totalCount--; //전체 게시물 수에서 시작해 1씩 감소
%>
<tr align="center">
<td><%= virtualNum %></td> <!-- 게시물 번호 -->
<td align="left"> <!--제목(+ 하이퍼링크)-->
<a href="View.jsp?num=<%= dto.getNum() %>"><%= dto.getTitle %><a> <!-- 9. -->
</td>
<td align="center"><%= dto.getId() %></td>
<td align="center"><%= dto.getVisitcount() %></td>
<td align="center"><%= dto.getPostdate() %></td>
</tr>
<%
}
}
%>
</table>
<!-- 10.목록 하단의 [글쓰기] 버튼 -->
<table border="1" width="90%">
<tr align="right">
<td><button type="button" onclick="location.href='Write.jsp';">글쓰기</button></td>
</tr>
</table>
</body>
</html>
- 검색폼
- 전송 방식은 get 방식이고, action 속성을 지정하지 않았으므로 submit하면 폼값이 현재 페이지로 전송됨
- 검색 항목(searchField)은 제목과 내용 중 선택할 수 있음 → 검색어가 없을 때와 있을 때를 구분하여 처리
- 검색 목록이 표 형태로 출력됨
- 표의 첫 줄은 각 컬럼의 이름이 옴
- 목록의 내용
- List 컬렉션에 저장된 내용이 하나도 없다면 간략하게 “등록된 게시물이 없습니다.”를 출력
- List 컬렉션에 저장된 게시물이 있다면 for문을 돌면서 하나씩 출력 → 게시물 정보는 모두 DTO 객체로부터 얻음
- 제목에 상세 보기 페이지로 이동하기 위한 링크가 추가됨 → 상세 보기는 일련번호를 통해 게시물을 조회하므로, num을 매개변수로 전달하고 있음
- [글쓰기] 버튼이 화면의 맨 아래에 위치함
4) List.jsp 파일 실행 결과
(1) 게시글을 불러오지 못했을 때
(2) 게시글 하나를 불러왔을 때
(3) 게시글 목록을 모두 불러왔을 때
- 더미 데이터 여러 개 추가 (cmd에서 sqlplus를 입력하고 ‘hello’, 1234로 로그인함)
- 웹 브라우저 새로고침 (F5키 입력) - 추가한 게시물들이 모두 잘 출력됨
(4) 게시물 검색 기능 동작 확인
- 검색폼에서 ‘제목’을 선택하고, ‘겨울’이라고 입력한 후 [검색하기] 클릭
→ List.jsp 파일의 코드에서 요청 객체의 getParameter()로 매개변수를 받아, Map 컬렉션에 저장한 후 DAO로 전달 (조건에 맞는 결과만 가져옴)
→ 검색 항목과 검색어가, 주소표시줄 뒷부분의 쿼리스트링을 통해 전송되게 됨
- 검색폼에서 ‘내용’을 선택하고, ‘여’이라고 입력한 후 [검색하기] 클릭
→ 위와 같은 원리
반응형
'자바(JAVA) > JSP 웹 프로그래밍 공부 (성낙현의 JSP 자바 웹 프로그래밍 참고)' 카테고리의 다른 글
JAVA/JSP 25. 모델1 방식의 회원제 게시판 만들기 - 게시글 상세 보기 (1) | 2024.01.01 |
---|---|
JAVA/JSP 24. 모델1 방식의 회원제 게시판 만들기 - 게시판 게시글 쓰기 (1) | 2023.12.31 |
JAVA/JSP 22. 모델1 방식의 회원제 게시판 만들기 - 프로젝트 구상, 모델1 구조와 모델2 구조(MVC 패턴) (0) | 2023.12.27 |
JAVA/JSP 21. 액션 태그(Action Tag) - <jsp:param> (1) | 2023.12.23 |
JAVA/JSP 20. 액션 태그(Action Tag) - <jsp:forward>, <jsp:useBean>, <jsp:setProperty>, <jsp:getProperty> (0) | 2023.12.07 |