Calling External APIs in Spring Boot: HttpClient, RestTemplate, and Feign

This article explains how to invoke external services from a Spring Boot application using three approaches—raw HttpClient, RestTemplate, and Feign—providing code examples, configuration steps, and tips for handling headers and tokens to ensure successful API communication.

Top Architect
Top Architect
Top Architect
Calling External APIs in Spring Boot: HttpClient, RestTemplate, and Feign

1. Introduction

SpringBoot inherits the excellent features of the Spring framework and further simplifies configuration, making it easy to build and develop applications. When a module needs to access external interfaces or URLs (for example, invoking an A‑PaaS workflow submission API), three non‑Dubbo methods are available.

2. Method 1: Using raw HttpClient

/*
 * @description get方式获取入参,插入数据并发起流程
 * @author lyx
 * @date 2022/8/24 16:05
 * @params documentId
 * @return String
 */
@RequestMapping("/submit/{documentId}")
public String submit1(@PathVariable String documentId) throws ParseException {
    // Convert data to JSON string
    Map<String,Object> map = task2Service.getMap(documentId);
    String jsonStr = JSON.toJSONString(map, SerializerFeature.WRITE_MAP_NULL_FEATURES, SerializerFeature.QuoteFieldNames);
    JSONObject jsonObject = JSON.parseObject(jsonStr);
    JSONObject sr = task2Service.doPost(jsonObject);
    return sr.toString();
}

/*
 * @description 使用原生httpClient调用外部接口
 * @author lyx
 * @date 2022/8/24 16:08
 * @params date
 * @return JSONObject
 */
public static JSONObject doPost(JSONObject date) {
    String assessToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9...";
    CloseableHttpClient client = HttpClients.createDefault();
    // URL to call
    String url = "http://39.103.201.110:30661 /xdap-open/open/process/v1/submit";
    HttpPost post = new HttpPost(url);
    JSONObject jsonObject = null;
    try {
        // Create request body
        StringEntity s = new StringEntity(date.toString());
        s.setContentType("application/json");
        s.setContentEncoding("UTF-8");
        post.setEntity(s);
        // Add Authorization header
        post.addHeader("Authorization", "Bearer " + assessToken);
        HttpResponse res = client.execute(post);
        if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            String result = EntityUtils.toString(res.getEntity());
            jsonObject = JSONObject.parseObject(result);
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return jsonObject;
}

3. Method 2: Using RestTemplate

SpringBoot provides RestTemplate for external calls. Below are examples of GET and POST usage.

GET request

Two main methods are getForObject and getForEntity. The getForEntity overloads include:

1.getForEntity(String url, Class responseType, Object… urlVariables)
2.getForEntity(URI url, Class responseType)

Example using URI:

// Build URI with parameters
RestTemplate restTemplate = new RestTemplate();
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://USER-SERVICE/user?name={name}")
    .build()
    .expand("dodo")
    .encode();
URI uri = uriComponents.toUri();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
String body = responseEntity.getBody();

Example using URL variables:

RestTemplate restTemplate = new RestTemplate();
Map<String,Object> params = new HashMap<>();
params.put("name", "dada");
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://USER-SERVICE/user?name={name}", String.class, params);

The getForObject methods are similar but directly return the converted body via HttpMessageConverterExtractor.

POST request

Three main methods are postForEntity, postForObject, and postForLocation. Below is an example of the second overload of postForEntity:

@PostMapping("/submit2")
public Object insertFinanceCompensation(@RequestBody JSONObject jsonObject) {
    String documentId = jsonObject.get("documentId").toString();
    return task2Service.submit(documentId);
}

Using RestTemplate to call an external API with headers and token:

public String submit(String documentId) {
    String assessToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9...";
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.add(HttpHeaders.AUTHORIZATION, "Bearer " + assessToken);
    httpHeaders.add(HttpHeaders.CONTENT_TYPE, "application/json");
    Map<String,Object> map = getMap(documentId);
    String jsonStr = JSON.toJSONString(map);
    HttpEntity<Map> httpEntity = new HttpEntity<>(map, httpHeaders);
    String url = "http://39.103.201.110:30661/xdap-open/open/process/v1/submit";
    ResponseEntity<String> forEntity = restTemplate.postForEntity(url, httpEntity, String.class);
    return forEntity.toString();
}

4. Method 3: Using Feign

Add the Feign starter dependency to the Maven project:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.2.2.RELEASE</version>
</dependency>

Enable Feign in the main application class:

@SpringBootApplication
@EnableFeignClients
@ComponentScan(basePackages = {"com.definesys.mpaas", "com.xdap.*"})
public class MobilecardApplication {
    public static void main(String[] args) {
        SpringApplication.run(MobilecardApplication.class, args);
    }
}

Define a mock controller for external calls:

@Autowired
PrintService printService;

@PostMapping("/outSide")
public String test(@RequestBody TestDto testDto) {
    return printService.print(testDto);
}

Define the service interface:

@Service
public interface PrintService {
    String print(TestDto testDto);
}

Implement the service:

@Service
public class PrintServiceImpl implements PrintService {
    @Override
    public String print(TestDto testDto) {
        return "模拟外部系统的接口功能" + testDto.getId();
    }
}

Create a Feign client that calls the external endpoint:

@Service
@FeignClient(url = "${outSide.url}", name = "service2")
public interface FeignService2 {
    @RequestMapping(value = "/custom/outSide", method = RequestMethod.POST)
    @ResponseBody
    String getMessage(@Valid @RequestBody TestDto testDto);
}

Expose a controller that uses the Feign client:

@Autowired
FeignService2 feignService2;

@PostMapping("/test2")
public String test2(@RequestBody TestDto testDto) {
    return feignService2.getMessage(testDto);
}

To add a token to Feign requests, implement RequestInterceptor:

@Configuration
public class FeignConfig implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9...");
    }
}

Use the interceptor in a Feign client that requires the token:

@FeignClient(url = "${outSide.url}", name = "feignServer", configuration = FeignDemoConfig.class)
public interface TokenDemoClient {
    @RequestMapping(value = "/custom/outSideAddToken", method = RequestMethod.POST)
    @ResponseBody
    String getMessage(@Valid @RequestBody TestDto testDto);
}

@PostMapping("/testToken")
public String test4(@RequestBody TestDto testDto) {
    return tokenDemoClient.getMessage(testDto);
}

The article concludes with a call for readers to like, share, and join the architect community, and provides links to additional resources and open‑source projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavafeignAPISpringBootresttemplateHttpClient
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.