陈斌彬的技术博客

Stay foolish,stay hungry

iOS 搭建 Webservice(原创)

之前公司项目需要做个登陆验证功能,今天总结下在 Webservice 这一块用到的一些知识,包括 HTTP 协议,SOAP 协议,XML 解析。从实际开发中掌握如何使用 Webservice。

首先搞清楚,Webservice 是什么?

其实,就我自己的理解,很简单,Webservice 就是个 API 接口,在服务端写好 API 之后,交给 iOS 客户端来接收数据,信息的处理是交给服务端来解决的。当然,可能是我目前的理解程度不高,只知道这么粗俗的理解 Webservice。下面引出一段官方定义的 Webservice。

Webservice是一个平台独立的,低耦合的,自包含的、基于可编程的 web 的应用程序,可使用开放的 XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。

HTTP 协议 和 SOAP 协议

HTTP 协议的 get 方法和 post 方法

数据的传递,要符合一定的传输协议。http 协议是属于应用层协议,可以用 get 方法或者是 post 方法来访问 web 端。get 方法和 post 方法的区别在于,get 方法的参数暴露在 URL 中,post 方法则是封装起来。下面给出项目中用到的 get 和 post 访问 Webservice 的代码清单:

get 方法:

-(void)startRequest
{
     NSString *strURL = [[NSString alloc] initWithFormat:@"http://www.rjt0663.com/RjtSchool/WebService/User_Login.asmx/login?number=%@&psw=%@",phonenumText.text,pswText.text];
    NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (connection) {

    }
}

post 方法:

-(void)startRequest
{

    NSString *strURL = [[NSString alloc] initWithFormat:@"http://www.rjt0663.com/RjtSchool/WebService/User_Login.asmx/login"];
    NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];
    NSString *post = [NSString stringWithFormat:@"number=%@&psw=%@",phonenumText.text,pswText.text];
    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:postData];

    NSURLConnection *connection = [[NSURLConnection alloc]
                                   initWithRequest:request delegate:self];
    if (connection) {

    }
 }

从上面可以清楚的看到,get 方法和 post 方法在访问时候的区别之处。

SOAP 协议

什么是 SOAP 协议?这个我真的以前都没听过。长这么大只知道 HTTP 是可以用来上网,SOAP 在上网查找相关资料后,后来使用后才知道它其实跟 HTTP 作用也是一样,都是一种传输协议,没文化真是可怕。

官方定义:Soap (Simple Object Access Protocol) 简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在 WEB 上交换结构化的和固化的信息。

在这里,还要了解下 webService 三要素,即 SOAP,WSDL(WebServicesDescriptionLanguage)、UDDI(UniversalDescriptionDiscovery andIntegration) soap 用来描述传递信息的格式, WSDL 用来描述如何访问具体的接口, uddi 用来管理,分发,查询 webService 。

SOAP消息格式:

<SOAP-ENV:Envelope
 各种属性>
<!--百度百科示例-->
 <SOAP:HEADER>
 </SOAP:HEADER>
 <SOAP:Body>
 </SOAP:Body>
</SOAP-ENV:Envelope>
主要在web服务中运用。

下面给出项目中用到的 SOAP 的代码清单:

-(void)startRequest
    {
NSString *strURL = [[NSString alloc] initWithFormat:@"http://www.rjt0663.com/RjtSchool/WebService/User_Login.asmx"];
    NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];

    NSString * envelopeText = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
    "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
    "<soap:Body>"
    "<getStuList xmlns=\"http://www.rjt0663.com/\">"
    "<id>%@</id>"
    "</getStuList>"
    "</soap:Body>"
    "</soap:Envelope>",saveLoginText.text];

    NSData *envelope = [envelopeText dataUsingEncoding:NSUTF8StringEncoding];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:envelope];
    [request setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%d", [envelope length]] forHTTPHeaderField:@"Content-Length"];

    NSURLConnection *connection = [[NSURLConnection alloc]
                                   initWithRequest:request delegate:self];

    if (connection) {

    }
}

这里 web 服务是用 C# 写的。

XML 解析

XML:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。

我最早接触 XML 是在2013年,那时候是学习 JAVA 的时候了解到的,后来发现 XML 很有用,不仅在 iOS 中用到,我后来学习 Android 开发的时候也发现, Android 界面其实是用 XML 来布局的。可见 XML 在实际生活中,一直在展现它的魅力。好了,废话不多说了,回到主题。

从 web 端接收到数据之后,格式为 NSData ,即二进制格式,我们需要经过 XML 解析,得到相应的数据信息。iOS 本身是自带 XML 的,直接添加委托协议 <NSXMLParserDelegate>, 实现需要的委托方法。这里根据实际项目需要,添加属性

@property (strong ,nonatomic) NSString * currentTagName; // 当前标签的名字 ,currentTagName 用于存储正在解析的元素名
@property (strong,nonatomic) NSMutableDictionary * dict; // 用来存储解析的字典型数据

然后在委托方法里,解析数据:

- (void)parserDidStartDocument:(NSXMLParser *)parser {
    //     NSLog(@"开始解析文档");
}

- (void)parserDidEndDocument:(NSXMLParser *)parser{
    //      NSLog(@"结束解析文档");
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {

    //把elementName 赋值给 成员变量 currentTagName
    _currentTagName  = elementName ;
}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    string  = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    if ([string isEqualToString:@""]) {
        return;
    }

if ([_currentTagName isEqualToString:@"ID"]) {
    [_dict setObject:string forKey:@"ID"];
}
if([_currentTagName isEqualToString:@"CreateDate"])
{
    [_dict setObject:string forKey:@"CreateDate"];
}
if ([_currentTagName isEqualToString:@"IsAvailable"]) {
    [_dict setObject:string forKey:@"IsAvailable"];
}
if([_currentTagName isEqualToString:@"StudentName"])
{
    [_dict setObject:string forKey:@"StudentName"];
}
if ([_currentTagName isEqualToString:@"Sex"]) {
    [_dict setObject:string forKey:@"Sex"];
}
if([_currentTagName isEqualToString:@"ParentsID"])
{
    [_dict setObject:string forKey:@"ParentsID"];
}
}

小结

Webservice 在 APP 开发中是几乎都得用到的,很少 APP 应用是不需要 Web 服务的。关于 Webservice 感兴趣的朋友,可以用 C# 在 Visual studio 上面搭建个简单的 Webservice 的 HelloWorld 实例,这样对整个 Webservice 会有更深刻的一个理解。Webservice 功能很强大,学习 Webservice,对分布式系统也有帮助。未来要学习的东西还很多,趁年轻,折腾吧,且学且总结,且行且珍惜!