ios - 如何在 iOS 中发送和接收 Web 服务请求和响应?

标签 ios objective-c json web-services

我有一个基于 Apache CXF 的网络服务和 Android 应用程序,它使用下面的代码向它发送请求。

现在我想编写一个简单的 iOS 应用程序,它向同一个 Web 服务发送相同的请求,但来自 iOS 设备。

什么是学习如何使用的良好起点

  1. JSON,
  2. 发送网络服务请求和
  3. 从服务器接收响应

在 Objective-C 中?

SaveLocationAsyncTask.java

public class SaveLocationAsyncTask extends
        AbstractAsyncTask<SaveLocationRequest, SaveLocationResponse> implements
        ISaveLocationAsyncTask {
    private static final String SERVICE_NAME = "SaveLocation";

    public SaveLocationAsyncTask(final IWebServiceTaskHelper aHelper,
            final ILogger aLogger, final IServerUrlStorage aServerUrlStorage) {
        super(aHelper, SaveLocationResponse.class, aLogger,
                new CbResponseParser<SaveLocationResponse>(), aServerUrlStorage,
                SERVICE_NAME);
    }
}

AbstractAsyncTask.java

import android.os.AsyncTask;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.concurrent.ExecutionException;

public class AbstractAsyncTask<Request, Response> extends
        AsyncTask<String, String, Response> implements
        IRequestSender<Request, Response> {

    private static final String REQUEST_AS_JSON_PARAMETER_NAME = "request";
    private IWebServiceTaskHelper helper;
    private Class<Response> responseClass;
    private ILogger logger = null;
    private IResponseParser<Response> responseParser = null;
    private IServerUrlStorage serverUrlStorage;
    private String serviceName;

    public AbstractAsyncTask(final IWebServiceTaskHelper aHelper,
                             final Class<Response> aResponseClass, final ILogger aLogger,
                             final IResponseParser<Response> aResponseParser,
                             final IServerUrlStorage aServerUrlStorage, final String aServiceName) {
        helper = aHelper;
        responseClass = aResponseClass;
        logger = aLogger;
        responseParser = aResponseParser;
        serverUrlStorage = aServerUrlStorage;
        serviceName = aServiceName;
    }

    private String convertToJson(final Object aRequest) {
        final ObjectMapper mapper = new ObjectMapper();
        String json = null;

        try {
            json = mapper.writeValueAsString(aRequest);
        } catch (final JsonProcessingException exception) {
            logger.error(exception);
        }
        return json;
    }

    @Override
    protected Response doInBackground(final String... aParams) {
        logger.debug("doInBackground: " + aParams);
        return new ResponseProcessor<Response>(logger, helper, responseParser,
                responseClass).processResponse(aParams);
    }

    @Override
    public Response sendRequest(final Request aRequest)
            throws InterruptedException, ExecutionException {
        final String json = convertToJson(aRequest);
        final String url = serverUrlStorage.getServerUrl() + serviceName;

        helper.addNameValuePair(REQUEST_AS_JSON_PARAMETER_NAME, json);

        execute(url);

        return get();
    }
}

CbResponseParser.java:

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class CbResponseParser<Response> implements IResponseParser<Response> {

    @Override
    public Response parseResponse(final String aResponseAsString,
                                  final Class<Response> aClass) throws IOException, JsonParseException,
            JsonMappingException {
        final ObjectMapper mapper = new ObjectMapper();
        final Response response = mapper.readValue(aResponseAsString, aClass);

        return response;
    }
}

更新 1(14.06.2014 15:47 MSD):

我试过 DJ_Lectr0 的方法。存在一个问题:服务器找不到网络服务。这是日志输出:

WARNING: No operation matching request path "/mobilecsdemo-server/mobilecsdemo/TestMessage" is found, Relative Path: /, HTTP Method: POST, ContentType: application/json, Accept: application/json,. Please enable FINE/TRACE log level for more details.

beans.xml 片段:

<bean id="TestMessage" class="ru.mycompany.mobilecsdemo.server.services.TestMessage"/>

<jaxrs:server id="services" address="/">
    <jaxrs:serviceBeans>
        <ref bean="TestMessage"/>
    </jaxrs:serviceBeans>
</jaxrs:server>

测试消息 bean :

@Path("/TestMessage")
public class TestMessage {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestMessage.class);

    @POST
    @Produces("text/plain")
    public String processTestMessage(@FormParam("request") final String aRequest)
    {
        try {
            final ObjectMapper mapper = new ObjectMapper();
            final TestMessageRequest request = mapper.readValue(aRequest,
                    TestMessageRequest.class);

            final TestMessageResponse response = new TestMessageResponse();

            response.setResponse(request.getMessage() + " - Response");

            return mapper.writeValueAsString(response);
        } catch (final JsonParseException exception) {
            LOGGER.error("getUserId", exception);
        } catch (final JsonMappingException exception) {
            LOGGER.error("getUserId", exception);
        } catch (final IOException exception) {
            LOGGER.error("getUserId", exception);
        }

        return "";
    }
}

