웹 서버 만들기(14) 게시글 검색 기능 및 날짜 지정 검색
게시글 검색 기능
목표
- 제목, 작성자, 내용, 제목+내용 을 유형으로 검색을 시도한다.
- 각 유형을 선택하고 검색을 시도하면 유형에 따라 검색문과 일치하는 결과의 게시글들을 보여준다.
유형 선택창
- 제목, 작성자, 내용, 제목+내용의 유형들로 선택창을 만들어 주었다.
- 기본으로 선택되어 있는 유형은
제목+내용
이다. - 유형을 선택하여 검색을 진행한다.
JSP 코드
notice_board.jsp
- servlet 에서 넘겨받은 optionVal 값을 이용하여 검색한 후에도 선택한 값을 계속 유지하여준다.
- id가
searchForm
인 form이 submit할 때 선택된 유형도 파라미터에 넣어저 서버로 요청을 보내게된다.?option_val=1&page=1&q=
<select name="option_val" form="searchForm">
<option value="1" <% if(optionVal == 1) { %> selected <% } %> >제목+내용</option>
<option value="2" <% if(optionVal == 2) { %> selected <% } %> >작성자</option>
<option value="3" <% if(optionVal == 3) { %> selected <% } %> >제목</option>
<option value="4" <% if(optionVal == 4) { %> selected <% } %> >내용</option>
</select>
<form action="" id="searchForm">
... 생략 ...
-
검색 전
-
검색 후
Servlet 코드 ( Java 코드 )
MainPage.java
- 사용자에게서 받은 option 값이 1~4 범위의 수인지 검사한다.
- option 값과 검색문 값을 이용하여 게시글 수와 게시글 목록을 받아온다.
public class MainPage extends HttpServlet{
private boolean uriSearch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
if(request.getMethod().equals("GET") && uri.equals(noticeBoard)){
// 검색 옵션 option_val
// 1 제목+내용
// 2 작성자
// 3 제목
// 4 내용
var ov = request.getParameter("option_val");
var optionVal = 1;
try {
optionVal = Integer.parseInt(ov);
}catch(Exception e){
e.printStackTrace();
optionVal = 1;
}
if(optionVal > 4 || optionVal < 1){
optionVal = 1;
}
... 생략 ...
// 검색 결과 총 게시글 수 알아보기
int cnt = noticeBoardDAO.getCount(optionVal,q, from, to);
... 생략 ...
// 검색 데이터 가져오기.
var array = noticeBoardDAO.getNoticeList(optionVal,q,start,number, from, to);
...
// 검색 옵션 값 jsp 로 보내기
request.setAttribute("optionVal", optionVal);
...
NoticeBoardDAO.java
- 옵션에 맞는 쿼리문을 만들어 DB 게시글 테이블에서 게시글 목록을 가져온다.
public class NoticeBoardDAO {
// 전체 목록 가져오기 or 검색 목록 가져오기
// 1 <= optionVal <= 4
// 1 제목 + 내용
// 2 작성자
// 3 제목
// 4 내용
// 날짜 범위
public ArrayList<Notice> getNoticeList(int optionVal,String question, int start, int number, long from, long to){
if(optionVal > 4 || optionVal < 1){
optionVal = 1;
}
var arr = new ArrayList<Notice>();
try{
Connection();
var query = new StringBuilder();
query.append("select * from ");
query.append(tableName);
if(optionVal == 1){
query.append(" where (title like '%'||?||'%' or main_text like '%'||?||'%')");
}else if(optionVal == 2){
query.append(" where (username like '%'||?||'%')");
}else if(optionVal == 3){
query.append(" where (title like '%'||?||'%')");
}else if(optionVal == 4){
query.append(" where (main_text like '%'||?||'%')");
}
query.append(" and (gen_time > ? and gen_time < ?)");
query.append(" order by gen_time desc ");
// 0번째 부터 5개의 자료만 출력해라.
query.append("OFFSET ? ROWS FETCH NEXT ? ROWS ONLY");
var pstmt = conn.prepareStatement(query.toString());
if(optionVal == 1){
pstmt.setString(1, question);
pstmt.setString(2, question);
pstmt.setLong(3, from);
pstmt.setLong(4, to);
pstmt.setInt(5, start);
pstmt.setInt(6, number);
}else{
pstmt.setString(1, question);
pstmt.setLong(2, from);
pstmt.setLong(3, to);
pstmt.setInt(4, start);
pstmt.setInt(5, number);
}
- 옵션에 맞는 쿼리문을 만들어 DB 게시글 테이블에 저장된 데이터 수를 알아낸다.
public class NoticeBoardDAO {
// 게시판 목록 수 가져오기
// 1 <= optionVal <= 4
// 1 제목 + 내용
// 2 작성자
// 3 제목
// 4 내용
public int getCount(int optionVal, String question, long from, long to){
if(optionVal > 4 || optionVal < 1){
optionVal = 1;
}
// var query = "select count(sid) from notice_board";
var query = new StringBuilder();
query.append("select count(sid) from ");
query.append(tableName);
if(optionVal == 1){
query.append(" where (title like '%'||?||'%' or main_text like '%'||?||'%')");
}else if(optionVal == 2){
query.append(" where (username like '%'||?||'%')");
}else if(optionVal == 3){
query.append(" where (title like '%'||?||'%')");
}else if(optionVal == 4){
query.append(" where (main_text like '%'||?||'%')");
}
query.append(" and (gen_time > ? and gen_time < ?)");
int re = 0;
try{
Connection();
var pstmt = conn.prepareStatement(query.toString());
pstmt.setString(1, question);
var cnt = 2;
if(optionVal == 1){
pstmt.setString(cnt, question);
cnt+=1;
}
결과
- 작성자 user2 검색결과
- 작성자 mq 검색결과
- 제목+내용 test 검색결과
게시글 날짜 지정 검색
목표
- 날짜 범위를 지정하여 검색을 시도하면 지정된 날짜 사이에 작상된 게시글들을 가지고 온다.
- 날짜 형식(yyyy-MM-dd)이 일치하지 않으면 디펄트로 설정된 값을 날짜로 지정한다.
날짜 선택창
- 사용자는 직접 날짜를 선택할 수 있다.
- 검색을 누르면 GET 요청으로 날짜가 파라미터에 들어가 서버로 전송된다.
?option_val=1&page=1&q=&date_from=2023-05-18&date_to=2023-06-01
JSP 코드
notice_board.jsp
- 타입이 date인 input 태그들을 추가하였다.
- date_from ~ date_to 사이의 결과를 검색할 수 있다.
<form action="" id="searchForm">
... 생략 ...
<input type="date" name="date_from">
<input type="date" name="date_to">
<input type="submit" value="검색">
</form>
Servlet 코드 ( Java 코드 )
MainPage.java
- 사용자로 부터 date_from, date_to 값을 받는다.
- 유효한 날짜인지 확인한다.
- DB 게시글 테이블에는 게시글 생성날짜가 long 타입으로 저장되어 있다. 따라서 사용자에게 받은 날짜들을 long 타입으로 변환한다.
- 검색된 게시글 수, 게시글 목록을 DB 테이블로 부터 가져온다.
public class MainPage extends HttpServlet{
private boolean uriSearch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
if(request.getMethod().equals("GET") && uri.equals(noticeBoard)){
... 생략...
// 검색 날짜 범위
var dateFrom = request.getParameter("date_from");
var dateTo = request.getParameter("date_to");
if(dateFrom == null || dateTo == null){
dateFrom = "";
dateTo = "";
}else if(dateFrom.equals("") || dateTo.equals("")){
dateFrom = "";
dateTo = "";
}
// 날짜 유효한지 검사
var re = "(19|20)\\d{2}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])";
if(!dateFrom.matches(re) || !dateTo.matches(re)){
dateFrom = "1980-01-01";
dateTo = "2999-12-31";
}
var obj = new SimpleDateFormat("yyyy-MM-dd HH:mm");
obj.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));
long from = 0;
long to = 0;
// long type 변환
try{
from = obj.parse(dateFrom+" 00:01").getTime();
to = obj.parse(dateTo+" 23:59").getTime();
}catch(Exception e){
from = 0;
to = Long.MAX_VALUE;
e.printStackTrace();
}
... 생략 ...
// 검색 결과 총 게시글 수 알아보기
int cnt = noticeBoardDAO.getCount(optionVal,q, from, to);
... 생략 ...
// 검색 데이터 가져오기.
var array = noticeBoardDAO.getNoticeList(optionVal,q,start,number, from, to);
... 생략 ...
// date from and date to
request.setAttribute("dateFrom", dateFrom);
request.setAttribute("dateTo", dateTo);
NoticeBoardDAO.java
- 쿼리문에 생성일 범위를 추가하여 특정 범위에 있는 게시글들을 가지고 온다.
public class NoticeBoardDAO {
public ArrayList<Notice> getNoticeList(int optionVal,String question, int start, int number, long from, long to){
... 생략 ...
var arr = new ArrayList<Notice>();
try{
Connection();
var query = new StringBuilder();
query.append("select * from ");
query.append(tableName);
if(optionVal == 1){
query.append(" where (title like '%'||?||'%' or main_text like '%'||?||'%')");
}else if(optionVal == 2){
query.append(" where (username like '%'||?||'%')");
}else if(optionVal == 3){
query.append(" where (title like '%'||?||'%')");
}else if(optionVal == 4){
query.append(" where (main_text like '%'||?||'%')");
}
// 게시글 범위
query.append(" and (gen_time > ? and gen_time < ?)");
query.append(" order by gen_time desc ");
// 0번째 부터 5개의 자료만 출력해라.
query.append("OFFSET ? ROWS FETCH NEXT ? ROWS ONLY");
var pstmt = conn.prepareStatement(query.toString());
if(optionVal == 1){
pstmt.setString(1, question);
pstmt.setString(2, question);
pstmt.setLong(3, from);
pstmt.setLong(4, to);
pstmt.setInt(5, start);
pstmt.setInt(6, number);
}else{
pstmt.setString(1, question);
pstmt.setLong(2, from);
pstmt.setLong(3, to);
pstmt.setInt(4, start);
pstmt.setInt(5, number);
}
- 쿼리문에 생성일 범위를 추가하여 특정 범위에 있는 게시글 수를 구한다.
public class NoticeBoardDAO {
public int getCount(int optionVal, String question, long from, long to){
var query = new StringBuilder();
query.append("select count(sid) from ");
query.append(tableName);
if(optionVal == 1){
query.append(" where (title like '%'||?||'%' or main_text like '%'||?||'%')");
}else if(optionVal == 2){
query.append(" where (username like '%'||?||'%')");
}else if(optionVal == 3){
query.append(" where (title like '%'||?||'%')");
}else if(optionVal == 4){
query.append(" where (main_text like '%'||?||'%')");
}
query.append(" and (gen_time > ? and gen_time < ?)");
int re = 0;
try{
Connection();
var pstmt = conn.prepareStatement(query.toString());
... 생략 ...
pstmt.setLong(cnt, from);
cnt +=1;
pstmt.setLong(cnt, to);
Notice.java
- 테이블에 저장된 생성시간(long)을 사람이 볼 수 있는 날짜로 변경한다.
public class Notice {
public String getGenDate(){
var obj = new SimpleDateFormat("dd MMM yyy HH:mm");
obj.setTimeZone(TimeZone.getTimeZone("Asia/Seoul")); // 타임존 한국
var res = new Date(genTime);
return obj.format(res);
}
결과
- 날짜 범위를 지정하고 검색하면 날짜 사이에 생성된 게시글 목록들을 볼 수 있다.
댓글남기기