记录下这个其实没有多大的意义,新入手 Play 框架的应该直接就是用版本 2 了,只因我们还要系统工作在 Play1 下,所以记下来,估计在 Play2 中已无借鉴作用了。
我们在 Play1 中访问外部 WebService 资源都是用 WS.url(url)
,然后调用它的 get(), post(), delete() 等相对应的 HTTP 请求方法。我们可以系统中所有通过 WS.url() 访问的 URL, 需找到切面,Play 是在哪里为访问的 URL 创建请求的。
看 WS 类的实现,它是一个 PlayPlugin 插件,其中定义了
private static WSImpl wsImpl = null;
来看 Play 是如何获得 WSImple 实现的,WS 插件的初始化方法中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
private synchronized static void init() { if (wsImpl != null) return; String implementation = Play.configuration.getProperty("webservice", "async"); if (implementation.equals("urlfetch")) { wsImpl = new WSUrlFetch(); if (Logger.isTraceEnabled()) { Logger.trace("Using URLFetch for web service"); } } else if (implementation.equals("async")) { if (Logger.isTraceEnabled()) { Logger.trace("Using Async for web service"); } wsImpl = new WSAsync(); } else { try { wsImpl = (WSImpl)Play.classloader.loadClass(implementation).newInstance(); if (Logger.isTraceEnabled()) { Logger.trace("Using the class:" + implementation + " for web service"); } } catch (Exception e) { throw new RuntimeException("Unable to load the class: " + implementation + " for web service"); } } } |
也就是 WSImpl 实现类优先从配置文件中,以 webservice
key 获得,默认为 async
, 也可设置为 urlfetch
。
基于此我们可以在 application.conf 中定义自己的 webservice,如
webservice=utilities.MyAsync
为了保持与默认行为一致,我们让 MyAsync 继承自 WSAsync,然后重写方法
public WSRequest newRequest(String url, String encoding)
这里就是每次访问的 URL,最后调用 super.newRequest(url, encoding) 返回即可。
完整的 MyWSAsync 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package utilities; import play.Logger; import play.libs.WS.WSRequest; import play.libs.ws.WSAsync; public class MyWSAsync extends WSAsync { public WSRequest newRequest(String url, String encoding) { Logger.trace("Access URL: %s", url); //这里输出了所有通过 WS.url() 访问的 URL return super.newRequest(url, encoding); } } |
这样既保持了系统的默认行为,又输出了每次通过 WS.url() 访问的 URL,以便于观察数据。
不总结不知道,一总结吓一跳,在写本文之前我在 MyWSAsync 还使用了返射构造函数来创建要返回的 WSRequest 实例,不知当初怎么想的。