okhttp3简单使用
文章目录
- 一、简介
- 1、特性
- 二、导入依赖
- 三、创建 get 请求
- 四、创建 post 请求
- 五、创建异步请求(MultipartBody 表单)
- 六、FormBody 表单参数
- 七、OkhttpConfig 配置类
- 八、OkhttpUtil 工具类
- 九、小结
一、简介
Square 公司开源的 OkHttp
okhttp 官网 https://square.github.io/okhttp/
- 网络编程(含 UrlConnection 发送 HTTP 请求下载文件):https://blog.csdn.net/qq_41538097/article/details/118722718
- Apache HttpComponents 简单使用:https://blog.csdn.net/qq_41538097/article/details/123719298
- RestTemplate简单使用:https://blog.csdn.net/qq_41538097/article/details/123560238
- okhttp3简单使用:https://blog.csdn.net/qq_41538097/article/details/123677614
- HttpURLConnection 简单使用:https://blog.csdn.net/qq_41538097/article/details/123697432
1、特性
1)支持HTTP2,对一台机器的所有请求共享同一个socket连接(同域名下所有通信都在单个连接上完成,消除了因多个连接而带来的延时和内存消耗)。
2)内置连接池,支持连接复用,减少请求延迟
3)透明的GZIP压缩减少响应数据的大小
4)通过缓存避免重复请求
5)失败时自动重连,自动重定向
当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。
使用:OkHttp 是一个适用于 Android、Kotlin 和 Java 应用的 HTTP 和 HTTP/2 客户端,它的请求/响应 API 使用构造器模式 builders 来设计,它支持阻塞式的同步请求和带回调的异步请求。
如果你使用 OkHttpClient,你不用重写你的代码,okhttp-urlconnection 模块实现了 java.net.HttpURLConnection 中的API,okhttp-apache 模块实现了 HttpClient 中的API
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.3</version>
</dependency>
持续更新,和上面的同版本更新
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp-urlconnection</artifactId><version>4.9.3</version>
</dependency>
2016 停止更新
<dependency><groupId>com.squareup.okhttp</groupId><artifactId>okhttp-apache</artifactId><version>2.7.5</version>
</dependency>
二、导入依赖
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.3</version></dependency>
三、创建 get 请求
因为是测试,OkHttpClient 是新建的对象,所以不需要配置类,如果需要 bean 工厂可以添加配置类步骤七
,工具类步骤八
@Testpublic void getUrlParams() throws IOException {OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间.build();String url = "http://127.0.0.1:8080/rest/get/url_path_params?name=admin&id=98";Request.Builder builder = new Request.Builder();Request request = builder.url(url).build();Response response = okHttpClient.newCall(request).execute();ResponseBody body = response.body();System.out.println(body.string());}
四、创建 post 请求
post 请求传递 json 数据 Content-Type:application/json; charset=utf-8
@PostMapping("/post/params_json_list")public JSONObject postParamsJsonList(@RequestBody List<Map<String, Object>> list) {JSONObject jsonObject = JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200,\"type\":\"okhttp3\"}");jsonObject.put("body", list);return jsonObject;}
RequestBody 封装 body 参数
@Testpublic void postParamsJson() throws IOException {OkHttpClient build = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build();String json = "{\"name\": \"admin\",\"id\": 10}";String url = "http://127.0.0.1:8080/okhttp3/post/params_json";RequestBody requestBody = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));Request request = new Request.Builder().post(requestBody).url(url).build();Response execute = build.newCall(request).execute();ResponseBody responseBody = execute.body();assert responseBody != null;log.info(responseBody.string());}
五、创建异步请求(MultipartBody 表单)
form 表单上传表单(含文件)Content-Type:multipart/form-data;
@PostMapping("/post/params_from_async")public JSONObject postParamsFromAsync(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws InterruptedException, IOException, ServletException {TimeUnit.SECONDS.sleep(30);JSONObject jsonObject;TreeMap<String, Object> treeMap = new TreeMap<>();Collection<Part> parts = request.getParts();parts.forEach((part) -> {if (part.getContentType() == null) {treeMap.put(part.getName(), request.getParameter(part.getName()));}});String s = UUID.randomUUID().toString().replace("-", "").substring(0, 5) + Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().indexOf("."));try {file.transferTo(new File("I:\\spring\\spring-boot-aop-test\\file\\" + s));jsonObject = JSON.parseObject("{\"message\":\"文件下载成功\",\"code\":200,\"type\":\"okhttp3\"}");jsonObject.put("body", treeMap);} catch (IOException e) {e.printStackTrace();jsonObject = JSON.parseObject("{\"message\":\"文件下载失败\",\"code\":201,\"type\":\"okhttp3\"}");}return jsonObject;}
测试方法
@Testpublic void postParamsFromAsync() throws IOException {String url = "http://127.0.0.1:8080/okhttp3/post/params_from_async";File file = new File("C:\\Users\\Administrator\\Pictures\\图标\\influxdb-studio.png");RequestBody multipartBody = MultipartBody.create(file, MediaType.parse("image/png"));MultipartBody body = new MultipartBody.Builder().addFormDataPart("file", "influxdb.png", multipartBody).addFormDataPart("age", "18").build();Request request = new Request.Builder().post(body).url(url).addHeader("Connection", "keep-alive").build();okHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {log.error("okhttp", "onFailure: " + e.getMessage());}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {log.info("okhttp", "onResponse: " + response.body().string());}});}
六、FormBody 表单参数
form 表单上传表单 Content-Type:application/x-www-form-urlencoded
@PostMapping("/post/params_from")public JSONObject postParamsFrom(HttpServletRequest request) throws InterruptedException, IOException, ServletException {JSONObject jsonObject;Map<String, Object> treeMap = new TreeMap<>();Map<String, String[]> parameterMap = request.getParameterMap();parameterMap.forEach((key, value) -> {if (value.length == 1) {treeMap.put(key, value[0]);} else {treeMap.put(key, value);}});jsonObject = JSON.parseObject("{\"message\":\"表单读取成功\",\"code\":200,\"type\":\"okhttp3\"}");if (treeMap.keySet().size() > 0) {jsonObject.put("body", treeMap);}return jsonObject;}
测试方法
@AutowiredOkHttpClient okHttpClient;@Testpublic void postParamsFrom() throws IOException {String url = "http://127.0.0.1:8080/okhttp3/post/params_from";LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();linkedHashMap.put("password", "123456");linkedHashMap.put("address", "西安");FormBody.Builder builder = new FormBody.Builder();builder.add("name", "admin");linkedHashMap.forEach((key, value) -> {builder.add(key, value);});RequestBody formBody = builder.build();Request request = new Request.Builder().post(formBody).url(url).addHeader("Connection", "keep-alive").build();Response response = okHttpClient.newCall(request).execute();log.info(response.body().string());}
七、OkhttpConfig 配置类
详细配置参考 https://www.freesion.com/article/3815946206/
@Configuration
@Slf4j
public class OkHttpConfig {@Beanpublic OkHttpClient okHttpClient() throws NoSuchAlgorithmException, KeyStoreException {// 详细配置可参考 https://www.freesion.com/article/3815946206/return new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS) //设置连接超时.readTimeout(60, TimeUnit.SECONDS) //设置读超时.writeTimeout(60, TimeUnit.SECONDS) //设置写超时.retryOnConnectionFailure(true) //是否自动重连// 设置https配置,此处忽略了所有证书.sslSocketFactory(sslSocketFactory(), new EasyX509TrustManager(null))// 验证服务器的证书域名。在https握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实现程序来确定是否应该允许此连接.hostnameVerifier(new HostnameVerifier() {@Overridepublic boolean verify(String hostname, SSLSession session) {return true;}})// 拦截器日志记录.addInterceptor((Interceptor.Chain chain) -> {Request request = chain.request();log.info("intercept 接口地址:" + request.url()+ "\r\n接口参数):" + request.body().toString());return chain.proceed(chain.request());})// 添加证书,一般不要设置.certificatePinner(new CertificatePinner.Builder().add("test1.com", "sha1/sdfsdsdsdsdsdsdsdsdsdsdds=").add("test2.com", "sha1/sdsdsdsdsdsdsdsdsdssdssds=").build())//.connectionSpecs(...) // 设置连接的规格、TLS版本和密码套件等,最好不要去设置//.socketFactory(new SocketFactory() {...}) // 使用定制的用于http请求的套接字
/* .authenticator(new Authenticator() { // 添加授权证书@Overridepublic Request authenticate(Route route, Response response) throws IOException {}}) */.cache(new Cache(new File("cache.tmp"), 10 * 1024 * 1024)) // 10M缓存// 定义连接池,最多有五个空闲连接,每个空闲连接最多保持6分钟.connectionPool(new ConnectionPool(5, 6, TimeUnit.MINUTES))// 指定分发器,即异步执行http请求时的线程池,http响应的回调也是在此线程池的线程中执行// .dispatcher(new Dispatcher(new ThreadPoolExecutor(...))).followRedirects(true) // 允许http重定向.followSslRedirects(false) // 截断https的重定向.pingInterval(30, TimeUnit.SECONDS) // 设置ping检测网络连通性的间隔。默认为0//.proxy(...) // 设置单个代理//.proxyAuthenticator(...) // 设置代理验证//.proxySelector(...) // 为不同的链接设置不同的代理.build();}public class EasyX509TrustManager implements X509TrustManager {private X509TrustManager standardTrustManager = null;/*** Constructor for EasyX509TrustManager.*/public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException,KeyStoreException {super();TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());factory.init(keystore);TrustManager[] trustmanagers = factory.getTrustManagers();if (trustmanagers.length == 0) {throw new NoSuchAlgorithmException("no trust manager found");}this.standardTrustManager = (X509TrustManager) trustmanagers[0];}/*** @see X509TrustManager#checkClientTrusted(X509Certificate[],* String authType)*/public void checkClientTrusted(X509Certificate[] certificates, String authType)throws CertificateException {standardTrustManager.checkClientTrusted(certificates, authType);}/*** @see X509TrustManager#checkServerTrusted(X509Certificate[],* String authType)*/public void checkServerTrusted(X509Certificate[] certificates, String authType)throws CertificateException {if ((certificates != null) && (certificates.length == 1)) {certificates[0].checkValidity();} else {standardTrustManager.checkServerTrusted(certificates, authType);}}/*** @see X509TrustManager#getAcceptedIssuers()*/public X509Certificate[] getAcceptedIssuers() {return this.standardTrustManager.getAcceptedIssuers();}}public SSLSocketFactory sslSocketFactory() {try {//信任任何链接SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, new TrustManager[]{new EasyX509TrustManager(null)}, new SecureRandom());return sslContext.getSocketFactory();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (KeyManagementException e) {e.printStackTrace();} catch (KeyStoreException e) {e.printStackTrace();}return null;}
}
八、OkhttpUtil 工具类
@Slf4j
@Component
public class OkHttpUtil{private static OkHttpClient okHttpClient;@Autowiredpublic OkHttpUtil(OkHttpClient okHttpClient) {OkHttpUtil.okHttpClient= okHttpClient;}/*** get* @param url 请求的url* @param queries 请求的参数,在浏览器?后面的数据,没有可以传null*/public static String get(String url, Map<String, String> queries) {String responseBody = "";StringBuffer sb = new StringBuffer(url);if (queries != null && queries.keySet().size() > 0) {boolean firstFlag = true;Iterator iterator = queries.entrySet().iterator();while (iterator.hasNext()) {Map.Entry entry = (Map.Entry<String, String>) iterator.next();if (firstFlag) {sb.append("?" + entry.getKey() + "=" + entry.getValue());firstFlag = false;} else {sb.append("&" + entry.getKey() + "=" + entry.getValue());}}}Request request = new Request.Builder().url(sb.toString()).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 put error >> ", e);} finally {if (response != null) {response.close();}}return responseBody;}/*** post** @param url 请求的url* @param params post form 提交的参数* @return*/public static String post(String url, Map<String, String> params) {String responseBody = "";FormBody.Builder builder = new FormBody.Builder();//添加参数if (params != null && params.keySet().size() > 0) {for (String key : params.keySet()) {builder.add(key, params.get(key));}}Request request = new Request.Builder().url(url).post(builder.build()).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post error >> ", e);} finally {if (response != null) {response.close();}}return responseBody;}/*** get* @param url 请求的url* @param queries 请求的参数,在浏览器?后面的数据,没有可以传null* @return*/public static String getForHeader(String url, Map<String, String> queries) {String responseBody = "";StringBuffer sb = new StringBuffer(url);if (queries != null && queries.keySet().size() > 0) {boolean firstFlag = true;Iterator iterator = queries.entrySet().iterator();while (iterator.hasNext()) {Map.Entry entry = (Map.Entry<String, String>) iterator.next();if (firstFlag) {sb.append("?" + entry.getKey() + "=" + entry.getValue());firstFlag = false;} else {sb.append("&" + entry.getKey() + "=" + entry.getValue());}}}Request request = new Request.Builder().addHeader("key", "value").url(sb.toString()).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 put error >> ", e);} finally {if (response != null) {response.close();}}return responseBody;}/*** Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}* 参数一:请求Url* 参数二:请求的JSON* 参数三:请求回调*/public static String postJsonParams(String url, String jsonParams) {String responseBody = "";RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);Request request = new Request.Builder().url(url).post(requestBody).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post error >> ", e);} finally {if (response != null) {response.close();}}return responseBody;}/*** Post请求发送xml数据....* 参数一:请求Url* 参数二:请求的xmlString* 参数三:请求回调*/public static String postXmlParams(String url, String xml) {String responseBody = "";RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);Request request = new Request.Builder().url(url).post(requestBody).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post error >> "+ e);} finally {if (response != null) {response.close();}}return responseBody;}
}
九、小结
okhttp 创建 request 请求常见的 body 类型
- RequestBody 适合传一个参数,如:json (2 和 3 示例)
- FormBody 表单参数(仅支持文本) (示例 6)
- MultipartBody 表单(支持文本 和 文件)(示例 4)
创建 okhttp 请求,主要生成 request(包含 method、url、body、header),最后通过 OkHttpClient 执行同步(execute)异步(enqueue)方法
Request request = new Request.Builder().post(formBody).url(url).addHeader("Connection", "keep-alive").build();Response response = okHttpClient.newCall(request).execute();
1、OkHttp3使用起来简单,但是实际上其原理代码十分复杂,这也使得OkHttp3功能很强大,包括缓存、gzip、长连接、重定向等。
2、OkHttp3原理复杂,但是它的主要功能就是网络访问,网络访问就是要完成读写功能,于是我们只需要好好把握HttpEngine中的sendRequest作用和readResponse作用即可,即sendRequest完成初始化,并通过Socket方式建立同服务器的网络连接,而readResponse通过Socket完成读写功能。
3、OkHttp3依赖于Okio,主要体现在网络访问数据放在okio.Buffer中,通过okio.Okio write方法写服务器数据,通过okio.Okio read方法读取服务器返回数据。
okhttp3简单使用相关推荐
- OkHttp3简单使用:请求和响应,post,get
一,HTTP请求.响应报文格式 要弄明白网络框架,首先需要先掌握Http请求的,响应的报文格式. HTTP请求报文格式: HTTP请求报文主要由请求行.请求头部.请求正文3部分组成. request. ...
- OKhttp3 简单使用
概述 okhttp 官网:https://square.github.io/okhttp/ HTTP是现代应用网络的方式.这就是我们交换数据和媒体的方式.有效地执行HTTP可以加快您的负载并节省带宽. ...
- Android网络框架okhttp3简单封装
1:在demo得build文件中添加依赖(这里以3.8.1版本为例) dependencies {compile 'com.squareup.okhttp3:okhttp:3.8.1' } 2:对网络 ...
- 添加okhttp+android+studio,OKHTTP3 简单使用(一) 介绍及Android Studio集成
HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽.OkHttp是一个高效的HTTP客户端,它有以下默认特性: 支持HTTP/2,允许所有同一个主机地址 ...
- 【OKHTTP3】OKHTTP3使用GET和POST
一.参考资料 OKHTTP3 简单使用(三) POST方法 | JesseHu Blog 使用OKHTTP方式发送POST请求,获取返回的JSON串 - 简书 OkHttp工具类 - 风中追风_lon ...
- okHttp3连接池简单使用
一.概述: HTTP是现代应用网络的方式.这就是我们交换数据和媒体的方式.有效地执行HTTP可以加快您的负载并节省带宽. OkHttp是一个默认有效的HTTP客户端: HTTP / 2支持允许对同一主 ...
- 安卓Okhttp3源码的简单分析
前言:现在的Android项目基本上都是以OkHttp来进行网络通信的(retrofit也是基于okhttp的) 下面记录下okhttp3中的一些实现方式和原理. 工作流程 以这张图出发,说一下几个注 ...
- AutoCompleteTextView+Okhttp3+ListView实现简单的网络数据搜索展示
首先用OKHttp3获取网络上的数据,并保存到Serializeable的Bean类集合 OkHttpClient client = new OkHttpClient();Request reques ...
- Android Banner(无限轮播图)控件的简单使用(网络数据OkHttp3)
一言不合就上图 banner是第三方集成好的直接注入依赖就可以用 老套路先注入依赖: //banner这个版本才是王道(我的studio是2.3.3)compile 'com.youth.banner ...
最新文章
- Sql 删除不保留日志
- Docker学习(一)
- 网络:浏览器静态资源缓存机制
- 一个数据应用闭环(转载)
- idea中右侧的Maven框消失了
- leetcode51. N 皇后(回溯算法)
- 深入::first-letter的研究
- C++ primer 第12章 12.3 使用标准库:文本查询程序
- ajax实现一个前台的进度条,前台ajax实现上传文件并且有进度条
- pcs7服务器一直显示在同步,【征文】PCS7 诡异的时间同步问题
- 【秋招】拼多多_数据分析岗_面试题整理
- Excel中怎么添加批注
- 百度网盘会员怎么购买最便宜
- CSP 202203-2出行计划
- 前端JS获取当前日期
- iOS图片加载渲染的优化
- 卫星通信放大器系统市场现状研究分析与发展前景预测报告
- 印能捷服务器系统怎么装,Prinergy印能捷JTP全自动建立工具(32/64bit)
- jmap heap输出解析
- 【校园卡】校园卡最近消息:2020校园卡还未停售,更新最新海报