转载请注明出处:http://blog.csdn.net/smartbetter/article/details/77893903

本篇文章带大家设计一套满意业务需求、代码健壮高效(高内聚低耦合)并且可拓展的网络框架。以最新的okhttp3为基础设计出高效可靠的网络缓存、多线程文件下载等架构模块。从此不局限于使用别人的框架,而步入了设计框架,让自己可以走的更远,我觉得这才是一名合格开发者所应该具备的能力。在开发中,选择一个开源框架的标准有很多,例如学习成本、文档是否齐全、github星数量、现在是否有人维护、流行程度、代码设计是否有借鉴性、代码体积等。

首先看一下当前主流网络框架对比:

网络框架 说明 开源地址
okhttp 适用于Android和Java应用程序的HTTP+HTTP/2客户端 https://github.com/square/okhttp
retrofit 在okhttp之上做了相应封装;解耦性,注解处理,简化代码;支持上传和下载文件;支持自动更换解析方式;支持多种http请求库 https://github.com/square/retrofit

Http网络框架设计图:

现在很多开源框架都是使用okhttp做底层协议的网络请求。所以我们适用时代潮流,使用okhttp做网络请求,而不是用传统的HttpURLConnection。

1.http协议

http协议,超文本传输协议,目前使用最普遍的还是http1.1版本,不过我们也来了解下http2.0协议:

http1.1的特点:

1)支持客户/服务器模式
2)简单快速,GET、POST(http的几种请求方式:Get、POST、HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS。)
3)灵活,允许传输任意类型的数据对象。
4)无连接,限制每次连接只处理一个请求。
5)无状态,协议对于事务处理没有记忆能力。

http2.0对比http1.1增加的特点:

1)多路复用允许同时通过单一的HTTP/2连接发起多重的请求-响应消息,单连接多资源的方式减少服务端的链接压力,内存占用更少,连接吞吐量更
大,由于TCP连接的减少而使网络拥塞状况得以改善,同时TCP慢启动时间的减少,使拥塞和丢包恢复速度更快;
2)头部压缩,每次都要传输UserAgent、Cookie这类不会变动的内容,使用HPACK算法进行压缩;
3)对请求划分优先级;
4)服务器推送流(即Server Push技术)。

http请求返回的一些响应码:

100-101:信息提示; 200-206:成功; 300-305:重定向; 400-415:客户端错误; 500-505:服务器错误。

2.网络框架的基石 okhttp3

需要添加 Maven 依赖:

<!-- okhttp3 -->
<dependency><groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.9.0</version> </dependency>

关于okhttp的使用方法官方文档中已经给出了说明:http://square.github.io/okhttp/,下面我们将对okhttp做出补充说明。

1.okhttp的同步请求和异步请求

同步请求(使用 JUnit 编写测试方法):

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
try {Response response = client.newCall(request).execute();if (response.isSuccessful()) {System.out.println(response.body().string());}
} catch (IOException e) { e.printStackTrace(); }

异步请求:

System.out.println(Thread.currentThread().getId());
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { System.out.println(Thread.currentThread().getId()); } } });

2.okhttp请求头和响应头的实际应用

请求头可参考:http://tools.jb51.net/table/http_header

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.baidu.com").addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) " + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36") .addHeader("Range", "bytes=2-") .addHeader("Accept-Encoding", "identity") .build(); try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { Headers headers = response.headers(); for (int i = 0; i < headers.size(); i++) { System.out.println(headers.name(i) + " : " + headers.value(i)); } } } catch (IOException e) { e.printStackTrace(); }

3.okhttp get请求和post请求

get用于信息获取,而且应该是安全的和幂等的。

请求 特点
get get用于信息获取,而且应该是安全的和幂等的,所谓安全的意味着该操作用于获取信息而非修改信息,不会影响资源的状态。幂等意味着对同一URL的多个请求应该返回同样的结果。
post post用于修改服务器上的资源,需要注意的是post必须要到Form(表单)。

get请求:

OkHttpClient client = new OkHttpClient();
HttpUrl httpUrl = HttpUrl.parse("http://localhost:8080/web/HelloServlet").newBuilder().addQueryParameter("username", "user").addQueryParameter("password", "user123") .build(); Request request = new Request.Builder().url(httpUrl.toString()).build(); try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { System.out.println(response.body().string()); } } catch (IOException e) { e.printStackTrace(); }

post请求:

默认地,表单数据会编码为”application/x-www-form-urlencoded”。就是说,在发送到服务器之前,所有字符都会进行编码,空格转换为”+”,特殊符号转换为ASCII HEX值。

除此之外,还有一个multipart/form-data,它不对字符编码,在使用包含文件上传的控件的表单时,必须使用该值,例如拍照上传等。okhttp已经对multipart/form-data进行了相应的封装,简化了很多操作。

OkHttpClient client = new OkHttpClient();
FormBody body = new FormBody.Builder().add("username", "user") //如果包含中文需要调用addEncoded方法进行转码,而不是add方法 .add("age", "18") .build(); Request request = new Request.Builder().url("http://localhost:8080/web/HelloServlet").post(body).build(); try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { System.out.println(response.body().string()); } } catch (IOException e) { e.printStackTrace(); }

3.okhttp上传文件

1.mutipart协议上传文件

自己实现上传文件的功能相对又复杂。第一,你需要了解文件上传之后http请求过程当中的具体协议的含义是什么,因为你需要自己去封装中间的一些参数信息;第二,你需要自己去搭建一个web服务。

后端接口可以参照 http://blog.csdn.net/smartbetter/article/details/52056377 中使用FileUpload实现文件上传部分。

2.okhttp使用mutipart协议上传文件

RequestBody imageBody = RequestBody.create(MediaType.parse("image/jpeg"), new File("/Users/macos/Desktop/temp.jpg"));
MultipartBody body = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("name", "zhangsan") .addFormDataPart("filename", "temp.jpg", imageBody) .build(); OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder(). url("http://192.168.1.20:8080/example/upload/api/file").post(body).build(); try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { System.out.println(response.body().string()); } } catch (IOException e) { e.printStackTrace(); }

4.okhttp数据缓存

1.http协议当中缓存的原理和关键字段

缓存关键字段:

Expires:指示响应内容过期的时间,格林威治时间GMT
Catche-Control:| no-cache:无缓存指令| max-age:如果缓存只是用来和服务器做验| only-if-cached:有时你会想显示可以立即| max-stale:设置最长过期时间来允许过期的response响应(有时候过期的response比没有response更好)。Last-Modified:判断客户端数据和服务端数据有没有变化。如果相同表示没有人修改,如果修改则Last-Modified事件发生变化。
ETag:对服务器返回的整个response做了相应的编码处理,得到了一个加密的值。
Date:
If-Modified-Since:请求头中标识的,客户端存取的该资源最后一次修改的时间,同Last-Modified。
If-None-Match:请求头中标识的。

2.okhttp实现数据缓存

okhttp缓存相关类:CacheInterceptor、CacheStrategy、Cache、DiskLruCache。

int maxCacheSize = 10 * 1024 * 1024;
Cache cache = new Cache(new File("/Users/macos/Desktop/source"), maxCacheSize); OkHttpClient client = new OkHttpClient.Builder().cache(cache).build(); Request request = new Request.Builder().url("http://www.163.com/") .cacheControl(new CacheControl.Builder().maxStale(365, TimeUnit.DAYS).build()) .build(); Response response = client.newCall(request).execute(); String body1 = response.body().string(); System.out.println("network response " + response.networkResponse()); System.out.println("cache response " + response.cacheResponse()); System.out.println("**************************"); Response response1 = client.newCall(request).execute(); String body2 = response1.body().string(); System.out.println("network response " + response1.networkResponse()); System.out.println("cache response " + response1.cacheResponse());

我们运行这个测试类,显示如下,可以看到,先请求了network,后请求了cache:

转载于:https://www.cnblogs.com/DaTouDaddy/p/7498785.html

