AutoNet-Ios 網絡框架(簡單且強大, 增加了攔截器新用法)

AutoNet-Ios(網絡框架, 加入了攔截器概念)

AutoNet封裝了URLSession並使用HandyJSON處理了Json數據。 提供了友好簡易且強大的回調及API去處理繁瑣的網絡請求代碼,加入了攔截器概念可更加方便用戶使用及監控網絡請求, 用戶直接拿到實體類, 是Ios開發網絡應用更加簡單, 只需關注業務即可。

Git地址

1. Ios版本:

ios版AutoNet

2. Android版本:

Android版AutoNet

AutoNet 技術交流羣:

QQ: 141027175

特色

  • 使用簡單、調用方便
  • 加入攔截器概念, 用戶可以更加方便的制定和監控自己的請求
  • 可動態添加和修改頭部
  • 可對請求參數數據進行加密
  • 可自主處理返回的頭部數據
  • 可自主處理返回的body數據
  • 可自定義返回數據的類型
  • 可定義固定、靈活及臨時的域名、頭部信息(優先級: 臨時>靈活>固定。 有效性: 固定 >= 靈活 > 臨時)
  • 支持網絡策略(網絡、本地、先本地後網絡、先網絡後本地)
  • 支持上傳文件和下載文件
  • 可直接獲得上游的發射器, 用戶自己進行操作結果。(eg: 使用zip去合併多個請求等)

Pod依賴

pod 'AutoNet', '~> 1.0.3'

簡易使用demo

image

攔截器介紹

1. 攔截器協議

/**
* 攔截器協議
**/
public protocol Interceptor {
/**
* 攔截器
* chain: 數據載體及回饋
* responseBack: 用於上層向下層反饋數據
**/
func intercept(chain: Chain, responseBack: @escaping AutoNetClosure.responseBack) ->Void
}

2. 事例:

1. AutoNet內部自帶的一個默認日誌攔截器

/**
* 默認日誌實現(用戶可根據自己的需求自定義攔截器去制定)
**/
class DefaultLogInterceptor: Interceptor{
	func intercept(chain: Chain, responseBack: @escaping AutoNetClosure.responseBack) {
		let request = chain.request()
		let url = request.getUrl()
		let method = request.getMethod()
		let params = request.getParam()?.getParams()
		let headers = request.getHeader()?.getHeaders()
		print("-------------------------------------------------------")
		print("---------------------網絡請求日誌------------------------")
		print("-\t請求地址: \(url)")
		print("-\t請求方式: \(method)")
		print("-\t請求頭部參數:")
		if(headers == nil || headers!.count <= 0){
				print("\t\t\t無")
			}else{
				for key in headers!.keys{
					print("\t\t\t\(key): \(headers![key] ?? "")")
				}
		}
		print("-\t請求參數:")
		if(params == nil || params!.count <= 0){
				print("\t\t\t無")
			}else{
				for key in params!.keys{
					print("\t\t\t\(key): \(String(describing: params![key]))")
				}
		}
		
		let bgnTime = Date().timeIntervalSince1970
		chain.proceed(request: request) { (response) in
		print("-\t數據返回:")
		print("\t\t\t\(response ?? "空")")
		
		let endTime = Date().timeIntervalSince1970
		print("-------------耗時:\(endTime - bgnTime)ms----------------")
		print("-------------------------------------------------------")
			responseBack(response)
		}
	}
}	

2. 自定義參數攔截器

final class ParamsInterceptor: Interceptor{
	func intercept(chain: Chain, responseBack: @escaping AutoNetClosure.responseBack) {
		
		var request = chain.request()
		
		let header = request.getHeader()
		// 構造新的頭部數據
		let newHeader = header?.newBuilder(isFollow: true)
		.addHeader(key: "token", value: "a")
		.addHeader(key: "userId", value: "0")
		.build()
		
		let param = request.getParam()
		// 構造新的參數數據
		let newParam = param?.newBuilder(isFollow: true)
		.addParam(key: "params1", value: "value1")
		.addParam(key: "params2", value: "value2")
		.build()
		
		request = request.newBuilder()
		.setHeaders(header: newHeader)
		.setParam(param: newParam).build()
		
		chain.proceed(request: request) { (response) in
			responseBack(response)
		}
	}
}

AutoNet提供出的Error

/**
	 * AutoNet 錯誤分類
	 **/
public enum AutoNetError : Error{
    /**
     * 空數據錯誤(用戶在攔截處理空時,可使用該錯誤)
     */
    case EmptyError
    
    /**
     * 網絡錯誤(當網絡錯誤,AutoNet會自動拋出該錯誤)
     */
    case NetError
    
    /**
     * 自定義錯誤(自定義錯誤, code及message可自定義。 其中json轉換錯誤時AutoNet就會以該形式拋出)
     */
    case CustomError(code: Int, message: String?)

}

使用

1. 初始化

1.1 AutoNetConfig(配置AutoNet的基本配置) 注意: 該配置基本是固定的, eg: 域名, 頭部數據等

  • 設置是否開啓默認的網絡日誌功能
  • 設置默認域名(key: default)
  • 設置多個域名
  • 設置頭部參數
  • 設置攔截器

1.2 AutoNet的初始化操作

AutoNet.getInstance().initAutoNet(config: config)
	.setEncryptionCallback(encryptionCallback: { (flag, encryptionContent) -> String in
		// 可通過key去加密參數
		return encryptionContent ?? ""
	})
	.setHeadsCallback { (flag, headers) in
		// 請求返回頭部數據回調
	}.setBodyCallback { (flag, response, emmit) -> Bool in
		// 自己處理需要返回true
		return false
	}
可以全局修改域名和頭部數據等, eg:
AutoNet.updateOrInsertDomainNames(key: "T##String", value: "T##String")
AutoNet.updateOrInsertHead(key: "T##String", value: "T##Any")

2 常用的閉包介紹

在請求時需要需要關注那些操作就實現那些協議即可, AutoNet會自動判斷及給你想要滴

2.1 數據相關的閉包

/**
* 數據相關回調
**/
public final class AutoNetDataClosure<T> {

	/**
	* 成功回調
	* t: 要返回的實體類對象
	**/
	public typealias onSuccess = (_ t: T) ->Void
	
	/**
	* 失敗回調
	* err: 錯誤
	**/
	public typealias onError = (_ err: Error) ->Void
	
	/**
	* 數據空回調
	**/
	public typealias onEmpty = () -> Void
	
	/**
	* 本地處理回調
	* params: 請求參數
	* emitter: 數據上游發射器
	* @return true: 攔截AutoNet處理, false: 結果交給AutoNet繼續處理(這裏需要注意: 如果本地處理, 需要返回true, 在本地操作中只要返回false, AutoNet分分鐘鍾給你一個AutoNetError.Empty, 因爲AutoNet真的不知道如何處理呢)
	**/
	public typealias optLocalData = (_ params: Dictionary<String, Any>?, _ emitter: RxSwift.AnyObserver<T>) -> Bool
}

2.2 數據轉換相關閉包

/**
* 數據轉換相關回調
**/
public final class AutoNetConvertClosure<T, Z>{

/**
* 數據提前處理轉換
* t: 需要轉換的前提類對象
* emitter: RxSwitf 上游發射器
* @return true: 攔截AutoNet處理, false: 結果交給AutoNet繼續處理
**/
public typealias handlerBefore = (_ t: T, _ emitter: RxSwift.AnyObserver<Z>) -> Bool 
}

2.3 全局數據回調相關閉包

/**
* 網絡數據body回調(全局)
* flag: 請求標識, 可追蹤指定請求
* body: 請求返回body內容
* emitter: 上游發射器(可自定義返回或者個性化處理)
* @return: true=> 攔截AutoNet處理, 交給自己處理, false=> 交於AutoNet自行處理
**/
public typealias body = (_ flag: Any?, _ body: String, _ emitter: AutoNetSimpleAnyObserver) -> Bool

/**
* 網絡頭部數據的返回回調(全局)
* flag: 請求標識, 可追蹤指定請求
* headers: 請求返回的頭部數據
**/
public typealias head = (_ flag: Any?, _ headers: Headers) -> Void

/**
* 參數解密回調
* key: 加密標識, 可根據不同的標識進行多個加密方式
* encryptionContent: 需要加密的數據
* @return: 加密後的數據
**/
public typealias encryption = (_ key: Int, _ encryptionContent: String?) -> String

2.3

/**
* 文件相關的閉包
**/
final class AutoNetFileClosure{
	
	/**
	* 文件進度回調
	* progress: 進度(0~100)
	**/
	public typealias onPregress = (_ progress: Float) -> Void
	
	/**
	* 文件完後回調
	* path: 文件路徑
	**/
	public typealias onComplete = (_ path: String) -> Void 
}

3 網絡調用

