1

別のプログラム内で Java コンポーネントを使用しようとしています。このプログラムは Tomcat で実行される Web アプリケーションであり、コンポーネントは Swing を使用して Web ブラウザーを開きます。ユーザーは特定のページに移動するように求められ、JFrame のコントロールを使用して、ページが HTML 形式でローカルに保存されます。このローカルに保存されたファイルは、後でさらに詳しく説明するために使用されます。問題は、Eclipse から実行すると、私のコードが問題なく動作することです。ただし、Tomcat で実行されているアプリケーション内でコンポーネントを使用すると、正しく実行されません。ウィンドウが表示され、ナビゲーションが機能し、データが問題なく取得されます。問題は、メイン アプリ (Tomcat で実行されているアプリ) は、コンポーネント (Java) が作業を完了した後に実行を再開する必要があるということです。明らかに、Web アプリが単にハングアップし、続行しないため、何か問題が発生しています。

私のコンポーネントでは、Browser と Helper の 2 つのクラスを使用しています。Browser は DJ NativeSwing ライブラリに基づいており、単純な Web ブラウザを初期化して表示するためのロジックが含まれています。Helper クラスは、ブラウザを独自のスレッドで実行できる「フロントエンド」メソッドを提供します。wait() と notify() の使用方法がよくわからないため、invokeLater の代わりに SwingUtilities.invokeAndWait を使用しています。私は試して失敗しました。

コードを要約すると、次のようになります。

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();
    }
}

そして Browser クラス:

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) スレッドが正常に終了しないことに関係があると思いますが、どうすればよいか途方に暮れています。

どんな助けでも大歓迎です!:)

4

1 に答える 1

0

あなたはそれを間違っています。

Tomcat は Web アプリケーション サーバーであり、Swing コンポーネントをポップアップ表示するべきではありません。サーバーが別の場所で実行されている場合、すべてのユーザーがサーバー上で Swing ウィンドウを起動することになり、ユーザーにはそれらが表示されません。あなたが経験していること (Tomcat が Swing ウィンドウを起動し、実際にそれを見ることができる) は、サーバーが で実行されているため、単なる偶然ですlocalhost

あなたがしたいことは、ユーザーが Web ブラウザーから始めて、適切なサイトに移動してコンテンツを消費するようにすることです。つまり、Web ブラウザーは既に使用可能になっている必要があります。ユーザーに代わって Web ブラウザーを起動する必要はありません。

于 2013-07-17T14:40:12.483 に答える