okHttp使用及优缺点

本文介绍了网络库OkHttp,强调了其高效性和特性,如连接复用、拦截器、GZIP压缩和请求缓存。详细讲述了OkHttp的初始化、GET和POST请求,特别是如何使用MultipartBuilder进行文件上传。同时,讨论了OkHttp的优缺点,并给出了封装建议。

前言

今天在这里要讲的是一个网络库,okHttp相对于其它网络库有很多不同,使用、效率、拦截器都有很多不同,当然也有坏处,比如callback回来

是在线程里面, 不能刷新UI,访问请求跟apache有很多不同,这点注意,还有访问请求的时候,Get和Post有不同就是看一个地方,如果是用其它

网络库,一定会迷惑到底那个才是Get\POST,文章中会细细解答,本文会以介绍、使用、优缺点来三大块阐述。

一、介绍

OKHttp是一款高效的HTTP客户端,支持连接同一地址的链接共享同一个socket,通过连接池来减小响应延迟,

还有透明的GZIP压缩,请求缓存等优势,其核心主要有路由、连接协议、拦截器、代理、安全性认证、连接池以

及网络适配,拦截器主要是添加,移除或者转换请求或者回应的头部信息,总流程图如下:

当然详细了解核心解刨内核东西网址如:

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0326/2643.html等。

二、使用

1.okhttp初始化

 Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
     @Override public Response intercept(Chain chain) throws IOException {
         Response originalResponse = chain.proceed(chain.request());
         return originalResponse.newBuilder()
                 .removeHeader("Pragma")
                 .header("Cache-Control", String.format("max-age=%d", 60))
                 .build();
     }
 };

 mOkHttpClient.setConnectTimeout(15000, TimeUnit.SECONDS);
 mOkHttpClient.setReadTimeout(15000, TimeUnit.SECONDS);
 mOkHttpClient.setWriteTimeout(15000, TimeUnit.SECONDS);
 mOkHttpClient.setRetryOnConnectionFailure(true);
 //-------------------------------设置http缓存,提升用户体验-----------------------------------
 Cache cache;
 File httpCacheDirectory =  StorageUtils.getOwnCacheDirectory(context,HTTP_CACHE_FILENAME);
 cache = new Cache(httpCacheDirectory, 10 * 1024);
 mOkHttpClient.setCache(cache);
 mOkHttpClient.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);
 //-------------------------------设置http缓存,提升用户体验-----------------------------------

// Handler mDelivery = new Handler(Looper.getMainLooper());

 if (false) {
     mOkHttpClient.setHostnameVerifier(new HostnameVerifier() {
         @Override
         public boolean verify(String hostname, SSLSession session) {
             return true;
         }
     });
 }


2.Get申请数据

Request request = new Request.Builder()
        .url("网络地址这里面设置一个传参数如何办")
        .addHeader("Accept", "application/json; q=0.5").build();
上面代码看到url缺么有带post,这就是get,我当时看到这个半天还在想这就是Get,至少带get的字样,缺么有,这就是Get,然后这
里面涉及的一个参数如何传。会有两个问题参数如何传、如果是apache的,如何转到okhttps,后面都会在我的github会封装一个库。
<span style="white-space:pre">	</span>FormEncodingBuilder body = new FormEncodingBuilder();
        for (ConcurrentHashMap.Entry<String, String> entry : params.urlParams.entrySet()) {
            body.addEncoded(entry.getKey(), entry.getValue());
        }
        Request request = new Request.Builder()
                .url(getUrlWithQueryString(true, params.url, params))
                .build();
        try {
            BaseOkHandler handler = new BaseOkHandler(callback, params);
            client.newCall(request).enqueue(handler);
        } catch (Exception e) {
            e.printStackTrace();
        }
