아래에 문의 내용이 뜨도록 하자.
주소에 치고 딱 들어갔을 때도 보여져야하며 문의를 남겼을 때에도 문의 내역이 보여야한다. = 어떤 상황이든 보이게 하자.
index.html
에서 Controller가 GET방식 요청이든 POST방식 요청이든 InquiryService통해서 InquiryEntity타입의 제네릭타입의 list를 html으로 넘겨줘야한다. (select)
modelAndView객체의 addObject를 사용 할 것이다.
addObject ( name ,value )
: Controller에서 html로 값을 넘겨줄 때 쓰는 것이다. 자바단에서 만들어준 데이터를 html에서 써야될 때 사용한다.
물론 문의를 남겼을 때에도 있어야하기 때문에 POST에도 추가해야한다.
(문의를 남겼을 때보는 페이지는 POST이다.)
GET / POST가 같은 페이지를 보게되는 이유는 setViewName의 값이 같이 때문에 GET이든 POST이든 같은 페이지를 보는 것이다.
inquirues를 똑같이 넘겨줘야만 문의 내역을 똑같이 띄울 수 있다.
modelAndView.addObject("inquirues", this.inquiryService.get());
index.html에 Thymeleaf를 추가하자.
xmlns:th="http://www.thymeleaf.org
- 얘를 적어주는 것은 thymeleaf 라는 문법을 쓰겠다는 것이다.
xmlns : XML Namespace
태초에 XML이란 파일타입이 있고 이거를 상속 받아서 만든게 HTML이다.
- 여기에 abc를 쓴다면
abc:if="~"
이런형식으로 문법을 작성한다.
-> index.html / index.css 작성
<body> <main id="main"> <h1 class="title"> <i class="icon fa-solid fa-headset"></i> <span class="text">고객문의</span> </h1> <form class="form" method="post"> <label class="input-container writer"> <span class="hint">작성자</span> <input class="input" maxlength="10" name="writer" type="text"> <span class="warning">작성자를 입력해주세요.</span> </label> <label class="input-container content"> <span class="hint">문의 내용</span> <input class="input" maxlength="100" name="content" type="text"> <span class="warning">문의 내용을 입력해주세요.</span> </label> <input class="button" type="submit" value="문의 남기기"> </form> <table class="inquiry-container"> <thead> <tr> <th>순번</th> <th>작성 일시</th> <th>문의 내용</th> <th>작성자</th> </tr> </thead> <tbody> <tr> <td class="no-inquiry" colspan="4">표시할 문의가 없습니다.</td> </tr> <tr> <td>2</td> <td>0000-00-00 00:00:00</td> <td>문의 내용 자리</td> <td>작성자 자리</td> </tr> <tr> <td>1</td> <td>0000-00-00 00:00:00</td> <td>문의 내용 자리</td> <td>작성자 자리</td> </tr> </tbody> <tfoot> <tr> <td class="page-td" colspan="4"> <div class="page-container"> <a class="page selected" href="#">1</a> <!-- selected 클래스 부여 --> <a class="page" href="#">2</a> <a class="page" href="#">3</a> <a class="page" href="#">4</a> <a class="page" href="#">5</a> <a class="page" href="#">6</a> <a class="page" href="#">7</a> <a class="page" href="#">8</a> <a class="page" href="#">9</a> <a class="page" href="#">10</a> </div> </td> </tr> <tr> <td class="search-td" colspan="4"> <form class="search-form" method="get"> <label class="input-container criteria"> <!-- 검색기준 --> <span class="hint" hidden>검색 기준</span> <!-- 장애인을 위한 접근성위해서 --> <select class="input criteria" name="criteria"> <option selected value="byContent">문의 내용</option> <option value="byWriter">작성자</option> </select> </label> <label class="input-container keyword"> <span class="hint" hidden>키워드</span> <input class="input keyword" maxlength="10" name="keyword" placeholder="검색어를 입력해주세요." type="text"> </label> <input class="button search" type="submit" value="검색"> <input class="button reset" disabled type="button" value="검색 초기화"> </form> </td> </tr> </tfoot> </table> </main> </body>
-> 현재 검색을 해보면 주소(경로)에 이렇게 뜬다.
http://localhost:8080/?criteria=byContent&keyword=검색함 <select> <input> name value name value
criteria = byContent
인 이유는 html에서 selected로 지정해둔 기본 값이기 때문이다.
insert해서 이 값들을 RequestParam 어노테이션을 이용해서 받아오자.
Controller에서 넘겨받은 inquirues(제네릭)을 html에서 사용하자.
Thymeleaf을 작성해서 정보를 불러오자.
- 만약 Thymeleaf 작성 시 자동완성이 안된다면
option + enter
로 위에 것을 추가해주자.id="inquiries"
의 Type을 고의로 뒤에 것으로 정해주겠다는 의미이다.
-> 조건에 따라 표시하도록 해보자.
th:if="조건"
- : 해당 조건이 참이 경우에만 해당 태그를 표시한다. 만약 거짓이라면 안보이는게 아니라 HTML 응답 자체에 포함되지 않음. (페이지 소스 보기 하면 없는 것을 의미한다.)
inquiries == null
null이거나inquiries.size() == 0
select 된 게 하나도 없으면 표시할 문의가 없다는 tr이 뜨도록 하자.
- 문의 내용이 있기 때문에 표시할 문의가 없다는 tr은 보이지 않는다.
-> 순번, 작성 일시, 문의 내용, DB에서 작성자를 불러오자.
- 실제로 넘어오는 inquiries가지고 있는 것들을 싹 다 돌려서 한줄 한줄 표시해주면 된다.
th:each
가 있는 요소 자체 하나가 반복이 되어야한다.
- inquiry객체가 가진 값을
<td>??</td>
에 넣으려면th:text
을 이용한다.
페이지 주소 치고 들어갔을 때 경로 →
/
검색을 하고 난 후의 경로 ↓http://localhost:8080/?criteria=byContent&keyword=검색함 <select> <input> name value name value
- 페이지 주소를 치고 들어갔을 때와 검색한 주소랑 동일한 주소를 요청한 것은 맞는데 다른 주소 처럼 보인다.
http://localhost:8080/
?
전까지는 똑같이 찍힌다.
왜냐하면?
뒤로 부터는 변수자리라서 실제 주소는 아니기 때문이다.
따라서 메인 페이지와 검색 후의 페이지 주소는 같은 주소이다.
게시글을 던져주든 검색걸과를 던져주든 Controller getIndex
메서드가 처리해주는게 맞다.
- getIndex 매개변수자리에 @RequestParam 추가
검색 기준 : @RequestParam(name = "criteria", required = false) String criteria, 검색어 : @RequestParam(name = "keyword", required = false) String keyword,
- html의 select태그의 criteria와 input태그의 keyword : name과 짝짝궁이 되어야한다!
System.out.printf("%s : %s\n", criteria, keyword);
localhost:8080/
으로 들어가면null:null
이 뜬다.
- 검색을 해보게 되면 이렇게 뜬다.
이렇게 해서 검색결과를 만들어서 돌려주면 되는데 this.inquiryService.get()
은 전체 검색 결과이다 검색결과에 맞게 뽑아줘야한다.
언제 모든 내역 언제 검색결과가 나와야하는지 언제 검색을 해야하는가?
criteria == null || keyword == null : 전체 내용 criteria != null || keyword != null : 검색 결과 내용
-> 둘 다 null 일 때
List<InquiryEntity> inquiries; if(criteria == null || keyword == null) { inquiries = this.inquiryService.get(); }
당연히 DB를 사용해야하는데 사용하지 않는다는 가정하에 짠 코드.
else { if (criteria.equals("byWriter")) { inquiries = this.inquiryService.get().stream() .filter(x -> x.getWriter().equals(keyword)) .collect(Collectors.toList()); } else { inquiries = this.inquiryService.get().stream() .filter(x -> x.getContent().contains(keyword)) .collect(Collectors.toList()); } }
criteria.equals("byWriter")
: 검색 기준이 작성자일 때- byWriter : 작성자 값이 전달 받은 keyword문자열과 일치한 것.
- byContent : 문의 내용이 키워드가 같은 것이 아니라! 키워드를 포함하고 있을 때.
이렇게 코드를 짰을 때 문제점이 있다.
만약 문의내역이 1만건이 있다고 가정을 했을 때 DB에서 가져온 값들이 this.inquiryService.get()
에 1만건이 다 쌓이게 된다.
검색조건과 키워드에 따라 (if문을 통해) 컷 당하게 되는데 리소스 낭비가 된다.
일반적으로 DB에 저장되는 내용들은 주 저장장치(HDD 하드, SSD)에 저장이 된다.
this.inquiryService.get()
에 저장되는 것은 메모리에 저장이 된다.
가져와놓고 자바에서 필터링을 하면 안되고 선택을 할떄 쿼리에서 필터링을 해야한다.
-> InquiryService
List<InquiryEntity>
타입을 돌려주는searchByWriter
메서드 생성 : 작성자 검색 일 떄
-> 쿼리 추가 InquiryDao
- selectByWriter 추가
"`WHERE` writer = ?\n" preparedStatement.setString(1, writer);
- 1번째
?
에 매개변수로 전달받은 writer라는 문자열을 넣는다.
-> InquiryService
return this.inquiryDao.selectByWriter(writer);
- selectByWriter에서 매개변수 writer 전달인자로 전달해준다.
inquiries = this.inquiryService.searchByWriter(keyword);
- 이렇게 줄일 수 있다.
- keyword를 전달해준다.
[작성자] criteria = byWriter
if (criteria.equals("byWriter"))
를 하면 true가 뜬다.
작성자선택 후 검색을 하면 criteria에 byWriter가 들어오고 if문이 실행된다.
그래서 실제 작성자의 값을 받는 것은 keyword이다.
고객이라고 검색하면 keyword = "고객"
이 된다.
검색되는 값자체는 keyword가 된다.
HomeController가 keyword를 서비스에게 writer로써 넘겨주고 Dao의 selectByWriter 메서드를 호출하면 그 writer를 다시 writer로 넘겨주어서 WHERE문으로 들어가게 된다. 결국 ?자리에는 "고객"이란게 들어가게 된다.
이러한 절차로 검색이 된다.
- 검색결과에 따라 검색이 되는 것을 확인 할 수 있다.