mustache 문법 : 틀cs 만들기
수정 시, 헤더 클래스만 수정하면 됨
list.mustache
에 section위로 자르기
- layout 폴더 생성 >
header.mustache
생성 및 붙이기
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>blog</title>
</head>
<body>
<nav>
<ul>
<li>
<a href="/">홈</a>
</li>
<li>
<a href="/board/save-form">글쓰기</a>
</li>
</ul>
</nav>
<hr>
- 챗 GPT mustache 문법 검색 템플릿 폴더의 레이아웃 폴더에 header.mustache파일 어떻게 쓰는지
detail.mustache
list.mustache
{{> layout/header}} <section> <div> 번호 : {{model.id}} <br> 제목 : {{model.title}} <br> 내용 : {{model.content}} <br> 작성일 : {{model.createdAt}} <br> </div> </section> </body> </html>
{{> layout/header}}
<section>
<table border="1">
<tr>
<th>번호</th>
<th>제목</th>
<th></th>
</tr>
{{#models}}
<tr>
<td>{{id}}</td>
<td>{{title}}</td>
<td><a href="/board/{{id}}">상세보기</a></td>
</tr>
{{/models}}
</table>
</section>
</body>
</html>
글 작성
save-form.mustache
생성- form 태그 방식
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
{{> layout/header}}
<section>
<!--
1. form태그에 input넣어 데이터 한번에 전송
2. submit 전송 버튼 생성. 버튼을 form태그에 넣으면 'submit'이 됨
3. 액션에 전송 주소 추가 <form action="/board/save"> -board를 save 해달라
-왜 해당 방식을 사용했는지? 답) http 1.0 방식에 기본기를 합침
4. http 메서드 생성 method="post" -post방식
5. 바디 데이터를 들고갈 contentType 설정
-->
<form action="/board/save" method="post" enctype="application/x-www-form-urlencoded">
<input type="text" name="title" placeholder="제목"><br>
<input type="text" name="content" placeholder="내용"><br>
<button type="submit">글쓰기</button>
</form>
</section>
</body>
</html>
title=제목6&content내용6 => application/x-www-form-urlencoded
key값은 input태그의 name
value값은 input태그에 사용자가 입력하는 값

중요) form 태그 방식 3개 HTTP에서 데이터가 전송되는 방식은 Content-Type 헤더에 의해 결정된다
username=John+Doe&age=25 가장 일반적인 폼 데이터 전송 방식 키-값 쌍을 key1=value1&key2=value2 형태로 인코딩하여 서버 전송 GET 요청은 URL의 쿼리스트링으로, POST 요청은 본문에 포함
데이터를 경계(boundary)로 구분하여 여러 부분으로 나누어 전송
message=Hello, world!
데이터를 순수 텍스트 형식 전송
추가적인 인코딩이 없고, 각 입력 필드는 "키=값" 형식으로 한 줄에 하나
BoardRepository
글쓰기 쿼리문 작성- 글쓰기 쿼리문 테스트
public void save(String title, String content) {
Query q = em.createNativeQuery("insert into board_tb(title, content, created_at) values (?, ?, now())");
q.setParameter(1, title);
q.setParameter(2, content);
q.executeUpdate(); // 넣고 커밋해 -정상 return값은 1
}
@Test
public void save_test() {
// given
String title = "제목6";
String content = "내용6";
// when
boardRepository.save(title, content);
// eye
Board board = boardRepository.findById(6);
System.out.println(board.getId());
System.out.println(board.getTitle());
System.out.println(board.getContent());
} // rollback (@Transactional)
- 컨트롤러
BorderRequest
요청DTO생성BoardController
- 리다이렉션 설명
- 클라이언트 요청 (POST)
- 클라이언트(브라우저)에서
/board/save
URL로 POST 요청을 보냄 - 요청 데이터는
x-www-form-urlencoded
형식 전송 - 컨트롤러 처리
- 요청 데이터 처리:
saveDTO
객체로 데이터를 받음 - DTO에는 클라이언트가 보낸 폼 데이터가 매핑
- 데이터 출력:
System.out.println(saveDTO)
로 요청 데이터 확인 - 서비스 호출
boardService.게시글쓰기(saveDTO)
를 통해 비즈니스 로직 실행- 데이터베이스에 새로운 게시글 저장 등의 작업이 진행
- HTTP 응답 생성 (Redirection)
- HTTP 응답 상태를 302로 설정 (
response.setStatus(302)
) Location
헤더에 리다이렉션 대상 URL ("/"
)을 지정 (response.setHeader("Location", "/")
)- 브라우저는 서버의 응답에 따라 리다이렉션 경로로 자동 이동
- 클라이언트 동작
- 브라우저는 서버 응답을 확인하고, 지정된 URL(
/
)로 GET 요청을 보냄 - 클라이언트는 리다이렉션된 페이지를 화면에 표시
package com.example.blog.Board;
import lombok.Data;
public class BorderRequest {
@Data
public static class SaveDTO { // static 없으면 에러
private String title;
private String content;
}
}
수정 중
해당 코드를 알고 이해해야지 진행됨
@PostMapping("/board/save")
// x-www는 클래스로 받을 수 있다
public void save(BoardRequest.SaveDTO saveDTO, HttpServletResponse response) throws IOException {
System.out.println(saveDTO); // @Data는 내부에 toString을 재정의해서 구현해준다.
boardService.게시글쓰기(saveDTO);
response.setStatus(302); // header 302
response.setHeader("Location", "/");
}
중요) 데이터 흐름 및 처리 과정
- 서비스
@Transactional
public void 게시글쓰기(BorderRequest.SaveDTO saveDTO) {
boardRepository.save(saveDTO.getTitle(), saveDTO.getContent());
} // commit
Share article