上面看到的params就相当于apache中的RequestParams类,里面传入参数就可以,借鉴的并做修改后得到。
 getUrlWithQueryString(boolean shouldEncodeUrl, String url, BaseParams params) {
        if (url == null)
            return null;

        if (shouldEncodeUrl) {
            try {
                String decodedURL = URLDecoder.decode(url, "UTF-8");
                URL _url = new URL(decodedURL);
                URI _uri = new URI(_url.getProtocol(), _url.getUserInfo(), _url.getHost(), _url.getPort(), _url.getPath(),
 _url.getQuery(), _url.getRef());
                url = _uri.toASCIIString();
            } catch (Exception ex) {
                // Should not really happen, added just for sake of validity
            }
        }

        if (params != null) {
            // Construct the query string and trim it, in case it
            // includes any excessive white spaces.
            String paramString = params.getParamString().trim();
            // Only add the query string if it isn't empty and it
            // isn't equal to '?'.
            if (!paramString.equals("") && !paramString.equals("?")) {
                url += url.contains("?") ? "&" : "?";
                url += paramString;
            }
        }

        return url;
    }
而这个函数就是把所有参数格式化拼接成一个字符串。

3.Post申请数据

 Request request = new Request.Builder()
      .url(url)
      .post(body)//post是关键,提交表单数据、这里面有封装好多库。
      .build();
      Response response = client.newCall(request).execute();

4.Post提交文件

 MultipartBuilder builder = new MultipartBuilder().type(MultipartBuilder.FORM);
        if (params.fileParams.size() > 0) {
            RequestBody fileBody = null;
       for (ConcurrentHashMap.Entry<String, BaseParams.FileWrapper> entry1 : params.fileParams.entrySet()) {
                {
                    File file = entry1.getValue().file;
                    String fileName = file.getName();
                    fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
                    //TODO 根据文件名设置contentType
                    builder.addPart(Headers.of("Content-Disposition",
                                "form-data; name=\"" + entry1.getKey() + "\"; filename=\"" + fileName + "\""),
                            fileBody);
                }
            }
        }
        Request request = new Request.Builder()
                .url(params.url)
                .post(builder.build())
                .build();
大家看到上传文件只要使用MultipartBuilder类表单传入就可以。

5.消息回来处理

public class BaseOkHandler implements Callback {

    private HttpCallback callBack;
    BaseParams param;

    public BaseOkHandler(HttpCallback response, BaseParams cacheParams) {
        this.callBack = response;
        param = cacheParams;
    }

    @Override
    public void onFailure(Request request, IOException e) {
    }

    @Override
    public void onResponse(Response response) throws IOException {
        try {
            if (response.isSuccessful()) {
                //成功得到文本信息
                String content = response.body().string();
                //通过Handler来传给UI线程。
                Message msg =new Message();
                msg.obj = content;
                msg.what=0;
                mHandler.sendMessage(msg);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 0:
                    //得到数据并去做解析类。
     BaseEntity entity = JsonPaserFactory.paserObj(msg.obj.toString(), param.paserType);
                    //通知UI界面
    callBack.onSuccess(msg.obj.toString(), entity, param.paserType);
                    break;
                default:
                    break;
            }
        }

    };
}

三、优缺点

1、优点
支持SPDY, 可以合并多个到同一个主机的请,使用连接池技术减少请求的延迟(如果SPDY是可用的话) ,
使用GZIP压缩减少传输的数据量,缓存响应避免重复的网络请求、拦截器等等。
2、缺点
第一缺点是消息回来需要切到主线程,主线程要自己去写,第二传入调用比较复杂。

四、封装okhttp

地址https://github.com/apple317?tab=repositories. 当前1.1版本已经开放完毕。
后续博客跟进:





