当前位置: 首页 > news >正文

HttpClient、OKhttp、RestTemplate接口调用对比( Java HTTP 客户端)

文章目录

    • HttpClient、OKhttp、RestTemplate接口调用对比
    • HttpClient
    • OkHttp
    • restTemplate

HttpClient、OKhttp、RestTemplate接口调用对比

HttpClient、OkHttp 和 RestTemplate 是三种常用的 Java HTTP 客户端库,它们都可以用于发送 HTTP 请求和接收 HTTP 响应,但在一些方面有所不同。
对比总结:
● 性能和效率: OkHttp 在性能和效率上通常优于 Apache HttpClient 和 RestTemplate,特别是在并发场景和对性能要求较高的情况下。
● 功能和灵活性: Apache HttpClient 提供了更丰富的功能和灵活的配置选项,适用于需要定制化的场景;而 OkHttp 和 RestTemplate 则更加简洁易用。
● 异步支持: OkHttp 提供了异步调用的支持,而 Apache HttpClient 和 RestTemplate 需要通过额外的工作来实现异步调用。
● 与框架集成: RestTemplate 与 Spring 框架集成度高,更适合于 Spring 项目;而 Apache HttpClient 和 OkHttp 可以在各种项目中独立使用。
● 更新维护: OkHttp 是 Square 公司维护的开源项目,更新迭代较为活跃;Apache HttpClient 在过去曾有一段时间的停滞,但也在持续维护;而 RestTemplate 在新项目中可能会被 WebClient 替代,不再是 Spring 官方推荐的首选。
综上所述,选择合适的 HTTP 客户端库取决于项目需求、性能要求、对框架集成的需求以及个人偏好等因素。

HttpClient:

  1. Apache HttpClient:
    ○ 成熟稳定: Apache HttpClient 是 Apache 软件基金会的一个项目,经过多年的发展,已经非常成熟和稳定。
    ○ 灵活性: 提供了丰富的配置选项和扩展点,可以灵活地定制和扩展功能。
    ○ 线程安全: HttpClient 的实例是线程安全的,可以在多线程环境中共享使用。
    ○ 相对庞大: 相对于其他库来说,Apache HttpClient 的体积较大,可能会增加应用程序的大小。

OkHttp:

  1. Square OkHttp:
    ○ 高性能: OkHttp 是一个现代化的 HTTP 客户端,具有优秀的性能和效率。
    ○ 简洁易用: 提供了简洁的 API 设计,易于学习和使用。
    ○ 支持 HTTP/2: 支持 HTTP/2,可以实现多路复用,提高并发性能。
    ○ 轻量级: OkHttp 的体积相对较小,对应用程序的大小影响较小。

RestTemplate:

  1. Spring RestTemplate:
    ○ 与 Spring 集成: RestTemplate 是 Spring 框架提供的一个 HTTP 客户端,与 Spring 生态集成度高。
    ○ 便捷的 RESTful 支持: 提供了便捷的 RESTful 风格的 API 调用支持,如 HTTP 方法映射、请求和响应消息转换等。
    ○ 同步阻塞: RestTemplate 是一个同步阻塞的 HTTP 客户端,对于高并发场景可能性能较差。
    ○ 可能过时: 随着 Spring 5 推出的 WebClient,RestTemplate 在新项目中可能会逐渐被 WebClient 替代。

HttpClient

Apache HttpClient 是一个用于执行 HTTP 请求的开源 Java 库。它提供了丰富的功能和灵活的接口,可以用来发送 HTTP 请求并处理 HTTP 响应。
HttpClient 是Apache的一个三方网络框架,网络请求做了完善的封装,api众多,用起来比较方便,开发快
功能特点:

  1. 支持多种 HTTP 方法: Apache HttpClient 支持 GET、POST、PUT、DELETE 等常见的 HTTP 方法,以及任意自定义的 HTTP 方法。
  2. 支持 HTTPS: HttpClient 支持使用 SSL/TLS 加密协议进行 HTTPS 请求,并可以自定义 SSL/TLS 配置。
  3. 连接管理: HttpClient 提供了连接池管理机制,可以有效地管理 HTTP 连接,减少连接建立的开销。
  4. 请求和响应拦截器: HttpClient 允许用户定义请求和响应的拦截器,可以在请求发送前或响应返回后对请求和响应进行处理。
  5. 自定义请求头和请求参数: HttpClient 允许用户自定义请求头和请求参数,可以灵活地设置 HTTP 请求的各种参数。
  6. 重定向处理: HttpClient 可以自动处理 HTTP 请求的重定向,并且允许用户配置重定向策略。
  7. Cookie 管理: HttpClient 支持自动管理 HTTP Cookie,可以处理 Cookie 的存储、发送和接收。
  8. 代理支持: HttpClient 可以配置使用代理服务器进行 HTTP 请求。
  9. 认证机制: HttpClient 支持多种认证机制,包括基本认证、摘要认证、OAuth 等。
    核心组件:
  10. HttpClient: HttpClient 类是 Apache HttpClient 的核心类,用于执行 HTTP 请求并处理 HTTP 响应。
  11. HttpRequest: HttpRequest 接口表示一个 HTTP 请求,包括请求方法、请求头、请求参数等信息。
  12. HttpResponse: HttpResponse 接口表示一个 HTTP 响应,包括状态码、响应头、响应体等信息。
  13. HttpClientBuilder: HttpClientBuilder 是用于创建 HttpClient 实例的构建器,可以配置 HttpClient 的各种参数。
  14. HttpEntity: HttpEntity 接口表示一个 HTTP 实体,包括请求体、响应体等信息。
  15. HttpClientContext: HttpClientContext 类表示一个 HTTP 执行上下文,包括请求的上下文信息、连接状态等。

