这是一个设计/模式问题。我有一项服务现在也需要作为 RESTful Web 服务公开。
在现有代码中,我有一个请求的概念,一套可能的服务操作(策略),任何服务操作的返回都是一个响应对象。这种方法将服务的内部工作与表示媒体(自定义 TCP 服务器、HTTP REST、HTTP SOAP 等)分离。
我现在开始实现一个看起来像这样的 MyServiceRESTfulServlet:
public void doGet(HttpRequest httpRequest, HttpResponse httpResponse) throws ServletException, IOException {
try {
/* Wrap an http servlet request with an adapter which hides all
* the messy details of an HttpRequest and exposes a nice interface
* for working with MyService
*/
IRequest serviceRequest = new MyServiceRESTfulRequest(httpRequest);
/* There's nothing HTTP related in this part, it's the exact same
* code you'd find in other presentation formats. A Response has
* no idea about HTTP, TCP Servers or the like.
*/
Response serviceResponse = dispatchRequest(serviceRequest);
/* A static helper which knows the interface of a Response
* and can translate that into REST-speak for feeding back via
* an HttpServletResponse.
*/
renderRESTfulResponse(serviceResponse, httpResponse);
} catch (Exception e) {
throw new ServletExcetion(e); // Caught by a seperate
// RESTfulErrorServlet
// configured in web.xml
// Rendering an appropriate
// response.
}
}
我的问题是响应可以是目前两种之一:
public enum ResponseKind() {
BINARY, METADATA;
}
对于二进制文件,我的 restful 响应助手将以一种方式呈现,对于元数据,它需要适当地呈现元数据——一个 HTML 表、一个 JSON blob 等。
弄清楚什么类型很容易 - 一个 Response 对象公开一个 getOriginalRequest() ,经过适当的检查后可以转换为一个 MyServiceRESTfulRequest ,它公开一个 .getAcceptablePresentation() - 一个枚举:
public enum RESTPresentationKind() {
HTML, JSON, XML, PROTOBUF_MYSERV_0.1;
}
我怎样才能最好地保持这个渲染代码与 Response 对象分离。毫无疑问,将来可能会有其他类型的反应。照原样,renderRESTfulResponse() 遍历 Request 对象并适当地构建写出数据。它与 Response 接口(我可以接受)非常紧密地耦合,但它也知道要遍历 Request 对象。
我只是不觉得我已经以干净和可维护的方式完成了这一点,因为我拥有这项服务的其余部分。我是每种可能的响应类型和每种可能的响应格式的“特殊外壳”。感觉超级hacky。
给定一个与表示无关的 Request 对象,你能建议任何方法来干净地处理呈现 RESTful 响应吗?