Java EE 架构设计——基于okhttp3 的网络框架设计相关推荐

  1. AJAX框架构成设计,基于Ajax的Web框架设计与实现

    摘要: 随着Web技术的发展和人们对Web使用的要求越来越高,传统的交互方式一方面使用户觉得难以使用,体验感太差,另一方面也不利于开发人员进行开发和维护.所以当Web2.0概念被提出,就立即得到了广泛 ...

  2. java ee架构_与Java EE和Spring的集成架构

    java ee架构 本周在纽约举行的O'Reilly软件体系结构大会将举行 . 我很高兴与Josh Long一起提供有关如何集成Java EE和Spring的教程. 一段时间以来,我们一直在开玩笑. ...

  3. JAVA EE架构师需要具备的知识

    JAVA EE架构师需要具备的知识 1.构架师胚胎(程序员):学习的知识是语言基础.设计基础.通信基础等,应该在大学完成,内容包括 java.c.c++.uml.RUP.XML.socket 通信(通 ...

  4. Java EE架构师认证

    SCEA  Java EE架构师认证考试. 本考试由三部分组成: 1.      多选题测试. 2.      任务指派. 3.      对指派的任务进行陈述和测试.即简答部分. 第一章  什么是体 ...

  5. python网络爬虫课程设计题目_山东建筑大学计算机网络课程设计《基于Python的网络爬虫设计》...

    山东建筑大学计算机网络课程设计<基于Python的网络爬虫设计> 山东建筑大学 课 程 设 计 成 果 报 告 题 目: 基于Python的网络爬虫设计 课 程: 计算机网络A 院 (部) ...

  6. 基于SEDA的异步框架设计与实现

    基于SEDA的异步框架设计与实现 一.SEDA国内外研究现状 1.SEDA架构的起源和特点    当前最流行的互联网服务器模型基本都是基于多线程/进程并发服务模型.然而当线程数目增加到一定值后,系统性 ...

  7. 【 C++ 技术】 C++ 高性能服务器网络框架设计细节

    作者:范蠡  原文:C++ 高性能服务器网络框架设计细节 前言 这篇文章我们将介绍服务器的开发,并从多个方面探究如何开发一款高性能高并发的服务器程序.需要注意的是一般大型服务器,其复杂程度在于其业务, ...

  8. python数据接口设计_基于python的接口测试框架设计(一)连接数据库

    基于python的接口测试框架设计(一)连接数据库 首先是连接数据库的操作,最好是单独写在一个模块里, 然后便于方便的调用,基于把connection连接放在__init__()方法里 然后分别定义D ...

  9. 云计算课程设计基于hadoop的词频统计设计

    云计算课程设计基于hadoop的词频统计设计实验报告 http://链接:https://pan.baidu.com/s/1ujUAg4q1sZZwmyeeKrNirg 提取码:maq7

最新文章

  1. 开启Windows 2003 最大内存支持
  2. Nmap扫描教程之网络基础服务DHCP服务类
  3. 苹果备忘录怎么调字体大小_苹果手机备忘录误删了怎么恢复?分享几个新技能...
  4. 一个C++程序执行main函数前和执行完main函数后会发生什么。
  5. Linux操作寄存器前为什么要ioremap
  6. CSS3概述、选择器、兼容性、样式
  7. 关键字:auto、static、register、const、volatile 、extern 总结
  8. qmc0文件怎么转换mp3_音频转换器哪个好 怎么剪切MP3音频制作手机铃声
  9. Mac 上删除用户或群组教程
  10. 再续2014年网页设计趋势
  11. LINUX虚拟机与WINDOWS主机,直接复制交换文件会有问题
  12. linux 防蓝光软件下载,教你如何从Git上checkout指定的文件夹至本地的代码
  13. vue2.0 axios封装
  14. 一杯茶的时间,上手第三方登录类库 JustAuth
  15. C++ 控制台编译时显示‘ ld returned 1 exit status’
  16. Python爬虫实战——Quora网站文字自动化爬取和正则匹配筛选信息
  17. 租酥雨的NOIP2018赛前日记
  18. 地图还可以这么画_3D版
  19. 一个计算机专业学生几年的Java编程经验汇总
  20. 如何免费开通蚂蚁金服开放平台系统服务商ISV查看PID

热门文章

  1. mysql的number类型对应的db2_【转】oracle数据库NUMBER数据类型
  2. centos 程序 mysql_Centos 源码安装 MySQL
  3. c语言中各个符号的意义及作用是什么,C语言特殊符号意义
  4. vue 深度拷贝数组_前端深拷贝和浅拷贝
  5. java中每个类都有子类,Java中所有的类都是从( )类或其子类派生而来的。
  6. anchor锚点 antvue_浅谈vue 锚点指令v-anchor的使用
  7. C语言学习笔记---打印函数printf()和sprintf()函数
  8. sqoop从hdfs上导出数据到MySQL报错:ClassNotFoundException:allclo
  9. Dcmtk在PACS开发中的应用(基础篇) 第一章 与影像设备互连 作者 冷家锋
  10. QtDesigner如何添加工具栏toolBar