HttpClient 是Apache的一个三方网络框架,网络请求做了完善的封装,api众多,用起来比较方便,开发快。

package org.example;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import java.io.*;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;/*** @desc httpClient工具类* @author liangliang* @date 2019/3/11 13:23*/@Slf4j
public class HttpClientUtil {/*** httpclient基础配置信息*/private static final RequestConfig requestConfig = RequestConfig.custom()// 设置连接超时时间(单位毫秒).setConnectTimeout(2000)// 设置请求超时时间(单位毫秒).setConnectionRequestTimeout(2000)// socket读写超时时间(单位毫秒).setSocketTimeout(1000)// 设置是否允许重定向(默认为true).setRedirectsEnabled(true)//是否启用内容压缩,默认true.setContentCompressionEnabled(true).build();/*** 获得Http客户端*/private static final CloseableHttpClient HTTP_CLIENT = HttpClientBuilder.create().setRetryHandler(new DefaultHttpRequestRetryHandler()) //失败重试,默认3次.build();/*** 异步Http客户端*/private static final CloseableHttpAsyncClient HTTP_ASYNC_CLIENT = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();/*** @desc 异步请求* @param httpRequestBase* @author liangliang* @date 2019/3/11 13:23*/private static void executeAsync(HttpRequestBase httpRequestBase) {HTTP_ASYNC_CLIENT.start();HTTP_ASYNC_CLIENT.execute(httpRequestBase, new FutureCallback<HttpResponse>() {@SneakyThrows@Overridepublic void completed(HttpResponse httpResponse) {log.info("thread id is : {}" ,Thread.currentThread().getId());StringBuffer stringBuffer = new StringBuffer();for (Header header : httpRequestBase.getAllHeaders()) {stringBuffer.append(header.toString()).append(",");}log.info("请求头信息: {}", stringBuffer.toString());String responseResult = null;HttpEntity responseEntity = httpResponse.getEntity();log.info("响应状态为:{}", httpResponse.getStatusLine());if (responseEntity != null) {responseResult = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);log.info("响应内容为:{}",responseResult);}stringBuffer = new StringBuffer();for (Header header : httpResponse.getAllHeaders()) {stringBuffer.append(header.toString()).append(",");}log.info("响应头信息: {}", stringBuffer.toString()));}@Overridepublic void failed(Exception e) {log.info("thread id is : {}",Thread.currentThread().getId());log.error("Exception responseResult:{}", e);e.printStackTrace();}@Overridepublic void cancelled() {log.info(httpRequestBase.getRequestLine() + " cancelled");}});}/*** @desc String请求* @param httpRequestBase* @return String* @author liangliang* @date 2019/3/11 13:23*/private static String execute(HttpRequestBase httpRequestBase) {log.info("请求地址: {},请求类型: {}", httpRequestBase.getURI().toString(,httpRequestBase.getMethod()));StringBuffer stringBuffer = new StringBuffer();for (Header header : httpRequestBase.getAllHeaders()) {stringBuffer.append(header.toString()).append(",");}log.info("请求头信息: {}", stringBuffer.toString());log.info("请求参数: {}", httpRequestBase.getURI().getQuery());String responseResult = null;// 响应模型CloseableHttpResponse response = null;try {// 将上面的配置信息 运用到这个Get请求里httpRequestBase.setConfig(requestConfig);long t1 = System.nanoTime();//请求发起的时间response = HTTP_CLIENT.execute(httpRequestBase);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();log.info("响应状态为:{}",response.getStatusLine());long t2 = System.nanoTime();//收到响应的时间if (responseEntity != null) {responseResult = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);log.info("响应内容为:{}",responseResult);}stringBuffer = new StringBuffer();for (Header header : response.getAllHeaders()) {stringBuffer.append(header.toString()).append(",");}log.info("响应头信息: {}", stringBuffer.toString());log.info("执行时间: {}", (t2 - t1));} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();} finally {try {if (response != null) {response.close();}} catch (IOException e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}}return responseResult;}/*** @desc byte[]请求* @param httpRequestBase* @return byte[]* @author liangliang* @date 2019/3/11 13:23*/private static byte[] executeBytes(HttpRequestBase httpRequestBase) {log.info("请求地址: {},请求类型: {}", httpRequestBase.getURI().toString(,httpRequestBase.getMethod()));StringBuffer stringBuffer = new StringBuffer();for (Header header : httpRequestBase.getAllHeaders()) {stringBuffer.append(header.toString()).append(",");}log.info("请求头信息: {}", stringBuffer.toString());log.info("请求参数: {}", httpRequestBase.getURI().getQuery());byte[] bytes = null;// 响应模型CloseableHttpResponse response = null;try {// 将上面的配置信息 运用到这个Get请求里httpRequestBase.setConfig(requestConfig);long t1 = System.nanoTime();//请求发起的时间response = HTTP_CLIENT.execute(httpRequestBase);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();log.info("响应状态为:{}", response.getStatusLine());long t2 = System.nanoTime();//收到响应的时间if (responseEntity != null) {bytes = EntityUtils.toByteArray(responseEntity);//判断是否需要解压,即服务器返回是否经过了gzip压缩--startHeader responseHeader = response.getFirstHeader("Content-Encoding");if (responseHeader != null && responseHeader.getValue().contains("gzip")) {GZIPInputStream gzipInputStream = null;ByteArrayOutputStream out = null;try {gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(bytes));out = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int offset = -1;while ((offset = gzipInputStream.read(buffer)) != -1) {out.write(buffer, 0, offset);}bytes = out.toByteArray();} catch (IOException e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();} finally {try {gzipInputStream.close();out.close();} catch (IOException e) {e.printStackTrace();}}}//判断是否需要解压,即服务器返回是否经过了gzip压缩--endlog.info("响应byte长度:{}", bytes.length);}stringBuffer = new StringBuffer();for (Header header : response.getAllHeaders()) {stringBuffer.append(header.toString()).append(",");}log.info("响应头信息: {}", stringBuffer.toString());log.info("执行时间: {}", (t2 - t1));} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();} finally {try {if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}return bytes;}/*** @desc get请求* @param url* @return tring* @author liangliang* @date 2019/3/11 13:23*/public static String get(String url) {return get(url, new HashMap<>());}/*** @desc get请求* @param url, params* @return tring* @author mal* @date 2019/3/11 13:23*/public static String get(String url, Map<String, Object> params) {HttpGet httpGet = null;List<NameValuePair> list = new ArrayList<>();for (String key : params.keySet()) {list.add(new BasicNameValuePair(key, params.get(key).toString()));}// 由客户端执行(发送)Get请求try {URI uri = new URIBuilder(url).addParameters(list).build();// 创建Get请求httpGet = new HttpGet(uri);} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}return execute(httpGet);}/*** @desc get请求* @param url, params* @return byte[]* @author liangliang* @date 2019/3/11 13:23*/public static byte[] getBytes(String url, Map<String, Object> params) {HttpGet httpGet = null;List<NameValuePair> list = new ArrayList<>();for (String key : params.keySet()) {list.add(new BasicNameValuePair(key, params.get(key).toString()));}// 由客户端执行(发送)Get请求try {URI uri = new URIBuilder(url).addParameters(list).build();// 创建Get请求httpGet = new HttpGet(uri);} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}return executeBytes(httpGet);}/*** @desc post请求* @param url* @return String* @author liangliang* @date 2019/3/11 13:23*/public static String post(String url) {return post(url, new HashMap<>());}/*** @desc post请求* @param url, params* @return String* @author liangliang* @date 2019/3/11 13:23*/public static String post(String url, Map<String, Object> params) {HttpPost httpPost = null;List<NameValuePair> list = new ArrayList<>();for (String key : params.keySet()) {list.add(new BasicNameValuePair(key, params.get(key).toString()));}try {URI uri = new URIBuilder(url).addParameters(list).build();httpPost = new HttpPost(uri);} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}return execute(httpPost);}/*** @desc post请求* @param url, params* @return byte[]* @author liangliang* @date 2019/3/11 13:23*/public static byte[] postBytes(String url, Map<String, Object> params) {HttpPost httpPost = null;List<NameValuePair> list = new ArrayList<>();for (String key : params.keySet()) {list.add(new BasicNameValuePair(key, params.get(key).toString()));}try {URI uri = new URIBuilder(url).addParameters(list).build();httpPost = new HttpPost(uri);} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}return executeBytes(httpPost);}/*** @desc post请求* @param url, json* @return String* @author liangliang* @date 2019/3/11 13:23*/public static String postJson(String url, String json) {return postJson(url, json, false);}/*** @desc post请求* @param url, json, gzip* @return String* @author liangliang* @date 2019/3/11 13:23*/public static String postJson(String url, String json, boolean gzip) {HttpPost httpPost = null;try {URI uri = new URIBuilder(url).build();httpPost = new HttpPost(uri);// post请求是将参数放在请求体里面传过去的,这里将entity放入post请求体中httpPost.setHeader("Content-Type", "application/json;charset=utf8");if (gzip) {httpPost.setHeader("Content-Encoding", "gzip");ByteArrayOutputStream originalContent = new ByteArrayOutputStream();originalContent.write(json.getBytes(StandardCharsets.UTF_8));ByteArrayOutputStream baos = new ByteArrayOutputStream();GZIPOutputStream gzipOut = new GZIPOutputStream(baos);originalContent.writeTo(gzipOut);gzipOut.finish();httpPost.setEntity(new ByteArrayEntity(baos.toByteArray(), ContentType.create("text/plain", "utf-8")));} else {StringEntity entity = new StringEntity(json, "UTF-8");httpPost.setEntity(entity);}} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}return execute(httpPost);}/*** @desc post请求byte流* @param url, bytes* @return String* @author liangliang* @date 2019/3/11 13:23*/public static String postInputBytes(String url, byte[] bytes) {return postInputBytes(url, bytes, false);}/*** @desc post请求byte流* @param url, bytes, gzip* @return String* @author liangliang* @date 2019/3/11 13:23*/public static String postInputBytes(String url, byte[] bytes, boolean gzip) {HttpPost httpPost = null;try {URI uri = new URIBuilder(url).build();httpPost = new HttpPost(uri);// post请求是将参数放在请求体里面传过去的,这里将entity放入post请求体中if (gzip) {httpPost.setHeader("Content-Encoding", "gzip");ByteArrayOutputStream originalContent = new ByteArrayOutputStream();originalContent.write(bytes);ByteArrayOutputStream baos = new ByteArrayOutputStream();GZIPOutputStream gzipOut = new GZIPOutputStream(baos);originalContent.writeTo(gzipOut);gzipOut.finish();httpPost.setEntity(new ByteArrayEntity(baos.toByteArray(), ContentType.create("text/plain", "utf-8")));} else {ByteArrayEntity entity = new ByteArrayEntity(bytes, ContentType.create("text/plain", "utf-8"));httpPost.setEntity(entity);}} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}return execute(httpPost);}/*** @desc post请求流* @param url, is* @return String* @author liangliang* @date 2019/3/11 13:23*/public static String postInputStream(String url, InputStream is) {return postInputStream(url, is, false);}/*** @desc post请求流* @param url, is, gzip* @return String* @author liangliang* @date 2019/3/11 13:23*/public static String postInputStream(String url, InputStream is, boolean gzip) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int ch;byte[] bytes = null;try {while ((ch = is.read(buffer)) != -1) {byteArrayOutputStream.write(buffer, 0, ch);}bytes = byteArrayOutputStream.toByteArray();byteArrayOutputStream.close();} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}return postInputBytes(url, bytes, gzip);}/*** @desc post请求文件* @param url, files* @return String* @author zhangh* @date 2019/3/11 13:23*/public static String postFile(String url, File[] files) {return postFile(url, new HashMap<>(), files);}/*** @desc post请求文件* @param url, params, files* @return String* @author zhangh* @date 2019/3/11 13:23*/public static String postFile(String url, Map<String, Object> params, File[] files) {HttpPost httpPost = null;try {URI uri = new URIBuilder(url).build();httpPost = new HttpPost(uri);MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();String filesKey = "files";for (File file : files) {//multipartEntityBuilder.addPart(filesKey,new FileBody(file)); //与下面的语句作用相同//multipartEntityBuilder.addBinaryBody(filesKey, file);// 防止服务端收到的文件名乱码。 我们这里可以先将文件名URLEncode,然后服务端拿到文件名时在URLDecode。就能避免乱码问题。// 文件名其实是放在请求头的Content-Disposition里面进行传输的,如其值为form-data; name="files"; filename="头像.jpg"multipartEntityBuilder.addBinaryBody(filesKey, file, ContentType.DEFAULT_BINARY, URLEncoder.encode(file.getName(), "utf-8"));}// 其它参数(注:自定义contentType,设置UTF-8是为了防止服务端拿到的参数出现乱码)ContentType contentType = ContentType.create("text/plain", StandardCharsets.UTF_8);for (String key : params.keySet()) {multipartEntityBuilder.addTextBody(key, params.get(key).toString(), contentType);}HttpEntity entity = multipartEntityBuilder.build();// post请求是将参数放在请求体里面传过去的,这里将entity放入post请求体中httpPost.setEntity(entity);} catch (Exception e) {log.error("Exception responseResult:{}", e.getMassage());e.printStackTrace();}return execute(httpPost);}}

OkHttp

高效的HTTP客户端,它能允许同一ip和端口的请求重用一个socket,这种方式能大大降低网络连接的时间,和每次请求都建立socket,再断开socket的方式相比,降低了服务器服务器的压力,透明的GZIP压缩减少响应数据的大小;缓存响应内容。
OkHttp 是一个现代化的 HTTP 客户端库,由 Square 公司开发并维护,用于在 Android 和 Java 应用程序中发送 HTTP 请求和接收 HTTP 响应。它具有以下特点和优势:
高性能: OkHttp 使用了连接池、复用连接、异步请求等技术,可以实现高效的 HTTP 请求和响应处理,性能优秀。
支持 HTTP/2: OkHttp 支持 HTTP/2,能够实现多路复用,提高了网络请求的并发效率。
简洁易用的 API: OkHttp 提供了简洁易用的 API 设计,使用起来非常方便,易于学习和使用。
丰富的功能: OkHttp 提供了丰富的功能,包括请求和响应的拦截、重定向、GZIP 压缩、连接池管理等,可以满足各种复杂的应用场景需求。
灵活性: OkHttp 提供了丰富的配置选项和扩展点,可以灵活地定制和扩展功能,满足各种特定需求。
支持同步和异步请求: OkHttp 支持同步和异步请求,可以根据需求选择合适的方式进行网络请求。
轻量级: OkHttp 的体积相对较小,对应用程序的大小影响较小,适合于移动端应用和对包大小敏感的项目。
持续更新和维护: OkHttp 是由 Square 公司维护的开源项目,更新迭代较为活跃,能够及时修复 bug 和添加新功能。

1、高效的HTTP客户端,它能允许同一ip和端口的请求重用一个socket,这种方式能大大降低网络连接的时间,和每次请求都建立socket,再断开socket的方式相比,降低了服务器服务器的压力,透明的GZIP压缩减少响应数据的大小;缓存响应内容。
2、okhttp 对http和https都有良好的支持。
3、okhttp 对大数据量的网络请求支持非常好。

import okhttp3.*;
import org.apache.commons.lang3.exception.ExceptionUtils;import java.io.File;
import java.util.Iterator;
import java.util.Map;@Slf4j
public class OkHttpUtil{private static OkHttpClient  okHttpClient;@Autowiredpublic OkHttpUtil(OkHttpClient  okHttpClient) {OkHttpUtil.okHttpClient= okHttpClient;} /*** get* @param url   请求的url* @param param 请求的参数* @return*/public static  String get(String url, Map<String, String> param) {String responseBody = "";StringBuffer sb = new StringBuffer(url);if (param!= null && param.keySet().size() > 0) {boolean firstFlag = true;Iterator iterator = param.entrySet().iterator();while (iterator.hasNext()) {Map.Entry entry = (Map.Entry<String, String>) iterator.next();if (firstFlag) {sb.append("?" + entry.getKey() + "=" + entry.getValue());firstFlag = false;} else {sb.append("&" + entry.getKey() + "=" + entry.getValue());}}}Request request = new Request.Builder().url(sb.toString()).build();Response response = null;try { response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post exception:{}", e.getMessage());} finally {if (response != null) {response.close();}}return responseBody;}/*** post** @param url    请求的url* @param params post form 提交的参数* @return*/public static String post(String url, Map<String, String> params) {String responseBody = "";FormBody.Builder builder = new FormBody.Builder();//添加参数if (params != null && params.keySet().size() > 0) {for (String key : params.keySet()) {builder.add(key, params.get(key));}}Request request = new Request.Builder().url(url).post(builder.build()).build();Response response = null;try { response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post exception:{}", e.getMessage());} finally {if (response != null) {response.close();}}return responseBody;}/*** get* @param url     请求的url* @param param 请求的参数* @return*/public static String getForHeader(String url, Map<String, String> param) {String responseBody = "";StringBuffer sb = new StringBuffer(url);if (param != null && param.keySet().size() > 0) {boolean firstFlag = true;Iterator iterator = param.entrySet().iterator();while (iterator.hasNext()) {Map.Entry entry = (Map.Entry<String, String>) iterator.next();if (firstFlag) {sb.append("?" + entry.getKey() + "=" + entry.getValue());firstFlag = false;} else {sb.append("&" + entry.getKey() + "=" + entry.getValue());}}}Request request = new Request.Builder().addHeader("key", "value").url(sb.toString()).build();Response response = null;try { response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post exception:{}", e.getMessage());} finally {if (response != null) {response.close();}}return responseBody;}/*** Post请求发送JSON数据* @param url 请求Url* @param jsonParams 请求的JSON*/public static String postJsonParams(String url, String jsonParams) {String responseBody = "";RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);Request request = new Request.Builder().url(url).post(requestBody).build();Response response = null;try { response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post exception:{}", e.getMessage());} finally {if (response != null) {response.close();}}return responseBody;}/*** Post请求发送xml类型数据* @param url 请求Url* @param xml 请求的xml*/public static String postXmlParams(String url, String xml) {String responseBody = "";RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);Request request = new Request.Builder().url(url).post(requestBody).build();Response response = null;try { response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post exception:{}", e.getMessage());} finally {if (response != null) {response.close();}}return responseBody;}
}

