发布网友 发布时间:2022-04-21 19:36
共2个回答
懂视网 时间:2022-05-14 01:53
搜集了一下网上的资源和自己看过的一些书,小小总结了一波HTTP,现在也只是很肤浅的了解,期望以后深入理解后能写出更有营养的笔记。HTTP协议的主要特点
+ 支持客户/服务器模式。
+ 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
+ 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
+ 无连接:无连接的含义是每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
+ 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
HTTP状态码
+ 1xx Informational(信息性状态码) 接收的请求正在处理
+ 2xx Success(成功状态码) 请求正常处理完毕
+ 3xx Redirection(重定向状态码) 需要进行附加操作以完成请求
+ 4xx Client Error(客户端错误状态码) 请求包含一个语法错误或不能完成,服务器无法处理请求
+ 5xx Server Error(服务器错误状态码) 服务器执行一个完全有效请求失败
详情如下↓
100——客户必须继续发出请求
101——客户要求服务器根据请求转换HTTP协议版本
200 OK——请求成功
201——提示知道新文件的URL
202——接受和处理、但处理未完成
203——返回信息不确定或不完整
204 No Content——请求收到,但返回信息为空
205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206——Partial Content服务器已经完成了部分用户的GET请求
300——请求的资源可在多处得到
301 Moved Permanently——永久性重定向。表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI
302 Found——临时性重定向。表示请求的资源已被分配了新的URI,希望用户本次能使用新的URI访问
303 See Other——建议客户访问其他URL或访问方式
304 Not Modify——客户端已经执行了GET,但文件未变化,直接使用客户端未过期的缓存
305——请求的资源必须从服务器指定的地址得到
306——前一版本HTTP中使用的代码,现行版本中不再使用
307 Temporary Redirect——申明请求的资源临时性删除
400 Bad Request——错误请求,如语法错误
401 Unauthorized——请求授权失败
402——保留有效ChargeTo头响应
403 Forbidden——请求不允许
404 Not Found——没有发现文件、查询或URl
405——用户在Request-Line字段定义的方法不允许
406——根据用户发送的Accept拖,请求资源不可访问
407——类似401,用户必须首先在代理服务器上得到授权
408——客户端没有在用户指定的饿时间内完成请求
409——对当前资源状态,请求不能完成
410——服务器上不再有此资源且无进一步的参考地址
411——服务器拒绝用户定义的Content-Length属性请求
412——一个或多个请求头字段在当前请求中错误
413——请求的资源大于服务器允许的大小
414——请求的资源URL长于服务器允许的长度
415——请求的资源不支持请求项目格式
416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求
也不包含If-Range请求头字段
417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下
一级服务器不能满足请求
500 Internal Server Error——服务器产生内部错误
501——服务器不支持请求的函数
502 Bad Gateway——服务器暂时不可用,有时是为了防止发生系统过载
503 Server Unavailable——服务器过载或暂停维修
504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长
505——服务器不支持或拒绝支持请求头中指定的HTTP版本
热心网友 时间:2022-05-13 23:01
OkHttp 是一个在开发可汗学院Android APP过程中非常重要的依赖库。它的默认的配置为我们提供了非常重要实用功能,下面一些步骤我们可以让Okhttp提供更多功能使用灵活和内省能力。
1. 启用文件系统上的响应缓存
默认情况下,Okhttp不支持响应缓存,包括HTTP Cache-Control头允许缓存响应。因此,客户端通过一次又一次的请求相同的资源浪费时间和带宽。而不是简单地读取初始响应后缓存的副本。
要在文件系统中启用响应缓存,需要配置com.squareup.okhttp.Cache实例,并把它传递给你的OkHttpClient实例的setCache方法。你必须初始化缓存与存放目录的文件,并以字节为单位的最大值。
响应返回数据可以写入给定目录文件,如果一个响应的缓存超过了给定的大小。我们可以采取 LRU policy 。
我们可以在 stackoverflow 查看 Jesse Wilson 的回复。我们可以通过context.getCacheDir()在子目录中缓存我们的响应:
// Base directory recommended by http://stackoverflow.com/a/32752861/400717.
// Guard against null, which is possible according to
// https://groups.google.com/d/msg/android-developers/-694j87eXVU/YYs4b6kextwJ and
// http://stackoverflow.com/q/4441849/400717.
final @Nullable File baseDir = context.getCacheDir();
if (baseDir != null) {
final File cacheDir = new File(baseDir, "HttpResponseCache");
okHttpClient.setCache(new Cache(cacheDir, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE));
}
// Base directory recommended by http://stackoverflow.com/a/32752861/400717.
// Guard against null, which is possible according to
// https://groups.google.com/d/msg/android-developers/-694j87eXVU/YYs4b6kextwJ and
// http://stackoverflow.com/q/4441849/400717.
final @NullableFilebaseDir = context.getCacheDir();
if (baseDir != null) {
final FilecacheDir = new File(baseDir, "HttpResponseCache");
okHttpClient.setCache(new Cache(cacheDir, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE));
}
在可汗学院的程序中我们指定 HTTP_RESPONSE_DISK_CACHE_MAX_SIZE as 10 * 1024 * 1024 , or 10 MB的大小
2. 集成Stetho
Stetho 是*的一个可爱的库,可以使用Chrome浏览器的Chrome开发人员工具功能来检查你的Andr oid应用程序。
Stetho除了允许你检查你的应用程序的SQLite数据库,还可以查看View的层次结构。允许你检查由OkHttp发起的每个请求和响应:
这种自省机制是确保服务器返回允许资源缓存的HTTP头是非常有用的,以及验证没有请求时,保证缓存的资源存在。
要想使用Stetho,只需添加一个StethoInterceptor实例的网络*列表:
okHttpClient.networkInterceptors().add(new StethoInterceptor());
okHttpClient.networkInterceptors().add(new StethoInterceptor());
然后,运行应用程序,打开浏览器后,输入chrome://inspect。然后你就会看到应用程序的设备和标识符的列表。然后鼠标右键选择inspect 打开开发者工具,然后打开新的tab,开始监控OkHttp请求。
3. 使用Picasso 和 Retrofit
你可能使用过 Picasso 来加载网络图片,或者使用 Retrofit 来简化发出请求和解码响应。这些第三方库将隐式地创建自己的OkHttpClient供内部使用,如果你不明确指定一个。
Picasso version 2.5.2的OkHttpDownloader类:
private static OkHttpClient defaultOkHttpClient() {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setWriteTimeout(Utils.DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
return client;
}
private static OkHttpClientdefaultOkHttpClient() {
OkHttpClientclient = new OkHttpClient();
client.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setWriteTimeout(Utils.DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
return client;
}
Retrofit也有类似的工厂方法来创建自己的OkHttpClient。
图片一般在应用程序中需要加载的比较大的资源。尽管Picasso自己维护它的LRU机制来缓存图片,在内存中严格执行。如果客户端尝试使用Picasso来加载图片。Picasso会找不到其在内存中缓存图像,然后将委托加载该图片到它的内部OkHttpClient实例。并且默认情况下该实例将始终从服务器加载图片资源。
作为defaultOkHttpClient的方法不能与上面提到的文件系统中的响应缓存配置结合起来。
指定你自己的OkHttpClient实例允许返回数据从文件系统缓存响应,图片不会从服务器加载。这是非常重要的在程序第一次启动以后。这个时候Picasso的内存缓存是冷的。所以它会频繁的委托OkHttpClient实例去加载图片。
这就需要构建配置了您Picasso 的OkHttpClient实例,如果你在你的代码中使用
Picasso.with(context).load(...)
Picasso.with(context).load(...)
加载图片,你是用的是Picasso的单例模式。这是通过with方法懒汉模式地实例化并配置自己的OkHttpClient。因此,我们必须使我们自己的Picasso实例在单例之前通过wiht方法调用。
实现这个,可以简单的将OkHttpClient实例封装在OkHttpDownloader中,然后传递给 Picasso.Builder 实例的downloader方法。
final Picasso picasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(okHttpClient))
.build();
// The client should inject this instance whenever it is needed, but replace the singleton
// instance just in case.
Picasso.setSingletonInstance(picasso);
final Picassopicasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(okHttpClient))
.build();
// The client should inject this instance whenever it is needed, but replace the singleton
// instance just in case.
Picasso.setSingletonInstance(picasso);
在Retrofit中要使用OkHttpClient实例,需要改造1.9.x的一个RestAdapter,需要将OkHttpClient封装OkClient的实例中。然后把它传递给RestAdapter.Builder实例的setClient方法。
restAdapterBuilder.setClient(new OkClient(httpClient));
restAdapterBuilder.setClient(new OkClient(httpClient));
在 Retrofit 2.0中只需要简单的将OkHttpClient传递给Retrofit.Builder实例的client方法。
在可汗学院的APP中我们通过 Dagger 依赖注入来确保我们只有一个OkHttpClient的实例。这种方法同样也适用于Picasso和Retrofit我们提供了一个为OkHttpClient实例提供单例模式的注解示例:
@Provides
@Singleton
public OkHttpClient okHttpClient(final Context context, ...) {
final OkHttpClient okHttpClient = new OkHttpClient();
configureClient(okHttpClient, ...);
return okHttpClient;
}
@Provides
@Singleton
public OkHttpClientokHttpClient(final Contextcontext, ...) {
final OkHttpClientokHttpClient = new OkHttpClient();
configureClient(okHttpClient, ...);
return okHttpClient;
}
OkHttpClient将会通过Dagger的注解创建一个实例提供给我们的Picasso和Retrofit。
4.指定一个用户代理*
日志文件和分析为我们提供了更多有用的信息,当客户在每个请求提供详细的User-Agent
header值的时候。默认情况下,Okhttp包含User-Agent值只有在特定的Okhttp版本中。为了指定我们自己的user
agent。首先创建*的替换值, 我们可以看stackoverflow的建议 。
public final class UserAgentInterceptor implements Interceptor {
private static final String USER_AGENT_HEADER_NAME = "User-Agent";
private final String userAgentHeaderValue;
public UserAgentInterceptor(String userAgentHeaderValue) {
this.userAgentHeaderValue = Preconditions.checkNotNull(userAgentHeaderValue);
}
@Override
public Response intercept(Chain chain) throws IOException {
final Request originalRequest = chain.request();
final Request requestWithUserAgent = originalRequest.newBuilder()
.removeHeader(USER_AGENT_HEADER_NAME)
.addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue)
.build();
return chain.proceed(requestWithUserAgent);
}
}
public final class UserAgentInterceptor implements Interceptor {
private static final String USER_AGENT_HEADER_NAME = "User-Agent";
private final String userAgentHeaderValue;
public UserAgentInterceptor(String userAgentHeaderValue) {
this.userAgentHeaderValue = Preconditions.checkNotNull(userAgentHeaderValue);
}
@Override
public Responseintercept(Chainchain) throws IOException {
final RequestoriginalRequest = chain.request();
final RequestrequestWithUserAgent = originalRequest.newBuilder()
.removeHeader(USER_AGENT_HEADER_NAME)
.addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue)
.build();
return chain.proceed(requestWithUserAgent);
}
}
为了创建User-Agent header值人然后传递给UserAgentInterceptor的构造器,使用你得到的任何信息。
我们可以使用:
android 的系统信息可以清晰的传递出这是一台android 设备
Build.MODEL 或者“制造商提供的用户可见最终可见的名称”
Build.BRAND或者“消费者可见的品牌与产品/硬件相关信息”
Build.VERSION.SDK_INT或者“消费者可见的Android提供的SDK版本号”
BuildConfig.APPLICATION_ID
BuildConfig.VERSION_NAME
BuildConfig.VERSION_CODE
最后三个值由的applicationID,VERSIONCODE和VERSIONNAME的值在我们的Gradle build脚本中
了解更多信息可以查看 versioning your applications 和 configuring your applicationId with Gradle
请注意,如果您的应用程序使用的是WebView,您可以配置使用相同的 User-Agent header值,你可以通过下面方法创建UserAgentInterceptor:
WebSettings settings = webView.getSettings();
settings.setUserAgentString(userAgentHeaderValue);
WebSettingssettings = webView.getSettings();
settings.setUserAgentString(userAgentHeaderValue);
5.指定合理的超时
2.5.0版本之前,OkHttp请求默认为永不超时。2.5.0版本开始如果建立连接请求超时,如果从连接读取下一个字节或写入的下一个字节到连接,花费超过10秒,就终止。这样做需要更新到2.5.0版本我们就不需要在我们的代码中修改bug。原因很简单是我因为我们第一次使用的时候使用了错误的路径。
要覆盖这些默认值,可以分别调用setConnectTimeout,setReadTimeout或setWriteTimeout。
需要注意的是Picasso和Retrofit为OkHttpClient实例指定不同的超时值时,默认情况下,Picasso指定:
连接超过15秒.
读取超过20秒
写入超过20秒
而Retrofit指定:
连接超过15秒.
读取超过20秒
没有写入超时
通过配置Picasso和Retrofit自己的OkHttpClient实例你可以确保所有的请求超时是一致的