Flutter网络通信-封装Dio
前言
dio 是一个强大的 Dart HTTP 请求库,支持全局配置、Restful API、FormData、拦截器、 请求取消、Cookie 管理、文件上传/下载、超时以及自定义适配器等。
Dio的pub地址为:dio | Dart package
封装要求
- 能够使用get、post、put、patch、delete、postForm、postStream请求
- 能够使用token
- 能够取消请求
- 不论网络通信是否成功,返回的格式保持一致
封装步骤
1.添加依赖
dart pub add dio
2.创建一个名称为HttpUtil的工厂函数
class HttpUtil {static final HttpUtil _instance = HttpUtil.internal();factory HttpUtil() => _instance;
}
在HttpUtil.internal中初始化Dio
- baseUrl是请求基地址,根据自己的需求转换
- InterceptorsWrapper中添加了拦截器
- 不论请求成功与否,返回的data都是DioResponse类型,我们根据DioResponse对数据进行解析
HttpUtil.internal() {// BaseOptions、Options、RequestOptions 都可以配置参数,优先级别依次递增,且可以根据优先级别覆盖参数BaseOptions options = BaseOptions(//请求基地址baseUrl: SERVER_API_URL,// baseUrl: storage.read(key: STORAGE_KEY_APIURL) ?? SERVICE_API_BASEURL,//连接服务器超时时间connectTimeout: const Duration(seconds: 20),// 响应流上前后两次接受到数据的间隔receiveTimeout: const Duration(seconds: 20),// Http请求头.headers: {},/// 请求的Content-Type,默认值是"application/json; charset=utf-8"./// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,/// 可以设置此选项为 `Headers.formUrlEncodedContentType`, 这样[Dio]/// 就会自动编码请求体.contentType: 'application/json; charset=utf-8',/// [responseType] 表示期望以那种格式(方式)接受响应数据。/// 目前 [ResponseType] 接受三种类型 `JSON`, `STREAM`, `PLAIN`.////// 默认值是 `JSON`, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。/// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 `STREAM`.////// 如果想以文本(字符串)格式接收响应数据,请使用 `PLAIN`.responseType: ResponseType.json,);dio = Dio(options);// CookieJar Dart 中用于 http 请求的 cookie 管理器,您可以通过它轻松处理复杂的 cookie 策略并持久化 cookie。// CookieJar cookieJar = CookieJar();// dio.interceptors.add(CookieManager(cookieJar));// 添加拦截器dio.interceptors.add(InterceptorsWrapper(onRequest: (RequestOptions options, RequestInterceptorHandler handler) {/// 如果你想完成请求并返回一些自定义数据,你可以使用 `handler.resolve(response)`。///这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response./// 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。/// 这样请求将被中止并触发异常,上层catchError会被调用。///return handler.next(options);},onResponse: (response, handler) {// 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。//这样请求将被中止并触发异常,上层catchError会被调用。// 请求成功是对数据做基本处理if (response.statusCode == 200) {response.data =DioResponse(code: 200, message: "请求成功啦", data: response.data);} else {response.data = DioResponse(code: response.statusCode,message: "请求失败啦",data: response.data);}return handler.next(response);},onError: (e, handler) {//停止加载// Loading.dismiss();print("-=-=-=-onError$e,-----$handler");EasyLoading.instance.userInteractions = true;EasyLoading.dismiss();DioResponse? eInfo;if ("$e".contains("The request connection took longer")) {eInfo = DioResponse(code: -1, message: "连接超时", data: "");} else {eInfo = createErrorEntity(e);}onError(eInfo);Response response = Response(data: eInfo, requestOptions: RequestOptions());return handler.resolve(response); //continue// 如果你想完成请求并返回一些自定义数据,可以resolve 一个`Response`,如`handler.resolve(response)`。// 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response.},),);
}
3.定义DioResponse
- code是请求返回的状态码
- data是后端返回的数据
class DioResponse<T> {/// 消息(例如成功消息文字/错误消息文字)final String message;/// 自定义code(可根据内部定义方式)final int? code;/// 接口返回的数据final T data;/// 需要添加更多/// .........DioResponse({required this.message,required this.data,required this.code,});factory DioResponse.fromJson(Map<String, dynamic> json) => DioResponse(code: json["code"],message: json["message"],data: json["data"],);Map<String, dynamic> toJson() => {"message": message,"data": data,"code": code,};
}
4.对错误请求进行DioResponse处理
//错误信息DioResponse createErrorEntity(DioError error) {// print('error.type${error.type}');var data = error.response?.data;print("进入了错误信息:error.type:${error.type},错误的码:¥「${error.response!.statusCode},,data:¥${data}");switch (error.type) {case DioErrorType.cancel:return DioResponse(code: -1, message: "请求取消", data: data);case DioErrorType.connectionTimeout:return DioResponse(code: -1, message: "连接超时", data: data);case DioErrorType.sendTimeout:return DioResponse(code: -1, message: "请求超时", data: data);case DioErrorType.receiveTimeout:return DioResponse(code: -1, message: "响应超时", data: data);case DioErrorType.badResponse:try {print("data:$data");int errCode =error.response != null ? error.response!.statusCode! : -1;return DioResponse(code: errCode, message: data["message"], data: data);} catch (e) {return DioResponse(code: -1, message: "badResponse抛出了异常", data: e);}case DioErrorType.unknown:{try {int errCode =error.response != null ? error.response!.statusCode! : -1;switch (errCode) {case 400:return DioResponse(code: errCode, message: "请求语法错误", data: data);case 401:return DioResponse(code: errCode, message: "没有权限", data: data);case 403:return DioResponse(code: errCode, message: "服务器拒绝执行", data: data);case 404:return DioResponse(code: errCode, message: "无法连接服务器", data: data);case 405:return DioResponse(code: errCode, message: "请求方法被禁止", data: data);case 500:return DioResponse(code: errCode, message: "服务器内部错误", data: data);case 502:return DioResponse(code: errCode, message: "无效的请求", data: data);case 503:return DioResponse(code: errCode, message: "服务器挂了", data: data);case 505:return DioResponse(code: errCode, message: "不支持HTTP协议请求", data: data);default:return DioResponse(code: errCode,message: error.response != null? error.response!.statusMessage!: "其他状态字异常",data: data);}} on Exception catch (_) {return DioResponse(code: -1, message: "unknown抛出了异常", data: data);}}default:{return DioResponse(code: -1, message: error.message.toString(), data: data);}}}
5.对错误信息进行统一的处理
//error进行统一处理onError(DioResponse eInfo) {debugPrint('错误----代码:${eInfo.code.toString()}, 错误内容:${eInfo.message}');String errText = '';switch (eInfo.code) {case 401: //401提示什么错误或者做些什么操作,比如token过期退出登录switch (eInfo.message) {case "Token has expired":case "Authentication failed":errText = "账号登录已过期,请重新登陆".tr;EasyLoading.showError(errText);Get.offNamed(AppRoutes.SIGN_IN);break;case "Invalid username or password":EasyLoading.showError("账号或密码不正确".tr);break;case "User account is not active":case "User account is locked due to security policy":break;}break;case 501:switch (eInfo.message) {case "The user does not exist, please register!":errText = "该账号不存在".tr;EasyLoading.showError(errText);break;case "User already exists!":errText = "用户已存在".tr;EasyLoading.showError(errText);break;}break;case 509:print("+++++++++++++++++++");errText = "验证码有误,请重新获取".tr;EasyLoading.showError(errText);break;case 511:errText = "验证码以过期,请重新输入".tr;EasyLoading.showError(errText);break;case 403:errText = "该账号没有权限登录,请联系管理员".tr;EasyLoading.showError(errText);break;case -1:EasyLoading.showError(eInfo.message);break;default://用弹窗提示错误errText = "未知错误".tr;EasyLoading.showError(errText);}}
6.配置请求类型和取消请求功能
//error进行统一处理onError(DioResponse eInfo) {debugPrint('错误----代码:${eInfo.code.toString()}, 错误内容:${eInfo.message}');String errText = '';switch (eInfo.code) {case 401: //401提示什么错误或者做些什么操作,比如token过期退出登录switch (eInfo.message) {case "Token has expired":case "Authentication failed":errText = "账号登录已过期,请重新登陆".tr;EasyLoading.showError(errText);Get.offNamed(AppRoutes.SIGN_IN);break;case "Invalid username or password":EasyLoading.showError("账号或密码不正确".tr);break;case "User account is not active":case "User account is locked due to security policy":break;}break;case 501:switch (eInfo.message) {case "The user does not exist, please register!":errText = "该账号不存在".tr;EasyLoading.showError(errText);break;case "User already exists!":errText = "用户已存在".tr;EasyLoading.showError(errText);break;}break;case 509:print("+++++++++++++++++++");errText = "验证码有误,请重新获取".tr;EasyLoading.showError(errText);break;case 511:errText = "验证码以过期,请重新输入".tr;EasyLoading.showError(errText);break;case 403:errText = "该账号没有权限登录,请联系管理员".tr;EasyLoading.showError(errText);break;case -1:EasyLoading.showError(eInfo.message);break;default://用弹窗提示错误errText = "未知错误".tr;EasyLoading.showError(errText);}}//错误信息DioResponse createErrorEntity(DioError error) {// print('error.type${error.type}');var data = error.response?.data;print("进入了错误信息:error.type:${error.type},错误的码:¥「${error.response!.statusCode},,data:¥${data}");switch (error.type) {case DioErrorType.cancel:return DioResponse(code: -1, message: "请求取消", data: data);case DioErrorType.connectionTimeout:return DioResponse(code: -1, message: "连接超时", data: data);case DioErrorType.sendTimeout:return DioResponse(code: -1, message: "请求超时", data: data);case DioErrorType.receiveTimeout:return DioResponse(code: -1, message: "响应超时", data: data);case DioErrorType.badResponse:try {print("data:$data");int errCode =error.response != null ? error.response!.statusCode! : -1;return DioResponse(code: errCode, message: data["message"], data: data);} catch (e) {return DioResponse(code: -1, message: "badResponse抛出了异常", data: e);}case DioErrorType.unknown:{try {int errCode =error.response != null ? error.response!.statusCode! : -1;switch (errCode) {case 400:return DioResponse(code: errCode, message: "请求语法错误", data: data);case 401:return DioResponse(code: errCode, message: "没有权限", data: data);case 403:return DioResponse(code: errCode, message: "服务器拒绝执行", data: data);case 404:return DioResponse(code: errCode, message: "无法连接服务器", data: data);case 405:return DioResponse(code: errCode, message: "请求方法被禁止", data: data);case 500:return DioResponse(code: errCode, message: "服务器内部错误", data: data);case 502:return DioResponse(code: errCode, message: "无效的请求", data: data);case 503:return DioResponse(code: errCode, message: "服务器挂了", data: data);case 505:return DioResponse(code: errCode, message: "不支持HTTP协议请求", data: data);default:return DioResponse(code: errCode,message: error.response != null? error.response!.statusMessage!: "其他状态字异常",data: data);}} on Exception catch (_) {return DioResponse(code: -1, message: "unknown抛出了异常", data: data);}}default:{return DioResponse(code: -1, message: error.message.toString(), data: data);}}}/// 取消请求/// 同一个cancel token 可以用于多个请求,当一个cancel token取消时,所有使用该cancel token的请求都会被取消。/// 所以参数可选void cancelRequests(CancelToken token) {token.cancel("cancelled");}/// 读取本地配置Map<String, dynamic>? getAuthorizationHeader() {var headers = <String, dynamic>{};var token = StorageUtil().read("token");print("token");if (token != null) {headers['X-Authorization'] = 'Bearer $token';}return headers;}/// restful get 操作/// refresh 是否下拉刷新 默认 false/// noCache 是否不缓存 默认 true/// list 是否列表 默认 false/// cacheKey 缓存key/// cacheDisk 是否磁盘缓存Future get(String path, {Map<String, dynamic>? queryParameters,Options? options,bool refresh = false,bool noCache = !CACHE_ENABLE,bool list = false,String cacheKey = '',bool cacheDisk = false,CancelToken? canceltoken,Map<String, dynamic>? data,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}try {print("入参:$path--$data");var response = await dio.get(path,queryParameters: queryParameters,options: requestOptions,cancelToken: canceltoken ?? cancelToken,data: data,);print("+++++++++++++++:$response");return response.data;} catch (e) {print("出现了错误$e");}}/// restful post 操作Future post(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? canceltoken,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}try {var response = await dio.post(path,data: data,queryParameters: queryParameters,options: requestOptions,cancelToken: canceltoken ?? cancelToken,);return response.data;} catch (e) {print("出现了错误:$e");return e;}}/// restful put 操作Future put(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}var response = await dio.put(path,data: data,queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}/// restful patch 操作Future patch(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}var response = await dio.patch(path,data: data,queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}/// restful delete 操作Future delete(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}var response = await dio.delete(path,data: data,queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}/// restful post form 表单提交操作Future postForm(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}var response = await dio.post(path,data: FormData.fromMap(data),queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}/// restful post Stream 流数据Future postStream(String path, {dynamic data,int dataLength = 0,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}requestOptions.headers!.addAll({Headers.contentLengthHeader: dataLength.toString(),});var response = await dio.post(path,data: Stream.fromIterable(data.map((e) => [e])),queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}
}
7.全部代码
import 'dart:math';import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart' as tr;
import 'package:get/get_core/src/get_main.dart';
import 'package:my_app/common/routes/routes.dart';
import 'package:my_app/common/utils/utils.dart';
import 'package:my_app/common/value/serve.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
// import 'package:get/get.dart';
// import 'package:dio/src/form_data.dart';
import './../value/cache.dart';class HttpUtil {static final HttpUtil _instance = HttpUtil.internal();factory HttpUtil() => _instance;late Dio dio;//可以通过 CancelToken 来取消发起的请求CancelToken cancelToken = CancelToken();HttpUtil.internal() {// BaseOptions、Options、RequestOptions 都可以配置参数,优先级别依次递增,且可以根据优先级别覆盖参数BaseOptions options = BaseOptions(//请求基地址baseUrl: SERVER_API_URL,// baseUrl: storage.read(key: STORAGE_KEY_APIURL) ?? SERVICE_API_BASEURL,//连接服务器超时时间connectTimeout: const Duration(seconds: 20),// 响应流上前后两次接受到数据的间隔receiveTimeout: const Duration(seconds: 20),// Http请求头.headers: {},/// 请求的Content-Type,默认值是"application/json; charset=utf-8"./// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,/// 可以设置此选项为 `Headers.formUrlEncodedContentType`, 这样[Dio]/// 就会自动编码请求体.contentType: 'application/json; charset=utf-8',/// [responseType] 表示期望以那种格式(方式)接受响应数据。/// 目前 [ResponseType] 接受三种类型 `JSON`, `STREAM`, `PLAIN`.////// 默认值是 `JSON`, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。/// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 `STREAM`.////// 如果想以文本(字符串)格式接收响应数据,请使用 `PLAIN`.responseType: ResponseType.json,);dio = Dio(options);// CookieJar Dart 中用于 http 请求的 cookie 管理器,您可以通过它轻松处理复杂的 cookie 策略并持久化 cookie。// CookieJar cookieJar = CookieJar();// dio.interceptors.add(CookieManager(cookieJar));// 添加拦截器dio.interceptors.add(InterceptorsWrapper(onRequest: (RequestOptions options, RequestInterceptorHandler handler) {/// 如果你想完成请求并返回一些自定义数据,你可以使用 `handler.resolve(response)`。///这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response./// 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。/// 这样请求将被中止并触发异常,上层catchError会被调用。///return handler.next(options);},onResponse: (response, handler) {// 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。//这样请求将被中止并触发异常,上层catchError会被调用。// 请求成功是对数据做基本处理if (response.statusCode == 200) {response.data =DioResponse(code: 200, message: "请求成功啦", data: response.data);} else {response.data = DioResponse(code: response.statusCode,message: "请求失败啦",data: response.data);}// 对某些单独的url返回数据做特殊处理// if (response.requestOptions.baseUrl.contains("???????")) {// //....// }return handler.next(response);},onError: (e, handler) {//停止加载// Loading.dismiss();print("-=-=-=-onError$e,-----$handler");EasyLoading.instance.userInteractions = true;EasyLoading.dismiss();DioResponse? eInfo;if ("$e".contains("The request connection took longer")) {eInfo = DioResponse(code: -1, message: "连接超时", data: "");} else {eInfo = createErrorEntity(e);}// print("111111111:$eInfo");onError(eInfo);Response response =Response(data: eInfo, requestOptions: RequestOptions());// e.data =eInfo;return handler.resolve(response); //continue// 如果你想完成请求并返回一些自定义数据,可以resolve 一个`Response`,如`handler.resolve(response)`。// 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response.},),);}//error进行统一处理onError(DioResponse eInfo) {debugPrint('错误----代码:${eInfo.code.toString()}, 错误内容:${eInfo.message}');String errText = '';switch (eInfo.code) {case 401: //401提示什么错误或者做些什么操作,比如token过期退出登录switch (eInfo.message) {case "Token has expired":case "Authentication failed":errText = "账号登录已过期,请重新登陆".tr;EasyLoading.showError(errText);Get.offNamed(AppRoutes.SIGN_IN);break;case "Invalid username or password":EasyLoading.showError("账号或密码不正确".tr);break;case "User account is not active":case "User account is locked due to security policy":break;}break;case 501:switch (eInfo.message) {case "The user does not exist, please register!":errText = "该账号不存在".tr;EasyLoading.showError(errText);break;case "User already exists!":errText = "用户已存在".tr;EasyLoading.showError(errText);break;}break;case 509:print("+++++++++++++++++++");errText = "验证码有误,请重新获取".tr;EasyLoading.showError(errText);break;case 511:errText = "验证码以过期,请重新输入".tr;EasyLoading.showError(errText);break;case 403:errText = "该账号没有权限登录,请联系管理员".tr;EasyLoading.showError(errText);break;case -1:EasyLoading.showError(eInfo.message);break;default://用弹窗提示错误errText = "未知错误".tr;EasyLoading.showError(errText);}}//错误信息DioResponse createErrorEntity(DioError error) {// print('error.type${error.type}');var data = error.response?.data;print("进入了错误信息:error.type:${error.type},错误的码:¥「${error.response!.statusCode},,data:¥${data}");switch (error.type) {case DioErrorType.cancel:return DioResponse(code: -1, message: "请求取消", data: data);case DioErrorType.connectionTimeout:return DioResponse(code: -1, message: "连接超时", data: data);case DioErrorType.sendTimeout:return DioResponse(code: -1, message: "请求超时", data: data);case DioErrorType.receiveTimeout:return DioResponse(code: -1, message: "响应超时", data: data);case DioErrorType.badResponse:try {print("data:$data");int errCode =error.response != null ? error.response!.statusCode! : -1;return DioResponse(code: errCode, message: data["message"], data: data);} catch (e) {return DioResponse(code: -1, message: "badResponse抛出了异常", data: e);}case DioErrorType.unknown:{try {int errCode =error.response != null ? error.response!.statusCode! : -1;switch (errCode) {case 400:return DioResponse(code: errCode, message: "请求语法错误", data: data);case 401:return DioResponse(code: errCode, message: "没有权限", data: data);case 403:return DioResponse(code: errCode, message: "服务器拒绝执行", data: data);case 404:return DioResponse(code: errCode, message: "无法连接服务器", data: data);case 405:return DioResponse(code: errCode, message: "请求方法被禁止", data: data);case 500:return DioResponse(code: errCode, message: "服务器内部错误", data: data);case 502:return DioResponse(code: errCode, message: "无效的请求", data: data);case 503:return DioResponse(code: errCode, message: "服务器挂了", data: data);case 505:return DioResponse(code: errCode, message: "不支持HTTP协议请求", data: data);default:return DioResponse(code: errCode,message: error.response != null? error.response!.statusMessage!: "其他状态字异常",data: data);}} on Exception catch (_) {return DioResponse(code: -1, message: "unknown抛出了异常", data: data);}}default:{return DioResponse(code: -1, message: error.message.toString(), data: data);}}}/// 取消请求/// 同一个cancel token 可以用于多个请求,当一个cancel token取消时,所有使用该cancel token的请求都会被取消。/// 所以参数可选void cancelRequests(CancelToken token) {token.cancel("cancelled");}/// 读取本地配置Map<String, dynamic>? getAuthorizationHeader() {var headers = <String, dynamic>{};var token = StorageUtil().read("token");print("token");if (token != null) {headers['X-Authorization'] = 'Bearer $token';}return headers;}/// restful get 操作/// refresh 是否下拉刷新 默认 false/// noCache 是否不缓存 默认 true/// list 是否列表 默认 false/// cacheKey 缓存key/// cacheDisk 是否磁盘缓存Future get(String path, {Map<String, dynamic>? queryParameters,Options? options,bool refresh = false,bool noCache = !CACHE_ENABLE,bool list = false,String cacheKey = '',bool cacheDisk = false,CancelToken? canceltoken,Map<String, dynamic>? data,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}try {print("入参:$path--$data");var response = await dio.get(path,queryParameters: queryParameters,options: requestOptions,cancelToken: canceltoken ?? cancelToken,data: data,);print("+++++++++++++++:$response");return response.data;} catch (e) {print("出现了错误$e");}}/// restful post 操作Future post(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? canceltoken,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}try {var response = await dio.post(path,data: data,queryParameters: queryParameters,options: requestOptions,cancelToken: canceltoken ?? cancelToken,);return response.data;} catch (e) {print("出现了错误:$e");return e;}}/// restful put 操作Future put(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}var response = await dio.put(path,data: data,queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}/// restful patch 操作Future patch(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}var response = await dio.patch(path,data: data,queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}/// restful delete 操作Future delete(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}var response = await dio.delete(path,data: data,queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}/// restful post form 表单提交操作Future postForm(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}var response = await dio.post(path,data: FormData.fromMap(data),queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}/// restful post Stream 流数据Future postStream(String path, {dynamic data,int dataLength = 0,Map<String, dynamic>? queryParameters,Options? options,}) async {Options requestOptions = options ?? Options();requestOptions.headers = requestOptions.headers ?? {};Map<String, dynamic>? authorization = getAuthorizationHeader();if (authorization != null) {requestOptions.headers!.addAll(authorization);}requestOptions.headers!.addAll({Headers.contentLengthHeader: dataLength.toString(),});var response = await dio.post(path,data: Stream.fromIterable(data.map((e) => [e])),queryParameters: queryParameters,options: requestOptions,cancelToken: cancelToken,);return response.data;}
}class DioResponse<T> {/// 消息(例如成功消息文字/错误消息文字)final String message;/// 自定义code(可根据内部定义方式)final int? code;/// 接口返回的数据final T data;/// 需要添加更多/// .........DioResponse({required this.message,required this.data,required this.code,});factory DioResponse.fromJson(Map<String, dynamic> json) => DioResponse(code: json["code"],message: json["message"],data: json["data"],);Map<String, dynamic> toJson() => {"message": message,"data": data,"code": code,};
}
相关文章:
Flutter网络通信-封装Dio
前言 dio 是一个强大的 Dart HTTP 请求库,支持全局配置、Restful API、FormData、拦截器、 请求取消、Cookie 管理、文件上传/下载、超时以及自定义适配器等。 Dio的pub地址为:dio | Dart package 封装要求 能够使用get、post、put、patch、delete、…...
matlab 读取csv
需要跳过第一行表头等信息 1、读取整个文件 csvread(FILENAME)%文件路径 文件名2、指定起始位置 csvread(FILENAME, R, C)%从文件的第R行和第C列开始读取数据 逗号分开3、指定数据范围 csvread(FILENAME, R, C, [R1 C1 R2 C2])%读取从(R1, C1)到(R2, C2)范围内的数据注意&am…...

