본 포스팅의 예제는 STS 또는 Eclipse를 사용하지 않고 Intellij를 통해 구현하고 있습니다.
그래서 기존의 STS(Spring Tool Studio)에서 생성된 Spring 프로젝트의 스프링 관련 설정 파일명과
프로젝트 구조가 약간 다를 수 있습니다.Intellij 스프링 mvc 프로젝트 생성 포스팅을 참고해주시면 감사하겠습니다.
Spring-MVC 기본 개념 및 테스트 예제 관련 포스팅 링크
순서 | 포스팅 제목 |
1 | Intellij에서 Spring MVC Project 생성하기 |
2 | Spring MVC - MariaDB 연결테스트 |
3 | Spring MVC - Mybatis 설정 및 테스트 |
4 | SpringMVC 구조 |
5 | SpringMVC + Mybatis |
6 | Spring MVC Controller 작성 연습 |
7 | Spring Interceptor |
Spring-MVC 게시판 예제 이전 포스팅 링크
1. 게시글 검색 구현
1.1 게시글 검색 테이블 구현
-- 게시글 검색 카테고리
drop table eden_board_search_category;
create table eden_board_search_category
(
search_category_no number primary key,
search_type varchar2(200) not null unique
);
-- 게시글 검색 카테고리 시퀸스
drop sequence eden_board_search_category_seq;
create sequence eden_board_search_category_seq;
insert into eden_board_search_category (search_category_no, search_type)
values (eden_board_search_category_seq.nextval, '제목');
insert into eden_board_search_category (search_category_no, search_type)
values (eden_board_search_category_seq.nextval, '내용');
insert into eden_board_search_category (search_category_no, search_type)
values (eden_board_search_category_seq.nextval, '작성자');
insert into eden_board_search_category (search_category_no, search_type)
values (eden_board_search_category_seq.nextval, '제목+내용');
insert into eden_board_search_category (search_category_no, search_type)
values (eden_board_search_category_seq.nextval, '내용+작성자');
insert into eden_board_search_category (search_category_no, search_type)
values (eden_board_search_category_seq.nextval, '전체');
게시글 검색시 쿼리 연동을 통한 타입 설정을 구현 하였습니다. search_type 컬럼에 unique 제약 조건이 사용되는 이유는 게시글 검색시 선택되는 타입이 중복되어서는 안되기 떄문입니다. 따라서 unique 제약 조건을 통해서 타입 추가시 중복이 안되도록 구현 할 수 있습니다.
1.2 게시글 검색 클래스 구현
src/기본패키지/board/domain 패키지 안에 SearchCategoryVo 클래스 생성 후 아래와 같이 내용을 작성 해주세요.
public class SearchCategoryVo {
private int search_category_no;
private String search_type;
public SearchCategoryVo() {
super();
}
public SearchCategoryVo(int search_category_no, String search_keyword) {
this.search_category_no = search_category_no;
this.search_type = search_keyword;
}
public int getSearch_category_no() {
return search_category_no;
}
public void setSearch_category_no(int search_category_no) {
this.search_category_no = search_category_no;
}
public String getSearch_type() {
return search_type;
}
public void setSearch_type(String search_type) {
this.search_type = search_type;
}
@Override
public String toString() {
return "SearchCategoryVo{" +
"search_category_no=" + search_category_no +
", search_type='" + search_type + '\'' +
'}';
}
}
1.3 게시글 검색 영속 계층 (Persistence Tire) 구현
src/기본패키지/board/persistence 패키지 안에 BoardDAO 인터페이스와 BoardDAOImpl 클래스 파일에 아래와 같이 내용을 수정 해주세요.
// 게시글 목록
public List<BoardVo> getBoardList(int search_category_no, String keyword);
// 게시글 목록 (카테고리별 정렬)
public List<BoardVo> getBoardByCategoryList(int category_no, int search_category_no, String keyword);
// 게시글 검색 카테고리 목록
public List<SearchCategoryVo> getBoardSearchCategoryList();
// 게시글 목록
@Override
@LogException
public List<BoardVo> getBoardList(int search_category_no, String keyword) {
HashMap<String, Object> param = new HashMap<>();
param.put("search_category_no", search_category_no);
param.put("keyword", keyword);
return sqlSession.selectList(NAMESPACE + ".getBoardList", param);
}
// 게시글 목록 (카테고리별 정렬)
@Override
@LogException
public List<BoardVo> getBoardByCategoryList(int category_no, int search_category_no, String keyword) {
HashMap<String, Object> param = new HashMap<>();
param.put("category_no", category_no);
param.put("search_category_no", search_category_no);
param.put("keyword", keyword);
return sqlSession.selectList(NAMESPACE + ".getBoardByCategoryList", param);
}
// 게시글 검색 카테고리 목록
@Override
@LogException
public List<SearchCategoryVo> getBoardSearchCategoryList() {
return sqlSession.selectList(NAMESPACE + ".getBoardSearchCategoryList");
}
/resources/mappers/board/BoardSQLMapper.xml 파일을 여신 후에 아래와 같이 내용을 수정 해주세요.
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mappers.board.BoardSQLMapper">
<!-- 게시글 목록 -->
<select id="getBoardList" resultType="BoardVo">
select eb.* from eden_board eb, eden_user eu where eb.user_no = eu.user_no
<if test="search_category_no != 0">
<choose>
<!-- 게시글 제목 검색 -->
<when test="search_category_no == 1">
and eb.board_title like '%' || #{keyword} || '%'
</when>
<!-- 게시글 내용 검색 -->
<when test="search_category_no == 2">
and eb.board_content like '%' || #{keyword} || '%'
</when>
<!-- 게시글 작성자 검색 -->
<when test="search_category_no == 3">
and eu.user_nickname like '%' || #{keyword} || '%'
</when>
<!-- 게시글 제목 + 내용 검색 -->
<when test="search_category_no == 4">
and (eb.board_title like '%' || #{keyword} || '%' or eb.board_content like '%' || #{keyword} || '%')
</when>
<!-- 게시글 작성자 + 내용 검색 -->
<when test="search_category_no == 5">
and (eu.user_nickname like '%' || #{keyword} || '%' or eb.board_content like '%' || #{keyword} || '%')
</when>
<!-- 게시글 전체 검색 -->
<when test="search_category_no == 6">
and (eb.board_title like '%' || #{keyword} || '%' or eb.board_content like '%' || #{keyword} || '%'
or eu.user_nickname like '%' || #{keyword} || '%')
</when>
</choose>
</if>
</select>
<!-- 게시글 목록 (카테고리별 정렬) -->
<select id="getBoardByCategoryList" resultType="BoardVo">
select eb.* from eden_board eb, eden_user eu where eb.user_no = eu.user_no and eb.category_no = #{category_no}
<if test="search_category_no != 0">
<choose>
<!-- 게시글 제목 검색 -->
<when test="search_category_no == 1">
and eb.board_title like '%' || #{keyword} || '%'
</when>
<!-- 게시글 내용 검색 -->
<when test="search_category_no == 2">
and eb.board_content like '%' || #{keyword} || '%'
</when>
<!-- 게시글 작성자 검색 -->
<when test="search_category_no == 3">
and eu.user_nickname like '%' || #{keyword} || '%'
</when>
<!-- 게시글 제목 + 내용 검색 -->
<when test="search_category_no == 4">
and (eb.board_title like '%' || #{keyword} || '%' or eb.board_content like '%' || #{keyword} || '%')
</when>
<!-- 게시글 작성자 + 내용 검색 -->
<when test="search_category_no == 5">
and (eu.user_nickname like '%' || #{keyword} || '%' or eb.board_content like '%' || #{keyword} || '%')
</when>
<!-- 게시글 전체 검색 -->
<when test="search_category_no == 6">
and (eb.board_title like '%' || #{keyword} || '%' or eb.board_content like '%' || #{keyword} || '%'
or eu.user_nickname like '%' || #{keyword} || '%')
</when>
</choose>
</if>
</select>
게시글 검색 시 선택한 타입에 따라 Mybatis 동적 쿼리를 활용한 IF 문 사용으로 타입별로 쿼리문이 실행 되도록 작성 되었습니다.
또한 두 가지 이상의 타입으로 검색시에 첫번쨰 조건 이후 or 연산자를 통한 조건을 기입 하였고 추후 오작동을 방지 하기 위해 () 을 통한 우선 순위를 설정 하였습니다.
1.4 게시글 검색 비지니스 계층 (Business Tire) 구현
src/기본패키지/board/service 패키지안에 BoardService 인터페이스와 BoardServiceImpl 클래스 파일 내용을 아래와 같이 수정 해주세요.
// 게시글 목록
public ArrayList<HashMap<String, Object>> getBoardList(int category_no, int search_category_no, String keyword);
// 게시글 검색 카테고리 목록
public List<SearchCategoryVo> getBoardSearchCategoryList();
// 게시글 목록
@Override
@LogException
public ArrayList<HashMap<String, Object>> getBoardList(int category_no, int search_category_no, String keyword) {
ArrayList<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
List<BoardVo> boardVoList;
if (category_no != 0) {
boardVoList = boardDAO.getBoardByCategoryList(category_no, search_category_no, keyword);
} else {
boardVoList = boardDAO.getBoardList(search_category_no, keyword);
}
for (BoardVo boardVo : boardVoList) {
int userNo = boardVo.getUser_no();
UserVo userVo = userDAO.getUserByNo(userNo);
CategoryVo categoryVo = boardDAO.getCategoryByNo(boardVo.getCategory_no());
int totalLikeCount = boardDAO.getTotalLikeCount(boardVo.getBoard_no());
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("boardVo", boardVo);
map.put("userVo", userVo);
map.put("categoryVo", categoryVo);
map.put("totalLikeCount", totalLikeCount);
data.add(map);
}
return data;
}
// 게시글 검색 카테고리 목록
@Override
@LogException
public List<SearchCategoryVo> getBoardSearchCategoryList() {
return boardDAO.getBoardSearchCategoryList();
}
1.5 게시글 검색 컨트롤러 구현
src/기본패키지/board/controller 패키지안에 BoardController 클래스 파일 안에 아래와 같이 내용을 수정 해주세요.
// 게시글 목록 페이지
@PostMapping(value = "postingList")
@LogException
public String postingList(@RequestParam(value = "category_no", defaultValue = "0") int category_no, Model model, @RequestParam(value = "search_category_no", defaultValue = "0") int search_category_no, @RequestParam(value = "keyword", defaultValue = "") String keyword) {
ArrayList<HashMap<String, Object>> dataList = boardService.getBoardList(category_no, search_category_no, keyword);
model.addAttribute("category_no", category_no);
model.addAttribute("dataList", dataList);
model.addAttribute("list", boardService.getBoardSearchCategoryList());
model.addAttribute("search_category_no", search_category_no);
model.addAttribute("keyword", keyword);
return "board/postingList";
}
위 소스코드에서 주목해서 봐야될 부분은
@RequestParam(value = "search_category_no", defaultValue = "0") int search_category_no)
@RequestParam(value = "keyword" defaultValue = "") String keyword)
두개의 부분입니다. 먼저 첫번쨰 부분은 게시글 검색시 옵션 입니다. (어떤 조건으로 검색할건지) 두번째 부분은 검색어 입니다.
사용자가 검색을 하지 않앗을 경우 기본적으로 각 변수값에 0과 "" 의 값이 할당 됩니다.
그 다음으로 주목해서 봐야될 부분은
model.addAttribute("search_category_no", search_category_no);
model.addAttribute("keyword", keyword);
두개의 부분입니다. 각 부분을 설명하자면 검색 이후에 출력된 페이지에서 검색 조건을 유지 하기 위한 부분입니다.
1.6 게시글 검색 뷰 페이지 구현(JSP)
web-inf/views/board 패키지안에 postingList.jsp 파일에 내용을 아래와 같이 전체 수정 해주세요.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../include/head.jsp" %>
<%@ include file="../include/user_menu.jsp" %>
<html>
<body class="hold-transition skin-green-light sidebar-mini" oncopy="return false" oncut="return false"
onpaste="return false">
<div class="wrapper">
<%@ include file="../include/top_menu.jsp" %>
<%@ include file="../include/left_menu.jsp" %>
<div class="content-wrapper">
<section class="content container-fluid">
<form name="detailsForm" role="form" method="post">
<input type="hidden" id="boardNo" name="board_no" value="">
</form>
<form name="writeForm" role="form" method="post">
<input type="hidden" id="category" name="category_no" value="">
</form>
<div class="box-header with-border">
</div>
<div class="box-body">
<table class="table table-bordered">
<thead>
<tr>
<th class="col-xs-1">글 번호</th>
<th class="col-xs-1">카테고리</th>
<th class="col-xs-2">제목</th>
<th class="col-xs-2">작성자</th>
<th class="col-xs-2">작성일</th>
<th class="col-xs-1">조회수</th>
<th class="col-xs-1">좋아요</th>
</tr>
</thead>
<tbody>
<c:forEach items="${dataList }" var="data">
<tr>
<td>${data.boardVo.board_no}</td>
<td>${data.categoryVo.category_name}</td>
<td><a
href="javascript:goPage(${data.boardVo.board_no});">${data.boardVo.board_title }</a>
<span class="badge bg-teal"><i class="fa fa-comment-o"></i> + ${data.totalCommentCount}</span>
</td>
<td>${data.userVo.user_nickname}</td>
<td><fmt:formatDate value="${data.boardVo.board_write_date }"
pattern="yyyy:MM:dd: HH:mm:ss"/></td>
<td><span class="badge bg-red">${data.boardVo.board_view_count}</span></td>
<td><span class="badge bg-teal">${data.totalLikeCount}</span></td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<div class="box-footer">
<form id="searchForm" action="../board/postingList" method="post">
<input type="hidden" name="category_no" value="${category_no}">
<div class="form-group col-sm-2">
<select name="search_category_no" class="form-control" id="categoryList">
<c:forEach items="${list}" var="search">
<c:choose>
<c:when test="${search_category_no == search.search_category_no}">
<option value="${search.search_category_no}" selected>
${search.search_type}
</option>
</c:when>
<c:otherwise>
<option value="${search.search_category_no}">
${search.search_type}
</option>
</c:otherwise>
</c:choose>
</c:forEach>
</select>
</div>
<div class="form-group col-sm-10">
<div class="input-group">
<input type="text" class="form-control" name="keyword" id="keywordInput"
value="${keyword}" placeholder="검색어">
<span class="input-group-btn">
<button type="submit" class="btn btn-primary btn-flat" id="searchBtn">
<i class="fa fa-search"></i> 검색
</button>
</span>
</div>
</div>
</form>
</div>
<div class="box-footer">
<div class="pull-right">
<a class="btn btn-success btn-flat" href="javascript:writePosting(${category_no});">
<i class="fa fa-pencil"></i> 글쓰기
</a>
</div>
</div>
</section>
</div>
<%@ include file="../include/footer.jsp" %>
</div>
<%@ include file="../include/plugin_js.jsp" %>
</body>
</html>
1.7 게시글 검색 화면 확인
'스프링 프레임워크 > 스프링 MVC' 카테고리의 다른 글
# Spring MVC 게시판 예제 21 : 게시글 페이징 (0) | 2023.03.24 |
---|---|
# Spring MVC 게시판 예제 19 : 게시글 북마크 (2) | 2023.03.19 |
# Spring MVC 게시판 예제 18 : 게시글 좋아요 (0) | 2023.03.15 |
# Spring MVC 게시판 예제 17 : 게시글 수정 및 삭제 (0) | 2023.03.13 |
# Spring MVC 게시판 예제 16 : 게시글 상세보기 (0) | 2023.03.10 |
댓글