转载 Okhttp3基本使用 基本使用——OkHttp3详细使用教程
一、简介
HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽。
OkHttp是一个高效的HTTP客户端,它有以下默认特性:
- 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
- 连接池减少,请求连接复用以提高效率
- 透明的GZIP压缩减少响应数据的大小
- 缓存响应内容,避免一些完全重复的请求
- 当网络出现问题时,OkHttp 会自动重试一个主机的多个 IP 地址
当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。
注:
- OkHttp 支持 Android 2.3 及以上版本Android平台, 对于 Java, JDK 1.7及以上.。
- socket:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
二、使用例子:
讲解:
Requests-请求:
每一个HTTP请求中都应该包含一个URL,一个GET或POST方法以及Header或其他参数,当然还可以含特定内容类型的数据流。request一旦build()之后,便不可修改。
Responses-响应:
响应则包含一个回复代码(200代表成功,404代表未找到),Header和定制可选的body。
OkHttpClient:
OkHttpClient可以发送一个Http请求,并读取该Http请求的响应,它是一个生产Call的工厂。 此外,受益于一个共享的响应缓存/线程池/复用的连接等因素,绝大多数应用使用一个OkHttpClient实例,便可以满足整个应用的Http请求。
三种创建实例的方法:
- 创建一个默认配置OkHttpClient,可以使用默认的构造函数。
- 通过new OkHttpClient.Builder()方法来一步一步配置一个OkHttpClient实例。
- 如果要求使用现有的实例,可以通过newBuilder()方法来进行构造。
OkHttpClient client = new OkHttpClient(); OkHttpClient clientWith30sTimeout = client.Builder() .readTimeout(30, TimeUnit.SECONDS) .build(); OkHttpClient client = client.newBuilder().build();
1.get请求方式
1.1 get异步提交请求
/** * get异步提交请求 * @param url */ public static void getAsyn(String url) { // 1.创建OkHttpClient对象 OkHttpClient okHttpClient = new OkHttpClient(); // 2.创建Request对象,设置一个url地址,设置请求方式。默认为get请求,可以不写。 final Request request = new Request.Builder() .url(url) .get() .build(); // 3.创建一个call对象,参数就是Request请求对象 Call call = okHttpClient.newCall(request); // 4.请求加入调度,重写回调方法 call.enqueue(new Callback() { // 请求失败执行的方法 @Override public void onFailure(Call call, IOException e) { logger.info("getAsyn-call"+call); logger.info("getAsyn-IOException:"+e); } // 请求成功执行的方法 @Override public void onResponse(Call call, Response response) throws IOException { logger.info("getAsyn-response:"+response); System.out.println(response.body().string()); System.out.println(response.body().byteStream()); logger.info("call"+call); } }); }
1.2 get同步提交请求
/** * get同步提交请求 * @param url */ public static void getSyn(String url) { // 1.创建OkHttpClient对象 OkHttpClient okHttpClient = new OkHttpClient(); // 2.创建Request对象,设置一个url地址,设置请求方式。 final Request request = new Request.Builder().url(url).build(); // 3.创建一个call对象,参数就是Request请求对象 final Call call = okHttpClient.newCall(request); // 4.同步调用会阻塞主线程,这边在子线程进行 new Thread(new Runnable() { @Override public void run() { try { // 同步调用,返回Response,会抛出IO异常 Response response = call.execute(); logger.info("getSyn-response:"+response); System.out.println(response.body().string()); } catch (IOException e) { e.printStackTrace(); } } }).start(); }
1.3 get异步下载文件
/** * get异步下载文件 * @param url */ public static void getFile(String url) { // 1.创建OkHttpClient对象 OkHttpClient okHttpClient = new OkHttpClient(); // 2.创建Request对象,设置一个url地址,设置请求方式。 Request request = new Request.Builder() .url(url) .get() .build(); // 3.创建一个call对象,参数就是Request请求对象,重写回调方法。 okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { logger.info("getFile-call"+call); logger.info("getFile-IOException:"+e); } @Override public void onResponse(Call call, Response response) throws IOException { // 拿到字节流 InputStream is = response.body().byteStream(); int len = 0; // 设置下载图片存储路径和名称 File file = new File("F:/img/","baidu.png"); FileOutputStream fos = new FileOutputStream(file); byte[] buf = new byte[128]; while ((len = is.read(buf)) != -1) { fos.write(buf,0,len); } fos.flush(); fos.close(); is.close(); } }); }
2.post请求方式
2.1 post异步请求String
/** * post异步请求String * @param url */ public static void postString(String url) { // "类型,字节码" MediaType mediaType = MediaType.parse("application/json;charset=utf-8"); // 1.创建OkHttpClient对象 OkHttpClient okHttpClient = new OkHttpClient(); String requestBody = "{name:nana}"; // 3.创建Request对象,设置URL地址,将RequestBody作为post方法的参数传入 Request request = new Request.Builder() .url(url) .post(RequestBody.create(mediaType,requestBody)) .build(); // 4.创建一个call对象,参数就是Request请求对象。请求加入调度,重写回调方法 okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { logger.info("postString-call"+call); logger.info("postString-IOException:"+e); } @Override public void onResponse(Call call, Response response) throws IOException { logger.info("postString-response:"+response); System.out.println(response.body().string()); System.out.println(response.body().byteStream()); logger.info("postString-call"+call); } }); }
2.2 post异步请求流
/** * post异步请求流 * @param url */ public static void postStreaming(String url) { final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown;charset=utf-8"); File file = new File("F:/img/baidu.png"); try { FileInputStream fileInputStream = new FileInputStream(file); RequestBody requestBody = new RequestBody() { @Nullable @Override public MediaType contentType() { return MEDIA_TYPE_MARKDOWN; } @Override public void writeTo(BufferedSink bufferedSink) throws IOException { OutputStream outputStream = bufferedSink.outputStream(); int length = 0; byte[] buffer = new byte[1024]; while ((length = fileInputStream.read(buffer)) != -1) { outputStream.write(buffer,0,length); } } }; Request request = new Request.Builder(). url(url). post(requestBody). build(); OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { logger.info("postFlow-call"+call); logger.info("postFlow-IOException:"+e); } @Override public void onResponse(Call call, Response response) throws IOException { logger.info("postFlow-response:"+response); logger.info(response.protocol()+" "+response.code() + " " + response.message()); Headers headers = response.headers(); for (int i=0;i< headers.size();i++) { System.out.println(headers.name(i)+":"+headers.value(i)); } System.out.println(response.body().string()); logger.info("postFlow-call"+call); } }); } catch (FileNotFoundException e) { e.printStackTrace(); } }
2.3 post异步上传Multipart文件
/** * post异步上传Multipart文件 * @param url */ public static void postMultipart(String url) { OkHttpClient okHttpClient = new OkHttpClient(); File file = new File("F:/img/","baidu.png"); MediaType mediaType = MediaType.parse("image/png"); RequestBody requestBody = new MultipartBody.Builder() // 设置表单类型 .setType(MultipartBody.FORM) // 添加数据 .addFormDataPart("name","nana") .addFormDataPart("file","baidu.png",RequestBody.create(mediaType,file)) .build(); Request request = new Request.Builder() .url(url) .post(requestBody) .build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { logger.info("postFlow-call"+call); logger.info("postFlow-IOException:"+e); } @Override public void onResponse(Call call, Response response) throws IOException { logger.info("postMultiportBody-response:"+response); System.out.println(response.body().string()); logger.info("postMultiportBody-call"+call); } }); }
2.4 post异步请求文件
/** * post异步请求文件 * @param url */ public static void postFile(String url) { MediaType mediaType = MediaType.parse("text/x-markdown;charset=utf-8"); OkHttpClient okHttpClient = new OkHttpClient(); File file = new File("F:/img/baidu.png"); Request request = new Request.Builder() .url(url) .post(RequestBody.create(mediaType,file)) .build(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { logger.info("postFile-call"+call); logger.info("postFile-IOException:"+e); } @Override public void onResponse(Call call, Response response) throws IOException { logger.info("postFile-response:"+response); logger.info(response.protocol()+" "+response.code() + " " + response.message()); Headers headers = response.headers(); for (int i=0;i< headers.size();i++) { System.out.println(headers.name(i)+":"+headers.value(i)); } System.out.println(response.body().string()); System.out.println(response.body().byteStream()); logger.info("postFile-call"+call); } }); }
2.5 post异步请求表单
/** * post异步请求表单 * @param url */ public static void postForm(String url) { // 1.创建OkHttpClient对象 OkHttpClient okHttpClient = new OkHttpClient(); // 2.通过new FormBody()调用build方法,创建一个RequestBody,可以用add添加键值对 RequestBody requestBody = new FormBody.Builder() .add("name","nana") .build(); // 3.创建Request对象,设置URL地址,将RequestBody作为post方法的参数传入 Request request = new Request.Builder() .url(url) .post(requestBody) .build(); // 4.创建一个call对象,参数就是Request请求对象。请求加入调度,重写回调方法 okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { if(e.toString().contains("closed")) { // 主动取消的请情况下 } logger.info("postForm-call"+call); logger.info("postForm-IOException:"+e); } @Override public void onResponse(Call call, Response response) throws IOException { logger.info("postForm-response:"+response); logger.info(response.protocol()+" "+response.code() + " " + response.message()); Headers headers = response.headers(); for (int i=0;i< headers.size();i++) { System.out.println(headers.name(i)+":"+headers.value(i)); } System.out.println(response.body().string()); System.out.println(response.body().byteStream()); logger.info("postForm-call"+call); } }); }
2.6 post异步请求表单
/** * post分块请求 * @param url */ public static void postMultiportBody(String url) { final String IMGUR_CLIENT_ID = "..."; final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); OkHttpClient client = new OkHttpClient(); MultipartBody body = new MultipartBody.Builder("Axad") .setType(MultipartBody.FORM) .addPart( Headers.of("Content-Disposition","form-data;name='name'"), RequestBody.create(null,"nana") ) .addPart( Headers.of("Content-Dispostion","form-data;name='image'"), RequestBody.create(MEDIA_TYPE_PNG,new File("img.png")) ) .build(); Request request = new Request.Builder() .header("Authorization","Client-ID "+IMGUR_CLIENT_ID) .url(url) .build(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { logger.info("postMultiportBody-call"+call); logger.info("postMultiportBody-IOException:"+e); } @Override public void onResponse(Call call, Response response) throws IOException { logger.info("postMultiportBody-response:"+response); System.out.println(response.body().string()); logger.info("postMultiportBody-call"+call); } }); }
2.7 post拦截器
/** * post拦截器 * @param url */ public static void postInterceptor(String url) { OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(new LoggerInterceptor()) .build(); Request request = new Request.Builder() .url(url) .header("User-Agent","OKHttp Example") .build(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { logger.info("postInterceptor-call"+call); logger.info("postInterceptor-IOException:"+e); } @Override public void onResponse(Call call, Response response) throws IOException { logger.info("postInterceptor-response:"+response); ResponseBody body = response.body(); if (body != null) { System.out.println(response.body().string()); body.close(); } logger.info("postInterceptor-call:"+call); } }); }
import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; public class LoggerInterceptor implements Interceptor { private static final Logger logger = LoggerFactory.getLogger(LoggerInterceptor.class); private static final String TAG = "LoggingInterceptor"; @Override public Response intercept(Chain chain) throws IOException { // 拦截请求,获取到该次请求的request Request request = chain.request(); long startTime = System.nanoTime(); logger.info(String.format("Sending request %s on %s%n%s", request.url(),chain.connection(),request.headers())); // 执行本次网络请求操作返回response Response response = chain.proceed(request); long endTime = System.nanoTime(); logger.info(String.format("Received response for %s in %.1fms%n%s", response.request().url(),(endTime - startTime)/1e6d,response.headers())); return response; } }