https://jangcenter.tistory.com/38에서 이어짐
주문 서비스(orders Microservice) 설계
기능 | apigateway-service URI | Method |
사용자 상품 주문 등록 | /order-service/{userId}/orders | POST |
사용자 상품 주문 내역 조회 | /order-service/{userId}/orders | GET |
주문 서비스 프로젝트 생성 및 기본설정
* h2의 버전 변경 자동으로 DB생성을 위해, modelmapper 의존성 추가
# porm.xml
.......
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
<version>1.3.176</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.8</version>
</dependency>
</dependencies>
.......
application.yml작성
# order-service/application.yml
server:
port: 0
spring:
application:
name: order-service
h2:
console:
enabled: true
settings:
web-allow-others: true
path: /h2-console
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb
username: sa
jpa:
hibernate:
ddl-auto: update-drop
eureka:
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:8761/eureka
order-service를 apigateway-service에 등록
어플리케이션 이름으로 접근/라우팅을 위해 apigateway-service에 등록
apigateway-service의 application.yml에 order-service의 라우팅 정보를 추가
# apigateway-service/application.yml
....
routes:
....
- id: order-service
predicates:
- Path=/order-service/**
uri: lb://ORDER-SERVICE
....
order-service 기능 구현
DB를 위한 VO, DTO, JPA 클래스
VO 패키지
// RequestOrder.java
// 주문에 대한 요청처리
package com.example.MSA_web.vo;
import lombok.Data;
@Data
public class RequestOrder {
private String productId;
private Integer qty;
private Integer unitPrice;
}
-----------------------------------------------------------------------------------------------
// ResponseOrder.java
// 응답 처리
package com.example.MSA_web.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseOrder {
private String productId;
private Integer qty;
private Integer unitPrice;
private Integer totalPrice;
private String orderId;
private String userId;
}
DTO 패키지
// OrderDto.java
package com.example.MSA_web.dto;
import java.io.Serializable;
import lombok.Data;
@Data
public class OrderDto implements Serializable {
private String productId;
private Integer qty;
private Integer unitPrice;
private Integer totalPrice;
private String orderId;
private String userId;
}
JPA 패키지
// OrderEntity.java
// 실제 DB 데이터
package com.example.MSA_web.jpa;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.ColumnDefault;
import lombok.Data;
@Data
@Entity
@Table(name="orders")
public class OrderEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable=false, length=120, unique=true)
private String productId;
@Column(nullable=false)
private Integer qty;
@Column(nullable=false)
private Integer unitPrice;
@Column(nullable=false)
private Integer TotalPrice;
@Column(nullable=false)
private String userId;
@Column(nullable=false, unique=true)
private String orderId;
@Column(nullable = false, updatable = false, insertable = false)
@ColumnDefault(value = "CURRENT_TIMESTAMP")
private Date createdAt;
}
----------------------------------------------------------------------------------------------
// OrderRepository.java
package com.example.MSA_web.jpa;
import org.springframework.data.repository.CrudRepository;
public interface OrderRepository extends CrudRepository<OrderEntity, Long> {
OrderEntity findByOrderId(String orderId);
Iterable<OrderEntity> findByUserId(String userId);
}
모듈 기능 구현
controller
// OrderController.java
package com.example.MSA_web.controller;
import java.util.ArrayList;
import java.util.List;
import org.apache.catalina.mapper.Mapper;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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 com.example.MSA_web.dto.OrderDto;
import com.example.MSA_web.jpa.OrderEntity;
import com.example.MSA_web.service.OrderService;
import com.example.MSA_web.vo.RequestOrder;
import com.example.MSA_web.vo.ResponseOrder;
@RequestMapping("/order-service")
@RestController
public class OrderController {
Environment env;
OrderService orderService;
@Autowired
public OrderController(Environment env, OrderService orderService) {
this.env = env;
this.orderService = orderService;
}
@GetMapping("/health_check")
public String healthCheck() {
// 할당받은 포트번호 출력
return String.format("OK ... Port num = %s", env.getProperty("local.server.port"));
}
@PostMapping("/{userId}/orders")
public ResponseEntity<ResponseOrder> createOrder(@PathVariable("userId") String userId, @RequestBody RequestOrder order){
ModelMapper mapper=new ModelMapper();
// ResponseOrder -> OrderDto
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
OrderDto orderDto =mapper.map(order, OrderDto.class);
// 본문에 저장되지 않은 유저 정보 저장
orderDto.setUserId(userId);
// create 서비스 호출
OrderDto resultDto=orderService.createOrder(orderDto);
//OrderDto -> ResponseOrder
ResponseOrder responseOrder=mapper.map(resultDto, ResponseOrder.class);
return ResponseEntity.status(HttpStatus.CREATED).body(responseOrder);
}
@GetMapping("/{userId}/orders")
public ResponseEntity<List<ResponseOrder>> getOrders(@PathVariable("userId") String userId){
Iterable<OrderEntity> orderList= orderService.getOrdersByUserId(userId);
List<ResponseOrder> resultList=new ArrayList<>();
orderList.forEach(v->{
resultList.add(new ModelMapper().map(v, ResponseOrder.class));
});
return ResponseEntity.status(HttpStatus.OK).body(resultList);
}
}
최종 테스트
각각의 연관관계 때무에 Eureka server -> apigateway-service -> user/catalog/order service 순으로 실행
Eureka 서버 확인
Eureka server, apigateway, user/catalog/order service가 전부 동작중인 것을 확인
각 서비스의 MSA 동작 확인 및 시나리오가 성공하는지 테스트
* 사용자 등록 -> 사용자 조회 -> 상품 조회 -> 주문 등록 -> 주문 조회 -> 추가 주문 -> 주문 조회
POST를 이용해 DB에 저장하기 편하게 하기 위해 Postman을 사용
사용자 등록
POST -- http://localhost:8000/user-service/users
{ "email": "tester@test.com", "name": "테스터", "pwd": "12341234" }
사용자 조회
GET -- http://localhost:8000/user-service/users
상품 조회
GET -- http://localhost:8000/catalog-service/catalogs
주문 등록
POST -- http://localhost:8000/order-service/USER_ID/orders
{ "productId": "CAT_01", "unitPrice": 1000, "qty": 20 }
주문 조회
GET -- http://localhost:8000/order-service/USER_ID/orders
추가 주문
POST -- http://localhost:8000/order-service/USER_ID/orders
{ "productId": "CAT_02", "unitPrice": 1500, "qty": 10 }
주문 조회
GET -- http://localhost:8000/USER_ID/orders
'Spring Cloud' 카테고리의 다른 글
Spring Cloud(MSA) 실습 - 웹 쇼핑몰 2. 카달로그 서비스 (0) | 2021.09.16 |
---|---|
Spring Cloud(MSA) 실습 - 웹 쇼핑몰 1. 기본 설정과 회원 서비스 (0) | 2021.09.15 |
Spring Cloud - 서비스 디스커버리 (0) | 2021.09.14 |
댓글