What to do?
정렬 기능
- 제목, 글쓴이, 해쉬태그, 작성일자
검색기능
- 제목, 본문 : 부분검색
- 해쉬태그, 작성일자 : Exact Match
- 작성자 : 인증기능을 완성한 후 추가 수정(TODO)
구현내용
- 정렬기능
- 테이블 헤더에서 Title을 클릭하면, Title 기준으로 정렬 → a 로 시작하는 게시물들부터 출력
- 검색기능
- zoo라는 Title을 가진 게시물들 검색
SearchType
- 검색유형을 enum으로 정의
- 제목(title), 본문(content), 작성자(author), 해쉬태그
- description 필드는 드롭박스에 표시할 내용
@Getter
@AllArgsConstructor
public enum SearchType {
TITLE("Title"), CONTENT("Content"), USERNAME("Author"), HASHTAG("Hashtag");
private String description;
}
Service
ArticleService.java
@Transactional(readOnly = true)
public Page<ArticleDto> searchArticleDtoPage(SearchType searchType, String keyword, Pageable pageable){
if (keyword == null || keyword.isBlank()){
return articleRepository.findAll(pageable).map(ArticleDto::from);
}
return switch (searchType){
case TITLE->articleRepository.findByTitleContaining(keyword, pageable).map(ArticleDto::from);
case USERNAME->articleRepository.findByUserAccount_UsernameContaining(keyword, pageable).map(ArticleDto::from);
case HASHTAG->articleRepository.findByHashtags(keyword, pageable).map(ArticleDto::from);
case CONTENT->articleRepository.findByContentContaining(keyword, pageable).map(ArticleDto::from);
default -> articleRepository.findAll(pageable).map(ArticleDto::from);
};
}
이전에 작성했던 Service의 코드 일부분을 발췌했다.
작성자로 검색했을 경우, UserAccount 필드에서 username을 추출하도록 했는데, 인증기능이 완성되지 않아서 이 부분은 추후 수정될 수 있다.
Controller
ArticleController.java
@GetMapping
public String articles(
@RequestParam(required = false) SearchType searchType,
@RequestParam(required = false) String keyword,
@PageableDefault(size=20, sort = "createdAt", direction = Sort.Direction.DESC)Pageable pageable,
ModelMap map){
Page<ArticleDto> articleDtoPage = articleService.searchArticleDtoPage(searchType, keyword, pageable);
List<Integer> pagination = articleService.getPaginationBarNumbers(pageable.getPageNumber(), articleDtoPage.getTotalPages());
map.addAttribute("articles", articleDtoPage.map(ArticlesResponse::from));
map.addAttribute("pagination", pagination);
map.addAttribute("searchTypes", SearchType.values());
return "article/index";
}
기존 코드에서 map.addAttribute("searchTypes", SearchType.values()) 한줄 추가했다.
HTML
resources/articles/index.html
- 검색창
<form id="search-form" name="searchForm">
<div class="input-group justify-content-between" id="search-bar" name="searchBar">
<!--Select Bar-->
<div class="w-20">
<select class="form-select" id="search-type" name="searchType">
<option value="title" selected>Title</option>
<option value="author">Author</option>
<option value="hashtag">Hashtag</option>
</select>
</div>
<!--Search Input-->
<div class="flex-fill">
<input type="search" class="form-control" placeholder="keyword..." name="keyword" id="keyword"/>
</div>
<!--Submit Button-->
<div class="w-20">
<button id="search-button" type="submit" class="btn btn-primary">
<span>Search</span>
</button>
</div>
</div>
</form>
- 테이블 헤더
<tr id="table-header" name="table-header">
<th scope="col" class="col-6 title"><a>Title</a></th>
<th scope="col" class="hashtags"><a>Hashtag</a></th>
<th scope="col" class="author"><a>Author</a></th>
<th scope="col" class="created-at"><a>Written At</a></th>
</tr>
Thymeleaf Template
resources/articles/index.th.xml
- 검색창
- param - 현재 url에 있는 parameter를 가져옴
<!--Search Bar-->
<attr sel="#search-form">
<attr sel="#keyword" th:value="${param.keyword}"/>
<attr sel="#search-type" th:remove="all-but-first">
<attr sel="option[0]" th:each="searchType:${searchTypes}"
th:value="${searchType.name}"
th:text="${searchType.description}"
th:selected="${param.searchType != null && (param.searchType.toString == searchType.name)}"/>
</attr>
</attr>
- 테이블 헤더
- sort - Pageable을 사용했기 때문에, url parameter에 sort 기준을 전달하면 정렬해서 Page를 넘겨줌
<!--Table Header-->
<attr sel="#table-header" th:object="${articles}">
<attr sel=".title/a" th:text="Title"
th:href="@{/articles(page=${articles.number},
sort='title' + (*{sort.getOrderFor('title')} != null ? (*{sort.getOrderFor('title').direction.name} != 'DESC' ? ',desc' : '') : ''),
searchType=${param.searchType},
searchValue=${param.searchValue})}"/>
<attr sel=".hashtags/a" th:text="Hashtag"
th:href="@{/articles(page=${articles.number},
sort='hashtags' + (*{sort.getOrderFor('hashtags')} != null ? (*{sort.getOrderFor('hashtags').direction.name} != 'DESC' ? ',desc' : '') : ''),
searchType=${param.searchType},
searchValue=${param.searchValue})}"/>
<attr sel=".author/a" th:text="Author"
th:href="@{/articles(page=${articles.number},
sort='createdBy' + (*{sort.getOrderFor('createdBy')} != null ? (*{sort.getOrderFor('createdBy').direction.name} != 'DESC' ? ',desc' : '') : ''),
searchType=${param.searchType},
searchValue=${param.searchValue})}"/>
<attr sel=".created-at/a" th:text="'Written At'"
th:href="@{/articles(page=${articles.number},
sort='createdAt' + (*{sort.getOrderFor('createdAt')} != null ? (*{sort.getOrderFor('createdAt').direction.name} != 'DESC' ? ',desc' : '') : ''),
searchType=${param.searchType},
searchValue=${param.searchValue})}"/>
</attr>
'Java > Spring' 카테고리의 다른 글
[Spring] 게시판 만들기 #11 (0) | 2022.11.24 |
---|---|
[Spring] 게시판 만들기 #10 (0) | 2022.11.23 |
[Spring] 게시판 만들기 #8 (0) | 2022.11.23 |
[Spring] 게시판 만들기 #7 (0) | 2022.11.22 |
[Spring] 게시판 만들기 #6 (0) | 2022.11.21 |