01. 게시판 프로젝트 소개
# 게시판 주요 기능
1. 글 쓰기(/board/save)
2. 글 목록 (/board/)
3. 글 조회(/board/{id})
4. 글 수정(/board/update/{id})
5. 글 삭제(/board/delete/{id})
6. 페이징 처리(/board/paging)
02. application.yml 세팅
- dependencies
- application.yml
# 서버 포트 설정
server:
port: 8092
# database 연동 설정
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?serverTimeZone=Asia/Seoul&characterEncoding=UTF-8
username: root
password: 1234
thymeleaf:
cache: false
# spring data jpa 설정
jpa:
database-platform: org.hibernate.dialect.MySQLDialect
open-in-view: false
show-sql: true
hibernate:
ddl-auto: create
전의 회원프로젝트와 같이 application.yml을 설정해준다.
포트 번호를 8092로 설정해두었기 때문에 localhost:8092로 접속한다.
ddl-auto 는 한 번 실행 후 create에서 update로 변경한다.
03. 게시글 작성 : (1) 작성 페이지 이동하기
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<button onclick="saveReq()">글 작성</button>
</body>
<script>
const saveReq=() => {
location.href="/board/save"
}
</script>
</html>
index 페이지에서 "글 작성" 버튼을 생성한다.
글 작성 버튼을 클릭하면 /board/save로 url이 이동한다.
function saveReq() { } 과 const saveReq = () => { } 는 같은 역할을 한다. (함수 호출)
const ~ 는 ES6 방식의 함수 호출이며, 자바 스크립트 최신 문법으로 자주 쓰인다.
-BoardController
@Controller
@RequiredArgsConstructor
@RequestMapping("/board")
public class BoardController {
private final BoardService boardService;
@GetMapping("/save")
public String saveForm(){
return "save";
}
/board/save를 get해올 때, save.html을 반환한다.
이때 @GetMapping("/board/save")를 사용해도 되지만, ("/board")를 먼저 붙이고, 메소드 마다 다른 url을 합칠 수 있다.
위의 코드처럼 @RequestMapping("/board")를 사용하고, 하단 GetMapping("/save")를 사용하면, 해당 url은 /board/save가 된다.
또 다른 Mapping을 BoardController에 추가하여도, 앞에 "/board"가 붙게 된다.
- save.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Save</title>
</head>
<body>
<!-- action속성: 목적지(서버주소), method속성: http request method(get, post) -->
<form action="/board/save" method="post" enctype="multipart/form-data">
writer: <input type="text" name="boardWriter"> <br>
pass: <input type="text" name="boardPass"> <br>
title: <input type="text" name="boardTitle"> <br>
contents: <textarea name="boardContents" cols="30" rows="10"></textarea> <br>
<input type="submit" value="글작성">
</form>
</body>
</html>
작성자, 비밀번호, 제목, 내용과 제출 버튼이 있는 페이지를 작성한다.
내용은 textarea로 선언하여 input type="text"보다 넓은 칸을 쓸 수 있게 만든다.
03. 게시글 작성 : (2) 게시글 작성 완료
- BoardController
@Controller
@RequiredArgsConstructor
@RequestMapping("/board")
public class BoardController {
private final BoardService boardService;
@GetMapping("/save")
public String saveForm(){
return "save";
}
@PostMapping("/save")
// 같은 주소, 다른 method 는 가능하지만 같은 주소 같은 method 는 불가능
public String save(@ModelAttribute BoardDTO boardDTO){
System.out.println("boardDTO = " + boardDTO);
boardService.save(boardDTO);
return "index";
}
}
BoardController에 PostMapping을 추가한다.
이때 @GetMapping("/save")와 url이 동일하다.
이처럼 같은 주소, 다른 method는 가능하지만, 같은 주소, 같은 method는 Ambiguous mapping 에러가 발생한다.
/board/save에 post요청이 들어오면 boardService.save(boardDTO)를 호출한다.
- BoardDTO
// DTO(Data Transfer Object), VO, Bean <----> (다른 목적) Entity
@Getter
@Setter
@ToString
@NoArgsConstructor // 기본 생성자
@AllArgsConstructor // 모든 필드를 매개변수로 하는 생성자
public class BoardDTO {
private Long id;
private String boardWriter;
private String boardPass;
private String boardTitle;
private String boardContents;
private int boardHits;
private LocalDateTime boardCreatedTime;
private LocalDateTime boardUpdatedTime;
}
데이터 전송을 위한 객체, DTO를 만들어준다.
사용자가 입력할 boardWriter, boardPass, boardTitle, boardContents를 선언한다.
그리고 데이터베이스에 저장할 나머지 조회수, 생성 시간, 수정 시간 또한 선언한다.
-BoardEntity
// DB의 테이블 역할을 하는 클래스
@Entity
@Getter
@Setter
@Table(name = "board_table")
public class BoardEntity extends BaseEntity{
@Id // pk 컬럼 지정. 필수
@GeneratedValue(strategy = GenerationType.IDENTITY) // auto_increment
private Long id;
@Column(length = 20, nullable = false) // 크기 20, not null
private String boardWriter;
@Column // 크기 255, null 가능
private String boardPass;
@Column
private String boardTitle;
@Column(length = 500)
private String boardContents;
@Column
private int boardHits;
public static BoardEntity toSaveEntity(BoardDTO boardDTO){
BoardEntity boardEntity = new BoardEntity();
boardEntity.setBoardWriter(boardDTO.getBoardWriter());
boardEntity.setBoardPass(boardDTO.getBoardPass());
boardEntity.setBoardContents(boardDTO.getBoardContents());
boardEntity.setBoardTitle(boardDTO.getBoardTitle());
boardEntity.setBoardHits(0);
return boardEntity;
}
}
Entity를 작성한다. DB의 테이블 역할을 하는 클래스이다.
@Column 후 아무것도 쓰지 않으면 기본적으로 크기가 255, null이 가능한 컬럼이다.
@Column(length = 20, nullable = false)은 크기가 20, not null인 컬럼이다.
DTO를 받아 Entity로 반환하는 함수, toSaveEntity를 작성한다.
- BaseEntity
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
public class BaseEntity {
@CreationTimestamp
@Column(updatable = false)
private LocalDateTime createdTime;
@UpdateTimestamp
@Column(insertable = false)
private LocalDateTime updatedTime;
}
생성 시간과 수정 시간은 게시판 외에 다른 곳에서도 공통적으로 사용될 가능성이 있기 때문에
BaseEntity로 따로 선언해둔다.
BoardEntity에서 extends BaseEntity를 통해 상속받아 사용한다.
- BoardRepository
public interface BoardRepository extends JpaRepository<BoardEntity, Long> {
}
! 인터페이스로 작성한다.
JpaRepository<접근할 Entity, pk컬럼의 타입>을 상속받는다.
- BoardService
// DTO -> Entity (Entity Class)
// Entity -> DTO (DTO Class)
@Service
@RequiredArgsConstructor
public class BoardService {
private final BoardRepository boardRepository;
public void save(BoardDTO boardDTO) {
BoardEntity boardEntity = BoardEntity.toSaveEntity(boardDTO);
boardRepository.save(boardEntity);
}
}
boardRespostiory를 사용하기 위해 @RequiredArgsConstructor을 추가한다.
BoardEntity에서 선언했던 toSaveEntity를 사용하여, DTO를 Entity로 변경한다.
변경된 Entity를 Repository에 저장(save)한다.
(Repository.save를 사용하기 위해서는 Entity객체가 들어가야 하기 때문)
보통 DTO -> Entity 변환은 Entity Class에서 정의하고,
그 반대의 경우 DTO Class에서 정의한다.
- 결과
글 작성을 클릭하면
데이터 베이스에 created_time과 더불어 id, writer, contents, pass, title이 저장된 것을 볼 수 있다.
해당 글은 코딩레시피님의 스프링 부트 쉽게 해보기 : 게시판 프로젝트 영상을 보고 공부한 글입니다.
https://youtu.be/YshcPPHClR4?si=IeT6iSwHJGLs_jgL
'Heute lerne ich > Java' 카테고리의 다른 글
[스프링부트 게시판 프로젝트] 목록/조회/수정/삭제 (0) | 2024.03.29 |
---|---|
[스프링부트 회원 프로젝트] ajax 이메일 중복체크 (1) | 2024.03.24 |
[스프링부트 회원 프로젝트] 로그아웃 (1) | 2024.03.24 |
[스프링부트 회원 프로젝트] 회원목록 출력/상세 조회/수정/삭제 (1) | 2024.03.23 |
[스프링부트 회원 프로젝트] 로그인 (0) | 2024.03.21 |