MSA Project[5] order service 추가

최준호·2021년 10월 3일
0

2021 msa

목록 보기
9/10

order service 추가

order service는 사용자의 주문과 주문을 확인할 수 있는 서비스를 제공한다.

프로젝트 생성

  1. Spring-web
  2. Spring devTools
  3. jpa
  4. h2
  5. lombok
  6. Eureka client

dependency를 추가하여 프로젝트를 생성해준다.

pom.xml 설정

이전 catalog service와 동일하게

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.3.176</version>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>2.3.8</version>
</dependency>

dependency를 추가하여 프로젝트 진행에 막히는게 없도록 한다.

application.yml 설정

application.properties 파일을 수정 또는 삭제 후 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:
    database-platform: org.hibernate.dialect.H2Dialect
    hibernate:
      ddl-auto: update
    show-sql: true

eureka:
  instance:
    #instance-id: ${spring.cloud.client.hostname} 으로 작성시 ip 번호로 들어옴
    instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
  client: #eureka에 등록할지에 대한 설정
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka #eureka 서버 정보

logging:
  level:
    com.example.orderserivce: DEBUG

설정 정보를 넣어준다. catalogs service와 거의 동일한 내용이고 jpa 부분만 수정되었다.

프로젝트의 구성

패키지를 다음과 같이 미리 생성해준 뒤 프로젝트를 하나씩 구성해가보겠다.

jpa 패키지

jpa라는 패키지는 jpa와 프로젝트가 연결되는데 필요한 Entity와 Repository를 설정하는 부분이다.

먼저 OrderEntity class를 생성한 후

@Data
@Entity
@Table(name = "orders")
public class OrderEntity implements Serializable {
    @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") //now()
    private Date createAt;
}

설정해주고 다음으로는 OrderRepository interface를 생성하여

public interface OrderRepository extends CrudRepository<OrderEntity, Long> {
    OrderEntity findByOrderId(String orderId);
    Iterable<OrderEntity> findByUserId(String userId);
}

설정을 해준다. 여기서 OrderEntity의 직렬화를 하는 이유는 우리가 작성한 object를 네트워크를 통해 전송하거나 데이터를 저장시키기 위해 byte stream으로 변환하는 과정을 위해 사용한다. 이렇게 하나의 객체를 저장과 전송에 알맞은 형태로 변환하는 과정을 마샬링이라 하고 객체를 전송받은 컴퓨터에서 해석하는 과정을 언마샬링이라 한다.

dto

@Data
public class OrderDto implements Serializable {
    private String productId;
    private Integer qty;
    private Integer unitPrice;
    private Integer totalPrice;

    private String orderId;
    private String userId;
}

vo

ResponseOrder

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseOrder {
    private String productId;
    private Integer qty;
    private Integer unitPrice;
    private Integer totalPrice;
    private Date createdAt;

    private String orderId;
}

RequestOrder

@Data
public class ReqeustOrder {
    private String productId;
    private Integer qty;
    private Integer unitPrice;
}

service

OrderService

public interface OrderService {
    OrderDto createOrder(OrderDto orderDetails);
    OrderDto getOrderByOrderId(String orderId);
    Iterable<OrderEntity> getAllOrdersByUserId(String userId);
}

OrderServiceImpl

@Service
public class OrderServiceImpl implements OrderService{

    OrderRepository orderRepository;

    @Autowired
    public OrderServiceImpl(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    @Override
    public OrderDto createOrder(OrderDto orderDto) {
        orderDto.setOrderId(UUID.randomUUID().toString());
        orderDto.setTotalPrice(orderDto.getQty() * orderDto.getUnitPrice());

        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        OrderEntity orderEntity = mapper.map(orderDto, OrderEntity.class);

        orderRepository.save(orderEntity);

        OrderDto returnValue = mapper.map(orderEntity, OrderDto.class);

        return returnValue;
    }

    @Override
    public OrderDto getOrderByOrderId(String orderId) {
        OrderEntity orderEntity = orderRepository.findByOrderId(orderId);
        ModelMapper mapper = new ModelMapper();
        OrderDto orderDto = mapper.map(orderEntity, OrderDto.class);
        return orderDto;
    }

    @Override
    public Iterable<OrderEntity> getAllOrdersByUserId(String userId) {
        return orderRepository.findByUserId(userId);
    }
}

controller

@RestController
@RequestMapping("/order-service")
public class OrderController {
    OrderService orderService;

    @Autowired
    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }

    @PostMapping("/{userId}/orders")
    public ResponseEntity<ResponseOrder> createOrder(@RequestBody ReqeustOrder order, @PathVariable("userId") String userId){
        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

        OrderDto orderDto = mapper.map(order, OrderDto.class);
        orderDto.setUserId(userId);
        OrderDto createOrder = orderService.createOrder(orderDto);

        ResponseOrder responseOrder = mapper.map(createOrder, ResponseOrder.class);

        return ResponseEntity.status(HttpStatus.CREATED).body(responseOrder);
    }

    @GetMapping("/{userId}/orders")
    public ResponseEntity<List<ResponseOrder>> getOrder(@RequestBody ReqeustOrder order, @PathVariable("userId") String userId){
        Iterable<OrderEntity> orderList = orderService.getAllOrdersByUserId(userId);

        List<ResponseOrder> result = new ArrayList<>();

        orderList.forEach(v -> {
            result.add(new ModelMapper().map(v, ResponseOrder.class));
        });

        return ResponseEntity.status(HttpStatus.OK).body(result);
    }
}

api gateway 등록

그림과 같이 api gateway에 order service를 추가로 등록해준다.

서비스 확인

지금까지 학습한 user service, catalog service, order service를 모두 실행시켜서 Eureka에 정상적으로 등록되는지 확인해보고 postman을 사용하여 실제로 테스트 해보자!

api gateway로 사용하기 때문에 8000번 포트로 user를 정상적으로 등록되는 것을 먼저 확인했다.

그 후 get method로 변경하여 검색 후 userId를 order를 위해 기억해두자.

catalog service도 정상적으로 실행되는 것을 확인하고

위에서 가져온 userId 값과 catalog에 등록된 상품 정보를 갖고 json 데이터로 post 요청을 해본다.

요청 결과가 우리가 지정한 상태 코드 값인 201로 반환되는 것을 확인할 수 있다.

그리고 get method로 다시 요청시 요청했던 주문을 확인할 수 있으며

하나의 주문을 더 생성하여 확인해보면 2개의 주문이 정상적으로 나온다.

출처

profile
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글