服务返回对象的设计
服务返回对象的设计
服务层的定义
本文中,服务层指暴露给其他进程调用的外部接口的集合。
英文单词含义
service:服务
response:服务返回对象
request:服务请求对象
服务调用模型
在同一个线程内,现代计算机语言一般会提供异常捕获(try-catch)机制,模型如图1 。
在这个模型中,response只需包含业务数据, 异常情况用异常捕获机制处理。
----------------- request / / response ------------> / service / -------------> /________________/ | | throw exception 图 1
然而,当服务的提供者和消费者不再同一线程,比如远程调用,消费者是无法捕获到服务提供者抛出的异常。
为了能让消费者知道异常情况,response除了包含业务数据外,还应该包含异常情况信息, 模型如图2 。
----------------- request / / response ------------> / service / -------------------> /________________/ | | | response with exception info --------------------------------> 图 2
我推荐的做法是,让response包含两个字段,一个字段指示是否异常, 一个字段承载业务数据(无异常情况下)。
例子(Java)
通用服务返回对象实现
/** * 服务返回对象实现 */ public class ServiceResponse<T extends Serializable> implements Serializable { private static final long serialVersionUID = 1L; /** * 服务返回码
* 这个字段用以指示是否异常。
* 由于“短篇”的限制, 关于对返回码设计的思考,我会写在另一篇文章中。 */ private String code; /** * 业务数据 */ private T data; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
服务接口案例
/** * 文章列表服务接口 */ public interface ArticleListService { ServiceResponse<ListArticleData> listArticle(ListArticleRequest request); }
/** * 文章列表服务业务数据 */ public class ListArticleData implements Serializable { private static final long serialVersionUID = 1L; // TODO 添加业务字段 }
/** * 文章列表服务请求对象 */ public class ListArticleRequest implements Serializable { private static final long serialVersionUID = 1L; // TODO 请求参数字段定义 }