CJNetworkClient 1.4.3

CJNetworkClient 1.4.3

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最后发布2021年10月

Li Chaoqianlcqian维护。



  • dvlproad

CJNetwork

免费API:https://api.you-fire.com/youapi/api/index

一、功能介绍(Feature introduce)

对AFNetworking进行二次封装,增加实现

  • 1、在接口请求中加密、解密
  • 2、上传资源文件(例如上传一张或多张图片等)
  • 3、对请求接口进行缓存数据的功能
  • 4、按指定格式输出请求信息(例如①在控制台查看请求信息、②当脱离调试模式时,你希望能够通过一个alert弹出显示你的log)

包含组件

  • CJNetwork/CJNetworkCommon:AFN请求过程中需要的几个公共方法(包括请求前获取缓存和请求后的成功与失败操作)
  • CJNetwork/AFNetworkingSerializerEncrypt:AFN的请求方法(加解密方法写在Method方法中)
  • CJNetwork/AFNetworkingMethodEncrypt:AFN的请求方法(加解密方法写在Method方法中)
  • CJNetwork/AFNetworkingUploadComponent:AFN的上传请求方法
  • CJNetwork/CJNetworkClient:网络请求的管理类,其他NetworkClient可以通过继承CJNetworkClient来实现,也可以自行实现
  • CJNetwork/CJRequestUtil:原生(非AFN)的请求
  • CJNetwork/CJCacheManager:自己实现的非第三方缓存机制

截图

CJNetwork

二、最少代码的实现自己的网络库 CJNetworkClient

CJNetworkClient类是基于二次封装请求接口类AFHTTPSessionManager+CJSerializerEncrypt.h,基于AFNetworking进行实现的网络库。

1、实现方式

通过直接继承CJNetworkClient并进行初始化,即可使用接口。

2、代码示例

@interface TestNetworkClient : CJNetworkClient

+ (TestNetworkClient *)sharedInstance;

@end



@implementation TestNetworkClient

+ (TestNetworkClient *)sharedInstance {
    static TestNetworkClient *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });
    return _sharedInstance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        AFHTTPSessionManager *cleanHTTPSessionManager = [TestHTTPSessionManager sharedInstance];
        TestHTTPSessionManager *cryptHTTPSessionManager = [TestHTTPSessionManager sharedInstance];
        [self setupCleanHTTPSessionManager:cleanHTTPSessionManager cryptHTTPSessionManager:cryptHTTPSessionManager];
        
        //TestEnvironmentManager *environmentManager = [TestEnvironmentManager sharedInstance];
        [self setupCompleteFullUrlBlock:^NSString *(NSString *apiSuffix) {
            NSString *baseUrl = @"http://xxx.xxx.xxx";
            NSString *mainUrl = [[baseUrl stringByAppendingString:apiSuffix] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
            return mainUrl;
            //return [environmentManager completeUrlWithApiSuffix:apiSuffix];
        } completeAllParamsBlock:^NSDictionary *(NSDictionary *customParams) {
            NSMutableDictionary *allParams = [NSMutableDictionary dictionaryWithDictionary:customParams];
            NSDictionary *commonParams = @{@"phone": @"iPhone6"};
            [allParams addEntriesFromDictionary:commonParams];
            return allParams;
            //return [environmentManager completeParamsWithCustomParams:customParams];
        }];
        
        [self setupResponseConvertBlock:^CJResponseModel *(id responseObject, BOOL isCacheData) {
            NSDictionary *responseDictionary = responseObject;
            CJResponseModel *responseModel = [[CJResponseModel alloc] init];
            responseModel.statusCode = [responseDictionary[@"status"] integerValue];
            responseModel.message = responseDictionary[@"message"];
            responseModel.result = responseDictionary[@"result"];
            responseModel.isCacheData = isCacheData;

            return responseModel;
            
        } checkIsCommonBlock:^BOOL(CJResponseModel *responseModel) {
            return NO;
            
        } getRequestFailureMessageBlock:^NSString *(NSError *error) {
            return @"网络错误";
        }];
        
        NSString *simulateDomain = @"https:///CJDemoDataSimulationDemo";
        [self setupSimulateDomain:simulateDomain];
    }
    return self;
}

如果您想从头开始实现CJNetworkClient,可以通过调用#import "AFHTTPSessionManager+CJSerializerEncrypt.h"来实现,只需要在请求时调用其中的方法即可。

三、基于AFNetworking进行二次封装的请求接口类AFHTTPSessionManager+CJSerializerEncrypt

(1)、功能:

在接口请求中执行加密、解密、缓存、记录日志。

(2)、场景:

为了确保数据安全,我们通常需要对接口请求进行加密和解密操作。原始的AFNetworking并未提供这些功能。因此,我们对AFNetworking进行了二次封装,以便于未来的使用。

