所有文章 > API开发 > Spring Boot中API集成的多种方法
Spring Boot中API集成的多种方法

Spring Boot中API集成的多种方法

介绍

Spring Boot 中,API集成有多种实现方式。API集成确保了应用程序与外部服务之间的顺畅通信。在现代应用程序开发和软件架构中,API集成扮演着至关重要的角色,因为它使不同系统能够相互交互、共享数据和扩展各自的功能。Spring Boot提供了多种途径来实现API集成。

1) Rest 模板

  • Rest模板是构建使用RESTful Web服务的应用程序的核心工具。
  • 它是一个用于发送HTTP请求的同步客户端。
  • 这是一种直接与API交互,执行GET、POST、PUT和DELETE操作的方式。
  • 通过运用exchange()方法,您可以调用支持所有HTTP方法的Web服务。

 
以下是使用 rest 模板创建 API 集成的示例

  • 自动装配Rest模板对象。
  • 利用HttpHeaders设置请求头。
  • 使用HttpEntity包装请求数据。
  • 指定exchange()方法的URL、HttpMethod和返回类型。
//ConsumeWebService.java
package com.ignek.restTemplateDemo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
@RestController
public class ConsumeWebService {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/ignek/products")
public String getProductList() {
HttpHeaders headers= new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity <String> entity = new HttpEntity<String>(headers);
return restTemplate.exchange(" http://localhost:8080/products", HttpMethod.GET,entity,String.class).getBody();
}
}

通过 RestTemplate – exchange() 方法使用 GET API

[
{
"id": "1",
"name": "pen"
},
{
"id": "2",
"name": "pencil"
}
]

为Rest Template创建Bean以自动关联Rest Template对象。

package com.ignek.restTemplateDemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class RestTemplateDemoApplication {

public static void main(String[] args) {
SpringApplication.run(RestTemplateDemoApplication.class, args);
}

@Bean
public RestTemplate getRestTemplate(){return new RestTemplate();}
}

2) Web客户端:

  • Spring WebClient 是一个非阻塞、反应式客户端,专门用于处理HTTP请求。
  • 与RestTemplate相比,WebClient在反应式编程场景中具备明显优势。
  • 用于展示同步和异步操作的 WebClient 用法的代码片段。
  • 它也是经典 Rest 模板的替代品。

以下是使用 Web 客户端创建 API 集成的示例

添加此依赖项

// Web Client dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
WebClient 配置:

可以创建一个配置类,通过该配置类为WebClient应用自定义设置,如定义超时、连接限制等。

// WebClientConfig.java
package com.ignek.webClientDemo.config;

import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;

@Configuration
public class WebClientConfig {

@Bean
public WebClient.Builder webClientBuilder() {

HttpClient httpClient = HttpClient.create().tcpConfiguration(tcpClient ->
tcpClient
.doOnConnected(conn -> conn
.addHandlerLast(new ReadTimeoutHandler(10))
.addHandlerLast(new WriteTimeoutHandler(10))
)
);

// Setup ExchangeStrategies to avoid buffer limit issues (if needed)
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
.build();

return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.exchangeStrategies(exchangeStrategies);
}
}

在Service或Controller中使用WebClient:

现在,您可以将已配置的WebClient注入到您的服务或控制器中,并利用它来发起HTTP请求。

@Service
public class ApiService {

private final WebClient webClient;

@Autowired
public ApiService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.build();
}

public Mono<String> fetchDataFromExternalAPI() {
return webClient.get()
.uri("https://api.example.com/data")
.retrieve()
.bodyToMono(String.class);
}
}

3) 第三方库

一些API会自带Java SDK或库,您可以直接在Spring Boot应用程序中利用这些库来与对应的服务进行集成。

在Spring Boot应用程序中集成第三方API,通常涉及向外部服务发送HTTP请求、接收数据,并在Spring Boot应用程序中处理这些响应。这可以通过多种方式实现,比如RESTful API调用、使用HTTP客户端,或者利用Retrofit、RestTemplate、Feign等库。

以下是一个使用Spring Boot集成第三方API的示例,特别是通过进行简单的RESTful API调用来实现。

假设您想与一个天气API集成,以便根据城市获取当前的天气信息。

为了处理响应,您需要创建一个模型类:

假设该API以JSON格式返回天气数据,您将定义一个模型类来映射这些数据。

// Weather.java
package com.ignek.thirdPartyDemo.model;

public class Weather {
private String city;
private double temperature;

}

创建一个 Service 以从 API 获取数据 :

// WeatherAPIService.java
package com.ignek.thirdPartyDemo.services;

import com.ignek.thirdPartyDemo.model.Weather;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;

@Service
public class WeatherAPIService {
private final RestTemplate restTemplate;

public WeatherAPIService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}

public Weather getWeatherByCity(String city) {
String apiKey = "YOUR_API_KEY";
String url = "https://weather-api.com/api/current?city=" + city + "&key=" + apiKey;

ResponseEntity<Weather> response = restTemplate.getForEntity(url, Weather.class);

if (response.getStatusCode() == HttpStatus.OK) {
return response.getBody();
} else {
// Handle errors
return null;
}
}
}

创建一个 Controller 来处理传入的请求 :

// WeatherController.java
package com.ignek.thirdPartyDemo.controller;

