IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> HttpClient和OkHttp -> 正文阅读

[移动开发]HttpClient和OkHttp

参考:https://blog.csdn.net/chendasheng/article/details/107075468

一、前言

今天看到Spring的RestTemplate底层既可以使用HttpClient,也可以使用OkHttp。不由想到两者之间有什么区别呢,什么情况下选择HttpClient,什么情况下选择OkHttp 。

果然又涉及到我的知识盲区了,所以晚上赶紧补一下课。

HttpClient和OkHttp都是用来远程调用提供http接口的服务

二、HttpClient的使用

参考:https://blog.csdn.net/yangsf_/article/details/124527687

导入依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

操作步骤:

  • 创建HttpClient实例
  • 创建某种请求方法的实例
  • 调用HttpClient实例的execute方法来执行请求方法
  • 读取response
  • 释放连接,无论执行方法是否成功

1、Get请求

public class GetTest {
    public static void main(String[] args) throws IOException {
        // 1. 创建HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 2. 创建GET请求方法实例
        HttpGet httpGet = new HttpGet("http://localhost:8082/getName");
        // 3. 调用HttpClient实例来执行GET请求方法,得到response
        CloseableHttpResponse response = httpClient.execute(httpGet);
        // 4. 读response,判断是否访问成功 2xx表示 成功。
        int status = response.getStatusLine().getStatusCode();
        if (status == 200 ) {
            // 对得到后的实例可以进行处理,例如读取回复体,读取html
            HttpEntity entity = response.getEntity();
            String res = EntityUtils.toString(entity);
            System.out.println("远程调用--->" + res);
        } else {
            throw new ClientProtocolException("Unexpected response status: " + status);
        }

        // 6. 释放连接
        response.close();
        httpClient.close();
    }
}

在这里插入图片描述

2、post请求

步骤基本上一模一样,只不过可以设置让post请求带上参数,携带json形式的body参数

public class PostTest {
    public static void main(String... args) throws IOException {
        // 1. 创建HttpClient实例
        CloseableHttpClient httpclient = HttpClients.createDefault();

        // 2. 创建HttpPost实例
        HttpPost httpPost = new HttpPost("http://localhost:8082/addUser");
        User user = User.builder().id(2L).name("houchen").build();
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        httpPost.setEntity(new StringEntity(JSONObject.toJSONString(user), "UTF-8"));
        // 3. 调用HttpClient实例来执行HttpPost实例
        CloseableHttpResponse response = httpclient.execute(httpPost);
        // 4. 读 response
        int status = response.getStatusLine().getStatusCode();
        if (status == 200) {
            HttpEntity entity = response.getEntity();
            String res = EntityUtils.toString(entity);
            System.out.println("res-->" + res);
        } else {
            throw new ClientProtocolException("Unexpected response status: " + status);
        }
        // 5. 释放连接
        response.close();
        httpclient.close();
    }
}

在这里插入图片描述

3、post表单请求

public class FormSubmitTest {
    public static void main(String[] args) throws IOException {
        // 1. 创建HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        // 2. 设置表单参数
        List<NameValuePair> kv =  new ArrayList<>();
        kv.add(new BasicNameValuePair("id", "1"));
        kv.add(new BasicNameValuePair("name", "zhangsan"));
        // 3. 创建HttpPost实例
        HttpPost httpPost = new HttpPost("http://localhost:8082/addUser");
        // 4. 让Post携带表单参数
        httpPost.setEntity(new UrlEncodedFormEntity(kv, Consts.UTF_8));
        // 5. 获取HttpResponse响应
        CloseableHttpResponse response = httpClient.execute(httpPost);
        // 6. 读response
        int status = response.getStatusLine().getStatusCode();
        if (status == 200) {
            HttpEntity entity = response.getEntity();
            String res = EntityUtils.toString(entity);
            System.out.println("res-->" + res);
        } else {
            throw new ClientProtocolException("Unexpected response status: " + status);
        }
        // 7. 释放资源
        response.close();
        httpClient.close();
    }
}

在这里插入图片描述

三、OkHttp的使用

参考:https://blog.csdn.net/qq_43842093/article/details/121877245

导入依赖

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

操作步骤:

  • 创建OkHttpClient对象
  • 创建Request对象
  • 将Request 对象封装为Call
  • 通过Call 来执行同步或异步请求,调用execute方法同步执行,调用enqueue方法异步执行

1、Get请求

public class OkHttpGetTest {
    public static void main(String[] args) throws IOException {
        //1、创建一个 OkHttpClient
        OkHttpClient client = new OkHttpClient();
        //2、创建Request对象
        Request request = new Request.Builder()
                .url("http://localhost:8082/getName")
                .build();
       //通过Call 来执行同步或异步请求,调用execute方法同步执行,调用enqueue方法异步执行
        Response response = client.newCall(request).execute();
        //通过Response对象的isSuccessful()方法可以判断请求是否成功。
        if (!response.isSuccessful())
            throw new IOException("Unexpected code " + response);
        String s = new String(response.body().bytes());
        System.out.println(s);
    }
}