restTemplate

RestTemplate 是 Spring 框架提供的一个用于进行 HTTP 请求的模板类,它简化了在 Java 中进行 HTTP 请求的操作。RestTemplate 提供了丰富的方法来发送 HTTP 请求,并且支持多种 HTTP 请求方法(如 GET、POST、PUT、DELETE 等),以及各种数据格式(如 JSON、XML 等)的处理。
RestTemplate 是由Spring提供的一个HTTP请求工具。比传统的Apache和HttpCLient便捷许多,能够大大提高客户端的编写效率。

1、Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
2、面向对 RESTful Web 服务调用的功能。
1、Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
2、面向对 RESTful Web 服务调用的功能。
在微服务中的使用
1、第三方服务调用,个人常用 RestTemplate, 这里RestTemplate未未进行封装,直接使用其方法。
2、微服务间调用,个人使用feign,同时使用OKhttp替换feign中默认的httpClient。
Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。 我们可以用HTTP Client 或 OKhttp 替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。

特点和优势:

  1. 与 Spring 集成: RestTemplate 是 Spring 框架的一部分,与 Spring 生态完美集成,可以轻松在 Spring 项目中使用。
  2. 简化 HTTP 请求: RestTemplate 封装了发送 HTTP 请求的底层细节,使得发送 HTTP 请求变得简单和方便。
  3. RESTful 支持: RestTemplate 提供了便捷的 RESTful 风格的 API 调用支持,可以方便地进行资源的增删改查操作。
  4. 丰富的方法: RestTemplate 提供了多种方法来发送不同类型的 HTTP 请求,包括 getForObject()、postForObject()、exchange() 等,以及一系列便捷的方法用于设置请求参数、请求头等。
  5. 支持数据转换: RestTemplate 支持自动将请求和响应的数据转换为 Java 对象,可以通过消息转换器实现 JSON、XML 等格式的数据转换。
  6. 同步阻塞: RestTemplate 是一个同步阻塞的 HTTP 客户端,发送请求后会阻塞当前线程直到收到响应或超时。
  7. 异常处理: RestTemplate 提供了异常处理机制,可以捕获和处理请求过程中可能出现的异常。
    RestTemplate 是由Spring提供的一个HTTP请求工具。比传统的Apache和HttpCLient便捷许多,能够大大提高客户端的编写效率。
    1、Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
    2、面向对 RESTful Web 服务调用的功能。
    1、Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
    2、面向对 RESTful Web 服务调用的功能。
    在微服务中的使用
    1、第三方服务调用,个人常用 RestTemplate, 这里RestTemplate未未进行封装,直接使用其方法。
    2、微服务间调用,个人使用feign,同时使用OKhttp替换feign中默认的httpClient。
    Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。 我们可以用HTTP Client 或 OKhttp 替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。

