依赖
compile 'com.squareup.okhttp3:okhttp:3.10.0'
类
OkHttpClient
核心类, 内部封装请求响应业务逻辑,由于体积庞大所以只生成一个对象。
RequestBody
post请求所用到的类,用于打包上传的数据,为了简化操作又分为两个子类。
FormBody
RequestBody的子类之一,只能用于打包键值对,默认编码方式为URL的utf-8。
MultipartBody
RequestBody另一个子类,同时打包多个类型数据。
MediaType
解析上传,接收文件类型,最后将信息封装在请求头中。
Headers
封装头文件所有信息,本质是一个String数组。
Response
无论是get或者Post请求最后都会从服务器得到一个响应,而Respones就是包装了这个响应的内容。
创建一个OkHttpClient
使用默认配置参数
OkHttpClient client=new OkHttpClient();
自定义参数
OkHttpClient client=new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS) //设置连接超时
.readTimeout(10, TimeUnit.SECONDS) //设置读超时
.writeTimeout(10,TimeUnit.SECONDS) //设置写超时
.retryOnConnectionFailure(true) //是否自动重连
.build(); //构建OkHttpClient对象
参数10指的是10秒,为默认值。
Headers详解
在HttpURLConnection中,头文件信息都是通过connection.addRequestProperty()方法添加的,整体代码耦合度较高,而okhttp完美解决这个问题,将头文件封装成一个对象最后统一处理,而这个对象就是Headers,headers的创建有两种方式;
方式一:建造者模式
Headers headers = new Headers.Builder().add("Height","5").add("Width","5").build();
这种方式方便在于直接通过add()方法以键值对形式保存头文件信息。
方式二:静态方法创建
Map<String, String> maps = new HashMap<>();
Headers headers = Headers.of(maps);
当我们拥有一个map集合时会通过这个方法创建。
两种方法的本质是相同的,看下Headers源码,
public final class Headers {
private final String[] namesAndValues;
Headers(Builder builder) {
this.namesAndValues = builder.namesAndValues.toArray(new String[builder.namesAndValues.size()]);
}
private Headers(String[] namesAndValues) {
this.namesAndValues = namesAndValues;
}
public static Headers of(Map<String, String> headers) {
String[] namesAndValues = new String[headers.size() * 2];
....
return new Headers(namesAndValues)
}
public Headers build() {
return new Headers(this);
}
}
最终都会将键值对转换成一个String数组
产生一个Request随即产生一个Headers对象,并且最终的Headers自带默认的几个头文件信息
笔者发起一个没有自定义Headers参数的get请求,这是servlet部分代码
Enumeration<String> enumeration = request.getHeaderNames();
while(enumeration.hasMoreElements()){
String key=enumeration.nextElement();
System.out.print(key+":");
Enumeration<String> values=request.getHeaders(key);
while(values.hasMoreElements()){
System.out.print(values.nextElement()+";");
}
System.out.println();
}
打印结果
host:***.***.***.***:8080;
connection:Keep-Alive;
accept-encoding:gzip;
user-agent:okhttp/3.10.0;
确实是这样,这些是信息是在 OkHttpClient里生成的,看下源码:
static {
Internal.instance = new Internal() {
@Override public void addLenient(Headers.Builder builder, String line) {
builder.addLenient(line);
}
@Override public void addLenient(Headers.Builder builder, String name, String value) {
builder.addLenient(name, value);
}
}
OkHttpClient静态域提供这些方法,我们可以看到有个参数为Headers.Builder,所以猜想在最后数据包装时将产生新的一个Headers
而post请求由于需要提交上传数据类型,所以构建RequestBody时需要我们为其提供一个。
**注意:**okhttp的Headers的键值不能含有中文字符,否则报错。
Request##
request内部封装了请求头,请求行,实体内容
public final class Request {
final HttpUrl url;
final String method;
final Headers headers;
final @Nullable RequestBody body;
final Object tag;
private volatile CacheControl cacheControl; // Lazily initialized.
Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
}
}
可以看到Request不能直接从外部创建
Request的创建
Request request = new Request.Builder().url("http://192.168.23.1:8080/Get/aa?帅=5&Height=5").post(request).build();
这是一个post请求,它的创建方式与Headers大径相同都是使用建造者模式先构建一个Build对象用于接收各种参数,最后通过build()方法创建一个含有这些参数的Request对象。
发起一个get请求
因为是get请求所以不需要RequestBody。
同步线程阻塞
OkHttpClient okHttpClient=new OkHtt