다음은 추천할 수 있는 추가기능이다.
질문과 답변에 대한 추천수가 높으면 추천수 높은 순 혹은 인기 게시물과 같이 분류할 수 있지 않을까?
기능을 만들어보자.
1. 엔티티 변경
엔티티를 수정해야 한다. 추천인을 넣을 컬럼을 만들어야 한다.
@ManyToMany
Set<SiteUser> voter;
하나의 사람이 여러 게시물을 추천할 수 있고, 하나의 질문에 여러 사람이 추천을 할 수 있다. 질문과 추천인은 대등한 관계로 @ManyToMany를 사용했다.
또한 List가 아닌 Set을 사용한 이유는 추천은 한 사람이 중복으로 투표할 수 없기 때문에 중복이 되지 않은 List은 Set을 사용했다.
2. 버튼 생성
html파일을 수정하여 버튼을 생성해보자.
<a href="javascript:void(0);" class="recommend btn btn-sm btn-outline-secondary"
th:data-uri="@{|/question/vote/${question.id}|}">
추천
<span class="recommend badge rounded-pill bg-success" th:text="${#lists.size(question.voter)}"></span>
</a>
수정 및 삭제 기능과 같이 script를 사용하는 코드이다.
class에 recommend 속성 값이 있을 경우에는 발생하는 script를 만들어 보자.
const recommend_elements = document.getElementsByClassName("recommend");
Array.from(recommend_elements).forEach(function(element) {
element.addEventListener('click', function() {
if(confirm("정말로 추천하시겠습니까?")) {
location.href = this.dataset.uri;
};
});
});
잘 출력 된다.
하지만, script를 사용하지 않고 알람을 출력할 수 있다.
<a onclick="if( !confirm('정말로 투표하시겠습니까?') ) return false;"
th:href="@{|/question/vote/${question.id}|}"
class="btn btn-sm btn-outline-secondary">
추천
<span class="badge rounded-pill bg-success" th:text="${#lists.size(question.voter)}"></span>
</a>
이 코드를 사용했다면 script를 사용하지 않아도 될 것이다.
3. QuestionController 수정
/question/vote/${question.id}를 Mapping할 수 있도록 Controller을 수정해 주어야 한다.
@PreAuthorize("isAuthenticated()")
@GetMapping("/vote/{id}")
public String questionVote(Principal principal, @PathVariable("id") Integer id) {
Question question = this.questionService.getQuestion(id);
SiteUser siteUser = this.userService.getUser(principal.getName());
this.questionService.vote(question, siteUser);
return String.format("redirect:/question/detail/%s", id);
}
로그인 한 사람만 추천할 수 있도록 @PreAuthorize("isAuthenticated()")를 사용하였고 어떠한 질문인지, 어떠한 사용자가 투표했는지에 대한 정보를 questionService에 vote 메서드를 통해 등록해준다.
4. QuestionService 수정
위에서 얘기했던 것 처럼 질문과 사용자의 정보를 갖고 추천할 수 있는 메서드를 만들어준다.
public void vote(Question question, SiteUser siteUser) {
question.getVoter().add(siteUser);
this.questionRepository.save(question);
}
question의 엔티티 안에서 Voter라는 SetList에 사용자를 추가한다. 어차피 Set이기 때문에 중복으로 등록되는 추천인은 자동으로 반영되지 않는다.
5. 결과
잘 나온다!
'Spring' 카테고리의 다른 글
[Spring]기능 - 검색 (0) | 2022.08.25 |
---|---|
[Spring]기능 - 앵커(anchor) (0) | 2022.08.23 |
[Spring]기능 - 질문 수정 및 삭제 (0) | 2022.08.22 |
[Spring]기능 - 작성자 출력하기 (0) | 2022.08.22 |
[Spring]기능 - 회원가입 (0) | 2022.08.18 |