Apache 的 HttpClient 在 Swing 应用程序中休眠

发布于 2024-11-16 20:30:47 字数 2651 浏览 3 评论 0原文

我遇到了非常奇怪的问题。编写一个应用程序,通过代理服务器支持从 Internet 下载一些数据,我决定使用 Apache 的 HttpClient 库。 jar 二进制文件已成功添加到 NetBeans 项目中,并且在一个简单的应用程序中执行了以下代码片段(也成功):

DefaultHttpClient httpclient = new DefaultHttpClient();
String proxyHost = "192.168.4.10";
Integer proxyPort = 8080;

HttpHost targetHost = new HttpHost("noaasis.noaa.gov", 80, "http");
HttpGet httpget = new HttpGet("/ptbus/ptbus167");

try {

    HttpHost proxy = new HttpHost(proxyHost, proxyPort);
    httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

    System.out.println("executing request: " + httpget.getRequestLine());
    System.out.println("via proxy: " + proxy);
    System.out.println("to target: " + targetHost);

    HttpResponse response = httpclient.execute(targetHost, httpget);
    HttpEntity entity = response.getEntity();

    System.out.println("----------------------------------------");
    System.out.println(response.getStatusLine());
    Header[] headers = response.getAllHeaders();
    for (int i = 0; i<headers.length; i++) {
        System.out.println(headers[i]);
    }

    System.out.println("----------------------------------------");
    System.out.println(response.getStatusLine());
    if (entity != null) {
        System.out.println("Response content length: " + entity.getContentLength());
    }
    EntityUtils.consume(entity);

}
catch (IOException ex) {

}
finally {
    // When HttpClient instance is no longer needed,
    // shut down the connection manager to ensure
    // immediate deallocation of all system resources
    httpclient.getConnectionManager().shutdown();
}

但是当我尝试在 Swing 应用程序中执行相同的操作时,它不起作用。例如,如下重写默认 Netbeans 桌面应用程序的“about”操作侦听器

@Action
public void showAboutBox() {

    new Thread(new Runnable() {

        public void run() {

            DefaultHttpClient httpclient = new DefaultHttpClient();

            ......
            ......
            ......

            finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }

        }
    }).start();
}

会导致应用程序的执行在

HttpResponse response = httpclient.execute(targetHost, httpget);

Leastways 中的某个位置停止,它永远不会返回...

有趣的是,如果我也在创建任何 Swing 之前将此代码片段放入应用程序的 main 方法中例如,传递了提到的行并收到了 HTTP 响应。然后调用 showAboutBox() 不会再导致问题 - 我也收到 HTTP 响应。

我做错了什么,伙计们?有什么窍门呢?我可以在我的 Swing 应用程序中使用 Apache 的库吗?我无法理解发生了什么,也没有在网上找到与此类似的内容。

感谢您的关注。希望有任何帮助!

I faced very strange problem. Writing an application to download some data from Internet with proxy server support I decided to use Apache's HttpClient library. jar binaries were successfully added to NetBeans project and the following code snippet was executed (successfully too) in a simple application:

DefaultHttpClient httpclient = new DefaultHttpClient();
String proxyHost = "192.168.4.10";
Integer proxyPort = 8080;

HttpHost targetHost = new HttpHost("noaasis.noaa.gov", 80, "http");
HttpGet httpget = new HttpGet("/ptbus/ptbus167");

try {

    HttpHost proxy = new HttpHost(proxyHost, proxyPort);
    httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

    System.out.println("executing request: " + httpget.getRequestLine());
    System.out.println("via proxy: " + proxy);
    System.out.println("to target: " + targetHost);

    HttpResponse response = httpclient.execute(targetHost, httpget);
    HttpEntity entity = response.getEntity();

    System.out.println("----------------------------------------");
    System.out.println(response.getStatusLine());
    Header[] headers = response.getAllHeaders();
    for (int i = 0; i<headers.length; i++) {
        System.out.println(headers[i]);
    }

    System.out.println("----------------------------------------");
    System.out.println(response.getStatusLine());
    if (entity != null) {
        System.out.println("Response content length: " + entity.getContentLength());
    }
    EntityUtils.consume(entity);

}
catch (IOException ex) {

}
finally {
    // When HttpClient instance is no longer needed,
    // shut down the connection manager to ensure
    // immediate deallocation of all system resources
    httpclient.getConnectionManager().shutdown();
}

But when I try to do the same thing in Swing application it doesn't work. For example, rewriting default Netbeans desktop application's "about" action listener as follows

@Action
public void showAboutBox() {

    new Thread(new Runnable() {

        public void run() {

            DefaultHttpClient httpclient = new DefaultHttpClient();

            ......
            ......
            ......

            finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }

        }
    }).start();
}

causes application's execution to stop somewhere in

HttpResponse response = httpclient.execute(targetHost, httpget);

Leastways, it never returns...

The interesting thing is if I also put this code snippet in application's main method just before creating any Swing instance the mentioned line is passed and HTTP response is received. And calling showAboutBox() doesn't cause the problem anymore then - I receive HTTP response too.

What am I doing wrong, guys? What's the trick? Can I use Apache's library in my Swing application? I cannot understand what happens and didn't find anything similar to this spending hours in the net.

Thank You for attention. Hope for any help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

听不够的曲调 2024-11-23 20:30:47

您正在阻止事件调度线程 (EDT)。使用 SwingWorker,如图此处

You're blocking the event dispatch thread (EDT). Use SwingWorker, as shown here.

鸠书 2024-11-23 20:30:47

这只是注释,但它的长度超过了允许的字符数......

为了避免错误的方向,基于 Swing 的 gui 并不关心您运行任何 BackGround 任务,Swing 是单线程的,并且所有到 GUI 的输出都必须在上完成EDT

1/ 将 GUI 的输出包装到 SwingUtilities.invokeLater(),这创建了您自己的 EDT,如果存在 EDT,则将实际任务移动到 EDT 的末尾

2/ 将输出包装到 GUI使用javax.swing.Action

3/或按照trashgod的建议让SwingWorker为该+1工作

that only comments but its longer than allowed number of chars....

to avoid wrong directions, Swing based gui doesn't any care that you running any of BackGround Task, Swing is single threaded and all output to the GUI must be done on EDT

1/ wrap output to the GUI to the SwingUtilities.invokeLater(), that's created your own EDT, and if there EDT exist then move actual task to the ends of the EDT

2/ wrap output to the GUI by using javax.swing.Action

3/ or as trashgod suggested let's SwingWorker works for that +1

左秋 2024-11-23 20:30:47

我通过排除 org.jdesktop.application.SingleFrameApplication 并将 FrameView 替换为 JFrame 解决了该问题。当然,人们会失去 FrameView 的优势,但所有必需的东西都可以通过扩展 JFrame 来实现。

不幸的是,我没有足够的时间来检查为什么 HttpClient 不能与 SingleFrameApplication 一起使用,因此提出的解决方案对我来说是可以接受的。

希望这会帮助其他人。

并感谢 Trashgod 和 mKorbel 的参与。谢谢你们,伙计们。两者都+1。

I solved the problem by excluding org.jdesktop.application.SingleFrameApplication and replacing FrameView by JFrame. Of course, one loses advantages of FrameView but all required things can be implemented extending JFrame.

Unfortunately, I have no enough time to examine why HttpClient doesn't work with SingleFrameApplication so the solution proposed is acceptable for me.

Hope this will help somebody else.

And thanks to trashgod and mKorbel for participation. Thank you, guys. Both +1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文