본문으로 바로가기

Reply JWT 적용

category Spring boot 2024. 11. 7. 09:10

ReplyController

package com.tenco.blog_v3.reply;

import com.tenco.blog_v3.user.User;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

@RequiredArgsConstructor
@Controller
public class ReplyController {

    private final ReplyService replyService;
    private final HttpSession session;

    // 댓글 생성 기능 만들기
    @PostMapping("/api/replies")
    public String save(ReplyDTO.SaveDTO reqDTO) {
        // 로그인 여부 확인
        User sessionUser = (User) session.getAttribute("sessionUser");
        if(sessionUser == null) {
            return "redirect:/login-form";
        }
        replyService.saveReply(reqDTO, sessionUser);
        return "redirect:/board/"+ reqDTO.getBoardId();
    }

    // 댓글 삭제
    @DeleteMapping("/api/replies/{id}")
    public String delete(@PathVariable(name = "boardId") Integer boardId, @PathVariable(name = "replyId") Integer replyId) {
        // 삭제도 권한 확인
        User sessionUser = (User) session.getAttribute("sessionUser");
        if(sessionUser == null) {
            return "redirect:/login-from";
        }
        replyService.deleteReply(replyId, sessionUser.getId(), boardId);
        return "redirect:/board/" + boardId;
    }

}

Reply

package com.tenco.blog_v3.reply;

import com.tenco.blog_v3.board.Board;
import com.tenco.blog_v3.user.User;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;

import java.time.LocalDateTime;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "reply_tb")
@ToString(exclude = {"user", "board"}) // 연관된 엔티티를 제외하여 순환 참조 방지 및 보안 강화 때문에 사용한다.
public class Reply {

    // 일반적으로 id는 Long 타입을 사용하는 것을 권장한다.
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    // null 값이 들어올 수 없어! - 기본 값을 null 허용
    @Column(nullable = false)
    private String comment;

    // 단방향 관계 설계 -> User 엔티티에는 Reply 정보가 없다!!!
    @ManyToOne(fetch = FetchType.LAZY) // 지연 로딩
    @JoinColumn(name = "user_id")
    private User user;

    // 양방향 매핑 (FK 주인은 댓글(Reply 이다)
    @ManyToOne(fetch = FetchType.LAZY) // 지연 로딩
    @JoinColumn(name = "board_id")
    private Board board;

    // JPA 엔티티에서 데이터베이스에 저장할 필요가 없는 필드를 정의할 때 사용한다.
    @Transient
    private boolean isReplyOwner;

    @Builder.Default
    private String status = "ACTIVE"; // 댓글 상태 (ACTIVE, DELETED)

    @CreationTimestamp // 엔티티가 생성될 때 자동으로 현재 시간으로 설정
    @Column(name = "created_at")
    private LocalDateTime createdAt;

    /**
     * 엔티티가 데이터베이스에 영속화 되기 전에 호출 되는 메서드가 있다면 사용한다.
     * @PrePersist 어노테이션은 JPA 라이프 사이클 이벤트 중 하나로 엔티가 영속화 되기전에 실행 된다.
     */
    @PrePersist
    protected void onCreate() {
        if(this.status == null) {
            this.status = "ACTIVE";
        }
        if (this.createdAt == null) {
            this.createdAt = LocalDateTime.now();
        }
    }

}

ReplyDTO

package com.tenco.blog_v3.reply;

import com.tenco.blog_v3.board.Board;
import com.tenco.blog_v3.user.User;
import lombok.Getter;
import lombok.Setter;

public class ReplyDTO {

    @Getter
    @Setter
    public static class SaveDTO {
        private Integer boardId;
        private String comment;

        // DTO --> JPA 영속성 컨텍스트로 저장 한다.. 엔티티로 변환 해야 한다.
        public Reply toEntity(User sessionUser, Board board) {
            return Reply.builder()
                    .comment(comment)
                    .board(board)
                    .user(sessionUser)
                    .build();
        }

    }
}

ReplyJPARepository

package com.tenco.blog_v3.reply;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

// 어노테이션 생략 가능 -> IoC 처리 됨
public interface ReplyJPARepository extends JpaRepository<Reply, Integer> {
    // 기본적인 주요 메서드 제공 받음 (구현체를 만들어 준다)

    // 1. 커스텀 쿼리를 만들어 본다. 어노테이션 사용
    // boardId 를 통해서 리플정보를 조회하는 기능
    @Query("select r from Reply r where r.board.id = :boardId")
    List<Reply> findByBoardId(@Param("boardId") Integer boardId); // 알아서 메서드의 바디를 만들어 준다.

}

ReplyService

'Spring boot' 카테고리의 다른 글

JWT 인터셉터 적용  (1) 2024.11.07
JDBC란 뭘까? - 1  (1) 2024.11.07
JwtUtil 만들어 보기  (3) 2024.11.06
JWT란 뭘까?  (0) 2024.11.06
RestAPI 컨트롤러 요청과 응답  (0) 2024.11.06