👨‍👧‍👦 4. User & Catalogs & Orders Microservice

2024. 3. 29. 14:05· MSA/MSA 강좌 - 이도원 강사님
목차
  1. 🦴 User Microservice 를 API Gateway에 등록
  2. ▶ 연동을 위해 application.yml 파일에 등록
  3. 🦴 User Microservice 기능 추가(사용자 조회와 정보, 주문 내역 조회)
  4. ▶ 전달 객체
  5. ▶ Controller 
  6. ▶ Service 와 ServiceImpl
  7. ▶ Repository
  8. ▶ 결과
  9. 🦴 Catalog Microservice 제작
  10. ▶ 전달 객체
  11. ▶ Controller 
  12. ▶ Service 와 ServiceImpl
  13. ▶ Repository
  14. ▶ 데이터 미리 넣기
  15. 🦴 Order Microservice 제작
  16. ▶ 전달 객체
  17. ▶ Controller 
  18. ▶ Service 와 ServiceImpl
  19. ▶ Repository
  20. 🦴 모든 서비스 등록

🦴 User Microservice 를 API Gateway에 등록

▶ 연동을 위해 application.yml 파일에 등록

routes:
  - id: user-service
    uri: lb://USER-SERVICE
    predicates:
      - Path=/user-service/**

 

🦴 User Microservice 기능 추가(사용자 조회와 정보, 주문 내역 조회)

  • 전체 사용자를 조회 할땐 현재 서비스에 가입된 회원 전체를 나타낸다
  • 사용자의 Id를 통해 회원을 보려고 한다면 회원의 정보와 회원이 주문한 내역까지 함께 나타낸다.

▶ 전달 객체

1. ResponseUser

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseUser {
    private String email;
    private String name;
    private String userId;
    private List<ResponseOrder> orders;
}
  • @JsonInclude(JsonInclude.Include.NON_NULL) : 불필요한 값인 null 인 데이터는 버리고 전달한다.
  • List<ResponseOrder> 를 통해서 사용자가 주문한 정보도 가져올 수 있게 데이터를 추가했다.

2. ResponseOrder

@Data
public class ResponseOrder {
    private String productId;
    private Integer qty;
    private Integer unitPrice;
    private Integer totalPrice;
    private LocalDateTime createdAt;

    private String orderId;
}
  • 주문의 데이터중 어떤 데이터를 넣어줄지 ResponseOrder를 통해 설정했다.

3. UserDto

@Data
public class UserDto {
    private String email;
    private String name;
    private String pwd;
    private String userId;
    private Date createdAt;

    private String encryptedPwd;

    private List<ResponseOrder> orders = new ArrayList<>();
}
  • 데이터 전달 객체인 DTO에도 order를 넣어줄 수 있다.

▶ Controller 

    @GetMapping("/users")
    public ResponseEntity<List<ResponseUser>> getUsers() {
        Iterable<UserEntity> userList = userService.getUserByAll();

        List<ResponseUser> result = new ArrayList<>();
        userList.forEach(v -> {
            result.add(new ModelMapper().map(v, ResponseUser.class));
        });

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

    @GetMapping("/users/{userId}")
    public ResponseEntity<ResponseUser> getUser(@PathVariable("userId")String userId) {
        UserDto user = userService.getUserByUserId(userId);

        ResponseUser returnValue = new ModelMapper().map(user, ResponseUser.class);

        return ResponseEntity.status(HttpStatus.OK).body(returnValue);
    }
  • 처음 메소드는 저장되어 있는 사용자의 정보를 모두 나타내는 것이다
    • JsonInclude로 user의 데이터에는 order의 정보가 없기 때문에 알아서null 인 값을 포함하지 않고 데이터를 내보낸다
  • 두번쨰 메소드는 PathVariable을 통해 들어온 값을 확인해 해당 회원의 내용을 주문 정보까지 모두 나타낸다.

▶ Service 와 ServiceImpl

1. Service

public interface UserService {
    UserDto create(UserDto userDto);
    List<UserEntity> getUserByAll();
    UserDto getUserByUserId(String userId);
}

2. ServiceImpl

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final BCryptPasswordEncoder passwordEncoder;

    ...
    @Override
    public List<UserEntity> getUserByAll() {
        return userRepository.findAll();
    }
    
    @Override
    public UserDto getUserByUserId(String userId) {
        UserEntity userEntity = userRepository.findByUserId(userId)
                .orElseThrow(() -> new UsernameNotFoundException("USer not found"));

        UserDto userDto = new ModelMapper().map(userEntity, UserDto.class);
        List<ResponseOrder> orderList = new ArrayList<>();
        userDto.setOrders(orderList);

        return userDto;
    }
}
  • getUserByAll() 은 사용자의 모든 데이터를 가져오기 때문에 List 형식으로 반환한다.
  • getUserByUserId() 는 사용자의 정확한 Id로 데이터를 가져오고 현재는 존재하지 않지만 주문 내역을 가져와 저장하는 것을 보여준다.

▶ Repository

public interface UserRepository extends CrudRepository<UserEntity, Long> {
    UserEntity findByUserId(String userId);
}

 

▶ 결과

🦴 Catalog Microservice 제작

  • 라이브러리는 User 와 동일합니다
  • yml 파일을 User 와 동일하게 설정해줍니다
  • 해당 서비스는 상품의 목록만 전달합니다. 이미 등록되어있다는 전제로 서비스가 진행됩니다.

▶ 전달 객체

1. CatalogEntity

@Data
@Entity
@Table(name = "catalog")
public class CatalogEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 120, unique = true)
    private String productId;
    @Column(nullable = false)
    private String productName;
    @Column(nullable = false)
    private Integer stock;
    @Column(nullable = false)
    private Integer unitPrice;

    @Column(nullable = false, updatable = false, insertable = false)
    @ColumnDefault(value = "CURRENT_TIMESTAMP")
    private Date createdAt;

}
  • @ColumnDefault를 통해 H2 DB에서 현재시간을 가져온다.

2. CatalogDto

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

    private String orderId;
    private String userId;
}

3. ResponseCatalog

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseCatalog {

    private String productId;
    private String productName;
    private Integer unitPrice;
    private Integer stock;
    private Date createdAt;
}

▶ Controller 

    @GetMapping("/catalogs")
    public ResponseEntity<List<ResponseCatalog>> getCatalogs() {
        Iterable<CatalogEntity> catalogList = catalogService.getAllCatalogs();

        List<ResponseCatalog> result = new ArrayList<>();
        catalogList.forEach(v -> {
            result.add(new ModelMapper().map(v, ResponseCatalog.class));
        });

        return ResponseEntity.status(HttpStatus.OK).body(result);
    }
  • 현재 서비스에 있는 모든 물품들의 정보를 담아 확인한다.

▶ Service 와 ServiceImpl

  • 오로지 등록되어 있는 물건만 가져오는 것이 목적이기 때문에 별다른 서비스가 없다.

1. Service

public interface CatalogService {
    Iterable<CatalogEntity> getAllCatalogs();
}

2. ServiceImpl

@Override
    public Iterable<CatalogEntity> getAllCatalogs() {
        return catalogRepository.findAll();
    }

▶ Repository

public interface CatalogRepository extends CrudRepository<CatalogEntity, Long> {
    CatalogEntity findByProductId(String productId);
}

▶ 데이터 미리 넣기

  • 우리는 등록된 물건을 가져오기만 하는 서비스를 만들었기 때문에 데이터를 넣는 과정이 없다. 때문에 데이터를 미리 넣어놓는 쿼리문을 작성해둔다
insert into catalog(product_id, product_name, stock, unit_price)
values ('CATALOG-001', 'Berlin', 100, 1500);
insert into catalog(product_id, product_name, stock, unit_price)
values ('CATALOG-002', 'Tokyo', 110, 1000);
insert into catalog(product_id, product_name, stock, unit_price)
values ('CATALOG-003', 'Stockholm', 120, 2000);

 

🦴 Order Microservice 제작

  • 라이브러리는 동일하다
  • yml 파일을 동일하게 설정하되 설정 정보 중 jpa.hibernate.ddl-auto를 update로 변경해준다.
  • 주문을 담당하는 서비스이기 때문에 한 사용자의 주문 내용을 담는다고 생각하면 편하다.

▶ 전달 객체

1. OrderEntity

@Entity
@Data
@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")
    private LocalDateTime createdAt;
}

2. OrderDto

@Data
public class OrderDto {

    private String productId;
    private Integer qty;
    private Integer unitPrice;
    private Integer totalPrice;

    private String orderId;
    private String userId;
}

3. RequestOrder

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RequestOrder {

    private String productId;
    private Integer qty;
    private Integer unitPrice;

}

4. ResponseOrder

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseOrder {

    private String productId;
    private Integer qty;
    private Integer unitPrice;
    private Integer totalPrice;
    private LocalDateTime createdAt;

    private String orderId;

}

▶ Controller 

    @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.getOrdersByUserId(userId);

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

        return ResponseEntity.status(HttpStatus.OK).body(result);
    }
  • createOrder : 사용자의 주문을 받고 service를 통해 데이터를 저장하고 그 내용을 Response를 통해 추가적인 데이터와 함께 전달합니다
  • getOrder : 해당 유저가 주문한 모든 데이터를 담아서 전달한다. UserService에서도 주문 정보를 가져오지만 User엔 사용자의 정보도 담겨있다.

▶ Service 와 ServiceImpl

1. Service

public interface OrderService extends Serializable {
    OrderDto createOrder(OrderDto orderDetails);

    OrderDto getOrderByOrderId(String orderId);

    Iterable<OrderEntity> getOrdersByUserId(String userId);

}

2. ServiceImpl

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

        ModelMapper mapper = new ModelMapper();
        // mapper 의 환경 설정정보 설정 ( 정확히 맞아야 한다 라는 뜻 )
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        OrderEntity orderEntity = mapper.map(orderDto, OrderEntity.class);

        orderRepository.save(orderEntity);

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

        return returnOrderDto;
    }

    @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> getOrdersByUserId(String userId) {
        return orderRepository.findByUserId(userId);
    }

▶ Repository

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

 

 

🦴 모든 서비스 등록

  • 이제 완료된 User, Catalog, Order 에 대한 Microservice가 Gateway에 등록이 되어야 한다. Discovery서버에 등록이 되었기 때문에 lb를 통해 uri경로를 잡아주기만 하면 된다.
      routes:
        - id: user-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/user-service/**
        - id: catalog-service
          uri: lb://CATALOG-SERVICE
          predicates:
            - Path=/catalog-service/**
        - id: order-service
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/order-service/**

 

  • 등록이 완료된것을 확인할 수 있다.

'MSA > MSA 강좌 - 이도원 강사님' 카테고리의 다른 글

👨‍👧‍👦6. Spring Cloud Config  (0) 2024.04.01
👨‍👧‍👦5. User Microservice 와 API Gateway - Security와 Filter 적용  (0) 2024.03.30
👨‍👧‍👦 3. UserMicroservice ( 사용자 서비스 제작 ) - 1  (0) 2024.03.28
👨‍👧‍👦 2. API Gateway Service (feat. Spring Cloud gateway)  (0) 2024.03.27
👨‍👧‍👦 1. ServiceDiscovery 등록 ( feat. Spring Cloud Netflix Eureka )  (1) 2024.03.26
  1. 🦴 User Microservice 를 API Gateway에 등록
  2. ▶ 연동을 위해 application.yml 파일에 등록
  3. 🦴 User Microservice 기능 추가(사용자 조회와 정보, 주문 내역 조회)
  4. ▶ 전달 객체
  5. ▶ Controller 
  6. ▶ Service 와 ServiceImpl
  7. ▶ Repository
  8. ▶ 결과
  9. 🦴 Catalog Microservice 제작
  10. ▶ 전달 객체
  11. ▶ Controller 
  12. ▶ Service 와 ServiceImpl
  13. ▶ Repository
  14. ▶ 데이터 미리 넣기
  15. 🦴 Order Microservice 제작
  16. ▶ 전달 객체
  17. ▶ Controller 
  18. ▶ Service 와 ServiceImpl
  19. ▶ Repository
  20. 🦴 모든 서비스 등록
'MSA/MSA 강좌 - 이도원 강사님' 카테고리의 다른 글
  • 👨‍👧‍👦6. Spring Cloud Config
  • 👨‍👧‍👦5. User Microservice 와 API Gateway - Security와 Filter 적용
  • 👨‍👧‍👦 3. UserMicroservice ( 사용자 서비스 제작 ) - 1
  • 👨‍👧‍👦 2. API Gateway Service (feat. Spring Cloud gateway)
늦은산책
늦은산책
늦은산책
중얼중얼블로그
늦은산책
전체
오늘
어제
  • 분류 전체보기
    • 오류 모음집
    • CS
      • 💾 자료구조
      • 👫🏼 정렬
      • 🖥 네트워크
      • 💻 운영체제
      • 💾 DB
      • 🌌 알고리즘
      • 📝 언어
    • 테스트
    • Git 초보에게 필요한 Git bash사용법
    • 프로젝트
      • 팀 프로젝트
      • 개인 프로젝트
      • 항해99 개인 프로젝트
      • 스위프 프로젝트(Lit Map)
    • Java
      • 객체 지향
    • Spring
      • 🌲 Spring
      • 👨‍💻 SpringSecurity
      • 🌵 JPA
    • MSA
      • MSA 강좌 - 이도원 강사님
    • Docker(도커)
    • 코딩테스트
      • 🧮 프로그래머스
      • 🎲 백준
    • 항해99
      • 🕛 1주차
      • 🕐 2주차
      • 🕑 3주차
      • 🕒 4주차
    • AWS
    • CI와CD

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • couchcoding
  • 카우치코딩
  • 항해99
  • 개발자취준
  • 개발자이력서
  • 취업리부트코스
  • 코딩테스트
  • 취리코
  • 카우치코딩_포트폴리오_멘토링
  • 개발자취업
  • 개발자포트폴리오
  • 카우치코딩_팀프로젝트
  • 개발자포토폴리오

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.0
늦은산책
👨‍👧‍👦 4. User & Catalogs & Orders Microservice
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.