高效的Http客户端 OkHttp3使用

(本文主要写Java后端Get Post请求)

好处:
高效加载HTTP,让资源加载更快,节省带宽,OKHttp是一种高效的HTTP客户端,节省带宽,
默认以下特性:
支持HTTP/2,允许所有同一主机地址的请求共享同一个插座连接
连接池减少请求延迟
透明的GZIP压缩减少响应数据大小
缓存响应内容,避免一些完全重复的请求

当网络出现问题时,OkHttp能够坚守职责,自动恢复一般的连接问题,
它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,
OkHttp会交替尝试你配置的其他IP ,OkHttp使用现代TLS技术(SNI,ALPN)初始化新的连接,
当握手失败时会回退到TLS 1.0。

注意:OkHttp支持Android 2.3及以上版本Android平台,对于Java,JDK 1.7及以上。

 

在springboot项目中添加依赖

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

1  GET请求
--new OkHttpClient
--构造Request请求对象
--Request对象封住为call
--用GEt执行同步或异步请求

String url="http://www.baidu.com"
OkHttpClient client=new OkClient();
Request request=new Request.Builder()
    .url(url)
    .get() //默认是Get请求  可以不写
    .build();
final Call call=client.newCall(request);


1.1GET异步请求
    通过call.enqueue(Callback)方法提交异步请求    

call.equeue(new Callback){
    @Override
    public void onFailure(Call call,IOException e){
        Log.d(TAG,"onFailuer:"+e);
    }
@Override
public void onResponse(Call call,Response response ) throws IOException{
   Log.d(TAG,"OnResonse:"+response.body().toString())
}


}

发送的异步请求会被加入到Dispatcher(调度)中的runningAsyncCalls双端的队列中通过线程池来执行。

1.2同步GET请求
通过call.excute() 提交同步请求,这种方式会阻塞线程,为了避免ANR异常,Android3.0以后已经不允许在主线程访问网络。
注意这种方式会阻塞调用线程,所以在安卓中应放在子线程中执行,
在OkHttp的同步get请求需要开启一个子线程

new Thread(new Runnable(){
    @Override
    public void run(){
            try{
        Response response=call.execute();
        Log.d(TAG,response.body().toString());
    }catch(IOException  e){
    e.printStackTrace();        
} 
}
}
}).start();

2.POST请求
    创建Post请求方式与Get请求方法类似,只需要增加步骤,
构造出一个请求对象RequestBody,用于携带我们需要提交的数据。(下面均以Post异步请求为例,Post同步请求只需要将call.enqueue()替代成call.execute()即可)
public Builder post(RequestBody body)
Request的Post方法所接收的参数是RequestBody对象, 所以只要是RequestBody类机器子类都可以当参数传入
RequestBody是一个抽象类,常用的RequestBody实现类有这么几种

2.1FormBody

//FormBody 是RequestBody的实现类,用于表单的请求
OkHttpClient client=new OkHttpClient();
//创建表单请求参数
FormBody.Builder  builder= new FormBody.Builder();
builder.add("name","zhangan");
builder.add("age","18")
FormBody formBody=builder.build();
    .url(url)
    .post(formBody)
    .build();
Client.newCall(request).enqueue(new Callback(){
    @Override
    public void onFailuer(Call call,IOException e){
}
@Overriade
public void onResponse(Call call,Response response) throws IOException{
}


})

2.2RequestBody.create(...)
    RequestBody 是一个抽象类,我们不能直接使用它,
但是可以通过调用它的静态create方法来获取一个RequestBody对象,
该方法会创建并返回一个 RequestBody 的匿名内部类实例
查看一下 RequestBody 类,发现它有这样几个 create 方法。

content-Type(Media Type)  即为Internet Media Type 互联网媒体类型,也就是MIME类型,在Http协议消息头中
使用Content-Type来表示具体请求中的媒体类型信息。
用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件。常见的媒体格式类型有:text/html:HTML格式
text/pain:纯文本格式
image/jpeg:jpg图片格式
application/json:JSON数据格式
application/octet-stream:二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded:form表单encType属性的默认格式,表单数据将以key/value的形式发送到服务端
multipart/form-data:表单上传文件的格式
使用 create 方法可以用来用于上传 String 和 File 对象,具体实现如下:

上传JSON字符串:
              OkHttpClient client = new OkHttpClient();
        //指定当前请求的 contentType 为 json 数据
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        String jsonStr = "{\"name\":\"zhangsan\",\"age\":\"20\"}";
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(JSON, jsonStr))
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
            }
        });

上传文件:
            OkHttpClient client = new OkHttpClient();
        File file = new File(filePath);
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(MediaType.parse("application/octet-stream"), file))
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
            }
        });

2.3使用MultipartBody同时上传多种类型数据

/**
 * @auther XuXin
 * @date 2019/2/11 13:25
 */
public class DEMO {

    /**
     * 多文件和键值对同时上传
     * @param file
     * @param url
     */
    private   void get(File file,String url){
        OkHttpClient client=new OkHttpClient();
        MultipartBody multipartBody=new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("name","zhangsan")
                .addFormDataPart("age","20")
                .addFormDataPart("file",file.getName(),
                        RequestBody.create(MediaType.parse("application/octet-stream"),
                                file)).build();
        Request request=new Request.Builder()
                .url(url)
                .post(multipartBody)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });
    }
}


3.Call请求器

OkHttp 客户端负责接收应用程序发出的请求,并且从服务器获取响应返回给应用程序。
理论听起来十分简单,但是在实践中往往会出现很多意想不到的问题。
通过配置 OkHttpClient,可以配置重写请求、重写响应、跟踪请求、重试请求等多种操作,
这样一来你发送的一个简单请求可能就会变成需要发送多个请求以及接收多个响应后才能获得想要的响应。
OkHttp 将这些多次的中间请求和响应任务建模成了一个 Call 对象,但是通常情况下中间请求及响应工作不会很多,
令人欣慰的是,无论发生URL重定向还是因为服务器出现问题而向一个备用IP地址再次发送请求的情况,你的代码都将正常运行。
执行Call有两种方式:

同步:请求和处理响应发生在同一线程。并且此线程会在响应返回之前会一直被堵塞。
异步:请求和处理响应发生在不同线程。将发送请求操作发生在一个线程,
并且通过回调的方式在其他线程进行处理响应。(一般在子线程发送请求,主线程处理响应)。
Calls可以在任何线程被取消。当这个Call尚未执行结束时,执行取消操作将会直接导致此Call失败!
当一个Call被取消时,无论是写入请求主体或者读取响应主体的代码操作,都会抛出一个IOException异常。

 

转载自:https://www.cnblogs.com/liyutian/p/9473747.html


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值