RestTemplate 是由Spring提供的一个HTTP请求工具。比传统的Apache和HttpCLient便捷许多,能够大大提高客户端的编写效率。

1、Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
2、面向对 RESTful Web 服务调用的功能。
1、Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
2、面向对 RESTful Web 服务调用的功能。
在微服务中的使用
1、第三方服务调用,个人常用 RestTemplate, 这里RestTemplate未未进行封装,直接使用其方法。
2、微服务间调用,个人使用feign,同时使用OKhttp替换feign中默认的httpClient。
Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。 我们可以用HTTP Client 或 OKhttp 替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。

SpringCloud 1.x
<!-- 使用Apache HttpClient替换Feign原生httpclient --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><dependency><groupId>com.netflix.feign</groupId><artifactId>feign-httpclient</artifactId><version>${feign-httpclient}</version></dependency>application.properties中添加:
feign.httpclient.enabled=true
<!-- 使用OKhttp替换Feign原生httpclient -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId><version>10.2.0</version>
</dependency>SpringColud 2.x
<!-- 使用OKhttp替换openFeign原生httpclient -->
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>3.10.0</version>
</dependency>

application.properties中添加:
feign.okhttp.enabled=true

相关文章:

HttpClient、OKhttp、RestTemplate接口调用对比( Java HTTP 客户端)

