지난 웹 애플리케이션 제작과 연결된다.
https://julian5383.tistory.com/42
[Spring] 웹 애플리케이션 제작
1. 프로젝트 구조 생성 - Spring Starter Project로 프로젝트 생성하고 라이브러리 생성 2. pom.xml에 라이브러리 추가 - Add를 눌러 라이브러리를 추가한다.(querydsl-apt, querydsl-jpa, thymeleaf-layout-dia..
julian5383.tistory.com
1. REST 방식과 @RestController
- GET 방식 데이터를 보여주거나 다른 사람들에게 알리는 방식:
기본적으로 정보확산 목적, 인터넷상의 URL은 하나의 고유 데이터를 찾는 이름이나 태그가 됨
- POST 방식 데이터를 이용해서 특별한 작업을 처리하는 방식:
정보 가공이 목적, 정확한 목적을 가지고 특정수업을 수행하기 위해 사용
- REST 방식:
전송 방식 | 역할 |
GET | 특정 리소스를 조회(read)하는 용도로 사용 ex) /products/123 |
POST | 특정 리소스를 생성(create)하는 용도로 사용 ex) /products/ 혹은 /member/123 |
PUT | 특정 리소스 수정 |
DELETE | 특정 리소스 삭제 |
- REST 방식 설계위한 어노테이션:
@RequestBody | 클라이언트가 보내는 JSON 데이터의 수집 및 가공 |
@ResponseBody | 클라이언트에게 전송되는 데이터에 맞게 MINE 타입 결정 |
@PathVariable | URL의 경로에 포함된 정보 누출 |
@RestController | 컨트롤러의 모든 메소드 리턴 타입으로 @ResponseBody를 기본으로 지정 |
2. JPA 설계 및 연관관계 설정
package org.zerock.domain;
import java.sql.Timestamp;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@Entity
@Table(name="tbl_webreplies")
@EqualsAndHashCode(of="rno")
@ToString
public class WebReply {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long rno;
private String replyText;
private String replyer;
@CreationTimestamp
private Timestamp regdate;
@UpdateTimestamp
private Timestamp updatedate;
@JsonIgnore
/*양방향의 경우 이러한 변환이 상호 호출되기 때문에
무한히 반복해서 생성하는 문제가 생길수 있어서 특정 속성은
JSON으로 변환되지 않도록 @JsonIgnore 적용*/
@ManyToOne(fetch = FetchType.LAZY)
//WebBoard와 WebReply는 양방향 관계로 설정해서 WebReply는 다대일로 설정
private WebBoard board;
}
- WebReply.java
package org.zerock.domain;
import java.sql.Timestamp;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@Entity
@Table(name="tbl_webboards")
@EqualsAndHashCode(of="bno")
@ToString
public class WebBoard {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long bno;
private String title;
private String writer;
private String content;
@CreationTimestamp
private Timestamp regdate;
@UpdateTimestamp
private Timestamp updatedate;
@OneToMany(mappedBy = "board", fetch = FetchType.LAZY)
private List<WebReply> replies;
// WebReply에는 WebBoard를 @ManyToOne 관계로 설정하고, WebBoard에는 @OneToMany 관계를 설정
// 연관관계의 설정
}
- WebBoard.java
3. WebReplyRepository 설계
package org.zerock.persistence;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.zerock.domain.WebBoard;
import org.zerock.domain.WebReply;
public interface WebReplyRepository extends JpaRepository<WebReply, Long>{
@Query("SELECT r FROM WebReply r WHERE r.board = ?1 "+" AND r.rno > 0 ORDER BY r.rno ASC")
public List<WebReply> getRepliesOfBoard(WebBoard webBoard);
}
4. WebReplyController 설계
- 각 작업을 위한 URL 설계(REST 방식)
기능 | 전송 방식 | URI 예 |
특정 게시물의 댓글 추가 | POST | /replies/게시물 번호 |
특정 게시물의 댓글 삭제 | DELETE | /replies/게시물 번호/댓글 번호 |
특정 게시물의 댓글 수정 | PUT | /replies/게시물 번호 |
특정 게시물의 댓글 댓글 | GET | /replies/게시물 번호 |
package org.zerock.controller;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import javax.annotation.PostConstruct;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.zerock.domain.WebBoard;
import org.zerock.domain.WebReply;
import org.zerock.persistence.WebReplyRepository;
@RestController
@RequestMapping("/replies/")
public class WebReplyController {
@Autowired
WebReplyRepository repo;
@PostConstruct
public void init() {
Long arr[] = {304L, 303L, 300L};
//tbl_webboards 테이블에서 304, 303, 300 번호를 입력
Arrays.stream(arr).forEach(num->{
WebBoard board = new WebBoard();
board.setBno(num);
IntStream.range(0, 10).forEach(i->{
//지정된 게시물의 번호를 이용해서 댓글을 10개씩 추가
WebReply reply = new WebReply();
reply.setReplyText("REPLY ..."+i);
reply.setReplyer("replyer"+i);
reply.setBoard(board);
repo.save(reply);
});
});
}
// 댓글 등록 후 목록 처리
@Transactional //addReply는 WebRepository에 save()작업과 findBoard()를 연속 호출해서 생성
@PostMapping("/{bno}")
public ResponseEntity<List<WebReply>> addReply(@PathVariable("bno")Long bno, @RequestBody WebReply reply){
WebBoard board = new WebBoard();
board.setBno(bno);
reply.setBoard(board);
repo.save(reply);
return new ResponseEntity<>(getListByBoard(board), HttpStatus.CREATED);
//ResponseEntity는 코드를 이용해서 직접 Http Response의 상태 코드와 데이터를 직접 제어해서 처리할 수 있음.
} // 댓글 추가하는 기능을 한다.
private List<WebReply> getListByBoard(WebBoard board)throws RuntimeException {
return repo.getRepliesOfBoard(board);
}
//댓글 삭제
@Transactional
@DeleteMapping("/{bno}/{rno}") //삭제 처리는 다음과 같이 변경
public ResponseEntity<List<WebReply>> remove(@PathVariable("bno")Long bno, @PathVariable("rno")Long rno){
repo.deleteById(rno);
WebBoard board = new WebBoard();
board.setBno(bno);
return new ResponseEntity<>(getListByBoard(board), HttpStatus.OK);
}
//댓글 수정
@Transactional
@PutMapping("/{bno}")
public ResponseEntity<List<WebReply>> modify(@PathVariable("bno")Long bno, @RequestBody WebReply reply) {
repo.findById(reply.getRno()).ifPresent(origin -> {
origin.setReplyText(reply.getReplyText());
repo.save(origin);
});
WebBoard board = new WebBoard();
board.setBno(bno);
return new ResponseEntity<List<WebReply>>(getListByBoard(board), HttpStatus.CREATED);
}
}
5. REST 방식 테스트
- 크롬 앱스토어에서 Yet Another REST Client 다운로드
1) 댓글 등록 처리 호출
- http://localhost:8080/replies/303을 입력하고 옆에 POST로 바꾼후 Payload에 위의 사진에 있는댈 입력하고 상태코드가 201이 뜨면 성공한 것이다.
2) 댓글 등록 후 목록 처리
- 프로젝트를 실행하고 YARC를 실행해 보면 댓글이 등록되고, 댓글들의 목록이 JSON 형태의 데이터로 반환
3) 댓글 삭제
- YARC에서 게시물 번호 300과 댓글 번호 25를 DELETE 방식으로 호출
- 자세히 보면 rno(댓글번호) 25가 지워져 있다.
4) 댓글 수정
- 화면 304번 게시물의 10번 댓글의 내용을 수정
- 댓글번호 10의 내용이 수정되었다.
'Spring_boot > Project' 카테고리의 다른 글
[Spring] 웹 보안 (0) | 2021.08.26 |
---|---|
[Spring] 스프링부트(Spring Tool suite) 설치 방법 (0) | 2021.08.22 |
[Spring] 웹 애플리케이션 제작 (0) | 2021.08.16 |
[Spring] Spring MVC를 이용한 통합 (0) | 2021.08.10 |
[Spring] Thymeleaf 동작 확인 (0) | 2021.08.08 |