网络层9——虚拟专用网VPN和网络地址转换NAT
目录 一、为什么有虚拟专用网? 二、如何理解“虚拟专用网”? 三、IP隧道技术实现虚拟专用网 四、网络地址变换 一、为什么有虚拟专用网? 第一,IPv4只有32位,最多有40亿个全球唯一的IP地址数量不够,无法…...

开源科学工程技术软件介绍 – EDA工具KLayout
link 今天向各位知友介绍的 KLayout是一款由德国团队开发的开源EDA工具。 KLayout是使用C开发的,用户界面基于Qt。它支持Windows、MacOS和Linux操作系统。安装程序可以从下面的网址下载: https://www.klayout.de/build.html KLayout图形用户界面&…...
【网络安全】Cookie SameSite属性
未经许可,不得转载。 文章目录 背景CSRF 攻击SameSite 属性StrictLaxNone背景 为了有效防止 CSRF 攻击并保护用户隐私,Chrome 从 51 版本开始引入了 SameSite 属性,专门用于限制第三方 Cookie 的使用,进而减少安全风险。 CSRF 攻击 跨站请求伪造(CSRF)攻击是指恶意网站…...

Linux 命令 | 每日一学,文本处理三剑客之awk命令实践
[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] 0x00 前言简述 描述:前面作者已经介绍了文本处理三剑客中的 grep 与 sed 文本处理工具,今天将介绍其最后一个且非常强大的 awk 文本处理输出工具,它可以非常方便…...

