Question ์์ฑ ์ถ๊ฐ
Question
@ManyToOne
private SiteUser author; //์ง๋ฌธ์
์ง๋ฌธ์ (์ ์ ) ํ๋ช ์ ๋ง์ ์ง๋ฌธ
Answer
@ManyToOne
private SiteUser author; //์ง๋ฌธ์
DBํ์ธํ๊ธฐ

ANSWER๊ณผ QUESTION ์ ๋ ๋ค AUTHOR_ID ์ถ๊ฐ ํ์ธ
AnswerController ์์ ์์ฑ์๋ฅผ ์ถ๊ฐํ๋ค
์ด๋ฏธ ์ธ์ ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ์๋๋ฐ, ๊ทธ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์ค๋ฉด ๋จ
@PostMapping("/create/{id}")
public String createAnswer(Model model, @PathVariable("id") Integer id,
@Valid AnswerForm answerForm, BindingResult bindingResult, Principal principal) {
}
Principal principal > ํ์ฌ ๋ก๊ทธ์ธ ํ ์ ์ ์ ๋ณด
UserService
//์ ์ ์กฐํ
public SiteUser getUser(String username) {
Optional<SiteUser> siteUser = userRepo.findByusername(username);
if(siteUser.isPresent()){
return siteUser.get();
}
else {
throw new DataNotFoundException("siteuser not found");
}
}
AnswerService - ์์ฑ์ ์ถ๊ฐ
//๋ต๋ณ ์ ์ฅ ์ ์ง๋ฌธ ๊ฐ์ฒด์ ๋ต๋ณ ๋ด์ฉ์ ์
๋ ฅ๋ฐ์์ ๋ต๋ณ์ ๋ฑ๋ก
public void create(Question question,String content,SiteUser author ) {
Answer answer = new Answer(); //๋ต๋ณ ๊ฐ์ฒด ๋ง๋๋ฆญ
answer.setContent(content);
answer.setCreateDate(LocalDateTime.now());//์ค๋๋ ์ง
answer.setQuestion(question);
answer.setAuthor(author);
this.aRepo.save(answer);//์ ๋ต๋ณ ์
๋ ฅ
}
AnswerController
@Autowired
private UserService uService;
//๋ต๋ณ ์ ์ฅ
@PostMapping("/create/{id}") //์ฃผ์์ ์๋ ๋ณ์ { }์์ ๋ฃ๊ธฐ
public String createAnswer(Model model, @PathVariable("id") Integer id,
@Valid AnswerForm answerForm, BindingResult result,
Principal principal) {
Question question = this.qService.getQuestion(id);
SiteUser siteUser = this.uService.getUser(principal.getName()); //์ถ๊ฐ
if(result.hasErrors()) {
model.addAttribute("question", question);
return "question_detail";
}
//๋ต๋ณ ์ ์ฅ
aService.create(question, answerForm.getContent(),siteUser);
return String.format("redirect:/question/detail/%s", id);//์ง๋ฌธ ์์ธ๋ณด๊ธฐ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ
}
QuestionService์๋ ๋์ผํ๊ฒ ์์ฑ์ ์ถ๊ฐํจ
//์ง๋ฌธ ๋ฑ๋ก ์ฒ๋ฆฌ
public void create(String subject , String content,SiteUser user) { //ํ๋ผ๋ฏธํฐ subject์ content๊ฐ ๋ค์ด๊ฐ
Question q = new Question(); //๊ฐ์ฒด๋ฅผ ์์ฑํด์ ํ๋ผ๋ฏธํฐ๋ก ๊ฐ์ ธ์จ ๊ฐ์ ๋ฃ๋๋ค.
q.setSubject(subject);
q.setContent(content);
q.setCreateDate(LocalDateTime.now());
q.setAuthor(user);
this.qRepo.save(q); // ์ ์ฅํ๋ค.
}
QuestionController - ์์ฑ์ ์ถ๊ฐ
@Autowired
private UserService uService;
//์ง๋ฌธ ๋ฑ๋ก ์ฒ๋ฆฌํ๊ธฐ
@PostMapping("/create")
public String questionCreate(@Valid QuestionForm questionForm, BindingResult result,Principal principal) {
if(result.hasErrors()) {
return"question_form"; //์ ํจ์ฑ ๊ฒ์ฌ ์๋ฌ
}
SiteUser siteUser = uService.getUser(principal.getName());
qService.create(questionForm.getSubject(), questionForm.getContent(), siteUser);
return "redirect:/question/list"; //์ง๋ฌธ ์ ์ฅ ํ ์ง๋ฌธ๋ชฉ๋ก์ผ๋ก ์ด๋
}
์ด๋ ๊ฒ ๋ฐ๊พธ๋ฉด test์์ ์ค๋ฅ๋จ


