本文主要描述使用okHttp实现简单的客户端,仅支持REST调用,即请求和响应均为文本,可以作为RestTemplate底层的实现支撑。
1、基于okHttp 3.10.0 +
2、仅实现同步调用。
3、通用客户端,仅支持Rest调用,即请求和响应均为文本类型。
类列表:
1、HttpClientConfiguration:客户端的主要配置,包括连接超时、连接池大小等。
2、HttpClientTemplate:接口,描述了客户端支持的基本操作。
3、AbstractHttpClientTemplate:2、接口的基本实现,主要用于构建默认参数和方法。
4、OkHttpClientTemplate:主要实现类,用户描述GET/POST操作的过程。
5、OkHttpClientBuilder:静态类,用于外部便捷的构建client,可以被spring、springboot集成(自动装配时使用)。
一、HttpClientConfiguration
/** * HTTP Client配置管理 **/ public class HttpClientConfiguration implements Serializable { //目前不能修改,常量值 private static final int DEFAULT_MAX_CONNECTIONS = 1024; //连接创建 public static final long DEFAULT_CONNECTION_TIMEOUT = 500; //SO_TIMEOUT public static final long DEFAULT_SOCKET_TIMEOUT = 500; //连接池中的连接被保活的时长 public static final long DEFAULT_KEEP_ALIVE_TIME = 6000; //请求异常(exception),重试的次数,默认为0,不重试 public static final int DEFAULT_HTTP_RETRY_TIMES = 0; //是否重试 public static final boolean DEFAULT_HTTP_RETRY_ON_FAILURE = false; public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT = 1500; public static final String HTTP_CLIENT_TYPE_OK_HTTP = "okHttp"; public static final String HTTP_CLIENT_TYPE_HTTP_COMPONENTS = "httpComponents"; //连接创建 private long connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; //SO_TIMEOUT private long socketTimeout = DEFAULT_SOCKET_TIMEOUT; //连接池中的连接被保活的时长 private long keepAliveTime = DEFAULT_KEEP_ALIVE_TIME; //请求异常(exception),重试的次数,默认为0,不重试 private int retryTimes = DEFAULT_HTTP_RETRY_TIMES; //是否重试 private boolean retryOnFailure = DEFAULT_HTTP_RETRY_ON_FAILURE; private String charset = ContextConstants.DEFAULT_CHARSET; //全局headers,即所有请求都会添加 private Map<String, String> globalHeaders; private int connectionRequestTimeout = 1500; private String clientType = HTTP_CLIENT_TYPE_HTTP_COMPONENTS; public void setConnectionTimeout(Long connectionTimeout) { this.connectionTimeout = connectionTimeout; } public void setSocketTimeout(Long socketTimeout) { this.socketTimeout = socketTimeout; } public void setKeepAliveTime(Long keepAliveTime) { this.keepAliveTime = keepAliveTime; } public void setRetryTimes(Integer retryTimes) { this.retryTimes = retryTimes; } public void setRetryOnFailure(Boolean retryOnFailure) { this.retryOnFailure = retryOnFailure; } public void setCharset(String charset) { this.charset = charset; } public Long getConnectionTimeout() { return connectionTimeout; } public Long getSocketTimeout() { return socketTimeout; } public Long getKeepAliveTime() { return keepAliveTime; } public Integer getRetryTimes() { return retryTimes; } public Boolean getRetryOnFailure() { return retryOnFailure; } public String getCharset() { return charset; } public Map<String, String> getGlobalHeaders() { return globalHeaders; } public void setGlobalHeaders(Map<String, String> globalHeaders) { this.globalHeaders = globalHeaders; } public int getMaxConnections() { return DEFAULT_MAX_CONNECTIONS; } public int getConnectionRequestTimeout() { return connectionRequestTimeout; } public void setConnectionRequestTimeout(int connectionRequestTimeout) { this.connectionRequestTimeout = connectionRequestTimeout; } public String getClientType() { return clientType; } public void setClientType(String clientType) { this.clientType = clientType; } private HttpClientConfiguration() { } /** * 构建一个常规配置 * * @param globalHeaders * @return */ public static HttpClientConfiguration common(Map<String, String> globalHeaders) { HttpClientConfiguration configuration = new HttpClientConfiguration(); configuration.setCharset(ContextConstants.DEFAULT_CHARSET);//UTF-8 configuration.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);//500 configuration.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT);//500 configuration.setKeepAliveTime(DEFAULT_KEEP_ALIVE_TIME);//6000 configuration.setRetryOnFailure(DEFAULT_HTTP_RETRY_ON_FAILURE);//FALSE configuration.setRetryTimes(DEFAULT_HTTP_RETRY_TIMES);//0 if (globalHeaders != null) { configuration.setGlobalHeaders(globalHeaders); } configuration.setConnectionRequestTimeout(DEFAULT_CONNECTION_REQUEST_TIMEOUT); return configuration; } public static HttpClientConfiguration common() { return common(null); } }
1)connectionTimeout、socketTimeout,我们约定为500ms,对于普通WEB接口而言,此参数为权衡值,你可以根据自己的业务现状适度调整。
2)keepAliveTime:连接池中的连接被保活的时长,默认为6000ms,不建议设置太大。
3)retryOnFailure:当请求调用失败时,是否支持重试,失败主要为IO异常,强烈建议此值为false。
4)retryTimes:当retryOnFailure=true时,失败重试的次数,建议为0。
5)连接池容量,需要注意okHttp其实不支持设置此值。为了与Apache HttpClient保持相同参数列表。
二、HttpClientTemplate
public interface HttpClientTemplate extends BeanLifeCycle { /** * 普通get操作 * * @param uri 不应该包含查询字符串 * @return */ public String get(String uri); /** * @param uri 不包含查询字符串 * @param parameters 查询字符串,编码之前原始字符串,内部会提供编码和转义。默认UTF-8 * @return */ public String get(String uri, Map<String, String> parameters); /** * @param uri 不应该包含查询字符串 * @param parameters 查询字符串,编码之前的原始字符串 * @param headers http header * @return */ public String get(String uri, Map<String, String> parameters, Map<String, String> headers); /** * 普通post * * @param uri 不应该包含查询字符串 * @return */ public String post(String uri); /** * 数据将通过body发送 * * @param uri 不应该包含查询字符串 * @param content JSON内容文本,应该使用与client相同的编码进行 * @return */ public String post(String uri, String content); /** * 数据将通过body发送 * * @param uri 不应该包含查询字符串 * @param content JSON格式文本 * @param parameters 查询字符串 * @return */ public String post(String uri, String content, Map<String, String> parameters); /** * 数据将通过body发送 * * @param uri 不应该包含查询字符串 * @param content JSON格式文本,body * @param parameters 查询字符串 * @param headers headers * @return */ public String post(String uri, String content, Map<String, String> parameters, Map<String, String> headers); /** * 返回底层的httpClient,通常情况是用户希望直接使用此client做自定义操作。 * * @return */ public Object getClient(); public String clientType(); }
三、AbstractHttpClientTemplate
public abstract class AbstractHttpClientTemplate implements HttpClientTemplate { //全局headers,即所有请求都会添加,可以被用户指定的headers覆盖 protected Map<String, String> globalHeaders; protected static final String CONTENT_TYPE_JSON = "application/json";//default //json格式,限定 protected static final String CONTENT_TYPE_JSON_PATTERN = CONTENT_TYPE_JSON + "; charset={0}";//default protected HttpClientConfiguration configuration = HttpClientConfiguration.common(); protected String charset = configuration.getCharset(); private volatile boolean init = false; public AbstractHttpClientTemplate() { } public AbstractHttpClientTemplate(HttpClientConfiguration configuration) { if (configuration != null) { this.configuration = configuration; this.globalHeaders = configuration.getGlobalHeaders(); } } public void setGlobalHeaders(Map<String, String> globalHeaders) { this.globalHeaders = globalHeaders; configuration.setGlobalHeaders(globalHeaders); } public synchronized void init() { if (init) { return; } init = true; } protected HttpClientConfiguration configuration() { return this.configuration; } }
四、OkHttpClientTemplate实现类
import okhttp3.*; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.net.URLEncoder; import java.text.MessageFormat; import java.util.HashMap; import java.util.List; import java.util.Map; /** **/ public class OkHttpClientTemplate extends AbstractHttpClientTemplate { private OkHttpClient httpClient; private volatile boolean init = false; private List<Interceptor> interceptors; public void setInterceptors(List<Interceptor> interceptors) { this.interceptors = interceptors; } public OkHttpClientTemplate() { super(); } public OkHttpClientTemplate(HttpClientConfiguration configuration) { super(configuration); } @Override public synchronized void init() { if (init) { return; } super.init(); httpClient = OkHttpClientBuilder.build(configuration(), interceptors); init = true; } @Override public String get(String uri) { return get(uri, null); } @Override public String get(String uri, Map<String, String> parameters) { return get(uri, parameters, null); } @Override public String get(String uri, Map<String, String> parameters, Map<String, String> headers) { if (StringUtils.isBlank(uri)) { return null; } try { Request.Builder builder = new Request.Builder(); builder.url(url(uri, parameters)); builder.header("Content-type", MessageFormat.format(CONTENT_TYPE_JSON_PATTERN, charset)); headers(builder, headers); Request request = builder.get().build(); return process(request); } catch (Exception e) { throw new RuntimeException("HttpClient error.", e); } } /** * 将URI与查询字符串进行编码拼装。 * * @param uri * @param parameters * @return * @throws Exception */ private String url(String uri, Map<String, String> parameters) throws Exception { if (parameters == null || parameters.isEmpty()) { return uri; } StringBuilder sb = new StringBuilder(uri); if (uri.indexOf("?") == -1) { sb.append("?1=1"); } for (Map.Entry<String, String> entry : parameters.entrySet()) { String value = entry.getValue(); String encodedValue = ""; //如果value为null,使用空串 if (value != null) { encodedValue = URLEncoder.encode(entry.getValue(), charset); } sb.append("&").append(entry.getKey()) .append("=") .append(encodedValue); } return sb.toString(); } /** * 整合headers,将用户指定的请求headers与配置的globalHeaders进行merge,并添加到request中。 * * @param builder * @param headers */ private void headers(Request.Builder builder, Map<String, String> headers) { if (headers == null && globalHeaders == null) { return; } Map<String, String> _headers = new HashMap<>(); if (globalHeaders != null && !globalHeaders.isEmpty()) { _headers.putAll(globalHeaders); } if (headers != null && !headers.isEmpty()) { _headers.putAll(headers);//允许自定义header覆盖全局 } for (Map.Entry<String, String> entry : _headers.entrySet()) { String value = entry.getValue() == null ? "" : entry.getValue(); builder.header(entry.getKey(), value); } } @Override public String post(String uri) { return post(uri, null); } @Override public String post(String uri, String content) { return post(uri, content, null); } @Override public String post(String uri, String content, Map<String, String> parameters) { return post(uri, content, parameters, null); } @Override public String post(String uri, String content, Map<String, String> parameters, Map<String, String> headers) { if (StringUtils.isBlank(uri)) { return null; } try { Request.Builder builder = new Request.Builder(); builder.url(url(uri, parameters)); headers(builder, headers); String contentType = MessageFormat.format(CONTENT_TYPE_JSON_PATTERN, charset); RequestBody body = RequestBody.create(MediaType.parse(contentType), content); builder.post(body); Request request = builder.build(); return process(request); } catch (Exception e) { throw new RuntimeException("HttpClient error.", e); } } private String process(Request request) throws Exception { Response response = null; try { response = httpClient.newCall(request).execute(); int statusCode = response.code(); if (statusCode != 200) { throw new RuntimeException("HttpClient error,status =" + response.code() + ",message:" + response.message()); } ResponseBody body = response.body(); String result = null; if (body != null) { result = body.string(); } return result; } finally { if (response != null) { response.close(); } } } @Override public OkHttpClient getClient() { return httpClient; } @Override public String clientType() { return HttpClientConfiguration.HTTP_CLIENT_TYPE_OK_HTTP; } @Override public void close() throws IOException { if (httpClient != null) { httpClient.dispatcher().executorService().shutdown(); } } }
五、OkHttpClientBuilder构建类
import okhttp3.ConnectionPool; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import java.util.List; import java.util.concurrent.TimeUnit; /** * 基于OkHttp实现的客户端,辅助builder,适用于外部应用在没有context配置情况下构建内置的HTTP组件 * okHttp的优点很多:特别的高效、简单易控、默认线程池、自动保活 + 断链等。 * 缺点就是:特性略少,不能便捷的自定义很多特殊的场景,比如cookie、form表单等等。 * <p> * 当使用者希望自己构建httpClient时,可以使用builder。 **/ public final class OkHttpClientBuilder { public static OkHttpClient build(HttpClientConfiguration configuration) { return build(configuration, null); } /** * used OkHttp * * @return */ public static OkHttpClient build(HttpClientConfiguration configuration, List<Interceptor> interceptors) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(configuration.getConnectionTimeout(), TimeUnit.MILLISECONDS); //不能设置最大连接数,默认连接是可重用的。 ConnectionPool connectionPool = new ConnectionPool(3, configuration.getKeepAliveTime(), TimeUnit.MILLISECONDS); builder.connectionPool(connectionPool); builder.readTimeout(configuration.getSocketTimeout(), TimeUnit.MILLISECONDS); builder.retryOnConnectionFailure(configuration.getRetryOnFailure()); builder.writeTimeout(configuration.getSocketTimeout(), TimeUnit.MILLISECONDS); if (interceptors != null) { for (Interceptor interceptor : interceptors) { builder.addInterceptor(interceptor); } } return builder.build(); } /** * 基于常规默认 * * @return */ public static OkHttpClient build() { HttpClientConfiguration configuration = HttpClientConfiguration.common(); return build(configuration); } }
相关推荐
本文将详细解析如何在Android项目中创建一个简单的OKHttp客户端,并利用其可编程的请求拦截器功能进行自定义操作。 首先,我们需要在项目中引入OKHttp的依赖。在`build.gradle`文件的dependencies块中添加以下代码...
Gander拦截并持久保存应用程序内的所有HTTP请求和响应,并提供一个UI界面用于检查其中的内容。
maven服务器项目: 1.搭建环境ubuntu16.04系统apache2+tomcat7.0 2.项目SSM框架:spring+springmvc+mybatis(mysql数据库) ...5.框架:okhttp框架 参考文章地址:https://user.qzone.qq.com/2482293743
Chuck是专为Android开发者设计的一个轻量级工具,它允许开发者在自己的应用程序中方便地检查和调试OkHttp客户端的HTTP通信。通过集成Chuck,开发者可以查看请求头、响应头、请求体以及响应体等关键信息,从而更好地...
使用可编程请求拦截器的简单OKHttp客户端模拟 进口 在您的build.gradle添加: dependencies { testImplementation ' com.github.gmazzo:okhttp-mock:<version> ' } 用法 创建一个OkHttp请求拦截器并记录一些规则...
Simpleinceptor是Android okhttp客户端的拦截界面工具,它便于测试或开发以及快速发现问题。 SimpleInterceptor Simpleinceptor是Android okhttp客户端的拦截接口工具,它便于测试或开发以及快速发现问题。 环境要求...
1. **OkHttp**: OkHttp是Google开发的一个高效的HTTP客户端库,它通过连接池、HTTP/2协议支持和重试机制提高了网络请求的性能。Gander利用OkHttp的强大功能,拦截并记录其处理的所有网络活动。 2. **网络拦截器**: ...
【标题】"oksocial,OKHTTP社交客户端.zip"所涉及的知识点主要集中在使用OkHttp库构建的社交客户端上。OkHttp是由Square公司开发的一款高效、易用的HTTP客户端库,适用于Android和Java平台。它旨在提供比标准Android ...
在Android开发中,HTTP客户端编程是一项基础且重要的技能,它使得Android应用能够与远程服务器进行数据交换,从而实现丰富的功能。本节主要讨论如何在Android平台上实现HTTP通信,特别是使用HttpUrlConnection接口来...
"SunnyDays"就是这样一款应用,它以简洁的平面设计风格,结合强大的Forecast.io API和okHTTP客户端,为用户提供实时、准确的天气信息。 首先,让我们来了解一下Forecast.io API。Forecast.io是Dark Sky公司提供的一...
通过一个完整的java示例来演示如何通过okhttp来调用远程的sse流式接口 背景:我们有一个智能AI的聊天界面,需要调用三方厂商的大模型chat接口,返回答案(因为AI去理解并检索你的问题的时候这个是比较耗时的,这个...
特别是在构建网络请求时,Kotlin DSL与OkHttp结合使用,能够创建出简洁且强大的HTTP客户端。本篇将详细介绍如何在Android项目中使用Kotlin DSL与OkHttp来构建高效的前端HTTP客户端。 首先,我们需要了解Kotlin DSL...
Java的强类型、面向对象的特性使得代码更易于维护和扩展,而Java标准库也提供了大量的网络编程工具和类,与OkHttp一起,可以构建出高效稳定的网络应用。 至于文件名`yschimke-okurl-6c199c5`,这很可能是项目的源...
OKHttp是Java编程语言中的一款高效且功能强大的网络请求库,尤其在移动开发领域,如Android应用程序中,它被广泛使用。标题中的"okhttp-2.0.0.jar+okhttp-apache-2.0.0.jar+okhttp-urlconnection-2.0.0.jar"分别指的...
OkHttp是Java编程语言中的一款高效、现代的HTTP客户端库,由Square公司开发。这个"okhttp-3.9.0.jar"是OkHttp的特定版本,即3.9.0,它提供了一套强大且易用的API,用于处理HTTP网络请求。OkHttp旨在通过减少网络延迟...
在Java后台,通常使用Servlet或Spring Boot等框架接收来自OkHttp客户端的请求。以下是一个简单的Servlet示例: 1. 在web.xml中配置Servlet: ```xml <servlet-name>MyServlet <servlet-class>...
2. **配置Retrofit**:创建Retrofit实例时,指定OkHttp客户端和基础URL。 3. **设置Dispatcher**:Flux的Dispatcher是数据流动的核心,需要正确配置以处理接收到的数据。 4. **创建Store**:Store用于存储数据并监听...
OkHttp 是一个高效的 HTTP 客户端库,广泛应用于 Android 开发中,因其出色的性能、易用性和灵活性而受到开发者们的喜爱。版本号 "okhttp3.12.1" 指的是 OkHttp 库的特定稳定版本,它包含了各种优化和改进,确保在 ...
本文将深入探讨如何使用OkHttp进行Android客户端与服务器端的交互,包括文件和图片的上传下载以及JSON数据的处理。 一、OkHttp简介 OkHttp是由Square公司开发的一款高性能的HTTP客户端库,它通过减少网络交互的延迟...
OkHttp是Java编程语言中的一款高效且易于使用的HTTP客户端库,由Square公司开发。这个库在3.4.1版本中提供了对网络请求的强大支持,优化了网络通信效率,降低了应用的内存消耗,并且提供了丰富的功能特性。Ok.IO是...