<think>好的,我需要回答用户关于Java中使用HttpClient和OkHttp进行POST请求的比较,并提供示例。首先,我要明确用户的需求是比较两者的实现方式,所以需要分别展示两者的代码示例,并指出它们的区别和特点。 首先,我需要回忆一下Java中的HttpClient和OkHttp库的基本用法。HttpClient是Java 11引入的标准库,而OkHttp是Square公司开发的第三方库,广泛用于Android和Java应用。用户希望看到POST请求的具体实现,所以需要分别编写两个示例。 接下来,我需要查阅提供的引用内容,看看是否有相关的代码示例。引用2中提到了Java 11的HttpClient的POST请求示例,引用4提到了OkHttp的RequestBody.create方法。不过具体的OkHttp POST示例可能需要我根据知识库中的信息来构造。 对于Java HttpClient的POST示例,引用2中的代码已经有一个例子,可以稍作调整,确保代码正确并符合用户需求。需要导入正确的包,构建请求,设置请求体和头信息,然后发送并处理响应。 对于OkHttp的POST示例,根据引用4中的信息,RequestBody.create可能已被更新,现在可能需要使用其他方法,比如使用RequestBody.create(content, mediaType)或者新的构建方式。需要确认OkHttp的最新用法,确保示例正确。 然后,需要比较两者的优缺点,比如是否支持异步、依赖管理、性能等。根据引用2和4,可以提到HttpClient是Java内置的,无需额外依赖,而OkHttp需要添加库,但功能更强大,支持连接池等优化。 还需要注意代码格式,用户可能希望看到清晰、简洁的代码块,并正确使用语法高亮。同时,按照用户的要求,行内数学表达式要用$...$,但这个问题可能不涉及数学公式,所以可能不需要处理这部分。 最后,生成相关问题,帮助用户进一步探索,比如比较性能、异常处理、异步请求等。 在检查过程中,需要确保代码示例正确,没有语法错误,并且比较点准确。比如,HttpClient的同步请求示例,OkHttp的同步请求示例,两者的依赖、可读性、功能差异等。 现在,整理这些思路,分步骤写出回答,确保结构清晰,代码正确,比较点明确。</think>### Java HttpClient与OkHttp的POST请求实现对比 #### 一、Java HttpClient (Java 11+)示例 ```java import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class HttpClientPostExample { public static void main(String[] args) throws Exception { String url = "https://example.com/api"; String jsonBody = "{\"name\":\"John\", \"age\":30}"; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(jsonBody)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("状态码: " + response.statusCode()); System.out.println("响应体: " + response.body()); } } ``` #### 二、OkHttp 4.x示例 ```java import okhttp3.*; public class OkHttpPostExample { public static void main(String[] args) throws Exception { String url = "https://example.com/api"; String jsonBody = "{\"name\":\"John\", \"age\":30}"; OkHttpClient client = new OkHttpClient(); RequestBody body = RequestBody.create( jsonBody, MediaType.parse("application/json") ); Request request = new Request.Builder() .url(url) .post(body) .addHeader("Content-Type", "application/json") .build(); try (Response response = client.newCall(request).execute()) { System.out.println("状态码: " + response.code()); System.out.println("响应体: " + response.body().string()); } } } ``` ### 关键差异对比 | 特性 | Java HttpClient | OkHttp | |---------------------|-------------------------------------|---------------------------------| | **依赖关系** | JDK 11+内置 | 需添加第三方依赖 | | **API设计** | 流式构建器 | 链式方法调用 | | **连接池** | 默认启用 | 支持可配置的连接池 | | **超时控制** | 通过`Timeout`类设置 | 支持更细粒度的超时配置 | | **异步支持** | 内置CompletableFuture | 通过Callback机制实现 | | **拦截器** | 不支持 | 支持请求/响应拦截器 | | **自动重试** | 默认不启用 | 默认处理可重试请求 | | **WebSocket** | 支持 | 支持 | ### 选择建议 1. **标准库优先**:若项目基于JDK 11+且无需高级功能,优先使用`HttpClient` 2. **复杂场景**:需要拦截器、自定义缓存或更灵活配置时选择`OkHttp` 3. **Android开发**:推荐使用OkHttp,因其为Android平台优化[^4]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值