java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring Boot RestTemplate调用三方接口

Spring Boot项目通过RestTemplate调用三方接口的最佳实践

作者:布朗克168

本文详细讲解了SpringBoot项目中使用RestTemplate调用第三方接口的实现方法,本教程将逐步指导您完成整个过程,确保结构清晰、易于理解,感兴趣的朋友跟随小编一起看看吧

在Spring Boot项目中,使用RestTemplate调用第三方接口是一种常见的HTTP客户端操作。RestTemplate是Spring框架提供的一个简单、同步的HTTP客户端工具,支持发送GET、POST等请求,并处理响应。本教程将逐步指导您完成整个过程,确保结构清晰、易于理解。教程基于Spring Boot 2.x版本(如2.7.x),如果您使用Spring Boot 3.x,部分配置可能需调整(例如,RestTemplate不再自动配置,需手动添加依赖和Bean)。

一、简单说明

1.准备工作

2.添加依赖

在Spring Boot 2.x中,spring-boot-starter-web已包含RestTemplate。打开pom.xml文件,添加或确认以下依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 如果需要JSON处理,添加Jackson依赖(通常已包含在starter-web中) -->
</dependencies>

保存文件后,运行mvn clean install或使用IDE重新加载项目。

3.配置RestTemplate Bean

RestTemplate需要被Spring容器管理。创建一个配置类来定义Bean。

在项目中新建一个类,例如RestTemplateConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

说明

如果需要自定义(如设置超时),可以添加HttpComponentsClientHttpRequestFactory

@Bean
public RestTemplate restTemplate() {
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
    factory.setConnectTimeout(5000); // 连接超时5秒
    factory.setReadTimeout(5000);    // 读取超时5秒
    return new RestTemplate(factory);
}
4.使用RestTemplate发送请求

现在,您可以在Service或Controller中使用RestTemplate。以下以发送GET和POST请求为例。

步骤

示例1:GET请求

假设调用天气API:https://api.weather.com/data?city={city},返回JSON数据。

创建一个Service类,例如WeatherService.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class WeatherService {
    private final RestTemplate restTemplate;
    @Autowired
    public WeatherService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    public String getWeatherData(String city) {
        String url = "https://api.weather.com/data?city={city}";
        // 发送GET请求,将响应解析为String
        String response = restTemplate.getForObject(url, String.class, city);
        return response; // 实际项目中,应解析JSON为对象
    }
}

说明

示例2:POST请求

public String loginUser(String username, String password) {
    String url = "https://api.example.com/login";
    // 创建请求体(例如Map或自定义对象)
    Map<String, String> requestBody = new HashMap<>();
    requestBody.put("username", username);
    requestBody.put("password", password);
    // 发送POST请求,请求体自动序列化为JSON
    String response = restTemplate.postForObject(url, requestBody, String.class);
    return response;
}

说明

5.处理响应

第三方接口通常返回JSON数据。建议定义POJO类来映射响应。

步骤

示例:假设天气API返回{"city":"Beijing","temp":25}

创建POJO类WeatherResponse.java

public class WeatherResponse {
    private String city;
    private int temp;
    // Getters and Setters
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    public int getTemp() { return temp; }
    public void setTemp(int temp) { this.temp = temp; }
}

在Service中修改方法:

public WeatherResponse getWeatherData(String city) {
    String url = "https://api.weather.com/data?city={city}";
    WeatherResponse response = restTemplate.getForObject(url, WeatherResponse.class, city);
    return response;
}

说明getForObject会自动将JSON反序列化为WeatherResponse对象。

6.错误处理

示例:在Service中添加错误处理。

import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
public WeatherResponse getWeatherData(String city) {
    String url = "https://api.weather.com/data?city={city}";
    try {
        return restTemplate.getForObject(url, WeatherResponse.class, city);
    } catch (HttpClientErrorException e) {
        // 处理客户端错误(如参数无效)
        System.err.println("客户端错误: " + e.getStatusCode());
        return null;
    } catch (HttpServerErrorException e) {
        // 处理服务端错误
        System.err.println("服务端错误: " + e.getStatusCode());
        return null;
    } catch (RestClientException e) {
        // 处理其他错误(如超时)
        System.err.println("请求失败: " + e.getMessage());
        return null;
    }
}

最佳实践:使用全局异常处理(如@ControllerAdvice)统一管理错误。

7.完整示例:集成到Controller

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WeatherController {
    private final WeatherService weatherService;
    @Autowired
    public WeatherController(WeatherService weatherService) {
        this.weatherService = weatherService;
    }
    @GetMapping("/weather/{city}")
    public WeatherResponse getWeather(@PathVariable String city) {
        return weatherService.getWeatherData(city);
    }
}

8.注意事项和最佳实践

HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer token");
HttpEntity<Object> entity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

通过以上步骤,您可以轻松在Spring Boot项目中集成RestTemplate调用三方接口。如果有具体接口需求,可进一步优化代码。

二、抽象设计

以下是为SpringBoot项目设计的通用API调用封装方案,满足您的所有需求:

1. 通用API服务类设计

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
public abstract class AbstractApiService {
    private static final Logger logger = LoggerFactory.getLogger(AbstractApiService.class);
    protected final RestTemplate syncRestTemplate;
    protected final AsyncRestTemplate asyncRestTemplate;
    private final ObjectMapper objectMapper = new ObjectMapper();
    protected AbstractApiService(RestTemplate restTemplate, AsyncRestTemplate asyncRestTemplate) {
        this.syncRestTemplate = restTemplate;
        this.asyncRestTemplate = asyncRestTemplate;
    }
    // 同步调用
    protected <T> ResponseEntity<String> executeSync(
            String url, 
            HttpMethod method, 
            HttpHeaders headers, 
            T body) {
        logRequest(url, method, headers, body);
        HttpEntity<T> requestEntity = new HttpEntity<>(body, headers);
        ResponseEntity<String> response = syncRestTemplate.exchange(
            url, method, requestEntity, String.class);
        logResponse(response);
        return response;
    }
    // 异步调用
    protected <T> ListenableFuture<ResponseEntity<String>> executeAsync(
            String url, 
            HttpMethod method, 
            HttpHeaders headers, 
            T body) {
        logRequest(url, method, headers, body);
        HttpEntity<T> requestEntity = new HttpEntity<>(body, headers);
        ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.exchange(
            url, method, requestEntity, String.class);
        future.addCallback(
            result -> logResponse(result),
            ex -> logger.error("Async call failed: {}", ex.getMessage())
        );
        return future;
    }
    // JSON格式日志记录
    private <T> void logRequest(String url, HttpMethod method, HttpHeaders headers, T body) {
        try {
            String logData = String.format(
                "{\"url\":\"%s\", \"method\":\"%s\", \"headers\":%s, \"body\":%s}",
                url, method, objectMapper.writeValueAsString(headers), 
                objectMapper.writeValueAsString(body)
            );
            logger.info("API请求: {}", logData);
        } catch (Exception e) {
            logger.error("请求日志序列化失败", e);
        }
    }
    private void logResponse(ResponseEntity<String> response) {
        try {
            String logData = String.format(
                "{\"status\":%s, \"headers\":%s, \"body\":%s}",
                response.getStatusCodeValue(),
                objectMapper.writeValueAsString(response.getHeaders()),
                response.getBody()
            );
            logger.info("API响应: {}", logData);
        } catch (Exception e) {
            logger.error("响应日志序列化失败", e);
        }
    }
}

2. 业务服务类实现

import org.springframework.http.*;
import org.springframework.stereotype.Service;
@Service
public class BusinessApiService extends AbstractApiService {
    public BusinessApiService(RestTemplate restTemplate, AsyncRestTemplate asyncRestTemplate) {
        super(restTemplate, asyncRestTemplate);
    }
    // 带请求体的业务调用
    public BusinessResponse callBusinessApi(BusinessRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("X-API-KEY", "your-api-key");
        headers.setContentType(MediaType.APPLICATION_JSON);
        ResponseEntity<String> response = executeSync(
            "https://api.example.com/business",
            HttpMethod.POST,
            headers,
            request
        );
        return parseResponse(response.getBody(), BusinessResponse.class);
    }
    // GET请求示例
    public BusinessData getBusinessData(String id) {
        String url = "https://api.example.com/data/" + id;
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer token");
        ResponseEntity<String> response = executeSync(
            url, HttpMethod.GET, headers, null
        );
        return parseResponse(response.getBody(), BusinessData.class);
    }
    // 异步调用示例
    public ListenableFuture<ResponseEntity<String>> asyncFetchData(AsyncRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return executeAsync(
            "https://api.example.com/async",
            HttpMethod.POST,
            headers,
            request
        );
    }
    private <T> T parseResponse(String body, Class<T> valueType) {
        try {
            return objectMapper.readValue(body, valueType);
        } catch (Exception e) {
            logger.error("响应解析失败: {}", body, e);
            throw new RuntimeException("API响应解析异常");
        }
    }
}
// 请求响应对象示例
public class BusinessRequest {
    private String param1;
    private int param2;
    // getters/setters
}
public class BusinessResponse {
    private String result;
    private int statusCode;
    // getters/setters
}

3. 控制器调用示例

import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class BusinessController {
    private final BusinessApiService apiService;
    public BusinessController(BusinessApiService apiService) {
        this.apiService = apiService;
    }
    @PostMapping("/business")
    public BusinessResponse handleBusiness(@RequestBody BusinessRequest request) {
        return apiService.callBusinessApi(request);
    }
    @GetMapping("/data/{id}")
    public BusinessData getData(@PathVariable String id) {
        return apiService.getBusinessData(id);
    }
}

4. 定时任务示例

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
    private final BusinessApiService apiService;
    public ScheduledTasks(BusinessApiService apiService) {
        this.apiService = apiService;
    }
    @Scheduled(fixedRate = 3600000) // 每小时执行
    public void hourlySync() {
        BusinessRequest request = new BusinessRequest();
        // 设置请求参数
        BusinessResponse response = apiService.callBusinessApi(request);
        // 处理响应
    }
}

5.关键设计说明:

注意:实际使用需在Spring配置中初始化RestTemplateAsyncRestTemplate Bean,并配置连接池、超时时间等参数。

到此这篇关于Spring Boot项目通过RestTemplate调用三方接口详细教程的文章就介绍到这了,更多相关Spring Boot RestTemplate调用三方接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文