What to do?
댓글 작성 기능 구현하기
구현내용
- 댓글 작성 후 제출 버튼 클릭
- 최신 댓글들을 위로 오게 정렬해서 댓글 보여주기
Controller
댓글 CRUD
- Create
- /comments/write 경로로 post 요청
- saveComment 메써드
- Read
- ArticleController에서 이미 구현함
- Update
- /comments 경로로 put 요청
- updateComment 메써드
- Delete
- /comments 경로로 delete 요청
- deleteComment 메써드
CommentController.java
@Controller
@RequestMapping("/comments")
@RequiredArgsConstructor
public class CommentController {
private final CommentService commentService;
@PostMapping("/write")
public String saveComment(WriteCommentRequest writeCommentRequest){
// TODO : 인증기능 구현 후에 createdBy는 실제 유저명 넣기
UserAccountDto userAccountDto = UserAccountDto.of("test email", "karma", "test password", "test description", RoleType.USER);
CommentDto commentDto = WriteCommentRequest.to(writeCommentRequest);
commentService.saveComment(userAccountDto, commentDto);
return String.format("redirect:/articles/%s", writeCommentRequest.getArticleId());
}
@PutMapping("/{commentId}")
public String updateComment(@PathVariable Long commentId, UpdateCommentRequest req){
// TODO : 인증기능 구현 후 자기가 작성한 댓글만 수정할 수 있도록
commentService.updateComment(commentId, req.getContent());
return String.format("redirect:/articles/%s", req.getArticleId());
}
@PostMapping("/{commentId}")
public String deleteComment(@PathVariable Long commentId, DeleteCommentRequest req){
// TODO : 인증기능 구현 후 자기가 작성한 댓글만 삭제할 수 있도록
commentService.deleteComment(commentId);
return String.format("redirect:/articles/%s", req.getArticleId());
}
}
Service
CommentService.java
@Service
@Transactional
@RequiredArgsConstructor
public class CommentService {
private final UserAccountRepository userAccountRepository;
private final ArticleRepository articleRepository;
private final CommentRepository commentRepository;
public void saveComment(UserAccountDto userAccountDto,CommentDto commentDto){
userAccountRepository.findByUsername(userAccountDto.getUsername())
.orElseThrow(()->{throw new MyException(
ErrorCode.USER_NOT_FOUND,
String.format("Username [%s] is not founded", userAccountDto.getUsername()));});
Article article = articleRepository.findById(commentDto.getArticleId()).orElseThrow(()->{
throw new MyException(
ErrorCode.ENTITY_NOT_FOUND,
String.format("Article with id [%s] is not founded", commentDto.getArticleId()));});
Comment comment = Comment.of(article, commentDto.getContent());
// Save
commentRepository.save(comment);
}
public void updateComment(Long commentId, String content){
Comment comment = commentRepository
.findById(commentId)
.orElseThrow(()->{throw new MyException(
ErrorCode.ENTITY_NOT_FOUND,
String.format("Comment with [%s] is not founded", commentId)
);});
comment.setContent(content);
commentRepository.save(comment);
}
public void deleteComment(Long commentId){
commentRepository.deleteById(commentId);
}
}
에러가 날 때 thorws new MyException과 같이 내가 정의한 에러를 던지도록 했다.
(UsernameNotFoundException, EntityNotFoundException 과 같이 이미 정의된 에러를 던지도록 해도 똑같이 동작한다)
HTML
resources/articles/detail/index.html
- Service, Controller에서는 댓글 작성/조회/수정/삭제를 구현해놓았지만, View에서는 댓글 작성/조회만 구현해놓았다.
- CommentController의 saveComment 메써드에서 /comments/write 경로로 post 요청을 보내면 댓글이 작성되도록 만들어 놓음 → form 태그 action="/comments/write" method="post"
<!--댓글쓰기-->
<div class="row mt-3">
<section id="write-comment-area" name="write-comment-area">
<form class="row" action="/comments/write" method="post">
<!--게시글 Id-->
<input name="articleId" id="article-id" hidden/>
<div class="col form-floating">
<!--댓글입력-->
<textarea class="form-control h-100" placeholder="Leave a comment here"
id="floatingTextarea" name="content" style="resize:none;"></textarea>
<label for="floatingTextarea">Comment</label>
</div>
<div class="col-1 align-self-center">
<button class="btn btn-primary" id="btn-submit" type="submit">Submit</button>
</div>
</form>
- 댓글보기
<!--댓글보기-->
<div class="accordion mt-3">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
See Comments
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse show" aria-labelledby="headingOne" data-bs-parent="#accordionExample">
<ul id="article-comments" class="row col-7">
<li class="list-group-item">
<div>
<strong>AUTHOR</strong>
<small><time>2022-01-01</time></small>
<p>COMMENT</p>
</div>
</li>
</ul>
</div>
</div>
</div>
Thymeleaf Template
- 댓글 작성
- 댓글 저장 시에 게시글 id가 필요해서 Aritcle Controller에서 받은 게시글 id를 주입
<!--Write Comment-->
<attr sel="#write-comment-area">
<attr sel="#article-id" th:value="${articleId}"/>
</attr>
- 댓글보기
<!--See Comments-->
<attr sel="#article-comments">
<attr sel="li" th:remove="all-but-first">
<attr sel="div" th:each="comment : ${comments.comments}">
<attr sel="strong" th:text="${comment.createdBy}"/>
<attr sel="small/time" th:datetime="${comment.createdAt}" th:text="${#temporals.format(comment.createdAt, 'yy년 MM월 dd일 hh시 mm분')}"/>
<attr sel="p" th:text="${comment.content}"/>
</attr>
</attr>
</attr>
'Java > Spring' 카테고리의 다른 글
[Spring] 길찾기 서비스 #5 (0) | 2022.12.11 |
---|---|
[Spring] 게시판 만들기 #12 (0) | 2022.11.26 |
[Spring] 게시판 만들기 #10 (0) | 2022.11.23 |
[Spring] 게시판 만들기 #9 (0) | 2022.11.23 |
[Spring] 게시판 만들기 #8 (0) | 2022.11.23 |