지난 페이징 처리에 이어서 페이징처리와 함께 쓰이는 검색처리를 작성해봤습니다.
페이징 처리의 마지막 단계는 검색 조건과 검색 키워드를 입력하고, 이에 맞는 검색 데이터를 추출하여 화면에 출력해주는 작업입니다.
검색 처리에서 가장 어려운 부분은 JSP단이 아닌 SQL문의 처리부분 입니다. 이를 위해서 MyBatis의 동적 SQL을 이용하여 처리할 것입니다.
검색에 필요한 데이터, SearchCriteria
사용자가 게시물을 검색 후, 목록 페이지에서 필요한 데이터는 다음과 같습니다.
- 현재 페이지의 번호(page)
- 페이지당 보여지는 데이터의 수(perPageNum)
- 검색의 종류(searchType)
- 검색의 키워드(keyword)
이 4개의 데이터를 전달하기 위한 객체를 만들어 줍니다.
SearchCriteria.java
public class SearchCriteria extends Criteria{ private String searchType; private String keyword; public String getSearchType() { return searchType; } public void setSearchType(String searchType) { this.searchType = searchType; } public String getKeyword() { return keyword; } public void setKeyword(String keyword) { this.keyword = keyword; } @Override public String toString() { return super.toString() + " SearchCriteria " + "[searchType=" + searchType + ", keyword=" + keyword + "]"; } }
검색조건과 검색키워드를 전달하는 객체입니다.
Criteria를 상속받습니다.
검색조건(searchType)과 검색키워드(keyword)에 대한 링크를 처리하기 위한 PageMaker.java
페이징 처리를 하기위한 PageMaker.java 에서의 검색조건과 키워드를 처리하는 메서드입니다.
public String makeSearch(int page) { UriComponents uriComponents = UriComponentsBuilder.newInstance() .queryParam("page", page) .queryParam("perPageNum", cri.getPerPageNum()) .queryParam("searchType", ((SearchCriteria) cri).getSearchType()) .queryParam("keyword", ((SearchCriteria) cri).getKeyword()) .build(); return uriComponents.toUriString(); }
UriComponentBuilder 객체는 url 생성을 도와주어 페이징 처리에 도움을 줍니다.
?page=1&perPageNum=10&searchType=t&keyword=테스트
이런식으로 URL이 생성됩니다.
JSP에서의 페이징 처리
화면단에서 페이징을 담당하는 부분을 pageMaker를 이용하여 처리합니다.
<ul class="pagination"> <c:if test="${pageMaker.prev}"> <li> <a href="list${pageMaker.makeSearch(pageMaker.startPage - 1) }">«</a> </li> </c:if> <c:forEach begin="${pageMaker.startPage }" end="${pageMaker.endPage }" var="idx"> <li <c:out value="${pageMaker.cri.page == idx?'class =active':''}"/>> <a href="list${pageMaker.makeSearch(idx)}">${idx}</a> </li> </c:forEach> <c:if test="${pageMaker.next && pageMaker.endPage > 0}"> <li> <a href="list${pageMaker.makeSearch(pageMaker.endPage +1) }">»</a> </li> </c:if> </ul>
검색처리를 담당하는 부분은 자바스크립트로 작성해줍니다.
<div class='box'> <div class="box-header with-border"> <h3 class="box-title">Board List</h3> </div> <div class='box-body'> <select name="searchType"> <option value="n" <c:out value="${cri.searchType == null?'selected':''}"/>> ---</option> <option value="t" <c:out value="${cri.searchType eq 't'?'selected':''}"/>> 제목</option> <option value="c" <c:out value="${cri.searchType eq 'c'?'selected':''}"/>> 내용</option> <option value="w" <c:out value="${cri.searchType eq 'w'?'selected':''}"/>> 작성자</option> <option value="tc" <c:out value="${cri.searchType eq 'tc'?'selected':''}"/>> 제목 OR 내용</option> <option value="cw" <c:out value="${cri.searchType eq 'cw'?'selected':''}"/>> 내용 OR 작성자</option> <option value="tcw" <c:out value="${cri.searchType eq 'tcw'?'selected':''}"/>> 제목 OR 내용 OR 작성자</option> </select> <input type="text" name='keyword' id="keywordInput" value='${cri.keyword }'> <button id='searchBtn'>Search</button> <button id='newBtn'>New Board</button> </div> </div> <script> $(document).ready(function() { $('#searchBtn').on("click",function(event) { str = "list" + '${pageMaker.makeQuery(1)}' + "&searchType=" + $("select option:selected").val() + "&keyword=" + encodeURIComponent($('#keywordInput').val()); alert(str); self.location = str; }); $('#newBtn').on("click", function(evt) { self.location = "register"; }); }); </script>
makeSearch() 메서드로 페이징링크에 대한 조작을 할수 있습니다.
MyBatis의 동적 SQL
화면단에서의 검색조건에 따라 SQL문이 달라지기 때문에 이를 처리하기 위해 MyBatis의 동적 SQL을 활용할 것입니다.
XML Mapper
<sql id="search"> <if test="searchType != null" > <if test="searchType == 't'.toString()"> and title like CONCAT('%', #{keyword}, '%') </if> <if test="searchType == 'c'.toString()"> and content like CONCAT('%', #{keyword}, '%') </if> <if test="searchType == 'w'.toString()"> and writer like CONCAT('%', #{keyword}, '%') </if> <if test="searchType == 'tc'.toString()"> and ( title like CONCAT('%', #{keyword}, '%') OR content like CONCAT('%', #{keyword}, '%')) </if> <if test="searchType == 'cw'.toString()"> and ( content like CONCAT('%', #{keyword}, '%') OR writer like CONCAT('%', #{keyword}, '%')) </if> <if test="searchType == 'tcw'.toString()"> and ( title like CONCAT('%', #{keyword}, '%') OR content like CONCAT('%', #{keyword}, '%') OR writer like CONCAT('%', #{keyword}, '%')) </if> </if> </sql> <select id="listSearch" resultType="BoardVO"> <![CDATA[ select * from tbl_board where bno > 0 ]]> <include refid="search"></include> <![CDATA[ order by bno desc limit #{pageStart}, #{perPageNum} ]]> </select> <select id="listSearchCount" resultType="int"> <![CDATA[ select count(bno) from tbl_board where bno > 0 ]]> <include refid="search"></include> </select>
MyBatis의 SQL 문을 동일 처리하고 재사용할 수 있는 태그인
<sql>
로 중복된 코드를 줄일 수 있습니다.사용할 땐
<include>
태그로 id값으로 불러오면 됩니다.
<if>
태그로 파라미터값인 검색조건(searchType) 에 따라 실행되는 SQL 구문이 달라지게 했습니다.
화면과 DB의 처리가 끝났으니 컨트롤러와 DAO 를 작성해줍니다
Controller
public class SearchBoardController { private static final Logger logger = LoggerFactory.getLogger(SearchBoardController.class); @Inject private BoardService service; @RequestMapping(value = "/list", method = RequestMethod.GET) public void listPage(@ModelAttribute("cri") SearchCriteria scri, Model model) throws Exception { logger.info(scri.toString()); model.addAttribute("list", service.listSearchCriteria(scri)); PageMaker pageMaker = new PageMaker(); pageMaker.setCri(scri); pageMaker.setTotalCount(service.listSearchCount(scri)); logger.info(pageMaker.makeSearch(scri.getPage())); model.addAttribute("pageMaker", pageMaker); } }
DAO
@Repository public class BoardDAOImpl implements BoardDAO{ @Inject private SqlSession session; @Override public List<BoardVO> listSearch(SearchCriteria cri) throws Exception { return session.selectList(namespace + ".listSearch", cri); } @Override public int listSearchCount(SearchCriteria cri) throws Exception { return session.selectOne(namespace + ".listSearchCount", cri); } }
'스프링' 카테고리의 다른 글
게시글의 페이징 처리 (0) | 2020.06.26 |
---|---|
스프링의 AOP 란? (0) | 2020.06.23 |
스프링의 @ModelAttribute 어노테이션 (0) | 2020.06.15 |
AJAX란? (0) | 2020.06.15 |
인터셉터(Interceptor)란? (0) | 2020.06.13 |