게시판 검색기능 구현

Jang Seok Woo·2020년 9월 8일
2

웹개발

목록 보기
2/31

게시판의 검색 기능을 구현해 보도록 하자

개발환경 : Oracle11g, Eclipse

먼저 기존의 게시판 bbs.jsp에 검색 입력을 받는 입력창과 검색 버튼을 추가한다.

<form method="post" action="searchedBbs.jsp">
<div class="col-lg-4">
	<input type="text" class="form-control pull-right" placeholder="Search" name="searchWord" />
	</div>
	<button class="btn btn-primary" type="submit" >
	<span class="glyphicon glyphicon-search">
	</span>
	</button>
</form>

Post 방식으로 검색어를 입력받아 name = searchWord 로 변수명을 정해주고 type=submit 버튼을 이용해 searchedBbs.jsp로 넘긴다.

SearchedBbs.jsp는 bbs.jsp를 기반으로 만든 게시판 jsp파일이다.

searchedBbs.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="java.io.PrintWriter"%>
<%@ page import="bbs.BbsDAO"%>
<%@ page import="bbs.Bbs"%>
<%@ page import="java.util.ArrayList"%>
<% request.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width" initial-scale="1">
<link rel="stylesheet" href="css/bootstrap.css">
<title>JSP JSW 게시판 웹사이트</title>
<style type="text/css">
a, a:hover {
	color: #000000;
	text-decoration: none;
}
</style>
</head>
<body>
	<%
		String userID = null;
		if(session.getAttribute("userID") != null) {
			userID = (String) session.getAttribute("userID");
		}
		int pageNumber =1;
		if(request.getParameter("pageNumber")!=null){
			pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
			System.out.println("pageNumber="+pageNumber);
		}
		String searchWord = null;
		if(request.getParameter("searchWord")!=null){
			searchWord = (String) request.getParameter("searchWord");
			System.out.println("searchword from parameter is :" + searchWord);
		}
		if(session.getAttribute("searchWord")!=null){
			searchWord = (String) session.getAttribute("searchWord");
			System.out.println("searchword from session is :" + searchWord);
		}
	%>
	<nav class="navbar navbar-default">
		<div class="navbar-header">
			<button type="button" class="navbar-toggle collapsed"
				data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"
				aria-expanded="false">
				<span class="icon-bar"></span> <span class="icon-bar"></span> <span
					class="icon-bar"></span>
			</button>
			<a class="navbar-brand" href="main.jsp">JSP 게시판 메인</a>
		</div>
		<div class="collapse navbar-collapse"
			id="bs-example-navbar-collapse-1">
			<ui class="nav navbar-nav">
			<li><a href="main.jsp">메인</a></li>
			<li class="active"><a href="bbs.jsp">게시판</a></li>
			</ui>
			<%
			if( userID ==null ) {
		%>
			<ui class="nav navbar-nav navbar-right">
			<li class="dropdown"><a href="#" class="dropdown-toggle"
				data-toggle="dropdown" role="button" aria-haspopup="true"
				aria-expanded="false">접속하기<span class="caret"></</span></a>
				<ul class="dropdown-menu">
					<li class="active"><a href="login.jsp">로그인</a></li>
					<li><a href="join.jsp">회원가입</a></li>
				</ul></li>
			</ui>
			<%	
			} else {
		%>
			<ui class="nav navbar-nav navbar-right">
			<li class="dropdown"><a href="#" class="dropdown-toggle"
				data-toggle="dropdown" role="button" aria-haspopup="true"
				aria-expanded="false">회원관리<span class="caret"></</span></a>
				<ul class="dropdown-menu">
					<li><a href="logoutAction.jsp">로그아웃</a></li>
				</ul></li>
			</ui>
			<% 
			}
		%>
		</div>
	</nav>
	<div class="container">
		<div class="row">
			<table class="table table-striped"
				style="text-align: center; border: 1px solid #dddddd">
				<thead>
					<div>
						<div class=" col-lg-4">
							<input type="text" class="form-control pull-right" placeholder="Search" id="txtSearch" />
						</div>
						<button class="btn btn-primary" type="submit">
							<span class="glyphicon glyphicon-search"></span>
							<a href="searchedBbs.jsp"></a>
						</button>
					</div>
					<tr>
						<th style="background-color: #eeeeee; text-align: center;">번호</th>
						<th style="background-color: #eeeeee; text-align: center;">제목</th>
						<th style="background-color: #eeeeee; text-align: center;">작성자</th>
						<th style="background-color: #eeeeee; text-align: center;">작성일</th>
					</tr>
				</thead>
				<tbody>
					<%
						BbsDAO bbsDAO = new BbsDAO();
						//System.out.println("here before getlist");
						ArrayList<Bbs> list = bbsDAO.getSearchedList(pageNumber,searchWord);
						//System.out.println("here after getlist" + list.get(0).getBbsDate().substring(0,11));
						for(int i=0;i<list.size();i++){
					%>
					<tr>
						<td><%=list.get(i).getBbsID()%></td>
						<td><a href="view.jsp?bbsID=<%=list.get(i).getBbsID()%>"><%=list.get(i).getBbsTitle().replaceAll(" ","&nbsp;").replaceAll("<","&lt;").replaceAll("<","&gt;").replaceAll("\n","<br>")%></a></td>
						<td><%= list.get(i).getUserID()%></td>
						<td><%=	list.get(i).getBbsDate().substring(0, 11) + list.get(i).getBbsDate().substring(11,13) + "시" + list.get(i).getBbsDate().substring(14,16) + "분"%></td>
					</tr>
					<% 
					
						}
					
					%>

				</tbody>
			</table>

				<tr>
				
					<td class = "pull-left">
					
					
					
						<% 
				if(pageNumber != 1) {
					session.setAttribute("searchWord",searchWord);
			%> <a href="searchedBbs.jsp?pageNumber=<%=pageNumber-1%>"
						class="btn btn-success btn-arrow-left">이전</a> <%		
				} if(bbsDAO.searchedNextPage(pageNumber,searchWord)) {
					session.setAttribute("searchWord",searchWord);
			%> <a href="searchedBbs.jsp?pageNumber=<%=pageNumber+1%>"
						class="btn btn-success btn-arrow-right">다음</a> <% 
				}
			%>
					</td>
					
					<td><a href="write.jsp" class="btn btn-primary pull-right">글쓰기</a>
					</td>
				</tr>

			
		</div>
	</div>
	<script src="http://code.jquery.com/jquery-3.1.1.min.js"></script>
	<script src="js/bootstrap.js"></script>
