OpenFeign相关记录
系列文章目录
文档是最方便获取的教学资料https://springdoc.cn/spring-cloud-openfeign/
文章目录
- 系列文章目录
- 一、编程式REST客户端
- 1、RestTemplate
- 2、WebClient
- 3、Apache HttpClient
- 4、OkHttp
- 二、声明式REST客户端
- 三、补充说明
- 四、OpenFeign
- 五、实验-openfeign 远程调用第三方API
一、编程式REST客户端
编程式 REST 客户端 是指通过编写代码的方式,直接调用远程 RESTful API 的方式。与使用像 Postman 这样的工具手动发送请求不同,编程式客户端是通过程序自动发起 HTTP 请求,并处理响应数据。常见的 Java 编程式 REST 客户端包括:RestTemplate(Spring 提供的旧版客户端)
WebClient(Spring 5 引入的非阻塞、响应式客户端)
Apache HttpClient
OkHttp
1、RestTemplate
RestTemplate 是 Spring 框架提供的一个用于简化 HTTP 请求的客户端类,它封装了底层的 HTTP 请求逻辑,使得开发者可以通过面向对象的方式调用 RESTful API。
虽然 RestTemplate 已被官方标记为 过时(deprecated),但在很多遗留项目中仍然广泛使用
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;public class RestTemplateExample {public static void main(String[] args) {// 1. 创建 RestTemplate 实例RestTemplate restTemplate = new RestTemplate();// 2. 构造 URL(可选)String url = "https://jsonplaceholder.typicode.com/posts/{id}";String id = "1";// 3. 发起 GET 请求String response = restTemplate.getForObject(url, String.class, id);// 4. 输出结果System.out.println("Response: " + response);}
}
import org.springframework.web.client.RestTemplate;public class RestTemplatePostExample {public static void main(String[] args) {RestTemplate restTemplate = new RestTemplate();// 要发送的数据(JSON 格式)String jsonBody = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";// 发送 POST 请求String response = restTemplate.postForObject("https://jsonplaceholder.typicode.com/posts",jsonBody,String.class);System.out.println("Response: " + response);}
}
2、WebClient
它是基于 Reactor 的非阻塞、响应式客户端,性能更好,更现代
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;public class WebClientGetExample {public static void main(String[] args) {WebClient webClient = WebClient.create();Mono<String> responseMono = webClient.get().uri("https://jsonplaceholder.typicode.com/posts/1").retrieve().bodyToMono(String.class);// 同步阻塞(不推荐用于生产环境)block()会阻塞当前线程String response = responseMono.block();System.out.println("Response: " + response);}
}
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;public class WebClientPostExample {public static void main(String[] args) {WebClient webClient = WebClient.create();String jsonBody = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";Mono<String> responseMono = webClient.post().uri("https://jsonplaceholder.typicode.com/posts").bodyValue(jsonBody).retrieve().bodyToMono(String.class);responseMono.subscribe(response -> {//异步处理,不阻塞主线程System.out.println("Response: " + response);});}
}
3、Apache HttpClient
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;public class HttpClientExample {public static void main(String[] args) throws Exception {try (CloseableHttpClient httpClient = HttpClients.createDefault()) {HttpGet request = new HttpGet("https://example.com");try (CloseableHttpResponse response = httpClient.execute(request)) {String result = EntityUtils.toString(response.getEntity());System.out.println(result);}}}
}
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;public class PostRequestExample {public static void main(String[] args) throws Exception {try (CloseableHttpClient httpClient = HttpClients.createDefault()) {HttpPost post = new HttpPost("https://example.com/api/data");String json = "{\"name\": \"John\"}";StringEntity entity = new StringEntity(json);post.setEntity(entity);post.setHeader("Content-Type", "application/json");try (CloseableHttpResponse response = httpClient.execute(post)) {String result = EntityUtils.toString(response.getEntity());System.out.println(result);}}}
}
4、OkHttp
import okhttp3.*;public class OkHttpGetExample {public static void main(String[] args) throws IOException {OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://example.com").build();try (Response response = client.newCall(request).execute()) {if (response.isSuccessful()) {System.out.println(response.body().string());} else {System.out.println("Request failed: " + response.code());}}}
}
import okhttp3.*;public class OkHttpPostExample {public static void main(String[] args) throws IOException {OkHttpClient client = new OkHttpClient();String json = "{\"name\": \"John\"}";RequestBody body = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));Request request = new Request.Builder().url("https://example.com/api/data").post(body).build();try (Response response = client.newCall(request).execute()) {if (response.isSuccessful()) {System.out.println(response.body().string());} else {System.out.println("Request failed: " + response.code());}}}
}
二、声明式REST客户端
声明式客户端 是一种通过接口定义的方式来编写 HTTP 客户端的方式,而不是手动构建请求和处理响应。它将 HTTP 请求的逻辑抽象为方法调用,让代码更加简洁、易读、易于维护。
接口驱动,方法即请求在 Java 生态中,常见的声明式 HTTP 客户端有:Spring WebClient(基于 Reactor 的响应式编程)
Feign(Netflix 提供,常用于微服务间通信)
OkHttp + 接口封装(虽然不是完全声明式,但可以模拟)
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(name = "github-client", url = "https://api.github.com")
public interface GitHubClient {@GetMapping("/users/{username}")User getUser(@PathVariable("username") String username);
}
三、补充说明
虽然 Spring MVC 的 Controller 和声明式客户端都使用了 @GetMapping 这样的注解,但它们的目的和使用场景完全不同:Controller 是为了处理请求,属于后端服务的“入口”。
声明式客户端 是为了调用其他服务,属于后端服务之间的通信。Spring MVC 中的 Controller 方法不是声明式客户端,它只是用于处理 HTTP 请求的控制器方法,而声明式客户端是用于调用外部 API 的接口定义方式
四、OpenFeign
注解驱动:指定远程地址: @FeignClient指定请求方式: @GetMapping,,,指定携带数据: @RequestHeader, @RequestParam,,,指定结果返回: 响应模型
@FeignClient(value = "product")
public interface ProductFeignClient {//mvn注解的两套使用逻辑//1. 标注在controller类上,是接收请求//2. 标注在FeignClient上,是发送这样的请求@GetMapping("/product/{id}")Product getProductById(@PathVariable("id") Long id);}
五、实验-openfeign 远程调用第三方API
阿里云,花2块钱,开通墨迹天机api 服务,可以用来测试,或者学习API/JSON这一块,适合新手
https://market.aliyun.com/detail/cmapi012364
@FeignClient(value = "weather",url = "http://aliv8.data.moji.com")
public interface WeatherFeignClient {@PostMapping("whapi/json/aliweather/aqiforecast5days")String getWeather(@RequestHeader("Authorization") String auth,@RequestParam("token") String token,@RequestParam("cityId") String cityId,@RequestParam("lat") String lat,@RequestParam("lon") String lon);}@SpringBootTest
public class WeatherTest {@AutowiredWeatherFeignClient weatherFeignClient;@Testvoid testWeather() {String weather = weatherFeignClient.getWeather("APPCODE 替换", "替换","2182", "39.91488908", "116.40387397");System.out.println("Weather Data: " + weather);// 测试天气服务// 1. 使用 FeignClient 调用天气服务// 2. 验证返回结果是否正确// 3. 验证异常处理逻辑// 4. 验证负载均衡是否正常工作}
}返回结果
Weather Data: {"code":0,"data":{"city":{"cityId":284609,"counname":"中国","ianatimezone":"Asia/Shanghai","name":"东城区","pname":"北京市","secondaryname":"北京市","timezone":"8"},"condition":{"condition":"阴","conditionId":"13","humidity":"57","icon":"2","pressure":"1005","realFeel":"25","sunRise":"2025-08-23 05:34:00","sunSet":"2025-08-23 19:00:00","temp":"26","tips":"今天有雨,冷热适宜,感觉很舒适。","updatetime":"2025-08-23 14:35:08","uvi":"3","vis":"30000","windDegrees":"0","windDir":"北风","windLevel":"4","windSpeed":"5.61"}},"msg":"success","rc":{"c":0,"p":"success"}}