User service
와 Order service
는 Eureka Service
에 등록되어 있는 상태이고, Spring cloud gateway
에 의해 라우팅된다. @Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@GetMapping("/orders/{userId}")
public ResponseEntity<List<ResponseOrder>> getOrderByOrderId(@PathVariable("userId") String userId) {
List<OrderDto> findOrders = orderService.getOrderByUserId(userId);
ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
List<ResponseOrder> result = new ArrayList<>();
findOrders.forEach( o -> {
result.add(mapper.map(o, ResponseOrder.class));
});
return ResponseEntity.status(HttpStatus.OK).body(result);
}
}
- id: order-service
uri: lb://ORDER-SERVICE
predicates:
Path=/order-service/**
endpoint는 /orders/{userId}
이고 api gateway에 order-service
로 등록되어 있으니 호출해야 하는 API의 uri는 http://127.0.0.1:8000/order-service/orders/{userId}
가 된다.
@RequiredArgsConstructor
+ final
로 받았어요.)private final RestTemplate restTemplate;
requestEntity
는 null로 하고 응답받을 타입은 ParameterizedTypeReference
로 지정한다.new ParameterizedTypeReference
에 알맞은 DTO를 정의하여 받아주면 정상적으로 다른 MSA의 API를 호출할 수 있다. String url = String.format("http://127.0.0.1:8000/order-service/orders/%s", userId);
ResponseEntity<List<ResponseOrder>> response = restTemplate.exchange(url, HttpMethod.GET, null,
new ParameterizedTypeReference<List<ResponseOrder>>() {
});
List<ResponseOrder> orders = response.getBody();
@FeignClient
에는 호출하고자 하는 MSA이름을 지정한다.@GetMapping
쪽을 보면 기존에 Controller에서 endpoint를 지정하는 것과 거의 동일한 것을 알 수 있다. 다만 세부 구현 내용은 필요로 하지 않는다.@FeignClient(name = "order-service")
public interface OrderServiceFeignClient {
@GetMapping("/order-service/orders/{userId}")
List<ResponseOrder> getOrders(@PathVariable String userId);
}
@RequiredArgsConstructor
+ final
로 주입받는private final OrderServiceFeignClient orderServiceFeignClient;
try-catch
문으로 예외를 처리한다.List<ResponseOrder> orders = null;
try {
orders = orderServiceFeignClient.getOrders(userId);
} catch (FeignException e) {
log.error(e.getMessage());
}
ErrorDecoder
를 이용하여 예외를 모아 관리할 수 있다.ErrorDecoder
를 구현하는 클래스를 생성하고 아래와 같은 리턴값, 매개변수를 갖는 decode 메서드를 오버라이딩한다.@Component
public class FeignClientErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String method, Response response) {
switch (response.status()) {
case 404:
if(method.contains("getOrders")) {
return new ResponseStatusException(HttpStatus.valueOf(response.status()), "User's order is empty.");
}
break;
default:
return new Exception(response.reason());
}
return null;
}
}
ErrorDecoder
를 구현하면 try-catch
없이 아래와 같이 깔끔하게 다른 MSA의 API를 호출할 수 있다.List<ResponseOrder> orders = orderServiceFeignClient.getOrders(userId);
진짜 배울게 많네요.