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

时间:2014-06-13 17:21:21

标签: ios objective-c json web-services

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

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

学习如何使用

的好起点
  1. JS​​ON,
  2. 发送网络服务请求和
  3. 从服务器接收回复
  4. 目标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的方法。有一个问题:服务器无法找到Web服务。这是日志输出:

    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>
    

    TestMessage 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 "";
        }
    }
    

    网络服务TestMessage的网址似乎是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);
    

1 个答案:

答案 0 :(得分:2)

这将为您服务。根据您的需要调整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的评论中所提到的,这是一个非常好的第三方库,很好地包装了这些方法。我个人更喜欢裸骨NSURLConnection方法。