returnvalue & xwrapper

introduction

背景是WebService,具体实现是XFire。由于某种原因XFire的Fault无法使用,导致只能使用返回值表示成功与错误的情况。举例如下:

实际实现时,发现服务有很多方法,每个方法有各自的返回类型,有部分重复。其次是服务端每个方法都必须try catch,把错误转化为返回值。第三是客户端代码也有重复,每次都要检查是否为null和是否成功。
为了减少重复代码,提供如下方案:

design & implementation

服务器端,抽取公共参数,success,message,分别代表是否成功和错误信息,即类ReturnValue。不同的返回类型创建不同的子类,比如返回类型为int的,创建IntWrapper,继承ReturnValue。如果你想问是否可以用泛型?答案可能是不行,原因是XFire的限制。所以你可能要为List和List创建不同的子类IntegersWrapper和LongsWrapper。
为了客户端读取方便,所有子类中都提供一个getValue()方法,无参,返回类型不同,返回内容即包裹前的返回值。比如IntWrapper,getValue方法返回类型为int,内容为被包裹的int型内容。
其次,XFire需要无参构造函数和setXXX方法。第三,部分方法没有返回,这里创建一个VOID的静态常量,表示正常结果。第四,为了拦截器和服务代码的方便,提供多个构造函数。实际代码大致如下:

以上是返回类型,接下来如何去除过多的try catch的。这里使用AOP的MethodInterceptor,在拦截器中try catch,在异常的时候通过反射取得返回类型(ReturnValue的子类)的构造方法,实例化一个表示错误的对象并返回。核心代码如下:

做了这两部之后,把环境搭起来,配置好Spring,服务代码就可以这样写了:

是不是很简单?

接下来是客户端的处理。客户端通用的逻辑有很多,唯一的不同是调用服务端的哪个方法。抽象出来的辅助类如下:

关注两个方法,一个是getValue,另一个是checkIfSuccess。前者针对有返回值的方法,后者是原先无返回值的方法。客户端使用如下:

经过这样改造后,服务端和客户端的代码冗余都比以前减少很多,降低了维护成本。