[Spring Boot] 상세 페이지 만들기

DANI·2023년 9월 30일
0
post-thumbnail

💻 상세 페이지 만들기

subject값에 상세 페이지 링크 만들기

💾 subject값에 상세 페이지 링크삽입하기

<table>
    <thead>
        <tr>
            <th>제목</th>
            <th>작성일시</th>
        </tr>
    </thead>
    <tbody>
        <tr th:each="questionlist : ${questionList}">
            <td>
				<a th:href="@{|/question/detail/${questionlist.id}|}" th:text="${questionlist.subject}"></a>
			</td>
            <td th:text="${questionlist.createDate}"></td>
        </tr>
    </tbody>
</table>

🔍 수정된 부분

<td>
<a th:href="@{|/question/detail/${question.id}|}" th:text="${question.subject}"></a>
</td>
  • th:href : 링크의 주소를 나타낼 때 사용, 반드시 @{ } 괄호 사이에 입력해야 한다.

/question/detail/과 같은 문자열과 ${question.id}와 같은 자바 객체의 값을 더할 때는 반드시 다음처럼 |과 | 기호로 좌우를 감싸 주어야 한다.

th:text="${question.subject}" 값에 th:href="@{|/question/detail/${question.id}|}" 링크를 추가한다는 의미!



💻"http://localhost:8080/question/list" 접속해보기

링크가 생성되었다~!




링크는 생성되었지만, 실제로 페이지를 매핑해놓지 않았다! 이제 생성된 링크에 메소드 매핑을 해야한다!

💾 detail 메소드와 주소값 매핑하기


package com.mysite.sbb.question;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class QuestionController {

	private final QuestionService questionService; // 서비스 생성
	
	@GetMapping("/question/list")
	public String list(Model model) {
		List<Question> questionList = this.questionService.getList(); // 서비스에서 getList 메소드 이용
		model.addAttribute("questionList", questionList);
		return "question_list";
	}
	
	 @GetMapping(value = "/question/detail/{id}")
	 public String detail(Model model, @PathVariable("id") Integer id) {
		Question question = this.questionService.getQuestion(id);
		model.addAttribute("question", question);
		return "question_detail";
	 }
	
}

🔍 추가된 부분

import org.springframework.web.bind.annotation.PathVariable;

@GetMapping(value = "/question/detail/{id}") // datail메소드를 value주소값에 매핑함
public String detail(Model model, @PathVariable("id") Integer id) {
	Question question = this.questionService.getQuestion(id); 
    // 서비스에 getQuestion 메소드를 사용하여 question 인스턴스 생성
	model.addAttribute("question", question);
    // 모델에 question이란 이름으로 값 추가
	return "question_detail";
    // question_datail html문서로 리턴
}
  • @PathVariable 애너테이션 : 변하는 id 값을 얻을 때 사용

이 때 @GetMapping(value = "/question/detail/{id}") 에서 사용한 id와 @PathVariable("id")의 매개변수 이름이 동일해야 한다.


detail메소드와 주소값 매핑은 완료 되었다! 이제
1. 서비스에 getQuestion메소드를 추가하고 2. 리턴할 html문서를 작성해보자!

💾 1. 서비스에 getQuestion메소드 추가하기


package com.mysite.sbb.question;

import java.util.List;
import java.util.Optional;

import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Service
public class QuestionService {

	private final QuestionRepository questionRepository;
	
	public List<Question> getList() {
		return this.questionRepository.findAll();
	}
	
    //getQuestion 메소드 추가
	public Question getQuestion(Integer id) { // Question타입으로 반환
		Optional<Question> question = this.questionRepository.findById(id); 
        // 입력된 id값을 조회해서 question 생성 
		if(question.isPresent()) { // 널값이 아닌 경우 true
			return question.get(); // id값에 해당하는 question값 get
		} else {
        	// 널값일 경우. 즉, 찾는 id값이 없을 경우 예외를 발생시킨다.
			throw new DataNotFoundException("question not found"); 
		}
	}
}

Optional 객체는 널값인지 아닌지 체크


💾 DataNotFoundException 클래스 생성

package com.mysite.sbb.question;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "entity not found")
public class DataNotFoundException extends RuntimeException { //RuntimeException객체를 상속
	
    private static final long serialVersionUID = 1L;
    
    // 생성자
	public DataNotFoundException(String message) {
		super(message);
	}
}

DataNotFoundException이 발생하면 @ResponseStatus 애너테이션에 의해 404 오류(HttpStatus.NOT_FOUND)가 나타날 것이다.



💾 2. 리턴할 question_detail.html문서 작성


<h1 th:text="${question.subject}"></h1>
<div th:text="${question.content}"></div>




💻"http://localhost:8080/" 접속해보기


💻 링크 눌러보기

quetion_detail.html 문서가 리턴되었고 주소는 /question/detail/{id} 에 매핑되었다!


💻 인위적으로 없는 링크 접속해보기 "http://localhost:8080/question/detail/4"

없는 id값을 넣을 경우 DataNotFoundException 예외가 만들어지고, 메세지에 "question not found"이 출력된다. 또한, DataNotFoundException가 발생할 경우 @ResponseStatus 애너테이션에 의해 404 오류(HttpStatus.NOT_FOUND)가 발생하고 reason에 "entity not found"가 출력된다





💬 URL 프리픽스(prefix)

package com.mysite.sbb.question;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.RequiredArgsConstructor;

@RequestMapping("/question") // @RequestMapping을 이용하여 중복된 주소값을 리퀘스트 할 수 있다.
@RequiredArgsConstructor
@Controller
public class QuestionController {

	private final QuestionService questionService; // 서비스 생성
	
	@GetMapping("/list") // question 제거
	public String list(Model model) {
		List<Question> questionList = this.questionService.getList(); // 서비스에서 getList 메소드 이용
		model.addAttribute("questionList", questionList);
		return "question_list";
	}
	
	 @GetMapping(value = "/detail/{id}") // question 제거
	 public String detail(Model model, @PathVariable("id") Integer id) {
		Question question = this.questionService.getQuestion(id);
		model.addAttribute("question", question);
		return "question_detail";
	 }
	
}

🔍 수정된 부분

import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/question")
@GetMapping("/list")
@GetMapping(value = "/detail/{id}")

QuestionController에서 사용하는 URL 매핑은 항상 /question 으로 시작해야 하는 규칙이 생긴 것

0개의 댓글