最近在学习Web System中的Caching技术,其中一种常见的是browser cache,对HTTP GET response应用cache,并通过某些HTTP Header字段控制cache policy。然而,我们web server是基于GWT开发,GWT有自己的一套RPC系统,利用HTTP POST实现client和server之间的异步通讯。这时候问题就来了,用户每一次点击将会触发若干GWT RPC,但browser不会cache HTTP POST response,导致每次点击都要等待后台处理。由于系统中大部分RPC是只读,如果能把browser cache利用起来,不仅可以改善用户体验,而且能减低后台的负载。
那么,很直接的想法是,能否将GWT RPC的POST方式改成GET。这种转换的一个前提是,对于很多的只读RPC,输入参数一般很简单,比如getRequest(int reqId),输入参数就是一个int,完全可以用REST方式将方法名和参数值嵌入URL,这样就能够通过GET发送RPC请求了。
想法成形了,但是如何修改GWT RPC内部机制呢?幸运的是,GWT提供在client和server端都提供了一些API,允许外部系统与RPC进行整合。下面从client和server两个方面来总结如何实现。
Client-side
通过ServiceDefTarget接口,可以设置custom RpcRequestBuilder,实现GET方式的RequestBuilder,并将方法名和参数值嵌入URL,代码段如下:
Server-side
需要实现一个Servlet来接受GET请求。参考如下doGet实现,一部分是从URL中取出方法名和参数值,然后调用真正的RPC方法,另一部分是集成GWT RPC系统。最重要的部分是调用RPC和RPCServletUtils的一些API,将方法返回值encode和serialize成GWT RPC定义的格式,并写入HttpServletResponse。
HTTP GET方式的RPC框架搭好后,需要应用servlet filter设置response HTTP Header的参数来通知browser使用cache并且告诉它cache policy。GWT server library是一个提供GWT和Spring整合的开源库,它提供了一个ResponseHeaderFilter,可以满足需求。最后,在web.xml中定义如下: