Java作为使用Swing的外部组件:主线程永远不会退出
我试图在另一个程序中使用Java组件。该程序是一个在Tomcat上运行的Web应用程序,我的组件使用Swing打开Web浏览器。系统会提示用户导航到特定页面,并使用JFrame上的控件将该页面以HTML格式保存在本地。这个本地保存的文件稍后将用于进一步的细化。 问题是,当从Eclipse执行时,我的代码工作时没有缺陷。但是,当我在Tomcat上运行的应用程序中使用该组件时,它没有正确运行。此时会出现窗口,导航正在工作,检索数据时不会出现问题。问题是,主应用程序(在Tomcat上运行的应用程序)必须在组件(Java)完成其工作后恢复执行。显然,有些地方出了问题,因为web应用程序只是挂起,永远不会继续 在我的组件中,我使用两个类:浏览器和助手。该浏览器基于DJ NativeSwing库,包含初始化和显示简单web浏览器的逻辑。Helper类为我提供了一个“前端”方法,允许我在自己的线程中执行浏览器。我使用SwingUtilities.invokeAndWait而不是invokeLater,因为我不太清楚如何使用wait()和notify()。我试过了,但失败了 总结代码,它看起来像这样:Java作为使用Swing的外部组件:主线程永远不会退出,java,swing,tomcat,Java,Swing,Tomcat,我试图在另一个程序中使用Java组件。该程序是一个在Tomcat上运行的Web应用程序,我的组件使用Swing打开Web浏览器。系统会提示用户导航到特定页面,并使用JFrame上的控件将该页面以HTML格式保存在本地。这个本地保存的文件稍后将用于进一步的细化。 问题是,当从Eclipse执行时,我的代码工作时没有缺陷。但是,当我在Tomcat上运行的应用程序中使用该组件时,它没有正确运行。此时会出现窗口,导航正在工作,检索数据时不会出现问题。问题是,主应用程序(在Tomcat上运行的应用程序)必
import javax.swing.SwingUtilities;
import chrriis.dj.nativeswing.swtimpl.NativeInterface;
public class Helper {
public String Browse() {
Browser vb = new Browser();
try {
Browser.log("This is Helper, now initiating.");
NativeInterface.open();
Thread th = new Thread(vb);
Browser.log("Helper is invoking thread...");
SwingUtilities.invokeAndWait(th);
NativeInterface.runEventPump();
Browser.log("Thread exited! Back to Helper!");
System.out.println(vb.getData());
Browser.log("Returning data to caller: \n" + vb.getData());
return vb.getData();
}catch (Exception ex) {
ex.printStackTrace();
Browser.log("MainFail: " + ex.getMessage());
return ex.getMessage();
}
}
和浏览器类:
import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import chrriis.dj.nativeswing.NativeSwing;
import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;
public class Browser extends JFrame implements ActionListener, Runnable {
private static final long serialVersionUID = 1L;
private JButton btn;
private JWebBrowser webBrowser;
private JPanel panel;
private String data = "";
public static void log(String s) {
try {
BufferedWriter ostr = new BufferedWriter(new FileWriter("F:/java_out.log", true));
Date dt = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("hh:mm:ss");
String str = formatter.format(dt) + "\t -> " + s + "\n";
ostr.write(str);
ostr.close();
} catch(Exception ex) {
System.out.println("Logger: " + ex.getMessage());
}
}
public Browser() {
Browser.log("Initializing...");
NativeSwing.initialize();
NativeInterface.open();
panel = new JPanel();
btn = new JButton();
btn.setText("Save Page");
btn.addActionListener(this);
btn.setMargin(new Insets(5, 5, 5, 5));
VisureBrowser.log("Button is ready!");
JPanel webBrowserPanel = new JPanel(new BorderLayout());
webBrowserPanel.setBorder(BorderFactory.createTitledBorder("Navigate and save"));
webBrowser = new JWebBrowser();
webBrowser.setButtonBarVisible(true);
webBrowser.setMenuBarVisible(false);
webBrowser.setLocationBarVisible(true);
VisureBrowser.log("Panel is ready!");
this.setTitle("Simple Browser");
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.setSize(800, 600);
this.setLayout(new BorderLayout());
this.setLocationByPlatform(true);
this.setLocationRelativeTo(null);
VisureBrowser.log("Frame is ready!");
this.add(btn, BorderLayout.BEFORE_FIRST_LINE);
btn.setVisible(true);
webBrowserPanel.add(webBrowser, BorderLayout.CENTER);
webBrowser.setVisible(true);
this.add(webBrowserPanel, BorderLayout.CENTER);
panel.setVisible(true);
this.setVisible(true);
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
Browser.log("Constructor: " + e.getMessage());
Browser.log(e.getStackTrace().toString());
e.printStackTrace();
}
Browser.log("Look and Feel ready as well! Off to work...");
}
public String getData() {
return this.data;
}
public void close() {
WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
}
public void run() {
Browser.log("Navigating to the index page...");
webBrowser.navigate("http://www.google.com/");
Browser.log("Navigation successful!");
}
@Override
public void actionPerformed(ActionEvent e) {
Browser.log("An action has been performed!");
Object src = e.getSource();
if (src.equals(btn)) {
try {
Browser.log("Getting data...");
this.data = webBrowser.getHTMLContent();
Browser.log("Closing...");
this.close();
} catch( Exception ex) {
Browser.log("ClickFail: " + ex.getMessage());
Browser.log(ex.getStackTrace().toString());
}
}
}
}
我从Eclipse获得的输出是:
12:28:54 -> Initializing...
12:28:55 -> Button is ready!
12:28:55 -> Panel is ready!
12:28:55 -> Frame is ready!
12:28:56 -> Look and Feel ready as well! Off to work...
12:28:56 -> This is Helper, now initiating.
12:28:56 -> Helper is invoking thread...
12:28:56 -> Navigating to the index page...
12:28:56 -> Navigation successful!
12:29:04 -> An action has been performed!
12:29:04 -> Getting data...
12:29:04 -> Closing...
12:29:06 -> Thread exited! Back to Helper!
12:29:06 -> Returning data to caller:
.....here comes all the data.....
我在Tomcat内部执行时得到的数据如下:
12:28:54 -> Initializing...
12:28:55 -> Button is ready!
12:28:55 -> Panel is ready!
12:28:55 -> Frame is ready!
12:28:56 -> Look and Feel ready as well! Off to work...
12:28:56 -> This is Helper, now initiating.
12:28:56 -> Helper is invoking thread...
12:28:56 -> Navigating to the index page...
12:28:56 -> Navigation successful!
12:29:04 -> An action has been performed!
12:29:04 -> Getting data...
12:29:04 -> Closing...
是的,我使用了相同的行,但是输出是这样的,它只持续到结束行。
我没有想到的是窗口关闭和主活动恢复之间的延迟:每次运行大约2-3秒。我认为它与辅助(GUI)线程没有正确退出有关,但我不知道如何继续
任何帮助都将不胜感激!:) 你做错了
Tomcat是一个web应用服务器,不应该弹出任何Swing组件。如果服务器在其他地方运行,那么每个用户最终都会在服务器上启动Swing窗口,用户将永远看不到它们。您所经历的(Tomcat启动Swing窗口并能够实际看到它)只是巧合,因为您的服务器运行在localhost
上
您要做的是让用户从web浏览器开始,然后导航到正确的站点以使用您的内容。也就是说,web浏览器应该已经可用:您不必代表您的用户启动浏览器。您能解释一下您试图用它实现什么吗?为什么要从web服务器启动浏览器?为什么不提供一个供用户浏览器访问的URL呢?我正在开发的web应用程序在内部数据库中获取与特定主题相关的数据。这些数据也可能来自外部来源,如其他公共服务。我试图做的是获取这些数据,从HTML文件中解析它。已经完成了,唯一的细节是我无法从我的应用程序访问数据。因此,我为用户提供了一个本机浏览器,它允许用户导航到他想要的页面,并且我拥有所有可用的HTML数据。我尝试过jQuery、Ajax等等:跨域请求阻止了我…:/另外,调用所有这些并打印“线程退出”消息的代码是无法正确运行的代码,但我在这里找不到它。你在说什么线程?你仍然没有回答这个问题:为什么用户不自己启动浏览器来访问你的应用程序?如果用户未启动浏览器,该web应用程序如何启动?Tomcat web应用程序不会在浏览器中运行。它在服务器上运行,可能没有任何屏幕连接,并且可能距离用户的机器很远。当服务器上的webapp等待服务器屏幕(如果有)上显示的JFrame中的输入时,用户将盯着浏览器。在您的开发机器上,服务器和客户机是相同的,但在生产中,这将不再是真的。这就是问题所在。你是对的。我不知道在实际条件下执行时会如何,但是我必须确保它首先在本地实现我想要的功能。这不是最好的做法,但这是我目前唯一的办法。我的问题是,尽管浏览器已经可用,但我还没有找到一种获取用户信息的替代方法。你需要什么“信息”?你是如何得到这个尴尬的设置?我正在开发一个数据库,收集科目的财务数据。显然,这是一个相当敏感的问题,我希望尽可能以最好的方式来处理。我目前也在考虑其他选择,但我不认为有任何简单的方法可以获得它…:/我上一次的调查让我相信使用代理PHP脚本进行跨域通信可能是一种可行的方法。你对此有何看法?:)我想你不知道你在做什么。我不明白为什么应用服务器需要启动web浏览器。。。如果用户需要通过web浏览器访问您的服务,用户将启动浏览器并转到您服务的URL。如果你需要用户提供的信息,那么就通过网络表单来获取。这个想法实际上已经被放弃了,更多的是个人的“尝试和错误”。我真的不知道我在做什么,我知道这听起来如何,但我想相信我会掌握窍门的。