文章目录 HttpClient、OKhttp、RestTemplate接口调用对比HttpClientOkHttprestTemplate HttpClient、OKhttp、RestTemplate接口调用对比 HttpClient、OkHttp 和 RestTemplate 是三种常用的 Java HTTP 客户端库&#xff0c;它们都可以用于发送 HTTP 请求和接收 HTTP 响应&#…...

[旅游] 景区排队上厕所

人有三急&#xff0c;急中最急是上个厕所要排队&#xff0c;而且人还不少&#xff01;这样就需要做一个提前量的预测&#xff0c;万一提前量的预测&#xff0c;搞得不当&#xff0c;非得憋出膀光炎&#xff0c;或者尿裤子。尤其是女厕所太少&#xff01;另外一点是儿童根本就没…...

三 maven的依赖管理

一 maven依赖管理 Maven 依赖管理是 Maven 软件中最重要的功能之一。Maven 的依赖管理能够帮助开发人员自动解决软件包依赖问题&#xff0c;使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中&#xff0c;避免出现版本冲突和依赖缺失等…...

iperf3 网络性能测试

iperf3测试 1、iperf3简介 iperf3是一个主动测试网络带宽的工具&#xff0c;可以测试iTCP、UDP、SCTP等网络带宽&#xff1b;可以通过参数修改网络协议、缓冲区、测试时间、数据大小等&#xff0c;每个测试结果会得出吞吐量、带宽、重传数、丢包数等测试结果 2、参数详解 通…...