RabbitMQ的工作队列在Spring Boot中实现(详解常⽤的⼯作模式)
上文着重介绍RabbitMQ 七种工作模式介绍RabbitMQ 七种工作模式介绍_rabbitmq 工作模式-CSDN博客 本篇讲解如何在Spring环境下进⾏RabbitMQ的开发.(只演⽰部分常⽤的⼯作模式) 目录 引⼊依赖 一.工作队列模式 二.Publish/Subscribe(发布订阅模式) …...
【web前端笔记】vue3 + vite的前端项目中,使用import.meta.glob()方法实现全局注册组件的通用代码
目录 1.1、如何读取所有文件 1.2、通用代码 1.3、在main.js引入 这篇文章介绍一下,在vue3和vite搭建的项目中,如何将【src/components】目录下所有的【*.vue】文件,当做一个组件全局注册到Vue对象里面。 1.1、如何读取所有文件 在vue3和vite搭建的项目里面,它给我们提…...

保险行业建立知识管理系统:提高效率和安全性的策略
在保险行业,知识管理系统(KMS)的建立对于提高工作效率和保障数据安全性至关重要。保险公司需要在复杂的生态系统中航行,这个生态系统由不断发展的法规、错综复杂的保单和投保人不断变化的需求所定义。以下是一些关键策略ÿ…...

