현 상태에서 http://localhost:8080/question/list 에 접속하면, 404 error가 뜬다.
→ /question/list URL에 대한 매핑이 있는 컨트롤러가 필요 !!
💡 @ResponseBody 이용
package com.mysite.sbb.question;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class QuestionController {
@GetMapping("/question/list")
@ResponseBody
public String list() {
return "question list";
}
}
💡 템플릿 이용하기
타임리프 템플릿 엔진 설치
경로: gdsc\web-board\build.gradle
dependencies {
(... 생략 ...)
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
}
queston_list 템플릿 만들기
경로: gdsc\web-board\src\main\resources\templates\question_list.html
<h2>Hello Template</h2>
@RequiredArgsConstructor
어노테이션import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Controller
public class QuestionController {
private final QuestionRepository questionRepository;
@GetMapping("/question/list")
public String list(Model model) {
List<Question> questionList = this.questionRepository.findAll();
model.addAttribute("questionList", questionList);
return "question_list";
}
}
th:
: 타임리프 템플릿 엔진 속성으로 자바 코드와 연결되는 부분<table>
<thead>
<tr>
<th>제목</th>
<th>작성일시</th>
</tr>
</thead>
<tbody>
<tr th:each="question : ${questionList}">
<td th:text="${question.subject}"></td>
<td th:text="${question.createDate}"></td>
</tr>
</tbody>
</table>
redirect:<URL>
- URL로 리다이렉트 (리다이렉트는 완전히 새로운 URL로 요청이 된다.)forward:<URL>
- URL로 포워드 (포워드는 기존 요청 값들이 유지된 상태로 URL이 전환된다.)package com.gdsc.webboard.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("/") //'/' URL을 매핑
public String root(){
return "redirect:/question/list";
}
}
package com.gdsc.webboard.question;
import java.util.List;
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();
}
}
Controller -> Service -> Repository
구조로 데이터를 처리할 예정package com.gdsc.webboard.question;
import lombok.RequiredArgsConstructor;
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 java.util.List;
@RequiredArgsConstructor //questionRepository 속성을 포함하는 생성자를 자동으로 롬복에서 생성
@Controller
public class QuestionController {
private final QuestionService questionService;
@GetMapping("/question/list")
public String list(Model model){ //모델: 컨트롤러에서 html 템플릿에 데이터를 넘기고 싶을때 사용
List<Question> questionList = this.questionService.getList();
model.addAttribute("questionList", questionList);
return "question_list";
}
th:href
속성: URL 주소를 나타낼때는 반드시 @{
문자와 }
문자 사이에 입력|
문자를 사용<table>
<thead>
<tr>
<th>제목</th>
<th>작성일시</th>
</tr>
</thead>
<tbody>
<tr th:each="question, index : ${questionList}">
<td>
<a th:href="@{|/question/detail/${question.id}|}" th:text="${question.subject}"></a>
</td>
<td th:text="${question.createDate}"></td>
</tr>
</tbody>
</table>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${question.subject}"></h1>
<div th:text="${question.content}"></div>
</body>
</html>
package com.gdsc.webboard.question;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@RequiredArgsConstructor
@Service
public class QuestionService {
private final QuestionRepository questionRepository;
public List<Question> getList(){
return this.questionRepository.findAll();
}
public Question getQuestion(Integer id){
Optional<Question> question = this.questionRepository.findById(id);
if(question.isPresent()){
return question.get();
}else{
throw new DataNotFoundException("Question not found");
}
}
}
HttpStatus.NOT_FOUND
)가 나타남package com.gdsc.webboard.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{
private static final long serialVersionUID = 1L;
public DataNotFoundException(String message) {
super(message);
}
}
@GetMapping(value = "/question/detail/{id}")
에서 사용한 id와 @PathVariable("id")
의 매개변수 이름이 동일해야 함package com.gdsc.webboard.question;
import lombok.RequiredArgsConstructor;
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 java.util.List;
@RequiredArgsConstructor //questionRepository 속성을 포함하는 생성자를 자동으로 롬복에서 생성
@Controller
public class QuestionController {
private final QuestionService questionService;
(... 생략 ...)
@GetMapping("/question/detail/{id}")
public String detail(Model model, @PathVariable("id") Integer id){ //모델: 컨트롤러에서 html 템플릿에 데이터를 넘기고 싶을때 사용
Question question = this.questionService.getQuestion(id);
model.addAttribute("question", question);
return "question_detail";
}
}
@RequestMapping("/question")
@RequiredArgsConstructor //questionRepository 속성을 포함하는 생성자를 자동으로 롬복에서 생성
@Controller
public class QuestionController {
private final QuestionService questionService;
@GetMapping("/list")
public String list(Model model){ //모델: 컨트롤러에서 html 템플릿에 데이터를 넘기고 싶을때 사용
List<Question> questionList = this.questionService.getList();
model.addAttribute("questionList", questionList);
return "question_list";
}
@GetMapping("/detail/{id}")
public String detail(Model model, @PathVariable("id") Integer id){ //모델: 컨트롤러에서 html 템플릿에 데이터를 넘기고 싶을때 사용
Question question = this.questionService.getQuestion(id);
model.addAttribute("question", question);
return "question_detail";
}
}