Spring

스프링 - Part 4 - REST 방식과 Ajax를 이용하는 댓글 처리 02 (Ajax 댓글 처리 - 02)

록's 2023. 3. 29. 18:38
728x90
반응형

https://rogi221.tistory.com/157

 

스프링 - Part 4 - REST 방식과 Ajax를 이용하는 댓글 처리 01 (REST 방식으로 전환)

REST 방식으로 전환 @RestController REST 방식에서 가장 먼저 기억해야 하는 점은 서버에서 전송하는 것이 순수한 데이터라는 점이다. 기존 Controller에서 Model에 데이터를 담아서 JSP 등과 같은(View)로 전

rogi221.tistory.com


 

Ajax 댓글 처리 - 02

 

서비스 영역과 Controller 처리

서비스 영역과 Controller의 처리는 기존의 BoardService와 동일하게 ReplyService 인터페이스와 ReplyServiceImpl 클래스로 작성한다.

 

 

ReplyService 인터페이스

// ReplyService.java

package org.codehows.service;

import java.util.List;

import org.codehows.domain.Criteria;
import org.codehows.domain.ReplyVO;

public interface ReplyService {

	public void register(ReplyVO board);
	
	public ReplyVO get(Long bno);
	
	public boolean modify(ReplyVO board);
	
	public boolean remove(Long bno);
	
	public List<ReplyVO> getList(Criteria cri, Long bno);
}

 

ReplyService를 구현하는 ReplyServiceImpl 클래스에는 @Service 어노테이션과 @Log4j를 적용한다.

 

ReplyServiceImpl 클래스

// ReplyServiceImpl.java

package org.codehows.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.codehows.domain.Criteria;
import org.codehows.domain.ReplyVO;
import org.codehows.mapper.ReplyMapper;


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 " + cri);
		
		return mapper.getListWithPaging(cri, bno);
	}
}

 

 

ReplyController의 설계

 

ReplyController는 앞의 예제에서 SampltController 와 유사하게 @RestController 어노테이션을 이용해서 설계하며 다음과 같은 URL을 기준으로 동작할 수 있게 작성한다.

 

 

REST 방식으로 동작하는 URL을 설계할 때는 PK를 기준으로 작성하는 것이 좋다.

PK만으로 조회, 수정, 삭제가 가능하기 때문이다. 

댓글의 목록은 PK를 사용할 수 없기 떄문에 파라미터로 필요한 게시물의 번호(bno)와 페이지 번호(page) 정보들을 URL에서 표현하는 방식을 사용한다.

 

 

ReplyController는 ReplyService 타입의 객체인 ReplyServiceImpl 객체를 주입받도록 설계한다.

 

ReplyController의 일부

// ReplyController.java

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 타입의 객체를 필요로 하는 생성자를 만들어서 사용한다.

 

 

 

 

등록 작업과 테스트

 

REST 방식으로 처리할 때 주의해야 하는 점은 브라우저나 외부에서 서버를 호출할 때 데이터의 포맷과 서버에서 보내주는 데이터의 타입을 명확히 설계해야 하는 것이다.

 

ReplyController 클래스

// ReplyController.java

package org.codehows.controller;

import org.codehows.domain.ReplyVO;
import org.codehows.service.ReplyService;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
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;
	
	@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() 의 파라미터는 @RequestBody를 적용해서 JSON 데이터를 ReplyVO 타입으로 변환하도록 지정한다.

 

 

테스트

POST 방식으로 전송 - JSON 형식으로 입력

{"bno":195, "reply":"Hello Reply","replyer":"user00"}

Send Request 클릭

성공했다면

 

작성된 댓글은 데이터베이스에 정상적으로 추가 되었는지 확인한다.

<sql>

select * from tbl_reply order by rno desc;

 

 

 

 

 

특정 게시물의 댓글 목록 확인

 

특정 게시물의 댓글 목록을 확인하는 작업은 아래와 같이 작성한다.

 

ReplyController 클래스

// ReplyController.java

... 생략 ...

	@GetMapping(value = "/pages/{bno}/{page}",
			produces = {
					MediaType.APPLICATION_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);
	}

 

ReplyController의 getList()는 Criteria를 이용해서 파라미터를 수집하는데, '/{bno}/{page}'의 'page' 값은 Criteria를 생성해서 직접 처리해야한다.

 

 

 

댓글 삭제/조회

 

RestController의 댓글의 수정/삭제/조회는 위와 유사한 방식으로 JSOn이나 문자열을 반환하도록 설계한다.

 

ReplyController 클래스

// ReplyController.java

... 생략 ...

	@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);
	}
}

 

 

 

댓글 수정

 

댓글 수정은 JSON 형태로 전달되는 데이터와 파라미터로 전달되는 댓글 번호(rno)를 처리하기 떄문에 아래와 같이 처리한다.

 

ReplyController.java

// ReplyController.java

... 생략 ...

@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 파라미터를 처리할 수 없기 때문에 직접 처리해주는 부분을 주의해야한다.

 

 

 

 


https://rogi221.tistory.com/160

 

728x90
반응형