(3)、如何使用:

我们提供了两个接口:GET和POST,根据需要调用相应的接口即可。

/**
 *  发起GET请求
 *
 *  @param Url              Url
 *  @param allParams        allParams
 *  @param settingModel     settingModel
 *  @param success          请求成功的回调success
 *  @param failure          请求失败的回调failure
 *
 *  @return NSURLSessionDataTask
 */
- (nullable NSURLSessionDataTask *)cj_getUrl:(nullable NSString *)Url
                                      params:(nullable NSDictionary *)allParams
                                settingModel:(CJRequestSettingModel *)settingModel
                                     success:(nullable void (^)(id _Nullable responseObject))success
                                     failure:(void (^)(NSString *errorMessage))failure;

/**
 *  发起POST请求(是否加密等都通过Serializer处理)
 *
 *  @param Url              Url
 *  @param allParams        allParams
 *  @param settingModel     settingModel
 *  @param success          请求成功的回调success
 *  @param failure          请求失败的回调failure
 *
 *  @return NSURLSessionDataTask
 */
- (nullable NSURLSessionDataTask *)cj_postUrl:(nullable NSString *)Url
                                       params:(nullable id)allParams
                                 settingModel:(CJRequestSettingModel *)settingModel
                                      success:(nullable void (^)(id _Nullable responseObject))success
                                      failure:(void (^)(NSString *errorMessage))failure;

2、文件上传:AFHTTPSessionManager+CJUploadFile

资源文件的上传(例如上传一张或多张图片等)。这里提供两个接口。

①一个是仅上传文件,不对上传过程中的各个时刻信息进行保存;

②一个是除了上传文件外,还对上传过程中的各个时刻信息进行保存(momentInfo:上传请求的各个时刻信息)。这在需要显示进度时经常需要使用。

两个接口分别如下:

/**
 *  上传文件的请求方法:除了上传文件,还对上传过程中的各个时刻信息的进行保存(momentInfo:上传请求的各个时刻信息)
 *  @brief 回调中momentInfoOwner其实就是传进来的fileValueOwner
 *
 *  @param Url              Url
 *  @param params           除fileKey之外的参数
 *  @param fileKey          fileKey
 *  @param fileValueOwner   要操作的上传模型组uploadFileModels的拥有者,fileValueOwner的uploadFileModels有值,而uploadFileModels中的operation和momentInfo是在请求过程中生成的(在执行过程中上传请求的各个时刻信息(正在上传、上传完成)的保存位置会被保存到此拥有者下)
 *  @param uploadMomentInfoChangeBlock          请求成功(上传成功、上传失败)、请求失败以及请求执行过程中的回调,即整个上传过程中各个时刻信息变化的回调(回调中momentInfoOwner其实就是传进来的fileValueOwner,请求成功、请求失败的返回信息都放在其responseModel属性里,且responseModel值在请求成功时候为在getUploadMomentInfoFromResopnseBlock中设置的,而请求失败的responseModel值为nil)
 *  @param getUploadMomentInfoFromResopnseBlock 上传成功后从response中获取该时刻信息的方法(正在上传、以及上传失败的以用默认方法)
 *
 *  @return 上传文件的请求
 */
- (nullable NSURLSessionDataTask *)cj_postUploadUrl:(nullable NSString *)Url
                                             params:(nullable id)params
                                            fileKey:(nullable NSString *)fileKey
                                     fileValueOwner:(nullable CJUploadFileModelsOwner *)fileValueOwner
                        uploadMomentInfoChangeBlock:(nullable void(^)(CJUploadFileModelsOwner * _Nonnull momentInfoOwner))uploadMomentInfoChangeBlock
               getUploadMomentInfoFromResopnseBlock:(nullable CJUploadMomentInfo * _Nonnull (^)(id _Nonnull responseObject))getUploadMomentInfoFromResopnseBlock;

/**
 *  上传文件的请求方法:只是上传文件,不对上传过程中的各个时刻信息的进行保存
 *
 *  @param Url              Url
 *  @param parameters       parameters
 *  @param fileKey          文件参数:有些人会用file,有些人用upfile
 *  @param uploadFileModels 文件数据:要上传的数据组uploadFileModels
 *  @param uploadProgress   uploadProgress
 *  @param success          上传成功执行的回调
 *  @param failure          上传失败执行的回调
 *
 *  @return 上传文件的请求
 */
- (nullable NSURLSessionDataTask *)cj_postUploadUrl:(nullable NSString *)Url
                                             params:(nullable id)parameters
                                            fileKey:(nullable NSString *)fileKey
                                          fileValue:(nullable NSArray<CJUploadFileModel *> *)uploadFileModels
                                           progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
                                            success:(nullable void (^)(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject))success
                                            failure:(nullable void (^)(NSURLSessionDataTask *_Nonnull task, NSError *_Nonnull error))failure;

