首先感谢下文作者,虽然没看你的内容,但是参考了参数。
最近遇到一个场景:
我作为一个中间件,连接一个没有提供接口的网站,htmlunit模拟html交互,然后把数据返回;对客户来说,我提供了一组标准接口。
因为该网站需要登录,网站登录过程很慢,所以面临两个问题:
第一是WebClient需要重用;
第二是不同的用户的htmlunit的WebClient实例是不能混用的,但是对于单用户来说,可能需要一个WebClient池。
本来想自己寨一个,后来想想细节太多不合适。先看了google guava cache,觉得api太复杂了,完全没看懂;然后又想到10年前看过apache commons pool源代码,查了一下现在是pool2了,完全重写,仔细看了看api,正好是我所需要的。
pool2实际使用很简单,但是官网的例子不太给力。其实只有三个要点(为什么是三点...):
1.Factory
回调。用于对象创建,销毁,验证,防止发呆等。
2.Pool的配置
池的参数。比如最大多少个,最小多少个,最长发呆时间(发呆过长就remove了),等等。
3.Pool实例
实际干活的。
针对我这个例子,首先定义一个factory
- import com.gargoylesoftware.htmlunit.BrowserVersion
- import com.gargoylesoftware.htmlunit.WebClient
- import com.hitoz.auexpress.express.WebClientKey
- import org.apache.commons.pool2.BaseKeyedPooledObjectFactory
- import org.apache.commons.pool2.PooledObject
- import org.apache.commons.pool2.impl.DefaultPooledObject
-
- /**
- * Created by Ken on 2014/5/27.
- */
- class WebClientFactory extends BaseKeyedPooledObjectFactory<WebClientKey, WebClient> {
-
- @Override
- void destroyObject(WebClientKey key, PooledObject<WebClient> p) throws Exception {
- key.worker?.doCleanup(p.object)
- }
-
- @Override
- public WebClient create(WebClientKey key) throws Exception {
- WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8)
- webClient.options.activeXNative = false
- webClient.options.redirectEnabled = true
- webClient.options.useInsecureSSL = true
- webClient.options.javaScriptEnabled = false
- webClient.options.cssEnabled = false
- webClient.options.timeout = 10 * 1000L//10s
- webClient.options.throwExceptionOnFailingStatusCode = false
-
- key.worker?.doInit(key, webClient)
- return webClient
- }
-
- @Override
- public PooledObject<WebClient> wrap(WebClient value) {
- return new DefaultPooledObject<WebClient>(value)
- }
-
- @Override
- void passivateObject(WebClientKey key, PooledObject<WebClient> p) throws Exception {
- p.object?.closeAllWindows()
- }
- }
然后是参数:
- GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig()
- config.setMaxTotal(500) //整个池最大值
- config.setMaxTotalPerKey(5) //每个key的最大
- config.setBlockWhenExhausted(true)
- config.setMinIdlePerKey(0)
- config.setMaxWaitMillis(-1) //获取不到永远等待
- config.setNumTestsPerEvictionRun(Integer.MAX_VALUE) // always test all idle objects
- config.setTestOnBorrow(true)
- config.setTestOnReturn(false)
- config.setTestWhileIdle(false)
- config.setTimeBetweenEvictionRunsMillis(1 * 60000L) //-1不启动。默认1min一次
- config.setMinEvictableIdleTimeMillis(10 * 60000L) //可发呆的时间,10mins
- config.setTestWhileIdle(false) //发呆过长移除的时候是否test一下先
最后是干活的pool
- WebClientFactory webClientFactory = new WebClientFactory()
- GenericKeyedObjectPool<WebClientKey, WebClient> pool = new GenericKeyedObjectPool<WebClientKey, WebClient>(webClientFactory)
ok,从现在开始,只需要操作pool就可以了。
获取对象是
def webClient = pool.borrowObject(key)
使用完毕记得在finally里面
pool.returnObject(key, webClient)
通篇都是groovy代码,加上分号就是java。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。