본문 바로가기

BackEnd/Spring

[코드로 배우는 스프링 웹 프로젝트] ch17 Ajax 댓글 처리 3 (ReplyController를 이용한 CRUD)

728x90
반응형

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를 이용하여 홈페이지를 구동하는 것에 대해 공부해볼게요!!

 

많은 분들의 피드백은 언제나 환영합니다!  많은 댓글 부탁드려요~~

 

 

728x90
반응형