https://bobo12.tistory.com/318
3. 서비스 영역과 Controller 처리
▷ 서비스 영역과 Controller 처리는 기존의 BoardService와 동일하게 ReplyService 인터페이스, ReplyServiceImpl 클래스 작성
◎ ReplyService 인터페이스 생성
package org.codehows.service; import java.util.List; import org.codehows.domain.Criteria; import org.codehows.domain.ReplyVO; public interface ReplyService { public int register(ReplyVO vio); public ReplyVO get(Long rno); public int modify(ReplyVO vo); public int remove(Long rno); public List<ReplyVO> getList(Criteria cri, Long bno); }
◎ ReplyServiceImpl 클래스 생성
▷ @Service 어노테이션, @Log4j 적용
package org.codehows.service; import java.util.List; import org.codehows.domain.Criteria; import org.codehows.domain.ReplyVO; import org.codehows.mapper.ReplyMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import lombok.Setter; import lombok.extern.log4j.Log4j; @Service @Log4j public class ReplyServiceImpl implements ReplyService { @Setter(onMethod_ = @Autowired) private ReplyMapper mapper; @Override public int register(ReplyVO vo) { log.info("register......" + vo); return mapper.insert(vo); } @Override public ReplyVO get(Long rno) { log.info("get......." + rno); return mapper.read(rno); } @Override public int modify(ReplyVO vo) { log.info("modify......" + vo); return mapper.update(vo); } @Override public int remove(Long rno) { log.info("remove......" + rno); return mapper.delete(rno); } @Override public List<ReplyVO> getList(Criteria cri, Long bno) { log.info("get Reply List of a Board : " + bno); return mapper.getListWithPaging(cri, bno); } }
ReplyServiceImpl은 ReplyMapper에 의존적인 관계이므로 위 코드와 같이 @Setter를 이용해서 처리합니다.
만약 스프링 4.3를 사용한다면 아래와 같이 생성자와 자동 주입을 통해 저리할 수 있습니다.@Service @Log4j @AllArgsConstructor public class ReplyServiceImpl implements ReplyService { private ReplyMapper mapper; ...(생략)... }
(1) ReplyController의 설계
▷ SampleController와 유사하게 @RestController 어노테이션을 이용해 설계하며 아래와 같은 URL 기준으로 동작
NO | 작업 | URL | HTTP 전송방식 |
1 | 등록 | /replies/new | POST |
2 | 조희 | /replies/:rno | GET |
3 | 삭제 | /replies/:rno | DELETE |
4 | 수정 | /replies/:rno | PUT or PATCH |
5 | 페이지 | /replies/pages/:bno/:page | GET |
▷ REST 방식으로 동작하는 URL 설계시 PK 기준으로 작성하는 것이 좋음 (PK만으로 조회, 수정, 삭제 가능하기 때문)
▷ 댓글의 목록은 PK를 사용할 수 없으므로 게시물 번호(bno)와 페이지 번호(page) 정보들을 URL에서 표현하는 방식 사용
◎ ReplyController 클래스 생성
▷ ReplyService 타입 객체인 ReplyServiceImpl 객체 주입 받도록 설계
package org.codehows.controller; import org.codehows.service.ReplyService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import lombok.AllArgsConstructor; import lombok.extern.log4j.Log4j; @RequestMapping("/replies/") @RestController @Log4j @AllArgsConstructor public class ReplyController { private ReplyService service; }
@Setter를 주입하거나 @AllArgsConstructor를 이용해 ReplyService 타입의 객체를 필요로 하는 생성자 만들어 사용
(2) 등록 작업 테스트
▷ REST 방식으로 처리할 때 주의할 점은 브라우저나 외부에서 서버를 호출할 때 데이터 포맷과 서버에서 보내주는 데이터 타입을 명확하게 설계해야 함
▷ 댓글 등록의 경우 브라우저에서는 JSON 타입으로 된 댓글 데이터를 전송, 서버에서는 댓글의 처리 결과가 정상적으로 되었는지 문자열로 결과를 알려줌
◎ ReplyController 클래스 일부
@PostMapping(value = "/new", consumes = "application/json", produces = { MediaType.TEXT_PLAIN_VALUE }) public ResponseEntity<String> create(@RequestBody ReplyVO vo){ log.info("ReplyVO: " + vo); int insertCount = service.register(vo); log.info("Reply INSERT COUNT: " + insertCount); return insertCount == 1 ? new ResponseEntity<>("success", HttpStatus.OK) : new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); }
create()는 @PostMapping으로 POST 방식으로만 동작하도록 설계하고,
consumes와 produces를 이용해 JSON 방식의 데이터만 처리하도록 하고, 문자열은 반환하도록 설계
▷ create()는 내부적으로 ReplyServiceImpl을 호출해 register()를 호출하고, 댓글이 추가된 숫자를 확인해 브라우저에서 '200 OK' 혹은 '500 Internal Server Error' 반환
▷ 테스트시 POST 방식으로 전송, 'Content-Type'은 'application/json'으로 지정
▷ 실제 존재하는 게시물 번호, 댓글 내용, 댓글 작성자를 JSON 문법에 맞게 작성하도록 주의
◎ URL : http://localhost:8080/replies/new
◎ Payload : {"bno" : 2005745, "reply" : "Hello Reply", "replyer" : "user00"}
오라클에 아래와 같이 전달된 것을 볼 수 있습니다.
(3) 특정 게시물의 댓글 목록 확인
▷ 특정 게시물의 댓글 목록 확인하는 작업 작성
◎ ReplyController 클래스 메소드 추가
@GetMapping(value = "/pages/{bno}/{page}", produces = { MediaType.APPLICATION_ATOM_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE }) public ResponseEntity<List<ReplyVO>> getList( @PathVariable("page") int page, @PathVariable("bno") Long bno){ log.info("getList................."); Criteria cri = new Criteria(page, 10); log.info(cri); return new ResponseEntity<>(service.getList(cri, bno), HttpStatus.OK); }
'/{bno}/{page}'의 'page' 값은 Criteria를 생성해서 직접 처리
게시물 번호는 @PathVariable을 이용해서 파라미터로 처리하고 브라우저에서 아래와 같이 테스트
▷ http://localhost:8080/replies/pages/2005745/1.json
만약 XML 타입으로 확인하고 싶다면 http://localhost:8080/replies/pages/2005745/1 의 주소로 접속
(4) 댓글 삭제/조회
▷ 댓글의 수정/삭제/조희는 JSON이나 문자열을 반환하도록 설계
◎ ReplyController 클래스 내용 추가
@GetMapping(value = "/{rno}", produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE }) public ResponseEntity<ReplyVO> get(@PathVariable("rno") Long rno){ log.info("get: " + rno); return new ResponseEntity<>(service.get(rno), HttpStatus.OK); } @DeleteMapping(value = "/{rno}", produces = {MediaType.TEXT_PLAIN_VALUE}) public ResponseEntity<String> remove(@PathVariable("rno") Long rno){ log.info("remove: " + rno); return service.remove(rno) == 1 ? new ResponseEntity<>("success", HttpStatus.OK) : new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); }
(5) 댓글 수정
▷ 댓글 수정은 JSON 형태로 전달되는 데이터와 파라미터로 전달되는 댓글 번호(rno)를 처리하기 때문에 아래와 같이 처리
@RequestMapping(method = {RequestMethod.PUT, RequestMethod.PATCH }, value = "/{rno}", consumes = "application/json", produces = {MediaType.TEXT_PLAIN_VALUE}) public ResponseEntity<String> modify( @RequestBody ReplyVO vo, @PathVariable("rno") Long rno){ vo.setRno(rno); log.info("rno: " + rno); log.info("modify: " + vo); return service.modify(vo) == 1 ? new ResponseEntity<>("success", HttpStatus.OK) : new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); }
▷ 댓글 수정은 'PUT' 방식이나 'PATCH' 방식을 이용하도록 처리
▷ 실제 수정되는 데이터는 JSON 포맷이므로 @RequestBody를 이용해서 처리
▷ @RequestBody로 처리되는 데이터는 일반 파라미터나 @PathVariable 파라미터 처리할 수 없어서 직접 처리해 주는 부분을 주의
이번에는 서비스 영역과 Controller 처리를 통해 ReplyController를 설계하고 등록, 확인, 삭제, 조회, 수정 등의 작업을 진행했습니다.
이전에 확장자 추가했던 것을 바탕으로 데이터를 전달하고 등록할 수 있는 방법 등에 대해서 배워보았습니다.
데이터베이스에 값을 전달하는 방법이 여러가지 있다는 것이 좀 신기하면서 왜 구분이 되어 있는지 의문이 좀 들었습니다.
아직 모르는 부분이 많은데 하나씩 알아가면서 공부를 해야겠다는 생각이 많이 드네요,,ㅎㅎ
다음 글에서는 JavaScript를 이용하여 홈페이지를 구동하는 것에 대해 공부해볼게요!!
많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~
'BackEnd > Spring' 카테고리의 다른 글
[코드로 배우는 스프링 웹 프로젝트] ch17 Ajax 댓글 처리 5 (댓글의 목록, 삭제 및 갱신, 수정, 조회 처리) (0) | 2023.04.03 |
---|---|
[코드로 배우는 스프링 웹 프로젝트] ch17 Ajax 댓글 처리 4 (JavaScript의 모듈화) (0) | 2023.04.02 |
[코드로 배우는 스프링 웹 프로젝트] ch17 Ajax 댓글 처리 2 (조회, 수정, 삭제) (0) | 2023.04.02 |
[코드로 배우는 스프링 웹 프로젝트] ch17 Ajax 댓글 처리 1(Ajax, 게시물 등록) (0) | 2023.04.02 |
[코드로 배우는 스프링 웹 프로젝트] ch16 REST 방식으로 전환 3(@RestController, 테스트 방법) (0) | 2023.03.31 |