์์ฑ์๊ฐ ์๋ค์ด๊ฐ์๊ทธ๋ผ null๋ก ์์์ ์ผ๋ก ๋ฐ๊ฟ์ฃผ๋ฉด ์ค๋ฅ ํ๋ฆผ
ํ ์คํธํ๊ธฐ




ํ์ง๋ง ๋ก๊ทธ์ธ์ ์ํ์ ๊ฒฝ์ฐ์๋ ์ค๋ฅ๊ฐ ๋จ


QuestionController
@PreAuthorize : ์ธ์ฆ์ด ๋์ด์ผ ํจ

//์ง๋ฌธ ๋ฑ๋กํ๊ธฐ
@PreAuthorize("isAuthenticated()")
@GetMapping("/create")
public String questionCreate(QuestionForm questionForm) {
return "question_form";
}
//์ง๋ฌธ ๋ฑ๋ก ์ฒ๋ฆฌํ๊ธฐ
@PreAuthorize("isAuthenticated()")
@PostMapping("/create")
public String questionCreate(@Valid QuestionForm questionForm, BindingResult result,Principal principal) {
if(result.hasErrors()) {
return"question_form"; //์ ํจ์ฑ ๊ฒ์ฌ ์๋ฌ
}
SiteUser siteUser = uService.getUser(principal.getName());
qService.create(questionForm.getSubject(), questionForm.getContent(), siteUser);
return "redirect:/question/list"; //์ง๋ฌธ ์ ์ฅ ํ ์ง๋ฌธ๋ชฉ๋ก์ผ๋ก ์ด๋
}
AnswerController๋ ์ถ๊ฐ
//๋ต๋ณ ์ ์ฅ
@PreAuthorize("isAuthenticated()")
@PostMapping("/create/{id}") //์ฃผ์์ ์๋ ๋ณ์ { }์์ ๋ฃ๊ธฐ
public String createAnswer(Model model, @PathVariable("id") Integer id,
@Valid AnswerForm answerForm, BindingResult result,
Principal principal) {
Question question = this.qService.getQuestion(id);
SiteUser siteUser = this.uService.getUser(principal.getName()); //์ถ๊ฐ
if(result.hasErrors()) {
model.addAttribute("question", question);
return "question_detail";
}
//๋ต๋ณ ์ ์ฅ
aService.create(question, answerForm.getContent(),siteUser);
return String.format("redirect:/question/detail/%s", id);//์ง๋ฌธ ์์ธ๋ณด๊ธฐ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ
}
SecurityConfig
@EnableGlobalMethodSecurity(prePostEnabled = true) ์ถ๊ฐ

SecurityConfig์ ์ ์ฉํ@EnableGlobalMethodSecurity ์ ๋ํ ์ด์ ์ prePostEnabled = true ์ค์ ์ QuestionController์ AnswerController์์ ๋ก๊ทธ์ธ ์ฌ๋ถ๋ฅผ ํ๋ณํ๊ธฐ ์ํด ์ฌ์ฉํ๋ @PreAuthorize ์ ๋ํ ์ด์ ์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ฐ๋์ ํ์ํ๋ค.
ํ ์คํธํ๊ธฐ
1. ๋ก๊ทธ์ธ ์ ๋ ์ํ์์ ์ง๋ฌธ ๋ฑ๋กํ๊ธฐ

2.๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋ํจ

3. ์ ์์ ์ผ๋ก ๋ก๊ทธ์ธํ๋ฉด ์๋ ์ด๋ํ๋ ค๊ณ ํ์๋ ์ง๋ฌธ ๋ฑ๋ก ํ์ด์ง๋ก ๋ฐ๋ก ์ด๋ํจ