08 Php学习:if语句、Switch语句

PHP 条件语句 当您编写代码时&#xff0c;您常常需要为不同的判断执行不同的动作。您可以在代码中使用条件语句来完成此任务。 在 PHP 中&#xff0c;提供了下列条件语句&#xff1a; if 语句 - 在条件成立时执行代码 if…else 语句 - 在条件成立时执行一块代码&#xff0c;…...

二分查找的边界问题是怎么产生的?

总结&#xff1a;二分查找的目标有两个&#xff0c;一个是左区件的右边界&#xff0c;一个是右区间的左边界 如何去理解二分的过程&#xff1f; 如果要查找的是左区间的右边界&#xff1a; 可以将[l, r]理解一个集合&#xff0c;这个集合范围内的数都有可能是最后需要得到的…...

华为 2024 届校园招聘-硬件通⽤/单板开发——第十套

华为 2024 届校园招聘-硬件通⽤/单板开发——第十套 部分题目分享&#xff0c;完整版带答案(有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09;&#xff08;共十套&#xff09;获取&#xff08;WX:didadidadidida313&#xff0c;加我…...

五子棋:不会下五子棋也没关系,会用Java写五子棋就行

关注公号“微澜网络”获取完整源代码&#xff01; 效果展示&#xff1a; 目录 效果展示&#xff1a; 导语&#xff1a; 游戏介绍&#xff1a; 程序设计&#xff1a; 1.游戏规则和功能&#xff1a; 2.用户界面设计&#xff1a; 3.程序架构设计&#xff1a; 4.可扩展性和灵…...

【VUE】使用Vue和CSS动画创建滚动列表

使用Vue和CSS动画创建滚动列表 在这篇文章中&#xff0c;我们将探讨如何使用Vue.js和CSS动画创建一个动态且视觉上吸引人的滚动列表。这个列表将自动滚动显示项目&#xff0c;类似于轮播图的方式&#xff0c;非常适合用于仪表盘、排行榜或任何需要在有限空间内展示项目列表的应…...