小程序如何完成订阅
小程序如何完成订阅 参考相关文档实践问题处理授权弹窗不再触发引导用户重新授权 参考相关文档 微信小程序实现订阅消息推送的实现步骤 发送订阅消息 小程序订阅消息(用户通过弹窗订阅)开发指南 实践 我们需要先选这一个模板,具体流程参考…...

JS学习日记(jQuery库)
前言 今天先更新jQuery库的介绍,它是一个用来帮助快速开发的工具 介绍 jQuery是一个快速,小型且功能丰富的JavaScript库,jQuery设计宗旨是“write less,do more”,即倡导写更少的代码,做更多的事…...

Uni-APP+Vue3+鸿蒙 开发菜鸟流程
参考文档 文档中心 运行和发行 | uni-app官网 AppGallery Connect DCloud开发者中心 环境要求 Vue3jdk 17 Java Downloads | Oracle 中国 【鸿蒙开发工具内置jdk17,本地不使用17会报jdk版本不一致问题】 开发工具 HBuilderDevEco Studio【目前只下载这一个就…...
Linux的基本用法
Linux的基本用法涵盖多个方面,包括用户登录、系统操作、文件和目录管理、系统工具使用等。以下是对Linux基本用法的详细介绍: 一、用户登录与系统操作 用户登录 普通用户登录:选择用户名并输入密码。超级用户(root)登…...
如何找出爬取网站的来源IP呢?
1.背景 最近网站数据库性能很不稳定,查询性能在某段时间很慢,服务器CPU也很高,平常时间很低,感觉被爬虫恶意搞了,因此我分析了一下最近的nginx访问日志 2.方法 找出访问量最大20个ip [root100 nginx]# cat liuhaih…...
Java爬虫(Jsoup)详解
文章目录 Java爬虫(Jsoup)详解一、引言二、Jsoup 快速入门1、Jsoup 简介1.1、添加依赖 2、解析 HTML 文档2.1、解析 HTML 字符串2.2、从 URL 加载 Document2.3、解析 body 片断 三、数据抽取1、使用 DOM 方法遍历文档3.1、获取元素 2、使用选择器语法查找…...