在这里插入图片描述

  • client执行newCall方法会得到一个Call对象,表示一个新的网络请求
  • Call对象的execute方法是同步方法,会阻塞当前线程,其返回Response对象
  • 通过Response对象的isSuccessful()方法可以判断请求是否成功

2、异步Get请求

@Slf4j
public class OkHttpAsyncGetTest {
    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("http://localhost:8082/getName")
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

                String s = new String(response.body().bytes());
                log.info("res--->:{}", s);
                log.info("异步请求执行完毕!!!");
            }
        });
        log.info("主线程执行完毕!!!");
    }
}

在这里插入图片描述

  • 要想异步执行网络请求,需要执行Call对象的enqueue方法,enqueue方法不会阻塞当前线程,会新开一个工作线程,让实际的网络请求在工作线程中执行。一般情况下这个工作线程的名字以“Okhttp”开头,并包含连接的host信息,比如上面例子中的工作线程的name是"http://localhost:8082/getName"
  • 当异步请求成功后,会回调Callback对象的onResponse方法,在该方法中可以获取Response对象。当异步请求失败或者调用了Call对象的cancel方法时,会回调Callback对象的onFailure方法。onResponse和onFailure这两个方法都是在工作线程中执行的

补充:请求头和响应头

响应头:
通过Headers.get(headerName)方法也可以获取某个响应头的值,比如通过headers.get(“Content-Type”)获得服务器返回给客户端的数据类型。
但是服务器返回给客户端的响应头中有可能有多个重复名称的响应头,比如在某个请求中,服务器要向客户端设置多个Cookie,那么会写入多个Set-Cookie响应头,且这些Set-Cookie响应头的值是不同的,访问百度首页,可以看到有7个Set-Cookie的响应头,如下图所示:
在这里插入图片描述
为了解决同时获取多个name相同的响应头的值,Headers中提供了一个public List values(String name)方法,该方法会返回一个List对象,所以此处通过Headers对象的values(‘Set-Cookie’)可以获取全部的Cookie信息,如果调用Headers对象的get(‘Set-Cookie’)方法,那么只会获取最后一条Cookie信息。

请求头:
同样的,也可能同时存在多个名称一样的请求头,调用header(name, value)方法就可以设置请求头的name和value,
调用该方法会确保整个请求头中不会存在多个名称一样的name。如果想添加多个name相同的请求头,应该调用addHeader(name, value)方法,这样可以添加重复name的请求头,其value可以不同

Request request = new Request.Builder()
        .url("https://api.github.com/repos/square/okhttp/issues")
        .header("User-Agent", "OkHttp Headers.java")
        .addHeader("Accept", "application/json; q=0.5")
        .addHeader("Accept", "application/vnd.github.v3+json")
        .build();

3、post发送String请求

@Slf4j
public class OkHttpPostTest {
    public static void main(String[] args) throws IOException {
        //1、创建一个 OkHttpClient
        OkHttpClient client = new OkHttpClient();
        //2、创建Request对象
        User user = User.builder().id(2L).name("houchen").build();
        String str = JSONObject.toJSONString(user);
        Request request = new Request.Builder()
                .url("http://localhost:8082/addUser")
                .post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), str))
                .build();
        //通过Call 来执行同步或异步请求,调用execute方法同步执行,调用enqueue方法异步执行
        Response response = client.newCall(request).execute();
        //通过Response对象的isSuccessful()方法可以判断请求是否成功。
        if (!response.isSuccessful())
            throw new IOException("Unexpected code " + response);
        /*String s = new String(response.body().bytes());
        System.out.println(s);*/
        log.info(response.body().string());
    }
}

4、设置超时

次HTTP请求实际上可以分为三步:

  • 客户端与服务器建立连接
  • 客户端发送请求数据到服务器,即数据上传
  • 服务器将响应数据发送给客户端,即数据下载

由于网络、服务器等各种原因,这三步中的每一步都有可能耗费很长时间,导致整个HTTP请求花费很长时间或不能完成。
为此,可以通过OkHttpClient.Builder的connectTimeout()方法设置客户端和服务器建立连接的超时时间,
通过writeTimeout()方法设置客户端上传数据到服务器的超时时间,
通过readTimeout()方法设置客户端从服务器下载响应数据的超时时间。

在2.5.0版本之前,Okhttp默认不设置任何的超时时间,从2.5.0版本开始,Okhttp将连接超时、写入超时(上传数据)、读取超时(下载数据)的超时时间都默认设置为10秒。如果HTTP请求需要更长时间,那么需要我们手动设置超时时间。

client = new OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(10, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .build();

5、ResponseBody

四、区别

  • OkHttp创建客户端的方式简单一点
  • OkHttp使用.post/.delete/.put/.get方法表示请求类型;HttpClient创建HttpGet、HttpPost等这些方法来创建请求类型
  • 如果HttpClient需要发送异步请求,需要额外的引入异步请求依赖
  • 单例模式下,HttpClient的响应速度要更快一些;非单例模式下,OkHttp的性能更好
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章           查看所有文章
加:2022-09-24 21:08:25  更:2022-09-24 21:12:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:20:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码