本文说一下最近有用到的 okHttp3 这个jar包 这个包是用来发送HTTP请求的。
注:文章是一步一步进行的。没有直接写这个请求咋发,那个响应咋处理。
应用场景就是 你项目中需要调其他人的接口。比如说你是Java开发,基于服务化开发。这时要想兼容其他语言。例如 Python 。你需要调Python的接口获取数据。你就可以用这个包来操作。发送Get Post RestFul的HTTP请求来获取响应数据。当然spring也可以用RestTemplate 。也很好用。关于网络的东西我也不是太懂。正在慢慢学习。
先安利一下postman。我有在用的一个发送请求的软件。
HTTP请求报文包括请求URL,请求头信息和请求体信息。
这个就是用来发送RestFul请求用的软件。后端用来测代码能不能跑通用的。
包括各种的请求方式。像我们用的最多的POST请求和GET请求还有PUT请求和DELETE请求。(除了这四个别的其实我也没用过)
params是拼接在URL后面的参数。Headers就是发送请求时的请求头,body是请求体可以有多种方式的请求体。
form-data形式的body: 也就是在form标签中的enctype = multipart/form-data 这个是用来传输各种文件图片啥的、也可以传输键值对。它的headers传输类型信息为Content-Type: multipart/form-data. 还会生成一个boundary 来分割上传的body。
每个部分加上Content-Dispositon。
x-www-form-urlencoded形式的body:这个就是表单传值了。会把表单的值整成键值对的方式分割开来传值。name=value&sex=1
Content-Type : application/x-www-form-urlencoded 。这种传输方式是默认值。
raw:这个是文本传输方式,最常用的json就是这里面的 。前端来个ajax整成json形式发给后端用的就是这种。
Content-Type : application/json
binary : 没用过。
上面这些是常用的。那个connection:keep-alive就是得到响应后不立即关闭
对于POST和get请求的区别。最大的区别就是get请求允许传输的字节比较小因为会拼到URL后面的缘故。我犯过这个错。URL过长是会报异常的。POST允许传的内容就大了。搁body里面。 get方式不安全因为会拼接在URL后面。POST会安全一些。
get是取值的请求。post是存值的请求。可以这么想。
接下来步入本文的正题okHttp3
这个okHttp3是比较火的一款HTTP包了。先简单看一下源码吧。随便看看
下面这个是变量和构造方法。可以看到构造方法入参的是Builder这个静态内部类。实际上就是把builder中设置的属性传给了OKHTTPclient的实例变量、我们还可以看到这些变量都是final修饰的。意味着当我们实例化后,这个类的实例就不能再重新修改赋值了。
下面是builder类。主要用到的类。
下面是获取OkHttplClient中Builder的方法。可以看到返回的是设置一些东西之后的this。
对于包中的OkHttpClient,request,response,headers都存在一个Builder静态内部类与之对应。感兴趣可以点进去仔细看一下。
还有一些其他常用的类。用到的时候会介绍。这个OKHTTP搞完打算补一个RESTTemplate的文章。
一.创建OkHttpClient对象实例。
这个okHttpClient实例我理解的就是相当于客户端浏览器似的。用这个客户端实例来发送请求。
public OkHttpClient() { //第一种创建方式,用这个构造方法,实际调的是default修饰的构造方法。默认的参数
this(new OkHttpClient.Builder());
}
public OkHttpClient.Builder newBuilder() { //第二种创建方式 。这个比较好用。自定义需求的参数
return new OkHttpClient.Builder(this);
}
这个是第二种创建方式。相等于给当前的this实例不停的装饰,直到调用Builder类的build方法。有好多装饰呢,只罗列了一个。这个是比较常用的。
private static final OkHttpClient CLIENT = new OkHttpClient().newBuilder().connectTimeout(60, TimeUnit.SECONDS).build();
这个是Builder中的build方法,相等于在调用这个方法时把当前的builder实例传给OkHttpClient取创建实例,由于OkHttpClient的变量是final修饰的,所以这个方法调用后也就不能改了。除了这个方法,"其他" builder中的方法返回的都是Builder。
对于这个连接池和线程池被所有的client一起享用。
二。先过一下这个request类。第六条会继续说request
看这个源码之前看一下RequestBody和MediaType的源码。因为这俩东西是跟发请求相关的。
requestBody是请求体。MediaType是文章前面说的body的content-type
三:HttpUrl。这个就是我们的URL还有我们的query查询参数封装在这块。就是拼在URL后面的那些东西。
所有jar无非是封装Java基础的东西。这个底层都是网络的东西,我现在还不太懂就先不写了。
这个类的中心思想就是确定HTTP报文的请求地址。(包括拼接的所有参数)
下面这个是拼接query查询参数的方法。
创建HttpURL。在request.url(httpurl);传入就OK了。 只介绍我用过的,没用过的特性就不写了。scheme是协议。
拼接结果: http://127.0.0.1:8080?key=value
四:下面附MediaType干活的方法。
这个里面具体咋实现的感兴趣的debug慢慢看 我就不看了。得知道入参String 就是我们的content-type MediaType.parse("application/json") 这个就是返回一个content-type为json的MediaType。在创建requestBody时候需要用。这个也是最常用的body格式json形式。反正我基本用的都是这个。
五:下面附requestBody的源码。我们调用的是create方法。
六:回到request这个类。简单看一下Builder静态内部类。这个tag我不知道是啥,目前没用上。
http://square.github.io/okhttp/3.x/okhttp/ 这个是文档。没写字段都啥意思。差评。
看上面这个Builder,在创建Builder的时候默认是Get方法。创建一个请求头。但是没有requestBody。这个不急我们可以通过装饰方法来装饰requestBody。实际上这些带Builder的类原理都差不多。
请求要说的就是这么些。接下来说一下调用请求。
七:执行请求request
这行代码就是执行请求的。CLIENT是创建的OKHTTPClient实例。这个是同步执行的。 并发低的时候完全OK。
Response response = CLIENT.newCall(request).execute(); // newCall();返回call实例。
八:response 响应
首先说一下遇到的一个问题 response.body();这个只能调用一次。 下面是源码,在finally中会关掉这个requestBody。
response要是没有用他返回的body的话,资源没有关闭得手动关闭资源,也就是response.close();实际调的是requestBody的close
而使用body().string();用过返回结果后会在finally中执行这个操作。
对于响应其他内容不再赘述了。我们要这个响应无非是获取状态码和响应体、感兴趣可以查看源码、
后续会学习下RestTemplate这款spring的HTTP请求包。
坑
最近发现这个OKHTTP要是发请求 直接输入 URI 10.32.22.44:asd
可能会报OKHttp java.lang.IllegalArgumentException: Unexpected url xxxxx 这个异常。
这个解决方法就在前面加上 http:// 就行了。 改成 http://10.32.22.44:asd 就可以了 。