안녕하세요!!! 오늘은 상세보기 화면에 대해 말해보도록 하겠습니다!
더 좋은 방법이 있으면 꼭 꼭 알려주세요.
우선 list.html의 제목부분에
<td style="text-align: left;"><a id="title" th:text="${list.qbTitle}" th:href="@{/questions/{qbNo}(qbNo=${list.qbNo})}"></a>
이렇게 하이퍼링크를 걸어주세요. Thymeleaf에서 동적경로변수포함하여 url를 만드는 방법입니다.
package com.jendh.meme.model;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import com.jendh.meme.entity.Member;
import com.jendh.meme.entity.MemeBoard;
import com.jendh.meme.entity.QuestionBoard;
import lombok.Builder;
import lombok.Getter;
@Getter
public class QuestionResponseDto {
private Long qbNo;
private String qbTitle;
private String qbContent;
private Member member;
private String qbNickName;
private int qbViews;
private LocalDateTime qbModifyDt;
private int commentCount;
@Builder
public QuestionResponseDto(QuestionBoard entity) {
this.qbNo= entity.getQbNo();
this.qbTitle= entity.getQbTitle();
this.qbContent= entity.getQbContent();
this.qbNickName = entity.getQbNickName();
this.member = entity.getMember();
this.qbViews = entity.getQbViews();
this.qbModifyDt = entity.getQbModifyDt();
this.commentCount = entity.getCommentCount();
}
}
우선 보드 응답을 담을 dto를 만듭니다.
/**
* 게시판 상세보기
*
* @param mbNo
* @param model
*
*/
@GetMapping("/questions/{qbNo}")
public String view(@PathVariable Long qbNo, Model model) {
// 게시판 불러오기
QuestionResponseDto questionResponseDto = questionBoardService.findByQbNo(qbNo);
model.addAttribute("detail", questionResponseDto);
return "board/question/detail";
}
게시판 번호를 담아서 서비스로 보냅니다.
// 게시판상세보기
@Transactional
public QuestionResponseDto findByQbNo(Long qbNo) {
QuestionBoard entity = questionBoardRepository.findById(qbNo)
.orElseThrow(() -> new IllegalArgumentException("해당 게시물이 없습니다. id" + qbNo));
return new QuestionResponseDto(entity);
}
jpa에서 제공하는 findById()를 이용하면 솔직히 끝입니다!
findById() 는 해당하는 엔티티를 ID로 찾아옵니다. 만약 해당하는 엔티티가 없을 경우에는 Optional 객체를 반환합니다.
orElseThrow() 메소드는 Optional 객체가 비어있을 때 예외를 던지는 메소드입니다. 이걸 이용해서 만약 해당 ID에 해당하는 엔티티가 없을 경우, IllegalArgumentException 예외가 발생하도록 설정합니다.
IllegalArgumentException는 자바에서 사용하는 예외클래스중에 하나로 보통 메소드에 대해 유효하지 않은 값이 전달될 때 발생합니다.
return으로 DB에서 가져온 QuestionBoard 엔티티의 데이터를 위의 Dto에 빌더 생성자로 값을 넣어주면 됩니다.
<!-- 게시글 구역 -->
<div class="title" th:text="${detail.qbTitle}">
</div>
<div class="nickName" th:text="${detail.qbNickName}" name="nickname">
</div>
<div class="timeViewLinkReportBox">
<span class="time" th:text="${detail.formattedModifyDt}">수정시간</span>
<span class="view-label">· 조회수</span>
<span class="view" th:text="${detail.qbViews}">조회수</span>
<span class="report">신고</span>
<span class="link">URL복사</span>
</div>
<div class="line">
</div>
<div class="content" th:utext="${detail.qbContent}">
</div>
<div class="writerOrGuestBox">
<div class="liketext">
<button class="list" th:onclick="|location.href='@{/questions}'|">목록</button>
</div>
<div th:if="${#authorization.expression('isAuthenticated()') and #authentication.principal !=null}">
<span th:if="${#authentication.principal.member.memberNo}==${detail.member.memberNo}">
<button id="buttonmeme">수정</button>
<input type="hidden" name="qbNo" th:value="${detail.qbNo}"/>
<button type="button" class="button_delete" id="buttonmeme">삭제</button>
</span>
</div>
</div>
<div class="line">
</div>
여기서 두가지 if문이 보이실텐데요.
th:if="${#authorization.expression('isAuthenticated()') and #authentication.principal !=null}"
이 조건문으로 스프링 시큐리티에서 현재 사용자가 인증되어 있는지를 확인합니다. 상세페이지는 로그인을 하지 않은 유저도 볼 수 있는 공간이기 때문에 아래 조건문만 넣을 시 오류가 나서 넣어주었습니다.
th:if="{#authentication.principal.member.memberNo}=={detail.member.memberNo}"
이건 현재 로그인한 유저가 글 작성자인지 묻는 조건문입니다. #authentication.principal은 현재 사용자에 대한 정보를 나타냅니다. 작성자가 아니라면 목록버튼만 뜨고 작성자라면 수정과 삭제버튼이 뜨도록 했습니다!
다음은 조회수 구현입니다!!
책"스프링 부트와 AWS로 혼자 구현하는 웹 서비스"