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>
/question/detail/과 같은 문자열과 ${question.id}와 같은 자바 객체의 값을 더할 때는 반드시 다음처럼 |과 | 기호로 좌우를 감싸 주어야 한다.
th:text="${question.subject}"
값에th:href="@{|/question/detail/${question.id}|}"
링크를 추가한다는 의미!
링크가 생성되었다~!
링크는 생성되었지만, 실제로 페이지를 매핑해놓지 않았다! 이제 생성된 링크에 메소드 매핑을 해야한다!
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문서로 리턴
}
이 때 @GetMapping(value = "/question/detail/{id}") 에서 사용한 id와 @PathVariable("id")의 매개변수 이름이 동일해야 한다.
detail메소드와 주소값 매핑은 완료 되었다! 이제
1. 서비스에 getQuestion메소드를 추가하고 2. 리턴할 html문서를 작성해보자!
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 객체는 널값인지 아닌지 체크
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)가 나타날 것이다.
<h1 th:text="${question.subject}"></h1>
<div th:text="${question.content}"></div>
quetion_detail.html 문서가 리턴되었고 주소는 /question/detail/{id} 에 매핑되었다!
없는 id값을 넣을 경우 DataNotFoundException 예외가 만들어지고, 메세지에 "question not found"이 출력된다. 또한, DataNotFoundException가 발생할 경우 @ResponseStatus 애너테이션에 의해 404 오류(HttpStatus.NOT_FOUND)가 발생하고 reason에 "entity not found"가 출력된다
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 으로 시작해야 하는 규칙이 생긴 것