
如何快速實現REST API集成以優化業務流程
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客戶端:
以下是使用 Web 客戶端創建 API 集成的示例
添加此依賴項
// Web Client dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
可以創建一個配置類,通過該配置類為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/