分布式结构化数据表Bigtable

文章目录 设计动机与目标数据模型行列时间戳 系统架构主服务器Chubby作用子表服务器SSTable结构子表实际组成子表地址组成子表数据存储及读/写操作数据压缩 性能优化局部性群组&#xff08;Locality groups&#xff09;压缩布隆过滤器 Bigtable是Google开发的基于GFS和Chubby的…...

langchain 加载 csv,json

csv from langchain_community.document_loaders.csv_loader import CSVLoaderloader CSVLoader(file_pathdata/专业描述.csv, csv_args{delimiter: ,,quotechar: ",fieldnames: [专业, 描述] }, encodingutf8, source_column专业)data loader.load() print(data)quote…...

Java-常见面试题收集(十三)

二十二 Redis 1 Redis 作用 Redis&#xff0c;全称Remote Dictionary Server&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSI C语言编写的、支持网络的、基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API。它主要用于缓存数据的计算…...

第二证券策略:股指预计维持震荡格局 关注汽车、工程机械等板块

第二证券指出&#xff0c;指数自今年2月份阶段低点反弹以来&#xff0c;3月份持续高位整理。进入4月份之后面对年报和一季报的双重财报发表期&#xff0c;预计指数短期保持高位整理概率比较大。前期缺乏成绩支撑的概念股或有回落的危险&#xff0c;主张重视成绩稳定、估值低、分…...

hcia datacom课程学习(6):路由与路由表基础

1.路由的作用 不同网段的设备互相通信需要具有路由功能的设备进行转发 具有路由功能的设备不一定是路由器&#xff0c;交换机可以有路由功能&#xff0c;同样的&#xff0c;路由器也可以有交换功能&#xff0c;像家里常用的路由器就是集路由功能和交换功能于一体的 2.路由相…...

AI PC元年,华为的一张航海图、一艘渡轮和一张船票

今天&#xff0c;从学术研究者到产业投资者&#xff0c;无不认为大模型掀起了一场人工智能的完美风暴。 所谓“完美风暴”&#xff0c;指的是一项新技术的各个要素&#xff0c;以新的方式互相影响、彼此加强&#xff0c;组合在一起形成了摧枯拉朽般的力量。 而我们每个人&#…...

NAT技术

网络技术深似海呀&#xff0c;一段时间不用又忘。 是什么 NAT技术是网络防火墙技术的一部分&#xff0c;可以作用在linux防火墙或者设备防火墙&#xff0c;NAT技术可以实现地址和端口的转换&#xff0c;主要还是为了网络连通性。 作用 存在以下三个IP&#xff0c;A(10.234.…...

新能源汽车“价格战”之后,充电桩主板市场将会怎样?

2024年2月底&#xff0c;国内新能源汽车市场开启了一场前所未有的“价格战”↓ 比亚迪率先抛出“王炸”车型——秦PLUS荣耀版和驱逐舰05荣耀版&#xff0c;起售价低至7.98万元&#xff0c;打响了价格战的“第一枪”&#xff0c;引爆了平静的汽车市场。 “电比油低”就此拉开序…...

appium driver install uiautomator2 安装失败

报错 Installing ‘uiautomator2’ using NPM install spec ‘appium-uiautomator2-driver’ Error: Encountered an error when installing package: npm command ‘install --save-dev --no-progress --no-audit --omitpeer --save-exact --global-style --no-package-lock…...

学浪已购买视频怎么下载到本地?

许多学习者在学浪购买了丰富的课程&#xff0c;然而&#xff0c;一些课程存在时间限制&#xff0c;使得学习者希望将其下载并永久保存。在这里&#xff0c;我们将介绍一款名为小浪助手的工具&#xff0c;它能够帮助你轻松将学浪已购买的视频下载到本地&#xff0c;让学习变得更…...

k8s-pod设置执行优先级

Pod的优先级管理是Kubernetes调度中的一个重要特性&#xff0c;通过PriorityClass&#xff08;优先级类&#xff09;的设置&#xff0c;我们可以为Pod指定不同的优先级&#xff0c;从而在资源有限的情况下更精细地调整调度顺序 什么是PriorityClass&#xff1f; PriorityClass是…...

const修饰指针

const修饰指针 常量指针 特点为指针的指向可以改&#xff0c;但是指针指向的值不可以修改 int a 10; int b 20; const int *p &a; *p 20; //错误&#xff0c;指针的指向的值不可更改 p &b; //正确 指针常量 特点是指针的指向不可以改&#xff0c;指针指向的值…...

php关于序列化r的指向

在PHP中&#xff0c;序列化字符串的索引是根据序列化过程中值的出现顺序来确定的。每个值&#xff08;包括数组的键和值&#xff09;在序列化字符串中都会被赋予一个顺序索引。为了理解这个顺序&#xff0c;我们需要知道以下几点&#xff1a; 序列化时&#xff0c;数组的键和值…...

从0到1实现RPC | 11 丰富测试案例

测试案例主要针对服务消费者consumer&#xff0c;复杂逻辑都在consumer端。 常规int类型&#xff0c;返回User对象 参数类型转换&#xff0c;主要实现逻辑都在TypeUtils工具类中。 测试方法重载&#xff0c;同名方法&#xff0c;参数不同 方法签名的实现&#xff0c;主要逻辑…...

在前端开发中用到了哪些设计模式?

在前端开发中用到了哪些设计模式&#xff1f; 1.单例模式2.观察者模式3.工厂模式4.适配器模式5.装饰器模式6.命令模式7.迭代器模式8.组合模式9.策略模式10.发布订阅模式 1.单例模式 确保一个类只有一个实例&#xff0c;提供一个全局访问点&#xff0c;vue就是一个单例模式&…...

ES6 的解构赋值

解构赋值&#xff08;Destructuring assignment&#xff09;是一种方便快捷的方式&#xff0c;可以从对象或数组中提取数据&#xff0c;并将数据赋值给变量。解构赋值是ES6中一项强大且常用的特性. 1. 基本数组解构 首先&#xff0c;让我们看看如何对数组进行解构赋值。假设我…...

蓝桥杯物联网竞赛_STM32L071KBU6_全部工程及国赛省赛真题及代码

包含stm32L071kbu6全部实验工程、源码、原理图、官方提供参考代码及国、省赛真题及代码 链接&#xff1a;https://pan.baidu.com/s/1pXnsMHE0t4RLCeluFhFpAg?pwdq497 提取码&#xff1a;q497...

关于UCG游戏平台的一些思考

UCG游戏平台&#xff0c;全称User Generated Content&#xff0c;即用户生成内容。它涵盖了所有玩家可以自主编辑的部分&#xff0c;包含并不限于换装、捏脸、关卡摆放等内容。 UCG概念在最近又火了起来&#xff0c;但这个模式出现的并不早。早在10多年前&#xff0c;war3编辑器…...

一起学习python——基础篇(20)

前言&#xff0c;之前经常从网上找一些免费的接口来测试&#xff0c;有点受制于人的感觉。想了想还不如直接写一个接口&#xff0c;这样方便自己测试。自己想返回什么格式就返回什么样子&#xff0c;不用担心服务报错&#xff0c;因为自己就可以完全掌控。然后宿舍二哥告诉我py…...

云服务器安装Mysql、MariaDB、Redis、tomcat

前置工作 进入根目录 cd / 创建java文件夹 mkdir java 进入java文件夹 cd java 上传压缩包 rz 压缩包 Mysql 1.下载并安装MySQL官方的 Yum Repository wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm rpm -ivh mysql-community-release-el7-5.noa…...

Android笔记--MediaCodec(二)

这一节主要了解MediaCodec处理音频&#xff0c;MediaCodec直译媒体解码器&#xff0c;用于访问媒体编解码器&#xff0c;即编码器/解码器组件&#xff0c;它是 Android 多媒体支持基础设施的一部分&#xff1b;从广义上讲&#xff0c;编解码器处理输入数据以生成输出数据。它异…...

网站做的自适应体验差/怎么能在百度上做推广

一 1.加入此行代码&#xff0c;注意不要比过去(左边为修改后&#xff0c;右为修改后)&#xff0c;先修改framework下的AntiTheftManager.java文件&#xff08;路径&#xff1a;alps\frameworks\base\packages\Keyguard\src\com\mediatek\keyguard\AntiTheft&#xff09; 2.这里…...

外网访问wordpress版式不对/百度关键词下拉有什么软件

链表 在内存空间中&#xff0c;数组和链表都是基本的数据结构&#xff0c;都是【表】&#xff0c;或者叫【线性表】。线性表是一个线性结构&#xff0c;它是一个含有n≥0个结点的有限序列&#xff0c;对于其中的结点&#xff0c;有且仅有一个开始结点没有前驱但有一个后继结点…...

苏州企业如何建网站/广告推广 精准引流

为什么80%的码农都做不了架构师&#xff1f;>>> 本文将介绍如何配置jenkins&#xff0c;使其可以支持基于角色的项目权限管理。 由于jenkins默认的权限管理体系不支持用户组或角色的配置&#xff0c;因此需要安装第三发插件来支持角色的配置&#xff0c;本文将使用…...

企业网站制作机构排名/百度网络营销中心官网

2020年3月9日&#xff0c;明道云私有部署版通过了腾讯云的审核&#xff0c;正式上架腾讯云应用镜像市场。安装和介绍页面&#xff1a;https://market.cloud.tencent.com/products/19148这意味着&#xff0c;如果您想要使用明道云私有部署版&#xff0c;只需要一个腾讯云账号&am…...

wordpress会员发布文章/上海公司排名

设置定时任务很简单&#xff0c;用Timer类就搞定了。一、延时执行首先&#xff0c;我们定义一个类&#xff0c;给它取个名字叫TimeTask&#xff0c;我们的定时任务&#xff0c;就在这个类的main函数里执行。代码如下&#xff1a;package test;import java.util.Timer;public cl…...

湘潭网站优化/seo外包公司哪家专业

PHP 开发工具 看到一篇介绍PHP开发工具的比较好的文章&#xff0c;转之作者 Harry Fuecks 来源 sitepoint.com 2004-06-21 PHP开发工具资源本文摘录自Harry Fuecks在sitepoint的一篇帖子&#xff0c;Easy按照软件开发的流程简单的整理了一下&#xff0c;希望大家能有所收获。…...