- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 RestEasy 客户端从 Web 服务器检索实体列表。这是我的代码:
@ApplicationScoped
public class RestHttpClient {
private ResteasyClient client;
@Inject
private ObjectMapper mapper;
@PostConstruct
public void initialize() {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 5000);
HttpClient httpClient = new DefaultHttpClient(params);
this.client = new ResteasyClientBuilder().httpEngine(new ApacheHttpClient4Engine(httpClient)).build();
}
public <E> List<E> getList(final Class<E> resultClass, final String path,
MultivaluedMap<String, Object> queryParams) {
ResteasyWebTarget target = this.client.target(path);
Response response = null;
try {
response = target.queryParams(queryParams).request().get();
String jsonString = response.readEntity(String.class);
TypeFactory typeFactory = TypeFactory.defaultInstance();
List<E> list = this.mapper.readValue(
jsonString, typeFactory.constructCollectionType(ArrayList.class, resultClass));
return list;
} catch (Exception e) {
// Handle exception
} finally {
if (response != null)
response.close();
}
return null;
}
}
它工作正常,但是...如果我快速连续多次调用 getList() 方法,有时我会收到错误“BasicClientConnManager 的使用无效:连接仍然分配”。我可以一遍又一遍地进行相同的调用序列,并且它至少在 90% 的时间内有效,因此这似乎是一个竞争条件。我正在finally block 中关闭Response 对象,这应该足以释放所有资源,但显然事实并非如此。我还需要做什么来确保连接被释放?我在网上找到了一些答案,但它们要么太旧,要么不是 RestEasy 特定的。我正在使用resteasy-client 3.0.4.Final。
最佳答案
我猜你只有一个 RestHttpClient 类实例,并且所有线程/请求都使用同一个对象。
默认的ResteasyClientBuilder不使用连接池。这意味着您一次只能有一个并行连接。在您再次使用 ResteasyClient 之前需要返回请求(错误消息“连接仍然分配”)。您可以通过增加连接池大小来避免这种情况:
ResteasyClientBuilder clientBuilder = new ResteasyClientBuilder();
clientBuilder = clientBuilder.connectionPoolSize( 20 );
ResteasyWebTarget target = clientBuilder.build().target( "http://your.host" );
我正在使用以下 RestClientFactory 来设置新客户端。它为您提供原始响应的调试输出,指定 keystore (客户端 ssl 证书所需)、连接池以及使用代理的选项。
public class RestClientFactory {
public static class Options {
private final String baseUri;
private final String proxyHostname;
private final String proxyPort;
private final String keystore;
private final String keystorePassword;
private final String connectionPoolSize;
private final String connectionTTL;
public Options(String baseUri, String proxyHostname, String proxyPort) {
this.baseUri = baseUri;
this.proxyHostname = proxyHostname;
this.proxyPort = proxyPort;
this.connectionPoolSize = "100";
this.connectionTTL = "500";
this.keystore = System.getProperty( "javax.net.ssl.keyStore" );
this.keystorePassword = System.getProperty( "javax.net.ssl.keyStorePassword" );
}
public Options(String baseUri, String proxyHostname, String proxyPort, String keystore, String keystorePassword, String connectionPoolSize, String connectionTTL) {
this.baseUri = baseUri;
this.proxyHostname = proxyHostname;
this.proxyPort = proxyPort;
this.connectionPoolSize = connectionPoolSize;
this.connectionTTL = connectionTTL;
this.keystore = keystore;
this.keystorePassword = keystorePassword;
}
}
private static Logger log = LoggerFactory.getLogger( RestClientFactory.class );
public static <T> T createClient(Options options, Class<T> proxyInterface) throws Exception {
log.info( "creating ClientBuilder using options {}", ReflectionToStringBuilder.toString( options ) );
ResteasyClientBuilder clientBuilder = new ResteasyClientBuilder();
ResteasyProviderFactory providerFactory = new ResteasyProviderFactory();
RegisterBuiltin.register( providerFactory );
providerFactory.getClientReaderInterceptorRegistry().registerSingleton( new ReaderInterceptor() {
@Override
public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
if (log.isDebugEnabled()) {
InputStream is = context.getInputStream();
String responseBody = IOUtils.toString( is );
log.debug( "received response:\n{}\n\n", responseBody );
context.setInputStream( new ByteArrayInputStream( responseBody.getBytes() ) );
}
return context.proceed();
}
} );
clientBuilder.providerFactory( providerFactory );
if (StringUtils.isNotBlank( options.proxyHostname ) && StringUtils.isNotBlank( options.proxyPort )) {
clientBuilder = clientBuilder.defaultProxy( options.proxyHostname, Integer.parseInt( options.proxyPort ) );
}
// why the fuck do you have to specify the keystore with RestEasy?
// not setting the keystore will result in not using the global one
if ((StringUtils.isNotBlank( options.keystore )) && (StringUtils.isNotBlank( options.keystorePassword ))) {
KeyStore ks;
ks = KeyStore.getInstance( KeyStore.getDefaultType() );
FileInputStream fis = new FileInputStream( options.keystore );
ks.load( fis, options.keystorePassword.toCharArray() );
fis.close();
clientBuilder = clientBuilder.keyStore( ks, options.keystorePassword );
// Not catching these exceptions on purpose
}
if (StringUtils.isNotBlank( options.connectionPoolSize )) {
clientBuilder = clientBuilder.connectionPoolSize( Integer.parseInt( options.connectionPoolSize ) );
}
if (StringUtils.isNotBlank( options.connectionTTL )) {
clientBuilder = clientBuilder.connectionTTL( Long.parseLong( options.connectionTTL ), TimeUnit.MILLISECONDS );
}
ResteasyWebTarget target = clientBuilder.build().target( options.baseUri );
return target.proxy( proxyInterface );
}
}
客户端界面示例:
public interface SimpleClient
{
@GET
@Path("basic")
@Produces("text/plain")
String getBasic();
}
创建客户端:
SimpleClient client = RestClientFactory.createClient(
new RestClientFactory.Options(
"https://your.service.host",
"proxyhost",
"8080",
"keystore.jks",
"changeit",
"20",
"500"
)
,SimpleClient.class
);
另请参阅: http://docs.jboss.org/resteasy/docs/3.0-beta-3/userguide/html/RESTEasy_Client_Framework.html#d4e2049
关于RestEasy客户端: Invalid use of BasicClientConnManager: connection still allocated,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22392961/
我正在尝试向 iOS 应用商店提交更新。我要从 Buzztouch 应用程序转到 Sprite Kit 应用程序。我能够存档 Xcode 项目并提交它。该应用程序的状态为“上传已收到”,但大约一分钟后
我收到了这个奇怪的警告。我不确定是什么原因造成的。 .dia文件扩展名应该表示核心有向图图形文件。我没有添加,应用程序几乎没有用户界面。 最佳答案 我对这个答案并不满意,但我认为它可以帮助人们,直到找
下面用作 Uri 参数的程序集限定字符串在 XAML 中工作,但在代码中使用时会出现错误。 我尝试了各种 UriKind,结果都相同。我该如何解决这个问题? [Test] public void La
我正在开发一个 Angular 应用程序,目的是将其部署到移动设备和 Web 浏览器上。设置表单样式以显示无效输入时,我应该定位 Angular“ng-invalid”类还是 HTML5“:inval
我有一个在 Google App Engine 上运行的应用程序,它是 Android 应用程序的后端。它基本上是 Android 应用程序和在我自己的服务器上运行的 MySQL 数据库之间的桥梁。
我的代码是这样的: func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle,
I need to encrypt using Python with the A256GCM algorithm, and getting back a JWT that I need to
无法成功编译webpack并生成bundle.js文件。据我了解,我的 src_dir 和 dist_dir 变量能够指向正确的路径,但在尝试编译时我仍然始终收到两个错误之一。 配置对象无效。 Web
因此,当我在 postgres 上运行 regexp_matches 时收到一条错误消息,并且无法弄清楚如何通过它。它似乎在 regex101 等 reg_exp 测试站点上运行良好,但不幸的是在实际
这些是我正在使用的导入: import com.novell.ldap.*; import java.io.UnsupportedEncodingException; 我正在尝试进行一个非常简单的密码
在记录器函数的简写情况下,Pylint 提示 Invalid constant name "myprint"(invalid-name)。 # import from utils import get
我试图创建一个HTML输入标签,该标签仅接受以2种格式之一输入的数字,并拒绝所有其他输入。 我只想接受以下格式的数字,包括破折号: 1234-12 和 1234-12-12 注意:不是日期,而是合法的
我一直在尝试使用 Bootstrap 的表单样式处理 AngularJS 的电子邮件验证,并遇到了这个 CSS block 。 input:focus:required:invalid, textar
我正在编写一个程序,以确保我了解如何在 C 中正确实现单向链表。我目前正在哈佛的 CS50 类(class)中学习,并且使用本教程,因为 CS50 人员不解释链接详细列出数据结构:https://ww
此问题与询问同一消息的另一个问题不重复,但在另一个上下文中。这个问题的上下文只是关于上传截图图像和获取消息。 今天,我在将图片上传到 App Store Connect 时收到一条新消息: Inval
我的代码似乎运行良好,但当我滑动以删除 UITableView 中的一行时,应用程序崩溃并显示以下内容: 错误 LittleToDoApp[70390:4116002] *** Terminating
当我尝试发送语音消息时,总是收到无效的url错误。我正在使用Whisper将音频转换为文本,但由于某种原因,我似乎无法将文件传递给Whisper。当我在Java脚本中使用它而不是在TypeScrip中
我正在尝试在 flutter 上对 http 客户端进行单元测试。在模拟 http 和我的存储库类之后: void main() { MockHttpCLient mockHttpCLient;
我正在使用 pandoc 作为一个库,相关的代码片段是: module Lib ( latexDirToTex, latexToTxt ) where import qualified
我正在开发一个(相对简单的)Rails应用程序。我正在使用Devise gem处理用户 session 。每当我导航到localhost:3000/users/sign_in时,我都会看到Devise
我是一名优秀的程序员,十分优秀!