Access token으로 사용자 정보 가져오기
댓글과 멤버 클래스를 N:1 연관관계로 설정하면서
댓글을 작성했을 때 따로 프론트에서 로그인 정보를 받지 않아도
헤더에 있는 access token으로 로그인 된 사용자의 정보를 가져와 자동으로 댓글의 작성자를 설정해주는 코드를 구현해봤다.
또, 댓글을 저장하면서 어떤 게시글의 댓글인지 정보를 받아 연관 관계를 맺는 코드도 구현했다.
1. Comment 클래스
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import solux.wansuki.OurNeighbor_BE.domain.Gathering.Gathering;
import solux.wansuki.OurNeighbor_BE.domain.Member.Member;
import solux.wansuki.OurNeighbor_BE.domain.RecommendPost.RecommendPost;
import solux.wansuki.OurNeighbor_BE.domain.UsedGoods.UsedGoods;
import javax.persistence.*;
@Getter
@NoArgsConstructor
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "comment_id")
private Long id;
private String content;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "gathering_id")
private Gathering gathering;
@Builder
public Comment (String content) {
this.content = content;
}
public void setMember(Member member) {
this.member = member;
if (!member.getComments().contains(this))
member.getComments().add(this);
}
public void setGathering(Gathering gathering) {
this.gathering = gathering;
if (!gathering.getComments().contains(this))
gathering.getComments().add(this);
}
}
2. Member 클래스
@OneToMany(mappedBy = "member")
private List<Comment> comments = new ArrayList<>();
public void addComment(Comment comment) {
this.comments.add(comment);
if (comment.getMember() != this)
comment.setMember(this);
}
-> 이렇게 댓글과 멤버를 N:1 양방향 관계로 설정해준다.
3. Comment Controller
@PostMapping("/comment/{postId}")
public Long saveComment(@RequestBody CommentSaveDto saveDto,
@PathVariable Long postId, @AuthenticationPrincipal User user) {
return commentService.save(saveDto, postId, user);
}
@AuthenticalPrincipal : UserDetailsService에서 return 한 객체를 파라미터로 직접 받아 사용할 수 있도록 하는 어노테이션 -> 이 어노테이션을 사용하면 헤더에 첨부되어 있는 access token에서 로그인 된 사용자의 정보를 받아와 사용할 ㅅ ㅜ있다.
4. CommentSaveDto
@Getter
@NoArgsConstructor
public class CommentSaveDto {
private String content;
private String postCategory;
@Builder
public CommentSaveDto(String content) {
this.content = content;
this.postCategory = getPostCategory();
}
public Comment toEntity() {
return Comment.builder()
.content(content)
.build();
}
}
다음과 같이 내용과 함께 postCategory라는 항목도 같이 프론트에서 받아오도록 했다.
5. Comment service
@Transactional
public Long save(CommentSaveDto saveDto, Long postId, User user) {
Long id = commentRepository.save(saveDto.toEntity()).getId();
Member member = memberRepository.findByLoginId(user.getUsername())
.orElseThrow(()->new IllegalArgumentException("해당 유저 없음"));
member.addComment(commentRepository.findById(id).orElseThrow());
if (saveDto.getPostCategory().equals("gathering")) {
Gathering gathering = gatheringRepository.findById(postId).orElseThrow();
gathering.addComment(commentRepository.findById(id).orElseThrow());
}
else if (saveDto.getPostCategory().equals("recommend")) {
RecommendPost recommendPost = recommendPostRepository.findById(postId).orElseThrow();
recommendPost.addComment(commentRepository.findById(id).orElseThrow());
}
else if (saveDto.getPostCategory().equals("usedGoods")) {
UsedGoods usedGoods = usedGoodsRepository.findById(postId).orElseThrow();
usedGoods.addComment(commentRepository.findById(id).orElseThrow());
}
return id;
}
@AuthenticalPrincipal 을 이용해 받아온 user 객체를 통해 user.getUsername으로 사용자의 로그인 아이디를 가져와서 멤버 객체를 찾는다. 그 후 멤버와 댓글을 연관 지어준다.
6. Comment repository
public interface CommentRepository extends JpaRepository<Comment,Long> {
List<Comment> findByGatheringId(Long gatheringId);
List<Comment> findByRecommendPostId(Long recommendPostId);
List<Comment> findByUsedGoodsId(Long usedGoodsId);
}
이처럼 JpaRepository를 extends하면 findBy 뒤에 GatheringId를 써서 gathering 클래스의 id 값을 통해 Comment의 리스트를 반환받을 수 있다.
7. Gathering service
public List<CommentResponseDto> getComment(Long id) {
List<CommentResponseDto> responseDtos = new ArrayList<>();
List<Comment> comments = commentRepository.findByGatheringId(id);
for (Comment comment : comments) {
CommentResponseDto commentResponseDto = CommentResponseDto.builder()
.commentId(comment.getId())
.content(comment.getContent())
.userNickName(comment.getMember().getNickName())
.build();
responseDtos.add(commentResponseDto);
}
return responseDtos;
}
이 메소드를 통해 프론트가 gatheringId를 전송하면 그 게시글에 있는 댓글들을 모두 반환받을 수 있다.