前言
SpringBoot 3.2推出了新的HTTP接口调用方式,其风格类似于OpenFeign,用于进行http接口调用。
HTTP Interface 是一种与 OpenFeign 相似的同步接口调用技术,它利用 Java interfaces 来定义远程接口调用的方法。这一理念与 SpringDataRepository 相呼应,旨在大幅度减少代码量。
为了让这些远程接口调用得以执行,我们需要借助 HttpServiceProxyFactory 来明确底层的 HTTP 接口调用库。目前,它支持三种调用库:RestTemplate、WebClient 和 RestClient。
一、实现步骤
引入依赖:
首先,需要引入spring-boot-starter-web依赖,这是进行HTTP接口调用的基础。
声明接口:
通过声明Java接口的方式,实现远程接口调用方法。在接口中,可以使用注解来指定HTTP请求的方法(如GET、POST等)、URL路径、请求头和请求参数等。
public interface MyService {
@GetExchange("/anything")
String getData(@RequestHeader("MY-HEADER") String headerName);
@GetExchange("/anything/{id}")
String getData(@PathVariable long id);
@PostExchange("/anything")
String saveData(@RequestBody MyData data);
@DeleteExchange("/anything/{id}")
ResponseEntity<Void> deleteData(@PathVariable long id);
}
使用声明的方法
类似于SpringDataRepository,使用HTTP Interface也非常简单。只需要在需要使用的地方,通过@Autowired注解注入对应的Bean即可。然后,就可以像调用本地方法一样,调用远程HTTP接口了。
public class MyController {
@Autowired
private MyService myService;
@GetMapping("/foo")
public String getData() {
return myService.getData("myHeader");
}
@GetMapping("/foo/{id}")
public String getDataById(@PathVariable Long id) {
return myService.getData(id);
}
@PostMapping("/foo")
public String saveData() {
return myService.saveData(new MyData(1L, "demo"));
}
@DeleteMapping("/foo")
public ResponseEntity<Void> deleteData() {
ResponseEntity<Void> resp = myService.deleteData(1L);
log.info("delete {}", resp);
return resp;
}
}
Controller中,注入声明好的 HTTP interface:
@Autowired
private MyService myService;
当接口被调用时,接口内部会通过注入的 MyService 声明的方法调用其它系统的接口。
RestClient restClient = RestClient.builder(restTemplate).baseUrl("https://httpbin.org").build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
实现HTTP Interface:
Spring framework通过HttpServiceProxyFactory来实现HTTP Interface方法。在配置类中,通过@Bean注解创建RestTemplate或RestClient的Bean,并通过HttpServiceProxyFactory的builderFor方法创建HttpServiceProxyFactory的实例。然后,使用HttpServiceProxyFactory的createClient方法,将声明的接口类传递给它,以创建该接口的代理实例。这样,就可以通过代理实例调用远程HTTP接口了。
@Configuration
public class MyClientConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
@Bean
public MyService myService(RestTemplate restTemplate) {
restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory("https://httpbin.org"));
RestTemplateAdapter adapter = RestTemplateAdapter.create(restTemplate);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
return factory.createClient(MyService.class);
}
}