问题背景:
项目中安卓端使用ksoap2调用webservice的函数获取数据。
在服务端发送给客户端的数据里,除了展示给用户的数据之外,还需要包含一些额外的逻辑代码给客户端。
如:
客户端登录一个用户,客户端发送了用户名aaa+密码111给服务端,那么服务端对aaa+111进行验证后,如果成功,也许返回aaa的详细资料(这是数据),还需要返回额外的信息提示客户端是登录成功?还是失败?
以上情况当然可以通过返回值true/false或者是否null来判断,但是,如果更友好一些,比如提示是用户名不存在?还是密码错误?等等。
所以,客户端与服务端交互的不单单是所需数据,而是用一个包含数据的“结果”。
我使用的方法是,自定义一个Result类,包含必要的逻辑标记(如是否成功?如果出错,错误的提示?是否带数据?)和数据。以下是Result类的部分代码,很简单。
服务端与客户端之间的所有的交互数据,都是一个Result对象,读不到这个对象就认为出现错误。(我将Result使用Json格式传送)。
// 结果类型枚举 public enum ResultType { Error, Success, Failed } public Result() { setValue(null, null, false, null); } public Result(ResultType type, String messgae, boolean hasReturnData, Object[] data) { setValue(type, messgae, hasReturnData, data); } public void setValue(ResultType type, String messgae, boolean hasReturnData, Object[] data) { this.mType = type == null ? ResultType.Error : type; this.mMessage = messgae == null ? "" : messgae; this.mhasReturnData = hasReturnData; this.mData = data; }
如何判断Ksoap2超时?
Ksoap2 某版本之前是不支持超时设定的,有网友通过扩展源码的方式来实现超时。但在我使用的2.6.5版本就已经自带超时功能,具体见:http://www.cnblogs.com/wangsx/p/3393026.html
这不是问题的重点。重点是,在“问题背景”中介绍了C/S交互中对错误类型的判断,但有一种错误还没包括进去:服务器挂了,没有响应。客户端根本就不能从服务器获得任何数据,那还怎么判断是什么类型的错误呢?
这类型的错误我觉得可以分为两种:1、超时(服务器正常,网络情况不好而已) 2、服务器挂了(也可以判断为超时,但是我的项目中要求客户端可以设置连接到的服务器,所以就得判断到底是网络不好?还是当前这台服务器不能用,如IP变了,需要连接另外个服务器?)
网上很多文章说明了如何设置超时,但好像没找到如何判断超时(是超时原因引起的,还是其他原因引起的异常)。下面是我的判断方法:
HttpTransportSE transport = new HttpTransportSE(serviceUrl, 3000); // 获取返回的数据 SoapObject resultso = null; try { /* step.5 使用call方法调用WebService方法 */ transport.call(null, envelope); // 第1个参数一般为null /* step.6 使用getResponse方法获得WebService方法的返回结果 */ if (envelope.getResponse() != null) { // 读取soapObject成功 resultso = (SoapObject) envelope.bodyIn; return so2Result(resultso); } else { resultso = null; return Result.getErrorResult("服务器好像出了一点问题 <( ̄3 ̄)> !"); } } catch (Exception e) { e.printStackTrace(); String msg = e.getMessage(); if (e instanceof java.net.SocketTimeoutException) { msg = "连接服务器超时,请检查网络"; } else if (e instanceof java.net.UnknownHostException) { msg = "未知服务器,请检查配置"; } return Result.getErrorResult(msg);
从上图可以看到,e.detailMessage属性显示了错误消息,所以在网上也有看到网友使用e.detailMessage.contain("after 3000ms")这类型的方法来判断是否超时。异曲同工,但我的好一点吧。哈哈哈~~
最后,结合问题背景,我对服务端与客户端之间的交互方法可以总结为:
1、C/S交互通过一个Result类实现,这个类的对象是包含逻辑标记+数据的对象。并且将Result变换为json格式传输字符串,客户端收不到这个对象就认为是出错。
2、服务端发回的结果,包含数据,以及服务端对这次请求的逻辑处理结果(成功or失败。失败的原因等)
客户端接收到服务端的结果,通过逻辑处理结果来决定表现行为(成功时跳转到详细页展示数据,失败时Toast提示失败)
3、客户端使用ksoap2发起请求,捕获超时异常后,ksoap2返回一个超时类型的Result给客户端自己,来提示超时(或IP错误等无法连接的错误类型)。
这样,该用的提示都有了,在发生错误后用户也知道怎么做。
虽然是很简单的问题,自己想办法解决还是很满足的。加油!