首页 文章 精选 留言 我的

精选列表

搜索[AI编程],共10000篇文章
优秀的个人博客,低调大师

C++并发编程中static变量的问题

在C++中,static表示的是“静态初始化”,由其声明的变量因此也叫作“静态变量”,他们从完成初始化后就一直存在于程序运行空间中(确切地说位于静态变量区),直至程序退出或销毁。 如果按照变量的作用域来划分,静态变量可以分为3类: global variable,即全局变量 static variable with file scope static variable with block scope 前两种不必多说,重点说一下第三种里的“block scope”,它可以表示类内部、函数内部,或者仅仅是由“{}”包括起来的一个code block。 同时,按照静态变量初始化的时机,初始化过程可分为:编译时初始化和加载(运行)时初始化,前者主要发生在静态常量的编译过程中,如程序中“static int a = 3”因为此处3为常量,编译时就能确定,因此这里就发生的是编译时初始化,反之,如果不是编译时初始化,那就必定进行的是加载时初始化。 static变量经常被用来实现单例模式。在设计模式中,单例模式广为人知,即使没有系统学习过设计模式的人很可能也对单例模式不会陌生。设计实现一个单例模式并非难事,但在多线程并发环境下这个问题就貌似不那么简单了。通常来说,一个单例模式的类中都包含一个指向static类实例的指针,并提供一个公共接口返回这个指针以实现对这个实例的调用。因为在程序整个执行周期中,static变量只加载一次,保证了“仅此一个”的事实,如下代码所示: #1 class A { #2 public: #3 static A* getInstance() { #4 if (instance_ == NULL) #5 instance_ = new A(); #6 return instance_; #7 } #8 private: #9 static A* instance_; #10 } #11 //static变量在类外定义 #12 A* A::instance_ = NULL; 如上代码就实现了一个简单的C++单例模式。在单线程程序中,这个单例类没有任何问题,但是在多线程环境下,很容易就能发现方法getInstance中存在race condition,如果线程A运行到了#4,此时instance_为NULL,这时线程B也运行到了这里,instance_此时还未进行构造,它的值还是NULL,那么接下来两个线程将分别执行new A()的操作,本为单例的类实际上并非单例。为了克服这个race condition,人们尝试用加锁、双阶段加锁等方法来解决它,虽然可以实现线程安全性,但毕竟增加了代码量以及复杂性,性能也受到了一定的影响。因此又有了另一种方法来实现单例类,如下代码所示: #1 class A { #2 public: #3 static A* getInstance() { #4 static A instance_; #5 return &instance_; #6 } #7 } 根据static的语义,其只在程序对类A加载时进行一次初始化,全局只有这一个实例。看起来很美好,而且代码更少了。但是这实际上是不对的,对于在编译时进行初始化的static变量,它一定是线程安全的,但是对于这种加载时进行初始化的变量,编译器生成的代码实际上类似这样: static bool initialized = false; static A instance_; if (initialized == false) { initialized = true; instance_ = A(); } return &instance_; 看到了吗?实际上还是会有race condition。那么如何在不加锁、不引入复杂设计的情况下实现单例模式呢?还是要感谢C++的发展,上述代码是在C++11以前的标准中得到的,而在C++11标准中,static的语义实际上已经是线程安全的了。引用C++11标准中的内容: If control enters the declaration concurrently while the variable is being initialized,the concurrent execution shall wait for completion of the initialization. 在网站cppreference中,也有类似的描述: If multiple threads attempt to initialize the same static local variable concurrently,the initialization occurs exactly once(since c++11) 因此,我认为在C++11中,以上代码是可以实现一个线程安全的单例类的。

优秀的个人博客,低调大师

Android 编程下获得应用程序的签名