import com.ignek.thirdPartyDemo.model.Weather;
import com.ignek.thirdPartyDemo.services.WeatherAPIService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/weather")
public class WeatherController {
private final WeatherAPIService weatherAPIService;

public WeatherController(WeatherAPIService weatherAPIService) {
this.weatherAPIService = weatherAPIService;
}

@GetMapping("/{city}")
public ResponseEntity<Weather> getWeather(@PathVariable String city) {
Weather weather = weatherAPIService.getWeatherByCity(city);
if (weather != null) {
return new ResponseEntity<>(weather, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

配置 RestTemplate :

在 Spring Boot 应用程序配置中,您需要配置 RestTemplate(或其他 HTTP 客户端)并设置错误处理、日志记录等。

// AppConfig.java
package com.ignek.thirdPartyDemo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class AppConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

4) 用于实时通信的 WebSocket

当需要实现实时通信或双向数据交换时,可以借助Spring的WebSocket支持与基于WebSocket的API进行集成。WebSocket协议能够使您的应用程序处理实时消息传递。WebSocket规范及其子协议可以在更高的应用程序级别上运行。其中,STOMP是Spring Framework支持的一种协议。STOMP是一种简单的基于文本的消息传递协议,它最初是为Ruby、Python和Perl等脚本语言设计的,用于与企业消息代理进行连接。

以下是一个使用WebSocket创建API集成的示例。首先,需要添加相应的依赖项。

//web socket dependency

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

配置 spring 以启用 WebSocket 和 STOMP 消息传递。

// WebSocketConfig.java
package com.ignek.webSocketDemo.config;

import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

@Override
public void registerStompEndpoints(StompEndpointRegistry
registry) {
registry.addEndpoint("/mywebsockets")
.setAllowedOrigins("mydomain.com").withSockJS();
}

@Override
public void configureMessageBroker(MessageBrokerRegistry config){
config.enableSimpleBroker("/topic/", "/queue/");
config.setApplicationDestinationPrefixes("/app");
}
}

实现一个将处理用户请求的控制器。它会将收到的消息广播给订阅给定主题的所有用户。

/ NewsControler.java
package com.ignek.webSocketDemo.controller;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.stereotype.Controller;

@Controller
public class NewsControler {

private SimpMessagingTemplate simpMessagingTemplate;

public void WebSocketController(SimpMessagingTemplate simpMessagingTemplate) {
this.simpMessagingTemplate = simpMessagingTemplate;
}

public NewsControler(SimpMessagingTemplate simpMessagingTemplate) {
this.simpMessagingTemplate = simpMessagingTemplate;
}

@MessageMapping("/news")
public void broadcastNews(String message) {
this.simpMessagingTemplate.convertAndSend("/topic/news", message);
}

@MessageMapping("/greetings")
@SendToUser("/queue/greetings")
public String reply(@Payload String message) {
return "Hello " + message;
}
}

你可以使用 SimpMessagingTemplate,以便在控制器内自动连接它。

@MessageMapping("/news")
public void broadcastNews(String message) {
this.simpMessagingTemplate.convertAndSend("/topic/news", message);
}

构建 WebSocket 客户端:

Autowire Spring STOMP 客户端。

@Autowired
private WebSocketStompClient stompClient;

打开一个连接。

String loggerServerQueueUrl = "your_logger_server_url"; // Replace this with your logger server URL

StompSessionHandler sessionHandler = new CustomStompSessionHandler();

try {
StompSession stompSession = stompClient.connect(loggerServerQueueUrl, sessionHandler).get();

// Send a message to a destination (e.g., "topic/greetings")
stompSession.send("topic/greetings", "Hello new user");
} catch (Exception e) {
// Handle exceptions or errors
e.printStackTrace();
}
}

我们需要用 @SendToUser 注解控制器的方法。

@MessageMapping("/greetings")
@SendToUser("/queue/greetings")
public String reply(@Payload String message) {
return "Hello " + message;
}

5)Feign 假客户端:

Feign是一个声明式的Web服务客户端,它极大地简化了Web服务客户端的编写工作。假客户端通过声明远程服务的HTTP API接口,抽象化了HTTP请求和响应的复杂性,提供了一种更为直接的方式来与RESTful服务进行通信。在Feign中,创建接口并添加注释是一项核心功能,它支持可插入的注释,如Feign注释和JAX-RS注释。Feign通过提供自定义编码器和解码器的支持,展现了其灵活性。Spring Cloud进一步丰富了Feign的功能,通过整合Spring MVC注释,并默认无缝地使用与Spring Web相同的HttpMessageConverters。当与Eureka集成时,Spring Cloud利用Feign促进了具有负载均衡功能的HTTP客户端,从而提升了系统的可扩展性和可靠性。

以下是一个使用Feign假客户端创建API集成的示例。首先,需要添加相应的依赖项。

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

在Spring Boot的主应用程序类或配置类中,您需要使用@EnableFeignClients注解来启用Feign客户端。

// FeignClientApplication.java
package com.ignek.feignClient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class FeignClientApplication {

public static void main(String[] args) {
SpringApplication.run(FeignClientApplication.class, args);
}

}

这是一个简单的REST API,用于提供信息发布功能,您希望在Spring Boot应用程序中通过Feign客户端来检索这些数据。

package com.ignek.feignClient;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(name = "exampleClient", url = "https://jsonplaceholder.typicode.com")
public interface ExampleFeignClient {

@GetMapping("/posts/{id}")
String getPostById(Long id);
}

您可以将Feign客户端接口注入到服务或控制器中,并利用它来向外部API发送请求。

值得注意的是,在使用Feign客户端时,控制器并非必需。Feign客户端完全可以在服务层或其他组件中独立使用。

// MyService.java
package com.ignek.feignClient.services;

import com.ignek.feignClient.ExampleFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MyService {

private final ExampleFeignClient exampleFeignClient;

@Autowired
public MyService(ExampleFeignClient exampleFeignClient) {
this.exampleFeignClient = exampleFeignClient;
}

public String getPostById(Long id) {
return exampleFeignClient.getPostById(id);
}
}

7) 现在,部署模块。

原文链接:https://www.ignek.com/blog/various-approaches-of-api-integration-in-spring-boot/

#你可能也喜欢这些API文章!