BackEnd/MSA Communications
FeignClient
hanseom
2022. 7. 23. 07:22
반응형
Overview
해당 글에서는 RestTemplate보다 사용이 간단하고 직관적인 FeignClient를 적용해 보겠습니다. FeignClient는 HTTP Client로 REST Call을 추상화 한 Spring Cloud Netflix 라이브러리입니다.
FeignClient 적용
의존성 추가
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
@EnableFeignClients 적용
package com.example.userservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
호출하려는 HTTP Endpoint에 대한 Interface 생성 (url은 config 파일로 관리합니다.)
package com.example.userservice.client;
import com.example.userservice.RestTemplateResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "jsonPlaceHolderClient", url = "https://jsonplaceholder.typicode.com/")
public interface JsonPlaceHolderClient {
@GetMapping("/todos/{id}")
RestTemplateResponse getTodos(@PathVariable String id);
}
FeignClient 사용
JsonPlaceHolderClient를 생성자 주입 받아 getTodos 메서드를 호출합니다. 단순 확인을 위한 호출로 Controller 단에서 수행하며, 이전 글의 RestTemplateResponse를 그대로 적용합니다.
package com.example.userservice;
import com.example.userservice.client.JsonPlaceHolderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/")
public class UserController {
/*** 생략 ***/
JsonPlaceHolderClient jsonPlaceHolderClient;
@Autowired
public UserController(Environment env, RestTemplate restTemplate,
JsonPlaceHolderClient jsonPlaceHolderClient) {
/*** 생략 ***/
this.jsonPlaceHolderClient = jsonPlaceHolderClient;
}
@GetMapping("/welcome")
public String welcome() {
String configMessage = env.getProperty("greeting.message");
/* RestTemplate */
// System.out.println(restTemplate.getForObject("https://jsonplaceholder.typicode.com/todos/1",
// RestTemplateResponse.class));
// restTemplate.getForObject("url", Object.class);
// restTemplate.postForObject("url", "Request.class", Object.class);
// restTemplate.put("url", "Request.class");
// restTemplate.delete("url");
/* FeignClient */
RestTemplateResponse response = jsonPlaceHolderClient.getTodos("1");
System.out.println(response);
return "Hello, User-service: " + configMessage;
}
}
FeignClient Logger
application.yml (com.example.userservice.client는 package 경로입니다.)
logging:
level:
com.example.userservice.client: DEBUG
@Bean 등록
package com.example.userservice;
import feign.Logger;
/*** 생략 ***/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class UserServiceApplication {
/*** 생략 ***/
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
서버 재기동 후 호출 시 아래와 같은 로그를 볼 수 있습니다.
FeignClient Exception 처리
ErrorDecoder 구현
FeignClient에서 발생하는 Exception을 한 곳에서 처리할 수 있습니다. @Component로 @Bean을 등록하고 ErrorDecoder를 상속받아 decode 메서드를 재정의하면 됩니다. 상태코드에 따라 적절한 처리를 해주면 됩니다.
package com.example.userservice.client;
import feign.Response;
import feign.codec.ErrorDecoder;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
@Component
public class FeignErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
switch (response.status()) {
case 400:
break;
case 404:
if (methodKey.contains("getTodos")) {
return new ResponseStatusException(HttpStatus.valueOf(response.status()),
"getTodos Bad Request Exception!!!");
}
break;
default:
return new Exception(response.reason());
}
return null;
}
}
[참고 정보]
반응형