OkHttp3 发送网络请求服务器
前言:应用程序需要发送网络请求服务器的接口,可使用OkHttp 3发送请求获取服务端数据
GitHut地址
Step 1:申请网络请求的权限:在manifests层的AndroidManifest.xml里的
<manifest控件里添加:
<!--允许程序打开网络套接字--><uses-permission android:name="android.permission.INTERNET" />
Step 2:引入依赖:在Gradle Scripts层的build.gradle(Module:app)里的dependencies 里添加:然后点击右上角的Sync Now下载,等待下载完成
//网络请求implementation 'com.squareup.okhttp3:okhttp:4.4.0'//打印网络日志implementation 'com.squareup.okhttp3:logging-interceptor:4.4.0'
Step 3:新建一个OkHttpTool工具类(此为施老师的):
package com.gx.hotel.util;//该工具类的包路径,根据自己路径修改import android.util.Log;import androidx.annotation.NonNull;import java.io.File;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;/*** create by qzlysxj* Fix bu qzlysxj on 2020-2-26* <p>* 便于使用okhttp3的工具类*/
public class OkHttpTool {//日志标志private static String TAG = "OkHttpTool";//OkHttpClient类private static final OkHttpClient myOkHttpClient;static {//========日志拦截器=========//Log拦截器HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {@Overridepublic void log(@NonNull String message) {Log.i(TAG, message);}});//设置日志显示级别HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;loggingInterceptor.setLevel(level);//========cookie处理--让服务端记住app//这里是设置cookie的,但是并没有做持久化处理;只是把cookie保存在内存中CookieJar cookieJar=new CookieJar() {private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();//保存cookie@Overridepublic void saveFromResponse(@NonNull HttpUrl url, @NonNull List<Cookie> cookies) {cookieStore.put(url.host(), cookies);}//获取cookie@Overridepublic List<Cookie> loadForRequest(@NonNull HttpUrl url) {List<Cookie> cookies = cookieStore.get(url.host());return cookies != null ? cookies : new ArrayList<Cookie>();}};//创建OkHttpClientmyOkHttpClient = new OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS)//连接超时.writeTimeout(60, TimeUnit.SECONDS)//写入超时.readTimeout(60, TimeUnit.SECONDS)//读取超时.addInterceptor(loggingInterceptor)//添加日志处理拦截器.cookieJar(cookieJar).build();}//================对外方法=====================/*** Get 请求* @param url{String} 请求地址* @param parameters{Map<String, Object>} 请求参数* @param responseCallback{ResponseCallback} 请求回调*/@SuppressWarnings("unused")public static void httpGet(String url, Map<String, Object> parameters, ResponseCallback responseCallback) {Request request = createGetRequest(url, parameters);doRequest(request, responseCallback);}/*** POST 请求* @param url{String} 请求地址* @param parameters{Map<String, Object>} 请求参数* @param responseCallback{ResponseCallback} 请求回调*/public static void httpPost(String url, Map<String, Object> parameters, ResponseCallback responseCallback) {Request request = createPostRequest(url, parameters);doRequest(request, responseCallback);}/*** POST 请求 JSON格式参数* @param url{String} 请求地址* @param json{String} JSON格式参数* @param responseCallback{ResponseCallback} 请求回调*/@SuppressWarnings("unused")public static void httpPostJson(String url, String json, ResponseCallback responseCallback) {Request request = createPostRequestJson(url, json);doRequest(request, responseCallback);}/*** POST 请求 文件上传* @param url{String} 请求地址* @param parameters{Map<String, Object>} 请求参数* @param files{Map<String, File>} 上传的文件列表* @param responseCallback{ResponseCallback} 请求回调*/@SuppressWarnings("unused")public static void httpPostWithFile(String url, Map<String, Object> parameters, Map<String, File> files, ResponseCallback responseCallback) {Request request = createPostRequestWithFile(url, parameters, files);doRequest(request, responseCallback);}/*** POST 请求 文件上传 byte数组* @param url{String} 请求地址* @param parameters{Map<String, Object>} 请求参数* @param files{Map<String, byte[]>}上传的文件列表* @param responseCallback{ResponseCallback} 请求回调*/@SuppressWarnings("unused")public static void httpPostWithFileByte(String url, Map<String, Object> parameters, Map<String, byte[]> files, ResponseCallback responseCallback) {Request request = createPostRequestWithFileByte(url, parameters, files);doRequest(request, responseCallback);}//=====回调接口======public interface ResponseCallback {void onResponse(boolean isSuccess, int responseCode, String response, Exception exception);}//===========私有方法===============//====构建请求====//构建 Get请求private static Request createGetRequest(String url, Map<String, Object> parameters) {StringBuilder urlBuilder = new StringBuilder();urlBuilder.append(url);if (url.indexOf('?') <= -1) {//未拼接参数urlBuilder.append("?");}for (Map.Entry<String, Object> entry : parameters.entrySet()) {urlBuilder.append("&");urlBuilder.append(entry.getKey());urlBuilder.append("=");urlBuilder.append(entry.getValue().toString());}return getBaseRequest().url(urlBuilder.toString()).build();}//构建 POST 请求private static Request createPostRequest(String url, Map<String, Object> parameters) {@SuppressWarnings("all")FormBody.Builder builder = new FormBody.Builder(Charset.forName("UTF-8"));if (parameters != null) {for (Map.Entry<String, Object> entry : parameters.entrySet()) {builder.add(entry.getKey(), entry.getValue().toString());}}FormBody formBody = builder.build();return getBaseRequest().url(url).post(formBody).build();}//构建 POST JSON格式参数请求private static Request createPostRequestJson(String url, String json) {MediaType mediaType = MediaType.parse("application/json;charset=utf-8");RequestBody body = RequestBody.create(json,mediaType);return getBaseRequest().url(url).post(body).build();}//构建 POST带文件的 请求private static Request createPostRequestWithFile(String url, Map<String, Object> parameters, Map<String, File> files) {// form 表单形式上传MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);if (files != null) {for (Map.Entry<String, File> fileEntry : files.entrySet()) {File file = fileEntry.getValue();if (file != null) {// MediaType.parse() 里面是上传的文件类型。RequestBody body = RequestBody.create(file,MediaType.parse("application/octet-stream"));String filename = file.getName();// 参数分别为, 请求key ,文件名称 , RequestBodyrequestBody.addFormDataPart(fileEntry.getKey(), filename, body);}}}if (parameters != null) {// map 里面是请求中所需要的 key 和 valuefor (Map.Entry<String, Object> entry : parameters.entrySet()) {String key = entry.getKey();String value = entry.getValue().toString();requestBody.addFormDataPart(key, value);}}return getBaseRequest().url(url).post(requestBody.build()).build();}//构建 POST带文件的 请求private static Request createPostRequestWithFileByte(String url, Map<String, Object> parameters, Map<String, byte[]> files) {// form 表单形式上传MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);if (files != null) {for (Map.Entry<String, byte[]> fileEntry : files.entrySet()) {byte[] file = fileEntry.getValue();if (file != null) {// MediaType.parse() 里面是上传的文件类型。RequestBody body = RequestBody.create(file,MediaType.parse("application/octet-stream"));// 参数分别为, 请求key ,文件名称 , RequestBodyrequestBody.addFormDataPart(fileEntry.getKey(), fileEntry.getKey(), body);}}}if (parameters != null) {// map 里面是请求中所需要的 key 和 valuefor (Map.Entry<String, Object> entry : parameters.entrySet()) {String key = entry.getKey();String value = entry.getValue().toString();requestBody.addFormDataPart(key, value);}}return getBaseRequest().url(url).post(requestBody.build()).build();}//===实际进行请求的方法private static void doRequest(final Request request, final ResponseCallback responseCallback) {//使用okhttp3的异步请求myOkHttpClient.newCall(request).enqueue(new Callback() {//失败回调@Overridepublic void onFailure(@NonNull Call call, @NonNull IOException e) {//回调responseCallback.onResponse(false, -1, null, e);//用于输出错误调试信息if (e.getMessage()!=null){Log.e(TAG, e.getMessage());}}//成功回调@Overridepublic void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {int responseCode = response.code();//获取响应码ResponseBody responseBody = response.body();//获取 ResponseBodyif (response.isSuccessful() && responseBody != null) {String strResponse = responseBody.string();//回调responseCallback.onResponse(true, responseCode, strResponse, null);} else {//回调responseCallback.onResponse(false, responseCode, null, null);}}});}//获取请求 指定client为Androidprivate static Request.Builder getBaseRequest() {Request.Builder builder = new Request.Builder();builder.addHeader("client", "Android");return builder;}
}//.addInterceptor(new Interceptor() {// @Override
// public Response intercept(@NonNull Chain chain) throws IOException {// Request request = chain.request().newBuilder()
// .addHeader("Connection", "close").build();
// return chain.proceed(request);
// }
//})/*以前自己写的日志拦截器*/
//添加日志处理拦截器
//.addInterceptor(new Interceptor() {// @Override
// public Response intercept(@NonNull Chain chain) throws IOException {// Request request = chain.request();
// long startTime = System.currentTimeMillis();
// Response response = chain.proceed(chain.request());
// long endTime = System.currentTimeMillis();
// long duration = endTime - startTime;
// MediaType mediaType = response.body().contentType();
// String content = response.body().string();
// Log.d(TAG, "\n");
// Log.d(TAG, "----------Start----------------");
// Log.d(TAG, "| " + request.toString());
// String method = request.method();
// if ("POST".equals(method)) {// StringBuilder sb = new StringBuilder();
// if (request.body() instanceof FormBody) {// FormBody body = (FormBody) request.body();
// for (int i = 0; i < body.size(); i++) {// sb.append(body.encodedName(i) + "=" + body.encodedValue(i) + ",");
// }
// if (sb.length() > 0) {// //在参数不为空的情况下处理最后的 “,”
// sb.delete(sb.length() - 1, sb.length());
// }
// Log.d(TAG, "| RequestParams:{" + sb.toString() + "}");
// }
// }
// Log.d(TAG, "| Response:" + content);
// Log.d(TAG, "----------End:" + duration + "毫秒----------");
// //由于前面的代码已经获取了响应结果,会导致后续代码无法获取到响应结果
// // 需要重新构建一个响应结果并返回
// return response.newBuilder()
// .body(ResponseBody.create(mediaType, content))
// .build();
// }
//})
ps:因为Android P系统限制了明文流量的网络请求,所以需要配置一下文件,具体如下:
查看自己的笔记(解决Android P系统限制了明文流量的网络请求) 或 查看该地址:地址
使用方法:
第一种:带参数或不带参数的:
/**访问服务器方法路径(ps :本人后台是ssm项目的,所以路径要根据自己的项目框架而定)!路径的结构:手机调试,路径为(ps:电脑和手机要连同一网络):http://+电脑网络的IPv4地址+/+项目名+/+控制器+/+方法例:String url="http://192.168.43.9:8080/CarTaketing/User/ifLoginSure.do";//也可以在这拼接参数虚拟机调试,不用连接网络:http://10.0.2.2:8080/+项目名称+/+控制器+/+方法例:String url="http://10.0.2.2:8080/CarTaketing/User/ifLoginSure.do";ps:如果用虚拟机调试,电脑连接wifi,可以用手机调试那种路径,虚拟机不用连接wifi*/String url="http://192.168.43.9:8080/CarTaketing/User/ifLoginSure.do";//也可以在这拼接参数//添加参数,设置值(参数名 和 接受类型要和 服务端一致,详细请看 下面的注释(这个注释:说明找不到服务器的这个方法(url)))Map<String,Object> map=new HashMap<>();map.put("name","liang");map.put("password","456");//==发送请求 ps:若不需要参数,参数2 的这个map可以为null//参数1为访问服务器的地址,参数2为map类型,里面有各个参数名和对应的值,参数3为发送网络后执行的回调,不管成功否都会执行OkHttpTool.httpPost(url, map, new OkHttpTool.ResponseCallback() {//isSuccess:值false为发送失败,true为成功;responseCode:值为200为发送成功,否则为失败;response:发送成功后,服务端返回的数据@Overridepublic void onResponse(final boolean isSuccess, final int responseCode, final String response, Exception exception) {//发送后,对当前的Activity的布局做出反应(如,弹出提示,对布局的更改),就得在该activity的ui线程上执行,若不需要,则不用在该ui线程上执行。MainActivity.this.runOnUiThread(new Runnable() {@Overridepublic void run() {if(isSuccess&&responseCode==200){//==说明访问到服务器的方法了 然后就可以对服务器返回的数据(即response)进行相关的操作/**解析服务器返回的数据(即response)说明:因为服务器返回的是json格式的字符串,所以要解析:ps.这里用的是alibaba的fastjson来解析,引入依赖://fastjsonimplementation 'com.alibaba:fastjson:1.2.68'一般来说,服务器把数据转为json前的原来数据是 List集合、bean类(po或vo类)、或数据类型(例:int ,boolea..等等八种)、或String类型,所以解析后的数据就要对应的类型接收。这里罗列出它们各种类型的接受方式:1.List集合类型: SelectOption为list的类型参数,要与服务端里的list的类型参数对应,解析接收如下:List<SelectOption> data=JSON.parseArray(response,SelectOption.class);2.bean类(po或vo类):2.1:如果是普通的bean类:例如:Message类,里面有属性:int code、String text 和它两的getset方法:解析接收如下:Message message = JSON.parseObject(response, Message.class);2.2:如果是bean类带有类型参数的话,例如:Bsgrid<T>类,里面有属性:int curPage、int totalRows、boolean success、List<T> data 和 它们的getset方法,那解析接收如下:Bsgrid<CarCheckVo> bsgrid=JSON.parseObject(response,new TypeReference<Bsgrid<CarCheckVo>>(){});ps:CarCheckVo是一个bean类,要与服务器里的类型参数一致。3.八种类型或String类型:用String类型举例解析:String str=JSON.parseObject(response, String.class);*///这里是一个普通的bean类型Message message = JSON.parseObject(response, Message.class);Toast.makeText(MainActivity.this,message.getText(),Toast.LENGTH_LONG).show();}else{/**说明找不到服务器的这个方法(url),原因:** 1.服务器的 路径(请求的方法路径) 和 这个 url(请求的方法路径) 是不是一致;* 2.这个服务器方法的形参名,是否和 map 里的 各个key名字 是否对应;* 3.这个服务器方法的形参接受的类型,是否和 map 里的 各个key值的接受类型 是否对应;*//**举例:服务器的方法:@RequestMapping(value = "ifLoginSure",produces = AJSON_UTF8)public String ifLoginSure(String name,String password)错误1,路径方法名没写对:http://192.168.43.9:8080/CarTaketing/User/ifLo5555ginS.do错误2,形参名不对应:map.put("namessss","liang"); 形参名是name,map添加的是namessss,不对应错误3,接受类型不对应:map.put("name",1111); 方法的形参的name 的接受类型是String,却传的是int类型,不对应,这个错误很容易犯,比如字符串的date,接受的是date类型,再如,形参类型是int ,传过来的是null,则无法接受,报错!!*/Toast.makeText(MainActivity.this,"连接服务器失败,请稍后重试!",Toast.LENGTH_LONG).show();}}});}});
第二种:带有文件上传:
//服务器方法路径String url= ServiceUtil.getUserUrl("uploadMemberPicture");//Object类型的参数集Map<String,Object> map=new HashMap<>();map.put("memberId",myApplication.getUserBean().getUserid());//文件类型的参数集Map<String,File> fileMap=new HashMap<>();fileMap.put("photo", fileUp);//ps:服务器接收类型记得是File类型哦,//例:public Object uploadMemberPicture(int memberId,@RequestParam(value="photo")MultipartFile mPhoto)//注解: @RequestParam(value="photo") 里的 photo 对应 fileMap.put("photo", fileUp);里的 photo //(ps:因是ssm项目,所以是这样写,实际根据自己项目框架写)//参数1为服务器路径、2为Object类型的参数集、3为文件类型的参数集OkHttpTool.httpPostWithFile(url, map, fileMap, new OkHttpTool.ResponseCallback() {@Overridepublic void onResponse(final boolean isSuccess,final int responseCode, final String response, Exception exception) {MainActivity.this.runOnUiThread(new Runnable() {@Overridepublic void run() { //这里的代码内容同第一种}});}});
更多方法请查看OkHttpTool的工具类源码!!
OkHttp3 发送网络请求服务器相关推荐
- vue如何发送网络请求,使用axios事半功倍!
目录 一.axios使用 1.支持多种请求方式: 2.安装 3.简单使用实例 4.发送并发请求 5.全局配置 二.axios的实例 1.为什么要创建 axios的实例呢? 2.使用 三..axios模 ...
- Fetch发送网络请求
1. 文档 https://github.github.io/fetch/ https://segmentfault.com/a/1190000003810652 2. 特点 fetch: 原生函数, ...
- axios发送网络请求
网络模块封装 选择什么网络模块 传统的Ajax 缺点:配置和调用方式等非常混乱 jQuery-Ajax 缺点:在Vue整个开发中都是不需要使用jQuery的 axios axios 功能特点: 在浏览 ...
- python 网络接口 开发_Python自动化学习笔记(八)——接口开发、发送网络请求、发送邮件、写日志...
1.接口开发(flask模块) Python自动化学习笔记(七)接口开发部分的内容补充 1.1参数为json格式: flask.request.is_json #判断参数是否是json格式 flask ...
- Python自动化学习笔记(八)——接口开发、发送网络请求、发送邮件、写日志...
1.接口开发(flask模块) Python自动化学习笔记(七)接口开发部分的内容补充 1.1参数为json格式: flask.request.is_json #判断参数是否是json格式 flask ...
- 网络编程-JavaScript中发送网络请求汇总
文章目录 1.前后端分离优势 2.HTTP协议的解析 2.1 HTTP的介绍 2.2 HTTP的组成 2.3 HTTP的版本 2.4 HTTP请求方式 2.5 HTTP请求头字段 2.6 HTTP响应 ...
- 微信小程序Api发送网络请求(request)
微信小程序发送网络请求(request) 下边的地址是微信小程序开发平台对网络请求的介绍. 微信小程序网络请求介绍 最近公司要求开发小程序,下面是我查看微信小程序文档,写的一个demo,记录下来方便以 ...
- 微信小程序中发送网络请求
文章目录 小程序项目 app.json pages/index/index.html pages/index/index.wxss pages/index/index.js 发送网络请求 网络请求函数 ...
- Python发送网络请求(requests)
Python发送网络请求(requests) Python已经是广泛使用的脚本语言了,我们可以使用requests库进行网络请求. 在PyPI中搜索requests,就可以找到这个库 1. 安装 pi ...
最新文章
- 对函数指针与typedef的理解:typedef void (*sighandler_t)(int)
- 普通背包问题-枚举算法(《算法竞赛宝典》 第二部 基础算法艺术)
- linux c 写文件 换行符,[Linux文件]带回车换行的写入字符串实例
- 11张高清Python全知识地图,强烈建议学习
- cadence ic5141安装包_linux下安装cadence ic5141
- 鸿蒙系统是电脑还是手机,鸿蒙系统什么时候能用在电脑上,华为鸿蒙系统什么时候能用...
- ARCore:ARCore的初体验
- CAD格式交换全能:CAD DLL 15.0 Crack
- 用Websocket聊天完整demo,做笔记用,各位大佬多多指教
- 小型数据库系统开发作业
- kettle使用--1.mysql多表关联导入mongoDB
- Linux中设置和重启网络的命令
- 吉林大学软件学院2021级计算机组成原理期末50道简答题
- magento Shopping Cart Price Rule 购物车促销规则
- centos安装nagios
- Library-Files-维持权限--对比自带CLSID打开程序
- python lib error
- ug许可证无法连接服务器,NX许可证错误:无法连接至许可证服务器系统。SPLM_LICENSE_SERVER错误[-15]...
- 2019FME博客大赛——基于FME和ArcGIS Pro的规划成果标准化建库方法
- 安装SSL证书后,解决混合内容造成页面错误提示的处理办法