力扣周赛:第424场周赛
👨🎓作者简介:爱好技术和算法的研究生 🌌上期文章:力扣周赛:第422场周赛 📚订阅专栏:力扣周赛 希望文章对你们有所帮助 第一道题模拟题,第二道题经典拆分数组/线段树都…...

预处理(1)(手绘)
大家好,今天给大家分享一下编译器预处理阶段,那么我们来看看。 上面是一些预处理阶段的知识,那么明天给大家讲讲宏吧。 今天分享就到这里,谢谢大家!!...
利用OpenAI进行测试需求分析——从电商网站需求到测试用例的生成
在软件测试工程师的日常工作中,需求分析是测试工作中的关键步骤。需求文档决定了测试覆盖的范围和测试策略,而测试用例的编写往往依赖于需求的准确理解。传统手工分析需求耗时长,尤其在面对大量需求和复杂逻辑时容易遗漏细节。本文将以电商网…...
深入探索:Scrapy深度爬取策略与实践
标题:深入探索:Scrapy深度爬取策略与实践 引言 在数据驱动的时代,深度爬取成为了获取丰富信息的重要手段。Scrapy,作为一个强大的Python爬虫框架,提供了多种工具和设置来帮助我们实现深度爬取。本文将详细介绍如何在…...

《生成式 AI》课程 第3講:訓練不了人工智慧嗎?你可以訓練你自己
资料来自李宏毅老师《生成式 AI》课程,如有侵权请通知下线 Introduction to Generative AI 2024 Spring 摘要 这一系列的作业是为 2024 年春季的《生成式 AI》课程设计的,共包含十个作业。每个作业都对应一个具体的主题,例如真假难辨的世界…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...

sshd代码修改banner
sshd服务连接之后会收到字符串: SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢? 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头,…...