
// QuestionService.java
package com.mysite.sbb.question;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.mysite.sbb.DataNotFoundException;
import java.util.List;
@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");
}
}
}
id 값으로 Question 데이터를 조회하는 getQuestion 메서드를 추가했다.
리포지터리로 얻은 Question 객체는 Optional 객체이기 때문에 위와 같이 isPresent 메서드로 해당 데이터가 존재하는지 검사하는 로직이 필요하다.
만약 id 값에 해당하는 Question 데이터가 없을 경우에는 DataNotFoundException을 발생시키도록 했다.
//DataNotFoundException.java
package com.mysite.sbb;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.http.HttpStatus;
import
@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);
}
}

에서 id가 1, 2인데 3을 url에 넣어 확인해본다면?

id가 1인 게시글의 상세보기는 잘 나왔다.

@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";
}
↑ 나는 슬래시가 빠진 ("question/list")로 했다. 그대신 application.properties에서 / 하나를 template 뒤에 붙여준다.
/question으로 시작한다는 것을 확인할 수 있었는데, 이런 경우 클래스명 위에
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 lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
✅ @RequestMapping("question")
@RequiredArgsConstructor
@Controller
public class QuestionController {
//private final QuestionRepository questionRepository;
private final QuestionService questionService;
@GetMapping("/list")
public String list(Model model) {
List<Question> questionList = this.questionService.getList();
model.addAttribute("questionList", questionList);
return "question_list";
}
@GetMapping(value="/detail/{id}")
public String detail(Model model, @PathVariable("id") Integer id){
Question question = this.questionService.getQuestion(id);
model.addAttribute("question", question);
return "question_detail";
}
}
list 메서드의 url 매핑은 /list이지만,
/question + /list 가 되어 최종적인 URL 매핑은
/question/list가 된다.
위와 같이 수정하면 기존과 완전히 동일한 기준으로 URL 매핑이 이루어진다.
앞으로 QuestionController에서 사용하는 URL 매핑은 항상 /question으로 시작해야하는 규칙이 생긴 것이다.