Web 服务 TestMessage 的 URL 似乎是 http://AAA.BBB.CCC.DDD:8080/mobilecsdemo-server/mobilecsdemo/TestMessage

iOS端发送请求代码:

NSDictionary *data = [NSDictionary dictionaryWithObject:@"test sending ios" forKey:@"message"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:kNilOptions error:&error];

NSURL *url = [NSURL URLWithString:@"http://AAA.BBB.CCC.DDD:8080/mobilecsdemo-server/mobilecsdemo/TestMessage"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url cachePolicy:nil timeoutInterval:60];
[req setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[req setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];
[req setHTTPMethod:@"POST"];
[req setHTTPBody:jsonData];
NSString *retStr = [[NSString alloc] initWithData:[NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil] encoding:NSUTF8StringEncoding];

NSLog(@"Response: %@", retStr);

http://AAA.BBB.CCC.DDD:8080/mobilecsdemo-server/mobilecsdemo?_wadl 显示如下:

<application xmlns="http://wadl.dev.java.net/2009/02" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <grammars/>
    <resources base="http://AAA.BBB.CCC.DDD:8080/mobilecsdemo-server/mobilecsdemo/">
        <resource path="/TestMessage">
            <method name="POST">
                <request>
                    <representation mediaType="application/x-www-form-urlencoded">
                        <param name="request" style="query" type="xs:string"/>
                    </representation>
                </request>
                <response>
                    <representation mediaType="text/plain">
                        <param name="result" style="plain" type="xs:string"/>
                    </representation>
                </response>
            </method>
        </resource>
    </resources>
</application>

我试图在 iOS 端将 AcceptContent-Type 更改为 application/x-www-form-urlencoded,但是它没有帮助。

更新 2 (16:36 MSD): 尝试使用 Fiddler2 发送请求并且这个有效:

Fiddler request

更新 3 (17:12 MSD):这个似乎有效。

NSDictionary *data = [NSDictionary dictionaryWithObject:@"test sending ios" forKey:@"message"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:kNilOptions error:&error];

NSURL *url = [NSURL URLWithString:@"http://AAA.BBB.CCC.DDD:8080/mobilecsdemo-server/mobilecsdemo/TestMessage"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url cachePolicy:nil timeoutInterval:60];


[req setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[req setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];
[req setHTTPMethod:@"POST"];

NSString* body = @"request={\"message\":\"message content\"}";
NSData *someData = [body dataUsingEncoding:NSUTF8StringEncoding];

[req setHTTPBody:someData];
NSString *retStr = [[NSString alloc] initWithData:[NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil] encoding:NSUTF8StringEncoding];

NSLog(@"jsonData: %@", jsonData);
NSLog(@"Response: %@", retStr);

最佳答案

这将为您服务。根据您的需要调整 NSDictionary。

NSDictionary *data = [NSDictionary dictionaryWithObject:@"test sending ios" forKey:@"value1"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:kNilOptions error:&error];

    NSURL *url = [NSURL URLWithString:@"http://webserveraddress"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url cachePolicy:nil timeoutInterval:60];
[req setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[req setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];
[req setHTTPMethod:@"POST"];
[req setHTTPBody:jsonData];
NSString *retStr = [[NSString alloc] initWithData:[NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil] encoding:NSUTF8StringEncoding];

NSURLConnection还有一个异步方法:

    [NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *res3, NSData *data, NSError *connectionError) {
NSString *retStr = [[NSString alloc] initWithData:data];
}

正如 Rohan Panchal 在评论中提到的那样 AFNetworking是一个非常棒的第 3 方库,很好地包装了这些方法。我个人更喜欢简单的 NSURLConnection 方法。

关于ios - 如何在 iOS 中发送和接收 Web 服务请求和响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24210726/

相关文章:

ios - 如何使用 alamofire 通过基本身份验证上传图像?

objective-c - NSTextView 的意外行为(因为没有标题栏的 NSWindow?)

iphone - 导航栏 + presentModalViewController

python - 为什么 python json 解码器会抛出带有 UTF-16 BOM 的字符串?

php - 在 php 脚本中访问发布的 Json 数据

javascript - Rails - 通过 AJAX 的 HTTParty 请求

ios - 自动布局 : Location anchors require being paired 崩溃

ios - PFQuery缓存一直为空

ios - 访问位于主屏幕中的文件夹

iOS Facebook SDK : which login system is better?