说明:应用程序的签名被封装在packageInfo 中,所以我们要获得应用程序的签名就需要获得PackageManager 来获得包含有签名信息的packageInfo,再通过packageInfo 获得Signature数组,循环遍历将签名进行拼接。 try { /** 通过包管理器获得指定包名包含签名的包信息 **/ PackageInfo packageInfo = getPackageManager().getPackageInfo( pkgname, PackageManager.GET_SIGNATURES); /******* 通过返回的包信息获得签名数组 *******/ Signature[] signatures = packageInfo.signatures; StringBuilder builder = new StringBuilder(); /******* 循环遍历签名数组拼接应用签名 *******/ for (Signature signature : signatures) { builder.append(signature.toCharsString()); } /************** 得到应用签名 **************/ String signature = builder.toString(); Logger.d("tag", "getSignature:" + signature); } catch (NameNotFoundException e) { 本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/5476894.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android Day05-网络编程之文件上传

Android文件上传实现 分析:利用抓包工具查看文件上传发现,文件上传的请求体十分的复杂,根本难以用 HttpURLConnection、HttpClient来实现。但是用AsyncHttpClient就能很轻易的实现了,只要 在RequestParams对象里面添加一对键值对,值存储文件的路径即可上传了。 AsyncHttpClient文件上传源代码: 记得先要导一下包 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 //创建AsyncHttpClient对象 AsyncHttpClientasyncHttpClient= new AsyncHttpClient(); //创建RequestParams对象,封装要上传的数据或文件。 RequestParamsparams= new RequestParams(); params.put( "music" ,uploadFile); //UploadaFile //执行post方法。 //注意最后一个类new的是参数子类的的实现类AsyncHttpResponseHandler asyncHttpClient.post(getApplicationContext(),servletPath, params, new AsyncHttpResponseHandler(){ @Override public void onSuccess( int statusCode,Header[]headers, byte []responseBody) { if (statusCode== 200 ) { Toast.makeText(getApplicationContext(), "文件上传成功" , 0 ).show(); } else { Toast.makeText(getApplicationContext(), "服务器忙" , 0 ).show(); } } @Override public void onFailure( int statusCode,Header[]headers, byte []responseBody,Throwableerror) { } }); 本文转自屠夫章哥 51CTO博客,原文链接:http://blog.51cto.com/4259297/1676570,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS编程——Objective-C KVO/KVC机制[转]

这两天在看和这个相关的的内容,全部推翻重写一个版本,这是公司内做技术分享的文档总结,对结构、条理做了更清晰的调整。先找了段代码,理解下,网上看到最多的一段的关于KVC的代码 先上代码 1.1.Person类 2.@implementationPerson 3.@synthesizename,age;//属性name将被监视 4.-(void)changeName 5.{ 6.name=@"changeNamedirectly"; 7.} 8.@end 9. 10. 11.2.PersonMonitor类监视了name属性 12.@implementationPersonMonitor 13. 14.-(void)observeValueForKeyPath:(NSString*)keyPath 15.ofObject:(id)object 16.change:(NSDictionary*)change 17.context:(void*)context 18.{ 19.if([keyPathisEqual:@"name"]) 20.{ 21.NSLog(@"changehappen,old:%@new:%@",[changeobjectForKey:NSKeyValueChangeOldKey],[changeobjectForKey:NSKeyValueChangeNewKey]); 22.} 23.} 24.@end 25. 26. 27.3测试代码 28. 29.//初始化被监视对象 30.Person*p=[[Personalloc]init]; 31.//监视对象 32.PersonMonitor*pm=[[PersonMonitoralloc]init]; 33.[paddObserver:pmforKeyPath:@"name"options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld)context:nil]; 34. 35.//测试前的数据 36.NSLog(@"p.nameis%@",p.name); 37. 38.//通过setvalue的方法,PersonMonitor的监视将被调用 39.[psetValue:@"namekvc"forKey:@"name"]; 40. 41.//查看设置后的值 42.NSLog(@"pnamegetbykvcis%@",[pvalueForKey:@"name"]); 43. 44.//效果和通过setValue是一致的 45.p.name=@"namechangeby.name="; 46. 47.//通过person自己的函数来更改name 48.[pchangeName]; 49. 50.结果是 51.输出 52.2011-07-0316:35:57.406Cocoa[13970:903]p.nameisname 53.2011-07-0316:35:57.418Cocoa[13970:903]changehappen,old:namenew:namekvc 54.2011-07-0316:35:57.420Cocoa[13970:903]pnamegetbykvcisnamekvc 55.2011-07-0316:35:57.421Cocoa[13970:903]changehappen,old:namekvcnew:namechangeby.name= 56.最后一次修改是直接修改所以没法产生通知 基本概念 MODEL 主要是英文文档里面经常出现的一些概念,讲解一下,方便英文文档的阅读。 IOS应用开发是遵循MVC设计模式的,Cocoa框架用Object Modeling的规则来规范一个Model的实现。 ObjectModeling有如下几个概念的规定: Entity:表示持有数据的一个实体 Property实体中的成员,分为Attribute和:Relationship Attribute:基本类型的成员,比如:数字、NSString。 Relationship:指向其它Entity的关系型成员,它又有to 1Relationship和to manyRelationship的区别。 AccessorMethod:getter,setter。 举例: 如下是一个部门和员工关系的Model 部门:Department 部门名称(NSString) 成员(NSArray) 部长(Employee) MIC (所有成员) 老王(一个成员) MIB 员工:Employee 名字(NSStirng) 所属部门(Department) 小王 MIC 使用KVC、KVO的优势 通过规定了一组通用的Cocoa命名法则、调用规则等,实现了如下功能: 1)使用一对高度规范化的访问方法,获取以及设置任何对象的任何属性的值。 2)通过继承一个特定的方法,并且指定希望监视的对象及希望监视的属性名称,就能在该对象的指定属性的值发生改变时,得到一个“通知”(尽管这不是一个真正意 义上的通知),并且得到相关属性的值的变化(原先的值和改变后的新值)。 3)通过一个简单的函数调用,使一个视图对象的一个指定属性随时随地都和一个控制器对象或模型对象的一个指定属性保持同步。 KVC 1、概述 KVC是KeyValue Coding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。 当使用KVO、Core Data、CocoaBindings、AppleScript(Mac支持)时,KVC是关键技术。 2、如何使用KVC 关键方法定义在:NSKeyValueCodingprotocol KVC支持类对象和内建基本数据类型。 获取值 valueForKey:,传入NSString属性的名字。 valueForKeyPath:,传入NSString属性的路径,xx.xx形式。 valueForUndefinedKey它的默认实现是抛出异常,可以重写这个函数做错误处理。 修改值 setValue:forKey: setValue:forKeyPath: setValue:forUndefinedKey: setNilValueForKey:当对非类对象属性设置nil时,调用,默认抛出异常。 一对多关系成员的情况 mutableArrayValueForKey:有序一对多关系成员NSArray mutableSetValueForKey:无序一对多关系成员NSSet 3、KVC的实现细节 搜索Setter、Getter方法 这一部分比较重要,能让你了解到KVC调用之后,到底是怎样获取和设置类成员值的。 搜索简单的成员 如:基本类型成员,单个对象类型成员:NSInteger,NSString*成员。 a.setValue:forKey的搜索方式: 首先搜索set<Key>:方法 如果成员用@property,@synthsize处理,因为@synthsize告诉编译器自动生成set<Key>:格式的setter方法,所以这种情况下会直接搜索到。 注意:这里的<Key>是指成员名,而且首字母大写。下同。 上面的setter方法没有找到,如果类方法accessInstanceVariablesDirectly返回YES(注:这是NSKeyValueCodingCatogery中实现的类方法,默认实现为返回YES)。 那么按_<key>,_is<Key>,<key>,is<key>的顺序搜索成员名。 如果找到设置成员的值,如果没有调用setValue:forUndefinedKey:。 b. valueForKey:的搜索方式: 1.首先按get<Key>、<key>、is<Key>的顺序查找getter方法,找到直接调用。如果是bool、int等内建值类型,会做NSNumber的转换。 2.上面的getter没有找到,查找countOf<Key>、objectIn<Key>AtIndex:、<Key>AtIndexes格式的方法。 如果countOf<Key>和另外两个方法中的一个找到,那么就会返回一个可以响应NSArray所有方法的代理集合(collection proxy object)。发送给这个代理集合(collection proxy object)的NSArray消息方法,就会以countOf<Key>、objectIn<Key>AtIndex:、<Key>AtIndexes这几个方法组合的形式调用。还有一个可选的get<Key>:range:方法。 3.还没查到,那么查找countOf<Key>、enumeratorOf<Key>、memberOf<Key>:格式的方法。 如果这三个方法都找到,那么就返回一个可以响应NSSet所有方法的代理集合(collection proxy object)。发送给这个代理集合(collection proxy object)的NSSet消息方法,就会以countOf<Key>、enumeratorOf<Key>、memberOf<Key>:组合的形式调用。 4.还是没查到,那么如果类方法accessInstanceVariablesDirectly返回YES,那么按_<key>,_is<Key>,<key>,is<key>的顺序直接搜索成员名。 5.再没查到,调用valueForUndefinedKey:。 查找有序集合成员,比如NSMutableArray mutableArrayValueForKey:搜索方式如下: 1.搜索insertObject:in<Key>AtIndex:、removeObjectFrom<Key>AtIndex:或者insert<Key>:atIndexes、remove<Key>AtIndexes:格式的方法。 如果至少一个insert方法和至少一个remove方法找到,那么同样返回一个可以响应NSMutableArray所有方法的代理集合。那么发送给这个代理集合的NSMutableArray消息方法,以insertObject:in<Key>AtIndex:、removeObjectFrom<Key>AtIndex:、insert<Key>:atIndexes、remove<Key>AtIndexes:组合的形式调用。还有两个可选实现的接口:replaceObjectIn<Key>AtIndex:withObject:、replace<Key>AtIndexes:with<Key>:。 2.否则,搜索set<Key>:格式的方法,如果找到,那么发送给代理集合的NSMutableArray最终都会调用set<Key>:方法。 也就是说,mutableArrayValueForKey取出的代理集合修改后,用set<Key>:重新赋值回去。这样做效率会差很多,所以推荐实现上面的方法。 3.否则,那么如果类方法accessInstanceVariablesDirectly返回YES,那么按_<key>,<key>的顺序直接搜索成员名。如果找到,那么发送的NSMutableArray消息方法直接转交给这个成员处理。 4.再找不到,调用setValue:forUndefinedKey:。 搜索无序集合成员,如:NSSet。 mutableSetValueForKey:搜索方式如下: 1.搜索add<Key>Object:、remove<Key>Object:或者add<Key>:、remove<Key>:格式的方法,如果至少一个insert方法和至少一个remove方法找到,那么返回一个可以响应NSMutableSet所有方法的代理集合。那么发送给这个代理集合的NSMutableSet消息方法,以add<Key>Object:、remove<Key>Object:、add<Key>:、remove<Key>:组合的形式调用。还有两个可选实现的接口:intersect<Key>、set<Key>:。 2.如果reciever是ManagedObejct,那么就不会继续搜索了。 3.否则,搜索set<Key>:格式的方法,如果找到,那么发送给代理集合的NSMutableSet最终都会调用set<Key>:方法。也就是说,mutableSetValueForKey取出的代理集合修改后,用set<Key>:重新赋值回去。这样做效率会差很多,所以推荐实现上面的方法。 4.否则,那么如果类方法accessInstanceVariablesDirectly返回YES,那么按_<key>,<key>的顺序直接搜索成员名。如果找到,那么发送的NSMutableSet消息方法直接转交给这个成员处理。 5.再找不到,调用setValue:forUndefinedKey:。 KVC还提供了下面的功能 值的正确性核查 KVC提供属性值确认的API,它可以用来检查set的值是否正确、为不正确的值做一个替换值或者拒绝设置新值并返回错误原因。 实现核查方法 为如下格式:validate<Key>:error: 如: -(BOOL)validateName:(id*)ioValueerror:(NSError**)outError { //Thenamemustnotbenil,andmustbeatleasttwocharacterslong. if((*ioValue==nil)||([(NSString*)*ioValuelength]<2]){ if(outError!=NULL){ NSString*errorString=NSLocalizedStringFromTable( @"APerson'snamemustbeatleasttwocharacterslong",@"Person", @"validation:tooshortnameerror"); NSDictionary*userInfoDict= [NSDictionarydictionaryWithObject:errorString forKey:NSLocalizedDescriptionKey]; *outError=[[[NSErroralloc]initWithDomain:PERSON_ERROR_DOMAIN code:PERSON_INVALID_NAME_CODE userInfo:userInfoDict]autorelease]; } returnNO; } returnYES; } 调用核查方法: validateValue:forKey:error:,默认实现会搜索validate<Key>:error:格式的核查方法,找到则调用,未找到默认返回YES。 注意其中的内存管理问题。 集合操作 集合操作通过对valueForKeyPath:传递参数来使用,一定要用在集合(如:array)上,否则产生运行时刻错误。其格式如下: Left keypath部分:需要操作对象路径。 Collectionoperator部分:通过@符号确定使用的集合操作。 Rightkey path部分:需要进行集合操作的属性。 1、数据操作 @avg:平均值 @count:总数 @max:最大 @min:最小 @sum:总数 确保操作的属性为数字类型,否则运行时刻错误。 2、对象操作 针对数组的情况 @distinctUnionOfObjects:返回指定属性去重后的值的数组 @unionOfObjects:返回指定属性的值的数组,不去重 属性的值不能为空,否则产生异常。 3、数组操作 针对数组的数组情况 @distinctUnionOfArrays:返回指定属性去重后的值的数组 @unionOfArrays:返回指定属性的值的数组,不去重 @distinctUnionOfSets:同上,只是返回值为NSSet 示例代码: 效率问题 相比直接访问KVC的效率会稍低一点,所以只有当你非常需要它提供的可扩展性时才使用它。 小结 Kvo是Cocoa的一个重要机制,他提供了观察某一属性变化的方法,极大的简化了代码。这种观察-被观察模型适用于这样的情况,比方说根据A(数 据类)的某个属性值变化,B(view类)中的某个属性做出相应变化。对于推崇MVC的cocoa而言,kvo应用的地方非常广泛。(这样的机制听起来类似Notification,但是notification是需要一个发送notification的对象,一般是notificationCenter,来通知观察者。而kvo是直接通知到观察对象。) 适用kvo时,通常遵循如下流程: 1、注册: -(void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context keyPath就是要观察的属性值,options给你观察键值变化的选择,而context方便传输你需要的数据(注意这是一个void型) 2、实现变化方法: -(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。 是不是很简单?kvo的逻辑非常清晰,实现步骤简单。 说了这么多,大家都要跃跃欲试了吧。可是,在此之前,我们还需要了解KVC机制。其实,知道了kvo的逻辑只是帮助你理解而已,要真正掌握的,不在于kvo的实现步骤是什么,而在于KVC,因为只有符合KVC标准的对象才能使用kvo(强烈推荐要使用kvo的人先理解KVC)。 KVC是一种间接访问对象属性(用字符串表征)的机制,而不是直接调用对象的accessor方法或是直接访问成员对象。 key就是确定对象某个值的字符串,它通常和accessor方法或是变量同名,并且必须以小写字母开头。Key path就是以“.”分隔的key,因为属性值也能包含属性。比如我们可以person这样的key,也可以有key.gender这样的key path。 获取属性值时可以通过valueForKey:的方法,设置属性值用setValue:forKey:。与此同时,KVC还对未定义的属性值定义了valueForUndefinedKey:,你可以重载以获取你要的实现(补充下,KVC定义载NSKeyValueCoding的非正式协议里)。 在O-C 2.0引入了property,我们也可以通过.运算符来访问属性。下面直接看个例子: @property NSInteger number; instance.number =3; [instance setValue:[NSNumber numberWithInteger:3] forKey:@"number"]; 注意KVC中的value都必须是对象。 以上介绍了通过KVC来获取/设置属性,接下来要说明下实现KVC的访问器方法(accessor method)。Apple给出的惯例通常是: -key:,以及setKey:(使用的name convention和setter/getter命名一致)。对于未定义的属性可以用setNilValueForKey:。 至此,KVC的基本概念你应该已经掌握了。之所以是基本,因为只涉及到了单值情况,kvc还可以运用到对多关系,这里就不说了,留给各位自我学习的空间 接下来,我们要以集合为例,来对掌握的KVC进行一下实践。 之所以选择array,因为在ios中,array往往做为tableview的数据源,有这样的一种情况: 假设我们已经有N条数据,在进行了某个操作后,有在原先的数据后多了2条记录;或者对N中的某些数据进行更新替换。不使用KVC我们可以使用reloadData方法或reloadRowsAtIndexPaths。前一种的弊端在于如果N很大消耗就很大。试想你只添加了几条数据却要重载之前N数据。后一种方法的不足在于代码会很冗余,你要一次计算各个indexPath再去reload,而且还要提前想好究竟在哪些情况下会引起数据更新, 倘若使用了KVC/kvo,这样的麻烦就迎刃而解了,你将不用关心追加或是更新多少条数据。 下面将以添加数据为例,说明需要实现的方法: 实现insertObject:inKeyAtIndex:或者insertKey:atIndexes。同时在kvo中我们可以通过change这个dictionary得知发生了哪种变化,从而进行相应的处理。 KVC就是一种通过字符串去间接操作对象属性的机制, 访问一个对象属性我们可以person.age也可以通过KVC的方式[person valueForKey:@"age"] keypath就是属性链式访问如person.address.street有点象java里面的pojoognl表达式子类的 假如给出的字符串没有对象的属性 会访问valueForUndefineKey方法 默认实现是raise一个异常但你可以重写这个方法, setValue的时候也是一样的道理 key path accounts.transactions.payee would return an array with all the payee objects, for all the transactions, in all the accounts. 当设置一个非对象属性为nil时会抛异常, 但你也可以重写方法 KVC就是一个在语言框架层面实现的观察者模式 通过KVC的方式修改属性时,会主动通知观察者 from:http://blog.csdn.net/catandrat111/article/details/8556455 欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处! 本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/p/3272866.html ,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android Day05-网络编程之提交数据

Android网络:HTTP之利用HttpURLConnection访问网页、获取网络图片实例 (附源码) http://blog.csdn.net/yanzi1225627/article/details/22222735 一、提交数据 手机App向服务器提交数据原理与web页面向服务器提交数据的原理是一样的,都是依赖于Http协 议,只是使用的API不一样而已。 Android最常见的提交数据的类有3个:HttpURLConnection、HttpClient、AsyncHttpClient,它 们都分get和post两种提交方式其中HttpURLConnection是SDK自带的类;HttpClient本来是第3方开源 项目,不过被google纳入了SDK;AsyncHttpClient是一个使用起来特别简单的第3方开源项目,需要去 GitHub下载jar包。 我将6种不同的提交方式整合到了一起,App UI界面如下: 以下是6种不同方式提交数据的源代码: 1)URLGet方式 URLGet的特点就是直接将请求参数拼接到提交地址的后面 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 //1-以URLGet方式登陆 public void loginByURLGet(){ new Thread(){ public void run(){ //如果用户名和账号不为空 if (checkEmpty()){ //已经得到用户名密码,直接拿过来用就行了。 StringservletPath= "http://192.168.17.71/QQCenter/login" ; //拼接地址(*********重要步骤*************) StringurlPath=servletPath+ "?username=" +username + "&password=" +password; try { //第1步:创建URL URLurl= new URL(urlPath); //第2步:创建HttpURLConnection连接 HttpURLConnectionconn=(HttpURLConnection)url .openConnection(); //第3步:设置请求参数 conn.setRequestMethod( "GET" ); conn.setConnectTimeout( 5 ); //第4步:得到响应码 int responseCode=conn.getResponseCode(); //第5步:判断响应码 if (responseCode== 200 ){ //获取服务器端的返回信息 InputStreamin=conn.getInputStream(); Stringcontent=NetUtils.readStream(in); showToast(content); System.out.println( "URLGet方式登陆" ); } else { showToast( "服务器找不到资源" ); } } catch (Exceptione){ e.printStackTrace(); showToast( "服务器忙!!!" ); } } } }.start(); } 2)URLPost方式 URLPost的特点就是将提交的参数通过流写到服务器,相比URLGet方式,要多设两个头信 息,且设置向服务器写入流的权限。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public void loginByURLPost(){ new Thread(){ public void run(){ //如果用户名和账号不为空 if (checkEmpty()){ //已经得到用户名密码,直接拿过来用就行了。 StringservletPath= "http://192.168.17.71/QQCenter/login" ; //要写入请求体的参数(*******关键步骤********) Stringdata= "username=" +username+ "&password=" +password; try { //第1步:创建URL URLurl= new URL(servletPath); //第2步:创建HttpURLConnection连接 HttpURLConnectionconn=(HttpURLConnection)url .openConnection(); //第3步:设置请求参数 conn.setRequestMethod( "POST" ); conn.setConnectTimeout( 5 ); //注意设置两个请求头信息(*****关键步骤*****) conn.setRequestProperty( "Content-Type" , "application/x-www-form-urlencoded" ); conn.setRequestProperty( "Content-Length" ,data.length() + "" ); //设置向服务器写入流的权限(****关键步骤***) conn.setDoOutput( true ); //得到输出流向服务器发送请求体数据(*****关键步骤******) OutputStreamout=conn.getOutputStream(); out.write(data.getBytes()); out.close(); //第4步:得到响应码 int responseCode=conn.getResponseCode(); //第5步:判断响应码 if (responseCode== 200 ){ //获取服务器端的返回信息 InputStreamin=conn.getInputStream(); Stringcontent=NetUtils.readStream(in); showToast(content); in.close(); System.out.println( "以URLPost方式登陆" ); } else { showToast( "服务器找不到资源" ); } } catch (Exceptione){ e.printStackTrace(); showToast( "服务器忙!!!" ); } } } }.start(); } 3)ClientGet方式 HttpClient这个类,相比HttpURLConnection语法上有很多的不同。将请求和响应单独封装 成了一个类。获取服务器数据是经过多层包装的,需要先得到数据的实体HttpEntity,根据实体 再得到服务器的输出流。 android DefaultHttpClient 超时 http://blog.csdn.net/howlaa/article/details/17437463 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public void loginByClientGet(){ new Thread(){ public void run(){ //如果用户名和账号不为空 if (checkEmpty()){ //已经得到用户名密码,直接拿过来用就行了。 StringservletPath= "http://192.168.17.71/QQCenter/login" ; //拼接地址 Stringdata= "username=" +username+ "&password=" +password; Stringurl=servletPath+ "?" +data; try { //第1步:创建HttpClient对象 HttpClientclient= new DefaultHttpClient(); //第2步:创建get请求对象 HttpGetget= new HttpGet(url); //第3步:执行get请求对象,得到response对象。 HttpResponseresponse=client.execute(get); //第4步:得到响应码 int responseCode=response.getStatusLine() .getStatusCode(); //第5步:判断响应码 if (responseCode== 200 ){ //获取服务器端的返回信息与URL不同,先获取的是数据实体。 HttpEntityentity=response.getEntity(); //从数据实体中得到服务的输出流 InputStreamin=entity.getContent(); Stringcontent=NetUtils.readStream(in); showToast(content); in.close(); System.out.println( "以ClientGet方式登陆" ); } else { showToast( "服务器找不到资源" ); } } catch (Exceptione){ e.printStackTrace(); showToast( "服务器忙!!!" ); } } } }.start(); } 4)ClientPost方式 相对ClientGet方式,这种方式提交数据稍微有些复杂。创建post请求的实体数据时,要经 过多层包装。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public void loginByClientPost(){ new Thread(){ public void run(){ //如果用户名和账号不为空 if (checkEmpty()){ //已经得到用户名密码,直接拿过来用就行了。 StringservletPath= "http://192.168.17.71/QQCenter/login" ; //请求体数据 Stringdata= "username=" +username+ "&password=" +password; Stringurl=servletPath; try { //第1步:创建HttpClient对象 HttpClientclient= new DefaultHttpClient(); //第2步:创建post请求对象 HttpPostpost= new HttpPost(url); //将请求参数封装到实体------过程稍微有点复杂 List<NameValuePair>listPairs= new ArrayList<NameValuePair>(); //注意name的值与服务器应统一 NameValuePairpair1= new BasicNameValuePair( "username" ,username); NameValuePairpair2= new BasicNameValuePair( "password" ,password); listPairs.add(pair1); listPairs.add(pair2); HttpEntitypostDataEntity= new UrlEncodedFormEntity( listPairs); post.setEntity(postDataEntity); //第3步:执行post请求 HttpResponseresponse=client.execute(post); //第4步:得到状态码 int statusCode=response.getStatusLine() .getStatusCode(); //第5步:判断状态码 if (statusCode== 200 ){ //得到数据的实体 HttpEntityrespEntity=response.getEntity(); //从实体得到流 InputStreamin=respEntity.getContent(); Stringcontent=NetUtils.readStream(in); showToast(content); in.close(); System.out.println( "以ClientPost方式登陆" ); } else { showToast( "找不到资源" ); } } catch (Exceptione){ e.printStackTrace(); showToast( "服务器忙!!!" ); } } }; }.start(); } 5)AsyncHttpClientGet方式 在使用这个类之前,去GitHub下载并导一下这个包com.loopj.android.http到项目的src目 录下。使用AsyncHttpClient还有一个十分爽的地方,就是这个类不需要使用在子线程中,那么 也就可以直接更新UI。请求地址就直接写servlet了,也不用拼接参数了,因为参数都写在了 RequestParams对象中去了。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public void loginByAsyncHttpClientGet(){ //如果用户名和账号不为空 if (checkEmpty()){ //已经得到用户名密码,直接拿过来用就行了。 StringservletPath= "http://192.168.1.109/QQCenter/login" ; try { AsyncHttpClientasyncHttpClient= new AsyncHttpClient(); //创建get请求参数 RequestParamsparams= new RequestParams(); params.put( "username" ,username); params.put( "password" ,password); asyncHttpClient.get(getApplicationContext(),servletPath,params, new AsyncHttpResponseHandler(){ //请求成功 @Override public void onSuccess( int statusCode,Header[]headers, byte []responseBody){ if (statusCode== 200 ) { //得到服务器的返回值 Stringcontent= new String(responseBody); Toast.makeText(getApplicationContext(),content, 0 ).show(); System.out.println( "AsyncHttpClientGet方式登陆" ); } else { Toast.makeText(getApplicationContext(), "找不到资源" , 0 ).show(); } } @Override public void onFailure( int statusCode,Header[]headers, byte []responseBody,Throwableerror){ //TODOAuto-generatedmethodstub } }); } catch (Exceptione){ e.printStackTrace(); showToast( "服务器忙!!!" ); } } } 6)AsyncHttpClientPost方式 和AsyncHttpClientGet方式相差无几,调用的是post方法。其它的一样 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public void loginByAsyncHttpClientPost(){ //如果用户名和账号不为空 if (checkEmpty()){ //已经得到用户名密码,直接拿过来用就行了。 StringservletPath= "http://192.168.17.71/QQCenter/login" ; try { //创建AsyncHttpClient对象 AsyncHttpClientasyncHttpClient= new AsyncHttpClient(); RequestParamsparams= new RequestParams(); params.put( "username" ,username); params.put( "password" ,password); asyncHttpClient.post(getApplicationContext(),servletPath,params, new AsyncHttpResponseHandler(){ @Override public void onSuccess( int statusCode,Header[]headers, byte []responseBody){ if (statusCode== 200 ) { //得到服务器的返回值 Stringcontent= new String(responseBody); Toast.makeText(getApplicationContext(),content, 0 ).show(); System.out.println( "AsyncHttpClientPost方式登陆" ); } else { Toast.makeText(getApplicationContext(), "找不到资源" , 0 ).show(); } } @Override public void onFailure( int statusCode,Header[]headers, byte []responseBody,Throwableerror){ } }); } catch (Exceptione){ e.printStackTrace(); showToast( "服务器忙!!!" ); } } } 提交数据的方式,这么多种,怎么使用呢? HttpClient已被AsyncHttpClient所替代,一般开发都用后者。但是遇到特殊需求时,还是需要 用到最基础的HttpURLConnection,因为它可以设置请求头的参数信息。 二、提交数据时中文乱码问题 待进一步理解 本文转自屠夫章哥 51CTO博客,原文链接:http://blog.51cto.com/4259297/1676565,如需转载请自行联系原作者

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册