홈페이지 - DBCP
DBCP 는 DataBase Connection Pool의 약자이며,
데이터베이스와 애플리케이션을 효율적으로 연결하는 커넥션 풀 라이브러리다
자바에서 DB에 직접 연결해서 처리하는 경우(=JDBC) 드라이버(Driver)를 로드하고 커넥션(connection) 객체를 받아와야 한다. 그러면 매번 사용자가 요청을 할 때마다 드라이버를 로드하고 커넥션 객체를 생성하여 연결하고 종료하기 때문에 매우 비효율적이다. 이런 문제를 해결하기 위해서 커넥션풀(DBCP)를 사용한다.
1. 먼저 DBCP를 다운받는다. (DBCP – Download Apache Commons DBCP) - commons-dbcp2-2.9.0-bin.zip
2. 다운 받은 후 WEB-INF -> lib에 넣는다.
3. META_INF -> context.xml 를 생성한다.
4. 현재 프로젝트를 해석(실행)할 때 알아야 하는 정보를 설정
DBCP를 수행할 수 있는 자원(도구) 등록
- driverClassName : DBMS에 연결하기 위한 드라이버 클래스 경로
- url : DBMS에 연결하기 위한 경로
- maxTotal : 총 연결(Connection)의 수
- minIdle : 유휴 연결(Connection) 최소 개수
- maxIdle : 유휴 연결(Connection) 최대 개수
- maxWaitMillis : 연결이 모두 사용중일 경우의 대기 시간
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource
name="jdbc/oracle"
type="javax.sql.DataSource"
auth="Container"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@localhost:1521:xe"
username="계정아이디"
password="계정비밀번호"
maxTotal="20"
minIdle="0"
maxIdle="5"
maxWaitMillis="3000"/>
</Context>
5. 연결 생성 : DBCP를 등록 하는 방법 (JdbcUtils에 생성)
- 연결을 직접 수행하는 것이 아니라 연결을 관리하는 업체를 두고 렌탈하는 방식
- 연결을 생성하는 시간이 줄어들어서 전체적인 성능과 안정성이 향상됨
- 설정 파일을 초기에 불러와야 한다.
package pj.beans;
import java.sql.Connection;
import java.sql.DriverManager;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class JdbcUtils {
private static DataSource ds;
static {
//context.xml에 있는 "jdbc/oracle" 이라는 이름을 가진 자원의 참조 정보를 획득
Context ctx;
try {
ctx = new InitialContext();
ds = (DataSource) ctx.lookup("java:comp/env/jdbc/oracle");
}
catch (Exception e) {
System.err.println("DataSource 생성 오류");
e.printStackTrace();
}
}
public static Connection connect() throws Exception{
return ds.getConnection();
}
}
홈페이지 - 페이징
게시판에 하단에 있는 이전페이지, 다음페이지 목록 보기 구현하기
ex) < 1 2 3 4 5 6 7 8 9 10 >
- BoardDao 페이징 목록 기능 만들기
public List<BoardDto> listByRownum(int begin, int end) throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "select * from ("
+ "select rownum rn, TMP.* from ("
+ "select * from board order by board_no desc"
+ ")TMP"
+ ") where rn between ? and ?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, begin);
ps.setInt(2, end);
ResultSet rs = ps.executeQuery();
List<BoardDto> list = new ArrayList<>();
while(rs.next()) {
BoardDto boardDto = new BoardDto();
boardDto.setBoardNo(rs.getInt("board_no"));
boardDto.setBoardWriter(rs.getString("board_writer"));
boardDto.setBoardTitle(rs.getString("board_title"));
boardDto.setBoardContent(rs.getString("board_content"));
boardDto.setBoardTime(rs.getDate("board_time"));
boardDto.setBoardRead(rs.getInt("board_read"));
boardDto.setBoardReply(rs.getInt("board_reply"));
boardDto.setBoardSuperno(rs.getInt("board_superno"));
boardDto.setBoardGroupno(rs.getInt("board_groupno"));
boardDto.setBoardDepth(rs.getInt("board_depth"));
list.add(boardDto);
}
con.close();
return list;
}
- BoardDao 페이징 검색 기능 만들기
public List<BoardDto> searchByRownum(String column, String keyword, int begin, int end) throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "select * from ("
+ "select rownum rn, TMP.* from ("
+ "select * from board where instr(#1, ?) > 0 order by board_no desc"
+ ")TMP"
+ ") where rn between ? and ?";
sql = sql.replace("#1", column);
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, keyword);
ps.setInt(2, begin);
ps.setInt(3, end);
ResultSet rs = ps.executeQuery();
List<BoardDto> list = new ArrayList<>();
while(rs.next()) {
BoardDto boardDto = new BoardDto();
boardDto.setBoardNo(rs.getInt("board_no"));
boardDto.setBoardWriter(rs.getString("board_writer"));
boardDto.setBoardTitle(rs.getString("board_title"));
boardDto.setBoardContent(rs.getString("board_content"));
boardDto.setBoardTime(rs.getDate("board_time"));
boardDto.setBoardRead(rs.getInt("board_read"));
boardDto.setBoardReply(rs.getInt("board_reply"));
boardDto.setBoardSuperno(rs.getInt("board_superno"));
boardDto.setBoardGroupno(rs.getInt("board_groupno"));
boardDto.setBoardDepth(rs.getInt("board_depth"));
list.add(boardDto);
}
con.close();
return list;
}
- BoardDao 페이징에서 마지막 블록을 구하기 위하여 게시글 개수를 구하는 기능 (목록/검색) 만들기
public int count() throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "select count(*) from board";
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
rs.next();
// int count = rs.getInt("count(*)");
int count = rs.getInt(1);
con.close();
return count;
}
- 페이징 모듈 구현
Pagination을 위한 도구 클래스
- 입력(준비물)
- 페이지번호(p)
- 검색분류(column)
- 검색어(keyword)
- 데이터 개수(count)
- 처리
- 출력(결과물)
package home.beans;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
public class Pagination {
//필수 데이터
private int p;
private int count;
//선택 데이터
private String column;
private String keyword;
//생성자를 이용하여 필수 데이터를 설정하도록 구현
public Pagination(HttpServletRequest req) {
try {
this.p = Integer.parseInt(req.getParameter("p"));
if(this.p <= 0) throw new Exception();
}
catch(Exception e) {
this.p = 1;
}
this.column = req.getParameter("column");
this.keyword = req.getParameter("keyword");
}
//계산 메소드
private int pageSize = 10;
private int blockSize = 10;
private int begin, end;
private int startBlock, finishBlock, lastBlock;
private List<BoardDto> list;
public void calculate() throws Exception {
//count 계산
BoardDao boardDao = new BoardDao();
if(isSearch()) {
this.count = boardDao.count(column, keyword);
}
else {
this.count = boardDao.count();
}
//rownum 계산
this.end = this.p * this.pageSize;
this.begin = this.end - (this.pageSize - 1);
//block 계산
this.lastBlock = (this.count - 1) / this.blockSize + 1;
this.startBlock = (this.p - 1) / this.blockSize * this.blockSize + 1;
this.finishBlock = this.startBlock + (this.blockSize - 1);
//list 계산
if(this.isSearch()) {
this.list = boardDao.searchByRownum(column, keyword, begin, end);
}
else {
this.list = boardDao.listByRownum(begin, end);
}
}
public int getPage() {
return p;
}
public int getCount() {
return count;
}
public String getColumn() {
return column;
}
public String getKeyword() {
return keyword;
}
public int getPageSize() {
return pageSize;
}
public int getBlockSize() {
return blockSize;
}
public int getBegin() {
return begin;
}
public int getEnd() {
return end;
}
public int getStartBlock() {
return startBlock;
}
public int getFinishBlock() {
return finishBlock;
}
public int getLastBlock() {
return lastBlock;
}
//추가 : 이전이 존재하나요?
public boolean isPreviousAvailable() {
return this.startBlock > 1;
}
//추가 : 다음이 존재하나요?
public boolean isNextAvailable() {
return this.finishBlock < this.lastBlock;
}
//추가 : 검색모드인가요?
public boolean isSearch() {
return this.column != null && !this.column.equals("") && this.keyword != null && !this.keyword.equals("");
}
//추가 : 진짜 마지막 블록 번호 반환
public int getRealLastBlock() {
return Math.min(this.finishBlock, this.lastBlock);
}
//추가 : 이전을 누르면 나오는 블록 번호
public int getPreviousBlock() {
return this.startBlock - 1;
}
//추가 : 다음을 누르면 나오는 블록 번호
public int getNextBlock() {
return this.finishBlock + 1;
}
//추가 : 컬럼이 특정 값인지 검사
public boolean columnIs(String column) {
return this.column != null && this.column.equals(column);
}
//추가 : null을 제거한 keyword 반환 메소드
public String getKeywordString() {
if(this.keyword == null)
return "";
else
return this.keyword;
}
@Override
public String toString() {
return "Pagination [p=" + p + ", count=" + count + ", column=" + column + ", keyword=" + keyword + ", pageSize="
+ pageSize + ", blockSize=" + blockSize + ", begin=" + begin + ", end=" + end + ", startBlock="
+ startBlock + ", finishBlock=" + finishBlock + ", lastBlock=" + lastBlock + "]";
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public void setBlockSize(int blockSize) {
this.blockSize = blockSize;
}
public List<BoardDto> getList() {
return list;
}
}
- list.jsp 재설정
<%@page import="home.beans.Pagination"%>
<%@page import="home.beans.BoardDto"%>
<%@page import="java.util.List"%>
<%@page import="home.beans.BoardDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//Pagination 모듈을 이용하여 계산을 처리하도록 위임
Pagination pagination = new Pagination(request);
//pagination.setPageSize(15);
//pagination.setBlockSize(5);
pagination.calculate();
%>
<%=pagination.toString()%>
<%-- 출력 --%>
<jsp:include page="/template/header.jsp"></jsp:include>
<h2>회원 게시판</h2>
<h6>타인에 대한 무분별한 비판은 제재 대상입니다</h6>
<a href="write.jsp">글쓰기</a>
<br><br>
<table border="1" width="90%">
<thead>
<tr>
<th>번호</th>
<th width="45%">제목</th>
<th>작성자</th>
<th>작성일</th>
<th>조회수</th>
</tr>
</thead>
<tbody align="center">
<%for(BoardDto boardDto : pagination.getList()){ %>
<tr>
<td><%=boardDto.getBoardNo()%></td>
<td align="left"><a href="detail.jsp?boardNo=<%=boardDto.getBoardNo()%>"><%=boardDto.getBoardTitle()%></a></td>
<td><%=boardDto.getBoardWriter()%></td>
<td><%=boardDto.getBoardTime()%></td>
<td><%=boardDto.getBoardRead()%></td>
</tr>
<%} %>
</tbody>
</table>
<br>
<a href="write.jsp">글쓰기</a>
<!-- 페이지 네비게이터 -->
<br><br>
<%if(pagination.isPreviousAvailable()){ %>
<%if(pagination.isSearch()){ %>
<!-- 검색용 링크 -->
<a href="list.jsp?column=<%=pagination.getColumn()%>&keyword=<%=pagination.getKeyword()%>&p=<%=pagination.getPreviousBlock()%>"><</a>
<%} else { %>
<!-- 목록용 링크 -->
<a href="list.jsp?p=<%=pagination.getPreviousBlock()%>"><</a>
<%} %>
<%} else { %>
<a><</a>
<%} %>
<%for(int i = pagination.getStartBlock(); i <= pagination.getRealLastBlock(); i++){ %>
<%if(pagination.isSearch()){ %>
<!-- 검색용 링크 -->
<a href="list.jsp?column=<%=pagination.getColumn()%>&keyword=<%=pagination.getKeyword()%>&p=<%=i%>"><%=i%></a>
<%}else{ %>
<!-- 목록용 링크 -->
<a href="list.jsp?p=<%=i%>"><%=i%></a>
<%} %>
<%} %>
<%if(pagination.isNextAvailable()){ %>
<%if(pagination.isSearch()){ %>
<!-- 검색용 링크 -->
<a href="list.jsp?column=<%=pagination.getColumn()%>&keyword=<%=pagination.getKeyword()%>&p=<%=pagination.getNextBlock()%>">></a>
<%} else { %>
<!-- 목록용 링크 -->
<a href="list.jsp?p=<%=pagination.getNextBlock()%>">></a>
<%} %>
<%} else {%>
<a>></a>
<%} %>
<br><br>
<!-- 검색창 -->
<form action="list.jsp" method="get">
<select name="column">
<%if(pagination.columnIs("board_title")){ %>
<option value="board_title" selected>제목</option>
<%}else{ %>
<option value="board_title">제목</option>
<%} %>
<%if(pagination.columnIs("board_content")){ %>
<option value="board_content" selected>내용</option>
<%}else{ %>
<option value="board_content">내용</option>
<%} %>
<%if(pagination.columnIs("board_writer")){ %>
<option value="board_writer" selected>작성자</option>
<%}else{ %>
<option value="board_writer">작성자</option>
<%} %>
</select>
<input type="search" name="keyword" placeholder="검색어 입력" required value="<%=pagination.getKeywordString()%>">
<input type="submit" value="검색">
</form>
<jsp:include page="/template/footer.jsp"></jsp:include>
페이징 구현된 모습
'Java 웹 개발' 카테고리의 다른 글
21.10.29 - 웹 개발 입문 55일차 (0) | 2021.10.29 |
---|---|
21.10.28 - 웹 개발 입문 54일차 (0) | 2021.10.28 |
21.10.26 - 웹 개발 입문 52일차 (0) | 2021.10.26 |
21.10.25 - 웹 개발 입문 51일차 (0) | 2021.10.25 |
21.10.22 - 웹 개발 입문 50일차 (0) | 2021.10.23 |