項(xiàng)目調(diào)接口時(shí),使用的框架AFNetworking亲茅,get正常娘纷,post時(shí)Java服務(wù)器收不到parameters信息嫁审,和服務(wù)器調(diào)了小半天才解決,所以做下記錄赖晶,下面貼代碼(只做參考律适,不能直接拿來用):
(底下的評論里有更好的方式解決類似問題)
原本代碼:
-(AFHTTPSessionManager *)configHTTPSessionManagerWith:(NSString *)apiSign{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//請求序列
AFJSONRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
[requestSerializer setValue:@"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
[requestSerializer setValue:apiSign forHTTPHeaderField:@"Api-Sign"];
[requestSerializer setValue:[self readCacheApiToken] forHTTPHeaderField:@"Api-Token"];
requestSerializer.timeoutInterval = kTimeOut;
manager.requestSerializer = requestSerializer;
//響應(yīng)序列
AFJSONResponseSerializer *responseSerialiazer = [AFJSONResponseSerializer serializer];
responseSerialiazer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/css",@"text/xml",@"text/plain", @"application/javascript", @"image/*", nil];
manager.responseSerializer = responseSerialiazer;
DLog(@"httpHeader %@",manager.requestSerializer.HTTPRequestHeaders);
return manager;
}
-(id)POSTHttpRequestAsynUrl:(NSString *)url methodType:(HTTPTYPE)methodType parameters:(NSDictionary *)parameters apiSign:(NSString *)apiSign body:(id)body{
NSString *m = [[RequestMethod sharedMethod] typeMethod:methodType];
if(STRISEMPTY(m)){
return nil;
}
dispatch_group_enter(self.dispathGroup);
AFHTTPSessionManager *manager=[self configHTTPSessionManagerWith:apiSign];
__block NSURLSessionDataTask *postDataTask = nil;
postDataTask = [manager POST:url parameters:parameters
progress:^(NSProgress * _Nonnull uploadProgress) {
// 這里獲取到目前數(shù)據(jù)請求的進(jìn)度
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[self requestSuccess:task responseObject:responseObject methodType:methodType];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[self requestFailure:task error:error methodType:methodType];
}];
[postDataTask resume];
RequestID *rid = [RequestID requestIdWith:methodType object:postDataTask andTag:_nextId++];
[self addRequestId:rid];
return rid;
}
服務(wù)器收不到parameters辐烂,但是在iOS端斷點(diǎn)獲取到的字典parameters為:
{
phone = 15011058118;
platform = ios;
timestamp = 1525419739;
}
不知道什么原因服務(wù)器收不到參數(shù),后來在TCP層數(shù)據(jù)流中得到參數(shù)傳過去的格式為:
{"phone":"15011058118","platform":"ios","timestamp":"1525423788"}捂贿,
(AFNetworking在請求時(shí)會把body里面的字典轉(zhuǎn)換為json格式或者h(yuǎn)ttp字符串格式)
那么收不到參數(shù)的原因就是服務(wù)器接受格式和客戶端傳送格式不一致纠修,由此修改請求傳送格式:
requestSerializer有三種格式:
- AFHTTPRequestSerializer:第一種是普通的http的編碼格式也就是mid=10&method=userInfo&dateInt=20160818,這種格式的厂僧。
- AFJSONRequestSerializer:第二種也是json編碼格式的扣草,也就是編碼成{"mid":"11","method":"userInfo","dateInt":"20160818"}
- AFPropertyListRequestSerializer:第三種沒用過
AFJSONRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
修改為:
AFHTTPRequestSerializer *requestSerializer = [AFHTTPRequestSerializer serializer];
改了之后還不成,
繼續(xù)調(diào)整到最后將body中字典參數(shù)parameters拼接成要傳的字符串格式颜屠,
另外把AFNetworking內(nèi)部 AFURLRequestSerialization.m 文件中的requestBySerializingRequest 方法中
//這一句注釋掉
// [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
//替換為:
NSData *postData = [parameters dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
[mutableRequest setHTTPBody:postData];
調(diào)整后代碼:
#define kTimeOut 35.f
//post請求
-(id)POSTHttpRequestAsynUrl:(NSString *)url methodType:(HTTPTYPE)methodType parameters:(NSDictionary *)parameters apiSign:(NSString *)apiSign body:(id)body{
NSString *m = [[RequestMethod sharedMethod] typeMethod:methodType];
if(STRISEMPTY(m)){
return nil;
}
dispatch_group_enter(self.dispathGroup);
AFHTTPSessionManager *manager=[self configHTTPSessionManagerWith:apiSign];
__block NSURLSessionDataTask *postDataTask = nil;
//將字典轉(zhuǎn)為字符串
NSString *parameterStr = [self dictToStringWithDict:parameters];
postDataTask = [manager POST:url parameters:parameterStr
progress:^(NSProgress * _Nonnull uploadProgress) {
// 這里獲取到目前數(shù)據(jù)請求的進(jìn)度
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//請求成功回調(diào)
[self requestSuccess:task responseObject:responseObject methodType:methodType];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//請求失敗回調(diào)
[self requestFailure:task error:error methodType:methodType];
}];
[postDataTask resume];
RequestID *rid = [RequestID requestIdWith:methodType object:postDataTask andTag:_nextId++];
[self addRequestId:rid];
return rid;
}
-(NSString *)dictToStringWithDict:(NSDictionary *)parameters{
NSDictionary *dic = parameters;
NSString *parameterStr = @"";
for (NSString *key in dic.allKeys) {
parameterStr = [NSString stringWithFormat:@"%@&%@=%@",parameterStr,key,dic[key]];
}
parameterStr = [parameterStr substringFromIndex:1];
return parameterStr;
}
-(AFHTTPSessionManager *)configHTTPSessionManagerWith:(NSString *)apiSign{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//如果服務(wù)器不接受json辰妙,則服務(wù)器收不到body參數(shù),需要改變請求格式(requestSerializer有三種編碼格式)
/*
AFHTTPRequestSerializer:第一種是普通的http的編碼格式也就是mid=10&method=userInfo&dateInt=20160818汽纤,這種格式的上岗。
AFJSONRequestSerializer:第二種也是json編碼格式的,也就是編碼成{"mid":"11","method":"userInfo","dateInt":"20160818"}
AFPropertyListRequestSerializer:第三種沒用過
*/
// AFJSONRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
// if (openHttpsSSL) {
// [manager setSecurityPolicy:[self customSecurityPolicy]];
// }
AFHTTPRequestSerializer *requestSerializer = [AFHTTPRequestSerializer serializer];
[requestSerializer setValue:@"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
[requestSerializer setValue:apiSign forHTTPHeaderField:@"Api-Sign"];
[requestSerializer setValue:[self readCacheApiToken] forHTTPHeaderField:@"Api-Token"];
requestSerializer.timeoutInterval = kTimeOut;
manager.requestSerializer = requestSerializer;
//響應(yīng)序列
AFJSONResponseSerializer *responseSerialiazer = [AFJSONResponseSerializer serializer];
responseSerialiazer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/css",@"text/xml",@"text/plain", @"application/javascript", @"image/*", nil];
manager.responseSerializer = responseSerialiazer;
DLog(@"httpHeader %@",manager.requestSerializer.HTTPRequestHeaders);
return manager;
}
一般用afn中請求時(shí)數(shù)據(jù)傳送requestSerializer用json格式就可以了蕴坪,但是如果服務(wù)器不按常規(guī)道路走不接收json肴掷,就得調(diào)整數(shù)據(jù)傳送格式了,一般調(diào)整幾個(gè)方面:
- parameters信息格式背传,看是不是需要用字典呆瞻;
- 查requestSerializer請求頭的"Content-Type"的值與服務(wù)器協(xié)商一致;
- 看requestSerializer的請求序列化數(shù)據(jù)傳送格式服務(wù)器能接收哪一種径玖。
如果是服務(wù)器返回的數(shù)據(jù)客戶端接收不到痴脾,就要看看responseSerialiazer中的acceptableContentTypes中接收格式是否缺少。