포트폴리오/SPRINGBOOT 옛날

2-15 : Create와 Form

서버관리자 페페 2022. 10. 2. 18:06

단 하나의 맥락

: @GetMapping으로 질문 등록 버튼 및 형식 구현, Validation Form으로 양식 제한 

 

 


Semiflow Bundle

- 질문 등록 버튼을 만들고, 이어지는 question/create URL을 컨트롤러에 매핑한다

- question_form.html 템플릿을 작성하고, 컨트롤러에서 Post 방식을 처리할 수 있도록 메소드를 추가한다(오버로딩)

- 메소드를 추가하는 과정에서, QuestionService에 create 메소드를 추가한다

 

- gradle에 validation을 설치하고 form class를 작성한다

- QuestionController에 Validation Session을 추가하고

- question_form.html이 오류 메세지를 출력할 수 있도록 추가

- 만약 post된 내용이 오류라면, 입력했던 내용을 다시 로드할 수 있도록 기능을 추가한다

 

- 답변 등록도 마찬가지로 생성, form을 적용한다

 


자각

 

-

 

질문 등록 버튼 생성을

- question_list.html에

- <a th:href="@{/question/create}"  class="btn btn-primary">질문 등록하기</a> 으로

- 테이블 아래 구현한다

 

 

질문 등록 버튼을 클릭 시 

- QuestionController에서

- @GetMapping("/create") 어노테이션을 

- public String questionCreate() method 상단에 적용한다

- "import org.springframework.web.bind.annotation.GetMapping;" P/I로 사용 가능하다

 

 

클릭 후 나오는 페이지를

- question_form.html에 fragement로 신규 작성

- <html layout:decorate="~{layout}"></html> 내부에 <div layout:fragment="content"  class="container"></div>로 P/I 지정

- <h5 class="my-3 border-bottom pb-2">질문등록</h5> 으로 title 표기

- <form th:action="@{/question/create}" method="post"></form> 으로 폼 형식 CSS

 

- <div class="mb-3"></div> 로 질문 subject와 content가 들어갈 2개의 자리를 만든다

- <label for="subject"  class="form-label">제목</label>

<input type="text"  name="subject"  id="subject"  class="form-control">

- <label for="content"  class="form-label">내용</label>

<textarea name="content"  id="content"  class="form-control"  rows="10"></textarea>

 

- <input type="submit"  value="저장하기"  class="btn btn-primary my-2"> 로 버튼 추가

 

 

저장하기 버튼을 누르면 발생되는 POST 요청을

- QuestionController에

- public String questionCreate(@RequestParam String subject, @RequestParam String content) 신규 메소드에

- @PostMapping("/create") 어노테이션을 추가한다

 

- 해당 method 내에 this.questionService.create(subject, content); 저장하는 작업을 시행하고

- return "redirect:/question/list";  로 post와 함께 리디렉션 역시 시행되게 한다

- QuestionService에 해당 메소드를 구현한다

 

 

(QuestionService)

(... 생략 ...)
import java.time.LocalDateTime;
(... 생략 ...)
public class QuestionService {

    (... 생략 ...)

    public void create(String subject, String content) {
        Question q = new Question();
        q.setSubject(subject);
        q.setContent(content);
        q.setCreateDate(LocalDateTime.now());
        this.questionRepository.save(q);
    }
}

 

-

 

validation을 위해

- QuestionForm.java 를 신규 작성한다

- @Getter와 @Setter가 필요하고, public class QuestionForm{} 형식으로 작성한다

- 클래스 내부는 Entity와 동일한 private String subject, content이며

- @NotEmpty(message="내용은 필수항목")와 @Size(max=200)를 각 인자의 어노테이션으로 둔다

- 해당 어노테이션은 implementation 'org.springframework.boot:spring-boot-starter-validation' 을 설치해서 사용 가능하며

"import javax.validation.constraints.NotEmpty;"

"import javax.validation.constraints.Size;" // 의 P/I로 사용 가능하다

 

-

 

QuestionForm의 적용을

- QuestionContorller에서

- questionCreate 메소드의 signal을 (@RequestParam String subject, content)에서 (@Valid QuestionForm questionForm, BindingResult bindingResult) 로 바꿔준다

- 해당 인자는 "import javax.validation.Valid;" 와 "import org.springframework.validation.BindingResult;" P/I로 사용 가능하다

 

- 메소드 내부의 this.questionService.create signal인 (String subject, String content)를 (questionForm.getSubject(), questionForm.getContent());로 바꿔주며

- 예외 처리를 위해 if (bindingResult.hasErrors()) {return "question_form";} PipeLine을 그 전에 꽃아준다

 

 

-

 

 

검증 비통과 시 오류 메세지를

> question_form.html에

- <div class="alert alert-danger"  role="alert"  th:if="${#fields.hasAnyErrors()}"></div> 로 alert 클래스 및 조건부 공간을 표시한다

- <div th:each="err : ${fields.allErrors()}"  th:text="${err}" /> 로 공간을 채워넣는다

- <form th:action="@{/question/create}" th:object="${questionForm}" method="post"> 추가

 

- 해당 메세지 코드는 post할 form 내부 최상단에 들어간다

 

> QuestionController에

- @GetMapping("/create")

- public String questionCreate() signal로 QuestionForm questionForm  추가

 

-

 

오류 발생시 입력 내용 유지를

> questionForm.html에

- <input type="text"  th:field="*{subject}"  class="form-control">

- <textarea th:field="*{content}"  class="form-control"  rows="10"></textarea> 로 변경

원래 name="subject"  name="content" 이 있는 내용부에 시행

 

 

-

 

 

답변 등록을 위해

- AnswerForm.java를 신규 작성한다

- public class AmswerForm을 작성

- @Getter @Setter 어노테이션을 달고

- private String content; 에

- 제목은 필요 없으니 @NotEmpty만 있으면 된다

 

-

 

답변 등록 폼을 적용하기 위해

- AnswerController의 @PostMapping method에 Form을 적용한다

- createAnswer의 signal은 총 4가지로 

- Model model, @PathVariable("id") Integer id, @Valid AnswerForm answerForm, BindingResult bindingResult 이다

- 나머지 처리는 questionController와 동일하나

- Q서비스에서 id를 통해 Q를 가져와야 한다는 것

- bindingResult 에러 처리에서 model.addAttribute("question", question); 메소드가 필요하다는 점

- this.answerService.create의 시그널로 (question, answerForm.getContent()); 이 필요하다는 것

- return String.format("redirect:/question/detail/%s, id"); 있으며

 

 

question_detail.html의 답변 등록 시 오류메세지 띄우기

- question_form과 똑같이 처리 하되

- th:object="*{answerForm}"으로 잡을 것

 

-

 

매개변수를 AnswerForm으로 변경했으므로 QController에도 변경 처리할 것

- import com.mysite.sbb.answer.AnswerForm; P/I를 가져온다

- detail method에 AnswerForm answerFrom signal로 변경