欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > Http客户端工具类

Http客户端工具类

2024/10/25 22:24:25 来源:https://blog.csdn.net/code_nn/article/details/142819501  浏览:    关键词:Http客户端工具类

参考文章:
https://www.baeldung.com/guide-to-okhttp
https://www.baeldung.com/rest-template

一、第三方工具类

1.1 OkHttp

OkHttp 是一个高效的 HTTP 客户端,它被广泛用于 Android 和 Java 应用程序中以发送网络请求。

添加依赖:

<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.12.0</version>
</dependency>

1.1.1 Get 请求

import okhttp3.*;
import java.io.IOException;public class OkHttpGetExample {private final OkHttpClient okHttpClient;// RequestHeaders 、RequestParams 就是一个Map的封装类 public <T> T executeGetRequest(String url, RequestHeaders headers, RequestParams params, Class<T> responseType) {HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();if (params != null) {for (Map.Entry<String, Object> entry : params.getParams().entrySet()) {urlBuilder.addQueryParameter(entry.getKey(), entry.getValue().toString());}}Request.Builder requestBuilder = new Request.Builder().url(urlBuilder.build());if (headers != null) {requestBuilder.headers(Headers.of(headers.getHeaders()));}Request request = requestBuilder.build();try (Response response = okHttpClient.newCall(request).execute()) {if (!response.isSuccessful()) {throw new HttpClientException("请求失败: " + response.code(),null);}String responseBody = response.body().string();return parseResponse(responseBody, responseType);} catch (IOException e) {throw new HttpClientException("请求失败: " + e.getMessage(),e);}}public void get(String url, RequestHeaders headers, RequestParams params, Callback callback) {Request request = new Request.Builder().url(buildUrlWithParams(url, params)).headers(Headers.of(headers.getHeaders())).build();// 异步请求client.newCall(request).enqueue(callback);}}

1.1.2 Post 请求

import okhttp3.*;public class OkHttpPostExample {private final OkHttpClient okHttpClient;public <T> T executePostJsonRequest(String url, RequestHeaders headers, String requestBody, Class<T> responseType) {RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestBody);Request.Builder requestBuilder = new Request.Builder().url(url).post(body);if (headers != null) {requestBuilder.headers(Headers.of(headers.getHeaders()));}Request request = requestBuilder.build();try (Response response = okHttpClient.newCall(request).execute()) {if (!response.isSuccessful()) {throw new HttpClientException("请求失败: " + response.code(),null);}String responseBody = response.body().string();return parseResponse(responseBody, responseType);} catch (IOException e) {throw new HttpClientException("请求失败: " + e.getMessage(),e);}}public <T> T executePostFormRequest(String url, RequestHeaders headers, RequestParams formData, Class<T> responseType) {FormBody.Builder formBodyBuilder = new FormBody.Builder();if (formData != null) {for (Map.Entry<String, Object> entry : formData.getParams().entrySet()) {formBodyBuilder.add(entry.getKey(), entry.getValue().toString());}}RequestBody body = formBodyBuilder.build();Request.Builder requestBuilder = new Request.Builder().url(url).post(body);if (headers != null) {requestBuilder.headers(Headers.of(headers.getHeaders()));}Request request = requestBuilder.build();try (Response response = okHttpClient.newCall(request).execute()) {if (!response.isSuccessful()) {throw new HttpClientException("请求失败: " + response.code(),null);}String responseBody = response.body().string();return parseResponse(responseBody, responseType);} catch (IOException e) {throw new HttpClientException("请求失败: " + e.getMessage(),e);}}public void postJson(String url, RequestHeaders headers, String requestBody, Callback callback) {RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestBody);Request request = new Request.Builder().url(url).headers(Headers.of(headers.getHeaders())).post(body).build();// 异步client.newCall(request).enqueue(callback);}public void postForm(String url, RequestParams formData, Callback callback) {FormBody.Builder formBuilder = new FormBody.Builder();for (Map.Entry<String, Object> entry : formData.getParams().entrySet()) {formBuilder.add(entry.getKey(), entry.getValue().toString());}RequestBody body = formBuilder.build();Request request = new Request.Builder().url(url).post(body).build();client.newCall(request).enqueue(callback);}}

1.2 RestTemplate

RestTemplate 是 Spring 框架中用于发送 HTTP 请求的类。

1.2.1 Get 请求

public class RestTemplateGetExample {public void doGet() {RestTemplate restTemplate = new RestTemplate();// 设置请求头HttpHeaders headers = new HttpHeaders();headers.set("Authorization", "Bearer token_value");headers.set("Custom-Header", "CustomValue");// 构建 HttpEntity,用于发送包含请求头的信息HttpEntity<String> entity = new HttpEntity<>(headers);// 发送 GET 请求,获取响应String url = "https://api.example.com/data";ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);// 打印响应结果System.out.println(response.getBody());}public void doGetAsync() {WebClient webClient = WebClient.builder().baseUrl("https://api.example.com").defaultHeader("Authorization", "Bearer token_value").build();// 异步 GET 请求Mono<String> responseMono = webClient.get().uri("/data").retrieve().bodyToMono(String.class);// 处理异步响应responseMono.subscribe(response -> {System.out.println("Response: " + response);});// 阻塞调用 - 仅用于演示,如果需要同步执行结果String response = responseMono.block();System.out.println("Synchronous response: " + response);}}

1.2.2 Post请求

public class RestTemplatePostExample {public void doPost() {RestTemplate restTemplate = new RestTemplate();// 设置请求头HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);headers.set("Authorization", "Bearer token_value");// 创建请求体Map<String, String> requestBody = new HashMap<>();requestBody.put("username", "john");requestBody.put("password", "secret");// 构建 HttpEntity,包含请求头和请求体HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestBody, headers);// 发送 POST 请求,获取响应String url = "https://api.example.com/login";ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);// 打印响应结果System.out.println(response.getBody());}
}

1.3 Fegin

Feign 是一个声明式的 HTTP 客户端,提供了一种简洁的方式来调用 REST API,它通过注解定义接口的方法映射到远程 HTTP 请求上。Feign 的主要优点是集成了 Spring Cloud 和 Ribbon,方便实现负载均衡、自动重试等功能。

添加依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

开启 Feign 客户端

@SpringBootApplication
@EnableFeignClients
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

接口定义

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(name = "userService", url = "https://api.example.com")
public interface UserClient {@GetMapping("/api/users/{id}")User getUserById(@PathVariable("id") Long id);@PostMapping("/api/users")User createUser(@RequestBody User user);@GetMapping("/api/users/{id}")User getUserById(@PathVariable("id") Long id, @RequestHeader("Authorization") String token);
}

● @FeignClient:声明这是一个 Feign 客户端,name 是客户端的名称,url 是远程服务的 URL。可以将 url 设置为动态的配置项。
● @GetMapping:指定 HTTP 请求类型,类似于 Spring MVC 的注解。
● @PathVariable:指定路径变量。

二、自定义封装

项目开发,统一调用方式。

2.1静态方法方案(不推荐)

public class HttpUtil {public static <T> T get(String url, Map<String, String> headers, Map<String, String> params, Class<T> responseType) throws IOException {//实现}
}

2.2 通用接口设计方案

静态方法更进一步的设计方案。面向 接口开发,隐藏实现细节,更易维护。
可以使用 Builder 模式 封装请求参数、请求头。
利用 重载 可以设计更多的接口满足业务需求。
但是维护起来还是比较麻烦的,方法太多了。

同步调用接口

package com.github.nan.http;import com.github.nan.http.dto.RequestHeaders;
import com.github.nan.http.dto.RequestParams;/*** 同步http客户端** 如果请求没有返回结果,responseType 建议使用 Void.class** @author NanNan Wang*/
public interface SyncHttpClient {/*** 发起一个简单的 GET 请求。** @param url 请求的 URL 地址* @param responseType 返回的结果类型* @param <T> 泛型类型* @return 请求的结果,类型为 T*/<T> T get(String url, Class<T> responseType);/*** 发起一个带有参数的 GET 请求。** @param url 请求的 URL 地址* @param params 请求的参数* @param responseType 返回的结果类型* @param <T> 泛型类型* @return 请求的结果,类型为 T*/<T> T get(String url, RequestParams params, Class<T> responseType);/*** 发起一个带有头部的 GET 请求。* @param url 请求的 URL 地址* @param headers 请求的头部信息* @param responseType 返回的结果类型* @return 泛型类型* @param <T> 请求的结果,类型为 T*/<T> T get(String url, RequestHeaders headers, Class<T> responseType);/*** 发起一个带有头部和参数的 GET 请求。** @param url 请求的 URL 地址* @param headers 请求的头部信息* @param params 请求的参数* @param responseType 返回的结果类型* @param <T> 泛型类型* @return 请求的结果,类型为 T*/<T> T get(String url, RequestHeaders headers,  RequestParams params, Class<T> responseType);/*** 发起一个带有 JSON 请求参数的 POST 请求。** @param url 请求的 URL 地址* @param requestBody JSON 请求体* @param responseType 返回的结果类型* @param <T> 泛型类型* @return 请求的结果,类型为 T*/<T> T postJson(String url, String requestBody, Class<T> responseType);/*** 发起一个带有 JSON 请求参数的 POST 请求。** @param url 请求的 URL 地址* @param headers 请求的头部信息* @param requestBody JSON 请求体* @param responseType 返回的结果类型* @param <T> 泛型类型* @return 请求的结果,类型为 T*/<T> T postJson(String url, RequestHeaders headers, String requestBody, Class<T> responseType);/*** 发起一个带有表单数据的 POST 请求。** @param url 请求的 URL 地址* @param formData 表单数据* @param responseType 返回的结果类型* @param <T> 泛型类型* @return 请求的结果,类型为 T*/<T> T postForm(String url, RequestParams formData, Class<T> responseType);/*** 发起一个带有表单数据的 POST 请求。** @param url 请求的 URL 地址* @param headers 请求的头部信息* @param formData 表单数据* @param responseType 返回的结果类型* @param <T> 泛型类型* @return 请求的结果,类型为 T*/<T> T postForm(String url, RequestHeaders headers, RequestParams formData, Class<T> responseType);}

异步调用接口

/*** 异步http客户端** @author NanNan Wang*/
public interface AsyncHttpClient {/*** 发起异步 GET 请求。** @param url 请求 URL* @param callback 回调函数*/void get(String url, Callback callback);/*** 发起一个带有头部的 GET 请求。** @param url 请求的 URL 地址* @param headers 请求的头部信息* @param callback 回调函数*/void get(String url, RequestHeaders headers, Callback callback);/*** 发起一个带有参数的 GET 请求。** @param url 请求的 URL 地址* @param params 请求的参数* @param callback 回调函数*/void get(String url, RequestParams params,  Callback callback);/*** 发起一个带有头部和参数的 GET 请求。** @param url 请求的 URL 地址* @param headers 请求的头部信息* @param params 请求的参数* @param callback 回调函数*/void get(String url, RequestHeaders headers, RequestParams params, Callback callback);/*** 发起一个带有 JSON 请求参数的 POST 请求。** @param url 请求的 URL 地址* @param requestBody JSON 请求体* @param callback 回调函数*/void postJson(String url, String requestBody, Callback callback);/*** 发起一个带有 JSON 请求参数和头部信息的 POST 请求。** @param url 请求的 URL 地址* @param headers 请求的头部信息* @param requestBody JSON 请求体* @param callback 回调函数*/void postJson(String url, RequestHeaders headers, String requestBody, Callback callback);/*** 发起一个带有表单数据的 POST 请求。** @param url 请求的 URL 地址* @param formData 表单数据* @param callback 回调函数*/void postForm(String url, RequestParams formData, Callback callback);/*** 发起一个带有表单数据和头部信息的 POST 请求。** @param url 请求的 URL 地址* @param headers 请求的头部信息* @param formData 表单数据* @param callback 回调函数*/void postForm(String url, RequestHeaders headers, RequestParams formData, Callback callback);}

2.3 链式客户端

在第二个方案上进一步优化,模仿 Stream ,设计一个链式调用接口。
更易维护和使用。

public interface HttpClient {// 设置URLHttpClient url(String url);// 指定请求方法,为了代码可读性,建议调用时显示声明HttpClient method(HttpMethod method);// 添加请求头HttpClient addHeader(Map<String, String> headers);// 添加请求头HttpClient addHeader(String key, String value);// 设置请求参数(适用于 GET 请求)HttpClient queryParam(String key, String value);// 设置JSON请求体(适用于 POST、PUT 等请求)HttpClient jsonBody(String json);// 设置Form表单请求体HttpClient formBody(Map<String, String> formData);// 设置Form表单请求参数HttpClient formBody(String key, String value);// 执行请求<T> T execute(Class<T> responseType);// 异步请求执行,带有回调<T> void executeAsync(Class<T> responseType, Callback<T> callback);// 回调接口interface Callback<T> {void onSuccess(T response);void onFailure(Exception e);}
}

使用参考

public class Demo {private HttpClient client = new DefaultHttpClient();public void doGet() {String response = client.url("https://api.example.com/data").method(HttpMethod.GET).addHeader("Authorization", "Bearer token_value").queryParam("filter", "active").execute(String.class);System.out.println("Response: " + response);}public void doPost() {String jsonRequestBody = "{\"name\": \"John\", \"age\": 30}";String response = client.url("https://api.example.com/users").method(HttpMethod.POST).addHeader("Content-Type", "application/json").jsonBody(jsonRequestBody).execute(String.class);System.out.println("Response: " + response);  }public void doGetAsync() {client.url("https://api.example.com/users").method(HttpMethod.GET).addHeader("Authorization", "Bearer token_value").executeAsync(String.class, new HttpClient.Callback<String>() {@Overridepublic void onSuccess(String response) {System.out.println("Async Response: " + response);}@Overridepublic void onFailure(Exception e) {System.err.println("Request failed: " + e.getMessage());}});}
}

具体实现类可以参考:
https://github.com/BJ-wnn/nanHub

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com