[MSA] Order-service 구현

jineey·2024년 11월 11일

MSA

목록 보기
16/36

Order-service

프로젝트 생성

📌 추가할 기능

  • 주문하기
  • 유저 아이디로 모든 주문 건들 확인
  • 주문 번호로 해당 주문 건 확인

📌 프로젝트 생성

  • Dependency 추가
    ➡ DevTools, Lombok, Web, Eureka Discovery Client, H2 Database,
    ModelMapper, Spring Data JPA

  • pom.xml 수정

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.2.224</version>
    <scope>runtime</scope>
</dependency>
<dependency>
      <groupId>org.modelmapper</groupId>
      <artifactId>modelmapper</artifactId>
      <version>2.3.8</version>
  </dependency>

📌 소스코드 작성

  • OrderServiceApplication.java 수정
package com.example.orderserivce;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class OrderSerivceApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderSerivceApplication.class, args);
    }

}
  • application.yml 수정
spring:
    application:
        name: order-service
    h2:
        console:
            enabled: true
            settings:
                web-allow-others: true
            path: /h2-console
    jpa:
        hibernate:
            ddl-auto: update
        database: h2
        defer-datasource-initialization: true
    datasource:
        driver-class-name: org.h2.Driver
        url: jdbc:h2:mem:testdb

server:
    port: 0

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://127.0.0.1:8761/eureka

logging:
    level:
        com.example.orderserivce: DEBUG
  • OrderEntity.java 추가
package com.example.orderserivce.jpa;

import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.ColumnDefault;

import java.io.Serializable;
import java.util.Date;

@Data
@Entity
@Table(name="orders")
public class OrderEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 120)
    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;

}

💡 직렬화(Serializable) 사용 이유
가지고 있는 Object를 다른 네트워크로 전송하거나 데이터베이스에 보관하기 위해서

  • OrderRepository.java 추가
package com.example.orderserivce.jpa;

import org.springframework.data.repository.CrudRepository;

public interface OrderRepository extends CrudRepository<OrderEntity, Long> {
    OrderEntity findByOrderId(String orderId);
    Iterable<OrderEntity> findByUserId(String userId);
}
  • OrderDto.java 추가
package com.example.orderserivce.dto;

import lombok.Data;

import java.io.Serializable;

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

    private String orderId;
    private String userId;
}
  • ResponseOrder.java 추가
package com.example.orderserivce.vo;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;

import java.util.Date;

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

    private String orderId;
}
  • OrderService.java 인터페이스 추가
package com.example.orderserivce.service;

import com.example.orderserivce.dto.OrderDto;
import com.example.orderserivce.jpa.OrderEntity;

public interface OrderService {
    OrderDto createOrder(OrderDto orderDetails);
    OrderDto getOrderByOrderId(String orderId);
    Iterable<OrderEntity> getAllOrdersByUserId(String userId);
}
  • OrderServiceImpl.java 추가
package com.example.orderserivce.service;

import com.example.orderserivce.dto.OrderDto;
import com.example.orderserivce.jpa.OrderEntity;
import com.example.orderserivce.jpa.OrderRepository;
import com.netflix.discovery.converters.Auto;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;

import java.util.UUID;

@Service
public class OrderServiceImpl implements OrderService {

    OrderRepository orderRepository;

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

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

        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        OrderEntity orderEntity = mapper.map(orderDetails, 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);
        OrderDto orderDto = new ModelMapper().map(orderEntity, OrderDto.class);

        return orderDto;
    }

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

💡 Dto와 Entity의 차이

  • Entity데이터베이스와의 직접적인 연관이 있는 객체이며, 데이터베이스에서 데이터를 가져오거나 저장할 때 사용
  • DTO데이터를 효율적으로 전송하기 위해 필요한 값만 포함한 객체이며, 서비스나 컨트롤러 간에 데이터를 주고 받을 때 사용하고, 필요에 따라 Entity에서 필요한 정보를 뽑아 전달
  • 둘은 서로 보완적인 역할을 하며, 다양한 계층 간에 데이터를 전송하고 관리하는데 중요한 역할
구분EntityDto
목적데이터베이스와 상호작용, 비즈니스 로직 포함데이터 전송 및 계층 간 데이터 교환
구성DB 테이블과 직접 매핑, 필드에서 실제 데이터 포함필요한 데이터만 포함, 간단한 구조
비즈니스 로직포함 가능 (데이터베이스 관련 로직 포함)포함하지 않음 (단순 데이터 구조)
사용 장소데이터베이스 저장/조회 작업서비스와 컨트롤러 간 데이터 전송
변경 주기데이터베이스와 함께 변경 (영속성 연관)데이터 전송 시 필요한 값만 포함
  • RequestOrder.java 추가
package com.example.orderserivce.vo;

import lombok.Data;

@Data
public class RequestOrder {
    private String productId;
    private Integer qty;
    private Integer unitPrice;
}
  • OrderController.java 추가
package com.example.orderserivce.controller;

import com.example.orderserivce.dto.OrderDto;
import com.example.orderserivce.jpa.OrderEntity;
import com.example.orderserivce.jpa.OrderRepository;
import com.example.orderserivce.service.OrderService;
import com.example.orderserivce.vo.RequestOrder;
import com.example.orderserivce.vo.ResponseOrder;
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.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("order-service")
public class OrderController {

    Environment env;
    OrderService orderService;

    @Autowired
    public OrderController(Environment env, OrderService orderService, OrderRepository orderRepository) {
        this.env = env;
        this.orderService = orderService;
    }

    @GetMapping("/health_check")
    public String healthCheck() {
        return String.format("It's Working in Order Service on PORT %s", env.getProperty("local.server.port"));
    }

    @PostMapping("/{userId}/orders")
    public ResponseEntity<ResponseOrder> createOrder(@PathVariable("userId") String userId, @RequestBody RequestOrder orderDetails){
        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        
        OrderDto orderDto = mapper.map(orderDetails, OrderDto.class);
        orderDto.setUserId(userId);
        OrderDto createdOrder = orderService.createOrder(orderDto);

        ResponseOrder responseOrder = mapper.map(createdOrder, ResponseOrder.class);
        return ResponseEntity.status(HttpStatus.CREATED).body(responseOrder);
    }

    @GetMapping("/{userId}/orders")
    public ResponseEntity<List<ResponseOrder>> getOrder(@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 등록

  • application.ml 수정
spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/order-service/**

📌 실행결과

  • Eureka 등록 확인

  • 사용자 등록

  • 카탈로그 상품 조회

  • 주문 서비스


    ➡ 사용자 아이디 13295d4a-eb42-41cb-9561-699484c4ceb0에 대하여 2건 주문 진행

  • 주문 확인

  • DB 확인

profile
새싹 개발자

0개의 댓글