同时,这里还为UIView增加了分类,实现view直接调用上传接口的功能,该分类名称为UIView+AFNetworkingUpload

4、断点续传

(1) 关于断点续传原理:

首先,如果想要进行断点续传,则需要简单了解一下断点续传的工作机制,在HTTP请求头中,有一个“Range”关键字,通过这个关键字可以告诉服务器返回哪些数据给我。例如:

bytes=500-999		表示从第500字节-第999字节
bytes=500- 		表示从第500字节往后的所有字节

然后我们再根据服务器返回的数据,将得到的data数据拼接到文件后面,就可以实现断点续传了。

1、AFNetworking 3.0+ 实现文件断点下载的方法:直接调用以下方法即可

- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
                                             progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                                          destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
                                    completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler

2、AFNetworking 2.0+ 实现文件断点下载的方法

3、使用NSURLSessionDataTask可以轻松实现断点续传,但有个致命的缺点就是无法进行后台下载,一旦应用程序进入后台,下载便会停止。所以无法满足我们的需求。而NSURLSessionDownloadTask是唯一可以实现后台下载的类,因此我们只能从这个类入手。

当使用NSURLSessionDownloadTask进行下载时,系统会在cache文件夹下创建一个下载路径,路径下会有一个以"CFNetworking"开头的.tmp文件(以下简称"下载文件",以防止混淆),这个就是我们正在下载中的文件。当我们调用了cancelByProducingResumeData:方法后,会得到一个data文件,通过字符串格式化后,发现是一个XML文件,其中包含了关于.tmp文件的一些关键点的描述,包括"Range"、"key"、"下载文件的路径"等等。而原本存在于download文件下的下载文件,则被移动到了系统临时文件夹目录下。而当我们再次进行恢复操作时,下载文件则又被移回到了download文件夹下。

版本介绍/更新记录

  • V0.6.4 2018-12-12
  1. 完善CJNetworkClient,增加回调仅用一个的情况,并优化接口分类;
  • V0.6.1 2018-11-21
  1. 为AFNetworking增加dns处理时的拦截及处理后的并发数控制,并发数控制放在Manager中,而不仅仅是每个请求的settingModel中;
  2. 将并发数的控制和Ulr的拦截独立抽取到Manager的一个分类中,方便问题的调查和以后方案的替换;
  3. 增加记录并发次数的信号量,确保所记录的并发次数的正确性。
  4. 增加一个独立测试并发次数的TestConcurrenModel和一个测试并发次数和拦截的TestConcurrenceManager,用于在测试网络前,测试所添加的并发次数控制方法是否正确。
  • V0.6.0 2018-11-15
  1. 通过不同的加密方式,实现不同的加密接口,并分类;
  2. 优化每个请求的参数设置,避免接口太长,同时提高可扩展性;
  3. 抽取每个请求的结果回调处理,为加入缓存处理做准备;
  4. 导入YYCache以方便使用缓存以及获取整个模型,而不仅仅是模型的数据。并实现CJNetworkCacheManager缓存类。
  5. 增加缓存策略CJNetworkCacheStrategy,支持以下几种实现。
///缓存策略
typedef NS_ENUM(NSUInteger, CJNetworkCacheStrategy) {
    CJNetworkCacheStrategyNoneCache,            /**< 成功/失败的时候,都不使用缓存,直接使用网络数据 */
    CJNetworkCacheStrategyEndWithCacheIfExist,  /**< 成功/失败的时候,如果有缓存,则不用再去取网络实际值 */
    CJNetworkCacheStrategyUseCacheToTransition, /**< 成功/失败的时候,如果有缓存,使用缓存过渡来快速显示,最终以网络数据显示 */
};

并对每个请求结果根据对应的缓存策略,进行结果输出与显示;

  • V0.5.0 2018-09-26
  1. 修改每个请求的回调结果为Model,以提供更全面的信息;
  • V0.4.2 2018-09-13

增加打印加密后的body的值;

  • V0.4.1 2018-09-11

修复0.4.0版本中加密算法不会调用的问题;

增加一个额外的post方法

  • V0.4.0 2018-08-14

请求内部方法改为直接调用AFNetworking方法,使得默认回调处于主线程中。

  • V0.3.1 2018-08-13

增加cjNetworkLog代码,用于有时候调试时可直接弹窗显示,接口请求信息。不过考虑到需要额外开辟内存保存cjNetworkLog,所以该信息默认注释了,需要时,自己去CJNetworkLogUtil中打开即可。

  • V0.3.0 2018-07-06

优化资源文件上传接口,使其更易于理解,参数更少。

作者或联系方式

结束语

欢迎Star、Follow、Fork、Pull Request!