RestTemplate 주문서비스 구현

2019. 10. 20. 00:12Spring Micro Services/RestTemplate

반응형

주문서비스

 

사용자의 입장에서 보면 시스템이 주문서비스,결제서비스,상품서비스로 나누어 져서 처리 된다는 것을 알지도 못하며 알필요도 없을 것이다. 

 

하지만 시스템의 입장에서는 모든 서비스의 정보를 입력 정보로 사용자로부터 전달 받아야 할것이다.

먼저 간단히 주문서비를 위한 시나리오를 만들어 보도록 하겠다.

 

 

시나리오


1.사용자는 800원짜리 진라면2개와 2900 짜리 참치 한개를 구매한다.

2.사용자는 결제를 카드결제 4000원 포인트결제 500원으로 해서 총 4500원 결제 처리를 한다.

3.시스템은 주문정보가 정상적으로 처리되면 결제서비스를 호출 하여 결제처리를 한 후 결제 처리를 한다.

4.시스템은 결제처리가 정상적으로 처리되면 상품서비스를 호출 하여 상품의 재고 수량을 수정 한다.

5.시스템은 사용자로 부터 전달 받은 주문정보를 주문서비스를 통하여 주문정보를 저장한다.

6.시스템은 주문상태를 완료로 업데이트 처리한다.

 

서비스 처리시 트랜잭션 문제가 발생할 수 있다. 결제처리는 완료 하고 상품이나 주문서비스 처리 중 오류가 발생하

   는 경우 Rollback 처리를 해야 하는데 하나의 서비스에서 처리하는 경우 서비스레벨에서 Transaction 처리를 하면 

   Rollback 처리가 가능 하나 Micro service 기반에서 불가능 하다. 

 

   이에 대한 해결방법은 Message Queue 방식을 많이들 이야기 한다. 이부분에 대해서는 나중에 다뤄 볼 생각이다.

 

   우선 이서비스에서는 주문 테이블에 주문상태를 최초에는 'T'로 설정 하고 결제와 상품 재고 처리가 완료 되면 'C'로

   변경 하도록 구현 하였다.

 

 

 

RestTemplate 연동


전체적인 소스 설명을 하기에는 너무 내용이 많기 때문에 소스는 Github에 공유 하도록 하겠습니다. 각 서비스를 연결하는 Controller 소스만 살펴 보도록 하겠다.

 

 

[OrderController]

호출URL: http://localhost:7000/order

package com.roopy.services.order.controller;

import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.roopy.services.order.domain.Order;
import com.roopy.services.order.helper.IDGeneratorHelper;
import com.roopy.services.order.service.IOrderService;

@RestController
public class OrderController {
	
	@Autowired
	private RestTemplate rest Template;
	
	@Autowired
	private IOrderService orderService;
	
	@Autowired
	private IDGeneratorHelper idGenerator;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value = "/order", method = RequestMethod.POST)
	public Order save(HttpServletRequest request, HttpServletResponse response,
			@RequestBody Order order) throws Exception {
		
		// 주문ID생성
		String orderId = idGenerator.getOrderId();
		
		// 주문ID설정
		order.setOrderId(orderId);
		
		// 주문날짜설정
		order.setOrderDtm(orderId.substring(1));
		
		// 결제처리
		HttpEntity<Order> ordRequest = new HttpEntity<>(order);
		ResponseEntity<List> pymentResponse =  restTemplate.postForEntity("http://localhost:7001/payment", ordRequest, List.class);
		
		// 상품수량업데이트처리
		ResponseEntity<List> productResponse = null;
		if (pymentResponse.getStatusCodeValue() == 200) {
			productResponse =  restTemplate.postForEntity("http://localhost:7002/product", ordRequest, List.class);
		}
		
		// 주문정보저장
		if (pymentResponse.getStatusCodeValue() == 200 && productResponse.getStatusCodeValue() == 200) {
			// 결제처리와 상품정보 업데이트가 정상적으로 처리 된 경우 주문상태를 완료로 변경한다.
			order.setOrderStatus("C");
			order = orderService.save(order);
			order.setPayments(pymentResponse.getBody());
		}
		
		return order;
	}
	
	@RequestMapping(value = "/order/{orderId}", method = RequestMethod.POST)
	public Order findOrder(HttpServletRequest request, HttpServletResponse response, @PathVariable String orderId,
			@RequestParam HashMap<String, String> param) throws Exception {
		
		return orderService.find(orderId);
	}
	
}

 

 

[PaymentController]

호출URL: http://localhost:7001/payment

package com.roopy.services.payment.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.roopy.services.payment.domain.Order;
import com.roopy.services.payment.domain.Payment;
import com.roopy.services.payment.service.IPaymentService;

@RestController
public class PaymentController {

	@Autowired
	private IPaymentService paymentService;

	@RequestMapping(value = "/payment", method = RequestMethod.POST)
	public List<Payment> save(HttpServletRequest request, HttpServletResponse response,
			@RequestBody Order order) throws Exception {
		
		order = paymentService.save(order);
		
		return order.getPayments();
	}
	
}

 

 

[ProductController]

호출URL: http://localhost:7002/product

package com.roopy.services.product.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.roopy.services.product.domain.Order;
import com.roopy.services.product.service.IProductService;

@RestController
public class ProductController {
	
	@Autowired
	private IProductService productService;

	@RequestMapping(value = "/product", method = RequestMethod.POST)
	public void save(HttpServletRequest request, HttpServletResponse response,
			@RequestBody Order order) throws Exception {
		
		/*상품수량업데이트*/
		productService.save(order);
	}
}

 

소스URL : https://github.com/roopy1210/spring-msa-with-resttemplate

 

 

 

서버 실행


테스트를 위해서 각 서비스를 시작한다.

 

1.주문서비스 시작

  - OrderApplication 선택 우클릭 후 Run As > 3 Spring Boot App 실행

 

2.결제서비스 시작

  - PaymentApplication 선택 우클릭 후 Run As > 3 Spring Boot App 실행

 

3.상품서비스 시작

  - ProductApplication 선택 우클릭 후 Run As > 3 Spring Boot App 실행

 

 

[서버실행화면]

 

 

 

Postman 테스트


[주문요청]

 

 

[처리결과]

반응형

'Spring Micro Services > RestTemplate' 카테고리의 다른 글

RestTemplate 프로젝트 설정  (0) 2019.10.11