๋ต๋ณ์ฐฝ๋ ๋ก๊ทธ์ธ ์ฌ๋ถ์ ๋ฐ๋ผ ์ฌ์ฉ๊ฐ๋ฅ ํ๊ฒ๋ ๋ง๋ฌ

<!-- ๋นํ์ ์ -->
<textarea
sec:authorize="isAnonymous()"
disabled
th:field="*{content}"
rows="10"
class="form-control"
></textarea>
<!-- ๋ก๊ทธ์ธ ์ -->
<textarea
sec:authorize="isAuthenticated()"
th:field="*{content}"
rows="10"
class="form-control"
></textarea>
ํ ์คํธ
1. ๋ก๊ทธ์ธ ์๋์ ๋ - ๋ต๋ณ ์ฐฝ ๋นํ์ฑํ

2. ๋ก๊ทธ์ธ ์ - ๋ต๋ณ ์ฐฝ ํ์ฑํ

๊ธ ๋ชฉ๋ก์๋ ๊ธ์ด์ด ์ถ๊ฐ
question_list.html

<tbody>
<tr th:each="question, loop : ${paging}">
<td
th:text="${paging.getTotalElements - (paging.number * paging.size) - loop.index}"
></td>
<td>
<a
th:href="@{/question/detail/__${question.id}__}"
th:text="${question.subject}"
></a>
<span
class="text-danger small ms-2"
th:if="${#lists.size(question.answerList)>0}"
th:text="${#lists.size(question.answerList)}"
>
</span>
</td>
<td>
<span
th:if="${question.author != null}"
th:text="${question.author.username}"
></span>
</td>
<td
th:text="${#temporals.format(question.createDate, 'yyyy-MM-dd HH:mm')}"
></td>
</tr>
</tbody>
ํ ์คํธํ๊ธฐ

์ง๋ฌธ ์์ธ๋ณด๊ธฐ์๋ ์์ฑ์ ์ด๋ฆ์ ์ถ๊ฐํ๋ค.
question_detail.html
<!-- ์ง๋ฌธ -->
<h2 class="border-bottom py-2" th:text="${question.subject}"></h2>
<div class="card my-3">
<div class="card-body">
<div
class="card-text"
style="white-space: pre-line"
th:text="${question.content}"
></div>
<div class="d-flex justify-content-end">
<div class="badge bg-light text-dark p-2 text-start">
<div class="mb-2">
<span
th:if="${question.author != null}"
th:text="
${question.author.username}"
></span>
</div>
<div
th:text="${#temporals.format(question.createDate, 'yyyy-MM-dd HH:mm')}"
></div>
</div>
</div>
</div>
</div>
<!-- ๋ต๋ณ ๋ฐ๋ณต ์์ -->
<div class="card my-3" th:each="answer : ${question.answerList}">
<div class="card-body">
<div
class="card-text"
style="white-space: pre-line"
th:text="${answer.content}"
></div>
<div class="d-flex justify-content-end">
<div class="badge bg-light text-dark p-2 text-start">
<div class="mb-2">
<span
th:if="${answer.author != null} th:text="
${question.author.username}
></span>
</div>
<div
th:text="${#temporals.format(answer.createDate, 'yyyy-MM-dd HH:mm')}"
></div>
</div>
</div>
</div>
</div>
ํ ์คํธํ๊ธฐ

'BACKEND > SpringBoot' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| ์ง๋ฌธ ์ญ์ ์ฒ๋ฆฌ (0) | 2023.11.10 |
|---|---|
| ์ง๋ฌธ ์์ ์ฒ๋ฆฌ (0) | 2023.11.10 |
| ๋ก๊ทธ์์ ์ฒ๋ฆฌ (0) | 2023.11.10 |
| ๋ก๊ทธ์ธ ๊ตฌํ (0) | 2023.11.10 |
| ํ์๊ฐ์ ์ฒ๋ฆฌ(์ ํจ์ฑ๊ฒ์ฌ, ๋น๋ฐ๋ฒํธ ์ํธํ, ์ค๋ณตํ์๊ฐ์ ์ฒ๋ฆฌ) (0) | 2023.11.10 |