// AutoNet請求實例1: 默認返回類型爲AutoNet定義好的AutoNetDefaultResponse(其中返回的數據存在對象內部response裏)
1. AutoNet.getInstance().createNet()
// AutoNet請求實例2: 不需要二次轉換,AutoNet會自動把請求數據進行轉換
2. AutoNet.getInstance().createNet(HandyJSON)
// AutoNet請求實例3: 需要二次轉換自己關心的數據, 需要複寫handlerBefore方法
3. AutoNet.getInstance().createNet(HandyJSON, ExpectResponse)
// 設置請求地址(去除域名)
.setSuffixUrl(suffixUrl: "T##String")
// 設置追蹤標誌
.setFlag(flag: "T##Any")
// 設置請求參數
.setParam(key: "T##String", value: "T##Any")
.setParams(params: Dictionary<String, Any>())
// 發起post請求
.doPost()
// 發起get請求
.doGet()
// 發起put請求
.doPut()
// 發起delete請求
.doDelete()
// 設置使用的域名的key(默認default)
.setDomainNameKey(domainNameKey: "T##String")
// 設置請求方式
.setNetPattern(netPattern: AutoNetPattern.get)
// 設置請求策略
.setNetStrategy(netStrategy: AutoNetStrategy.NET)
// 設置請求類型(JSON/FORM/STREAM/OTHER)
.setReqType(reqType: AutoNetType.JSON)
// 設置返回類型(JSON/FORM/STREAM/OTHER)
.setResType(resType: AutoNetType.JSON)
// 設置額外參數(主要解決動態的拼在URL中的參數。eg: www.xxx.com/news/1, 最後的那個動態的參數1)
.setExtraDynamicParam(extraDynamicParam: "T##String")
// 設置連接超時時間
.setConnectOutTime(outTime: 5000)
// 設置讀取超時時間
.setReadOutTime(readOutTime: 5000)
// 設置寫入超時時間
.setWriteOutTime(writeOutTime: 5000)
// 設置解密的key
.setEncryptionKey(encryptionKey: 0)
// 是否開啓加密功能
.isEncryption(isEncryption: true)
// 設置MediaType
.setMediaType(mediaType: "T##String")
// 下載文件
.setPullFileParams(filePath: "T##String", fileName: "T##String")
// 上傳文件
.setPushFileParams(pushFileKey: "T##String", filePath: "T##String")
// 設置頭部數據(臨時有效)
.setHeads(heads: Dictionary<String, Any>())
// 獲取上游發射者
(1).getObservable()
// 開始請求
(2).start(...)

4 獲取上游並處理(已zip合併爲例, 這裏只是用了兩個, 其實RxSwift提供了好多, 當然還有其他用法,詳情可以看RxSwift的用法)

// json 數據
let first: Observable =  AutoNet.getInstance().createNet(BaseResponse<String>())
.doGet()
.setDomainNameKey(domainNameKey: "test")
.setFlag(flag: "xiaoxige")
.setSuffixUrl(suffixUrl: "/user/test")
.getObservable()
// 百度數據
let second:Observable = AutoNet.getInstance().createNet()
.doGet()
.setFlag(flag: "zhuxiaoan")
.getObservable()

Observable<ContainEntity>.zip(first, second) { (firstEntity, secondEntity) -> ContainEntity in
		// 合併
		let containEntity: ContainEntity = ContainEntity()
		containEntity.setFirst(first: firstEntity.getMessage())
		containEntity.setSecond(second: secondEntity.getResponse())
		return containEntity
	}.subscribe(onNext: { (entity) in
		print("entity.first = \(entity.getFirst()), entity.second = \(entity.getSecond())")
	}, onError: { (erro) in
		print("出錯了 error = \(erro)")
	}, onCompleted: {
	}) {

}

簡單的例子

初始化

let config = AutoNetConfig.Builder()
.setIsOpenDefaultLog(isOpen: true)
.setDefaultDomainName(value: "http://xxx.xxx.com")
.build()
AutoNet.getInstance().initAutoNet(config: config)
	.setBodyCallback { (flag, response, emitter) -> Bool in
		// 全局, 所有請求都會經過這裏
		// 可以在這裏根據統一的字段去判讀code什麼的是成功
		// 如果不成功可以拋出異常,最後會在onError或者onEmpty中回調
		// 可以根據用戶自己業務邏輯處理
		/**
		 * eg: 僞代碼(假設 code:0成功, 1000: 數據爲空, 其他爲錯誤)
		 * let baseResponse = jsonToModel(response)
		 * let code = baseResponse.getCode()
		 * if(code != 0){
		 *      if(code == 1000){
		 *          emmit.onError(AutoNetError.Empty)
		 *       } else {
		 *          emmit.onError(AutoNetError.Custom(code, baseResponse.getMessage))
		 *       }
		 *      return true
		 *  }
		 **/
		
		return false
	}

使用

AutoNet.getInstance().createNet(BaseResponse<String>(), String())
.doGet()
.setDomainNameKey(domainNameKey: "test")
.setSuffixUrl(suffixUrl: "/user/test")
.start(handlerBefore: { (response, emmit) -> Bool in
	let data: String? = response.getData()
	if(data == nil){
		emmit.onError(AutoNetError.EmptyError)
		return true
	}
	emmit.onNext(data!)
	return true
}, optLocalData: nil, onPregress: nil, onComplete: nil, onSuccess: { (entity) in
	print("data = \(entity)")
}, onError: { (error) in
	print("請求錯誤: \(error)")
}) {
	print("請求數據爲空")
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章