</body>
</html>

검색어를 처음에 post 방식으로 넘겨 getParameter함수를 이용해 가져오고
아래에도 getAttribute가 있는 이유는 나중에 설명하도록 한다.

String searchWord = null;
		if(request.getParameter("searchWord")!=null){
			searchWord = (String) request.getParameter("searchWord");
			System.out.println("searchword from parameter is :" + searchWord);
		}
		if(session.getAttribute("searchWord")!=null){
			searchWord = (String) session.getAttribute("searchWord");
			System.out.println("searchword from session is :" + searchWord);
		}

Print 함수는 중간중간 코딩하면서 변수가 잘 넘어오는지 확인하기 위함이다.

이제 검색어를 기반으로 데이터 리스트를 불러 올 함수를 만들어야한다.
우선 DAO와 연동시키는 부분에서 getList(pageNumber) 함수를 getSearchedList(pageNumber, searchWord)로 바꾸어준다.

파라미터 중 pageNumber는 페이지당 10개의 데이터를 불러오는데 사용할 것이고, searchWord는 검색어 문자열을 Query에 이용하기 위함이다.

<%
	BbsDAO bbsDAO = new BbsDAO();
	//System.out.println("here before getlist");
	ArrayList<Bbs> list = bbsDAO.getSearchedList(pageNumber,searchWord);
	//System.out.println("here after getlist" + list.get(0).getBbsDate().substring(0,11));
	for(int i=0;i<list.size();i++){
%>

다음은 bbsDAO.java 파일에 검색기능을 가진 함수를 만들어 준다.

public ArrayList<Bbs> getSearchedList(int pageNumber, String searchWord){
		
		int no2=0;
		
		if(getNext()>pageNumber*10) {
			no2 = pageNumber*10;
		} else {
		  no2 = getNext();
		}
		
		int no1=(pageNumber -1)*10+1;
		
		String SQL = "select * from (select row_number() over (order by bbsDate desc) NUM, A.* from bbs A	where bbsavailable=1 and bbstitle like'%"
				+ searchWord
				+ "%' order by bbsDate desc) where NUM between "
				+ no1
				+ " and "
				+ no2;
				
		ArrayList<Bbs> list = new ArrayList<Bbs>();
		try {

			System.out.println("sql statement : "+SQL);
			Statement stmt = conn.createStatement();
			rs = stmt.executeQuery(SQL);
			
			while(rs.next()) {
				Bbs bbs = new Bbs();
				bbs.setBbsID(rs.getInt(2));
				bbs.setBbsTitle(rs.getString(3));
				bbs.setUserID(rs.getString(4));
				bbs.setBbsDate(rs.getString(5));
				bbs.setBbsContent(rs.getString(6));
				bbs.setBbsAvailable(rs.getInt(7));
				list.add(bbs);
			}
		}catch(Exception e) {
			System.out.println("Exception:search");
			e.printStackTrace();
		}
		System.out.println(" resultset_return list:search");
		return list;
	}

다른 부분은 앞서 게시판을 만들 때 사용한 getList함수와 동일하고 다른 부분인 쿼리를 보면,

"select * from (select row_number() over (order by bbsDate desc) NUM, A.* from bbs A	where bbsavailable=1 and bbstitle like'%"
				+ searchWord
				+ "%' order by bbsDate desc) where NUM between "
				+ no1
				+ " and "
				+ no2;

터미널을 옆에 켜두고 원하는 쿼리를 완성시키는게 좋다.

예시로 asdf 더미 데이터를 넣어둔다.

터미널에 쿼리를 열심히 구글링하며 만들어 보고 날려본다.

select * from (select row_number() over (order by bbsDate desc) NUM, A.* from bbs A	where bbsavailable=1 and bbstitle like'%asdf%' order by bbsDate desc) where NUM between 11 and 20;

다음과 같은 쿼리가 완성되었다. 다른 부분은 게시판 불러오는 쿼리와 동일하고 다른 부분을 살펴보자.

Where bbsAvailable=1 and bbstitle like ‘%asdf%’

bbsAvailable 변수를 이용해 글이 삭제되지 않은 글만 불러오고, 글 제목(bbsTitle) 중 asdf라는 문자열을 포함한 데이터를 가져온다.

데이터를 불러올 시 getNext() 함수도 bbsID를 기준으로 불러오다보니 32개의 데이터 중 4개를 지웠을 시 bbsID는 32를 가리키고 있기 때문에 4페이지까지 넘어가는 걸 확인했다.
Row_number() 를 이용해 num을 부여하고 해당하는 데이터의 개수만 새로 불러오도록 getNext() 쿼리를 수정했다.

public int getNext() {
		String SQL = "select NUM from (select row_number() over (order by bbsDate desc) NUM, A.* from bbs A where bbsavailable=1 order by NUM desc)";
		try {
			//PreparedStatement pstmt = conn.prepareStatement(SQL);
			//rs = pstmt.executeQuery();
			Statement stmt = conn.createStatement();
			rs = stmt.executeQuery(SQL);
			if(rs.next()) {
				return rs.getInt(1)+1;
			}
			return 1;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

마지막으로 다음 이전 페이지 넘기기 버튼 부분을 수정한다.

<% 
if(pageNumber != 1) {
		session.setAttribute("searchWord",searchWord);
%> <a href="searchedBbs.jsp?pageNumber=<%=pageNumber-1%>"
	class="btn btn-success btn-arrow-left">이전</a> <%		
		} if(bbsDAO.searchedNextPage(pageNumber,searchWord)) {
					session.setAttribute("searchWord",searchWord);
%> <a href="searchedBbs.jsp?pageNumber=<%=pageNumber+1%>"
	class="btn btn-success btn-arrow-right">다음</a> <% 
		}%>

각 페이지가 넘어갈 시에 searchWord를 session에 넣어줌으로써 페이지간 변수를 주고 받을 수 있도록 한다.

if(session.getAttribute("searchWord")!=null){
			searchWord = (String) session.getAttribute("searchWord");
			System.out.println("searchword from session is :" + searchWord);
		}

그래서 위에 getAttribute를 추가로 작성했다.

검색된 새로운 데이터를 기반으로 다음 버튼을 생성해야 하기에 searchedNextPage 함수를 새로 만들어준다.

public boolean searchedNextPage(int pageNumber,String searchWord) {
		
		try {
			if(getSearchedNext(searchWord)>(pageNumber)*10) {
				return true;
			} else {
				return false;
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
		return false;
	}

여기서 getNext 함수는 검색된 데이터를 이용하는 함수가 아니라 전체 데이터를 대상으로 하는 함수이므로 getSearchedNext 함수를 새로 만들어준다.

	public int getSearchedNext(String searchWord) {
		String SQL = "select NUM from (select row_number() over (order by bbsDate desc) NUM, A.* from bbs A where bbsavailable=1 and bbsTitle like '%"+searchWord+"%' order by NUM desc)";
		try {
			//PreparedStatement pstmt = conn.prepareStatement(SQL);
			//rs = pstmt.executeQuery();
			System.out.println("query for searched NEXT : "+SQL);
			Statement stmt = conn.createStatement();
			rs = stmt.executeQuery(SQL);
			if(rs.next()) {
				return rs.getInt(1)+1;
			}
			return 1;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

다른 부분은 getNext와 동일하고 변경된 쿼리를 한번 보자

우리가 원하는 쿼리는 먼저 검색어를 포함하고있는 데이터를 불러오는 것이다.

Select * from bbs where bbsavailable=1 and bbstitle like ‘%검색어%’;

여기에 row_number()를 이용해 숫자를 매겨 불러온 데이터의 개수를 리턴하는데 도움을 주도록 한다.

select count(*) from bbs where bbsavailable=1;

이 쿼리를 이용해도 된다는 사실을 뒤늦게 알아버렸다. 효율성을 위해선 위 쿼리를 이용하는게 좋아보인다. 차후에 시간이 나면 수정해보도록 하겠다.

무튼 그래서 row_number()를 이용해 데이터에 숫자를 매겨 리턴시켜 보았다.

select NUM from (select row_number() over (order by bbsDate desc) NUM, A.* from bbs A where bbsavailable=1 and bbsTitle like '%"+searchWord+"%' order by NUM desc)

잘 넘어온다.

성공!

profile
https://github.com/jsw4215

0개의 댓글