首页 > 解决方案 > Java Web Start Swing App如何显示servlet信息?

问题描述

当我输入我的问题时,出现了类似的问题,比如这个 [ How can Icommunicate Servlet from Swing ],但我查看了它,并没有找到我正在寻找的答案,所以这是我的问题。

我正在为内部呼叫中心开发一个网络应用程序,它使用 Java 应用程序 [CCT:呼叫中心技术] 来调用星号服务器进行呼叫,这个 CCT 有很多 servlet 来生成 html 网页,所以呼叫代理可以访问网页并拨打电话。为了更好地开发和调试,我添加了一个 Swing GUI 面板,所以当它在我的开发 PC 上运行时,它会打开一个带有很多按钮的窗口,每个按钮代表一个调用者代理及其设置信息,所以我可以点击看看细节。它运行良好,我已将代码复制到测试服务器,当它在那里运行时,我可以远程访问它并查看带有代表每个调用者代理的 JButtons 的 Swing 面板。

但问题是,当这个 Java 应用程序在生产服务器上运行时,它会作为 Windows 服务运行[所以我是老板告诉我的],并且不会有显示,所以不会看到 Swing 面板,因此我想到了 Java web Start,有了它,我可以有一个带有“WebStartLaunchButton”的网页,所以当我点击那个按钮时,它会让我下载一个 Jar 文件,该文件将启动一个 Swing 应用程序。但后来我意识到 Jar 文件将被下载到我的本地 PC 上,并从 PC 上运行,它不知道 servlet 设置/信息,它是独立的,与呼叫中心 Web 应用程序 sevlet 无关,并且无法显示来电代理信息。我是对的,有没有办法让 Swing 应用程序在服务器上运行并从我的 PC 上查看 [有权访问] 它?

这里有更多细节,从 servlet 有一个像这样的类:

public class DialerService extends Service implements Runnable
{
  private boolean running = false;
  private Thread thread;

  private CallManager cm = null;
  private AgentDialListManager adlm = null;            // <-- My Swing program
  private DataAccessManager dam = null;
  ...

  public void run()
  {
    adlm = new AgentDialListManager();                 // <-- My Swing program
    ...
  }
  ...

  private CallData getNextDial(SessionManager sm, SessionData session)
  {
    CallData nextDial = null;

    AgentData agent = session.getAgentData();
    if (agent != null)
    {
      SystemSettingsData settings = dam.getSystemSettings();
      if (settings.isNextDialBufferOn())
      {
        nextDial = adlm.getNextNumber(dam,session);   // <-- My Swing program : Get a number from self-managed agent dial list
      }
      ...
    }
  }
  ...

}

这是我的主要 Swing 程序 [未显示其他相关类]:

package com.amerisave.cct.call;

import com.amerisave.cct.data.DataAccessManager;
import com.amerisave.cct.session.AgentData;
import com.amerisave.cct.session.SessionData;
import com.orderlysoftware.orderlycalls.OrderlyCalls;
...
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
...

public class AgentDialListManager extends JPanel implements Runnable
{
  public static final long serialVersionUID = 26362862L;
  static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
  static int W = 1136, H = 800, updateInterval = 1000;
  HashMap<Integer,AgentDialListRunner> agentDialListMap = null;
  HashMap<Integer,JFrame> Agent_Panel_Frame_Map = null;
  AgentData agent;
  Insets anInset = new Insets(0,0,0,0);
  AgentDialListRunner adlr;
  JPanel agentPanel = new JPanel(),Log_Panel=new JPanel(new FlowLayout(1,0,0));
...
  static JTabbedPane Tabbed_Pane;
  static JTextArea Log_TextArea = new JTextArea(Get_System_Properties());
  String hostAddress,hostName,dialerServerInfo="";
  List dialerServerList = null;
  Thread agentDialListManagerThread;

  AgentDialListManager()
  {
    if (!agentDialListManager_Exists_B)
    {
      agentDialListMap = new HashMap();
      Agent_Panel_Frame_Map = new HashMap();
      shutdown = false;
      if (showGUI_B) Init();
      start();
      agentDialListManager_Exists_B = true;
    }
  }

  void Init()
  {
    setLayout(new FlowLayout(1,0,1));
    Tabbed_Pane=new JTabbedPane();
    Tabbed_Pane.setDoubleBuffered(true);
    Tabbed_Pane.setPreferredSize(new Dimension(W - 20,H - 42));
    Tabbed_Pane.setAutoscrolls(true);
    Tabbed_Pane.setFont(new Font("Times New Roman",0,16));
    Tabbed_Pane.setForeground(new Color(0,0,230));
    add(Tabbed_Pane);

    agentPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.RAISED,Color.white,new Color(134,134,134))," Agents",TitledBorder.CENTER,TitledBorder.TOP,new Font("Times New Roman",0,15),new Color(0,60,198)));
    agentPanel.setPreferredSize(new Dimension(W - 20,H - 42));
    Tabbed_Pane.addTab("Agents",null,agentPanel,"");

    JPanel bottomPanel = new JPanel(new FlowLayout(1,0,0));

    JPanel skipRatioPanel = new JPanel(new FlowLayout(1,0,0));
    skipRatioPanel.setBorder(new EtchedBorder(EtchedBorder.RAISED,new Color(0,188,250),new Color(134,134,134)));
    skipRatioPanel.setPreferredSize(new Dimension(330,30));
    bottomPanel.add(skipRatioPanel);

...

    Tabbed_Pane.addTab("Log",null,Log_Panel,"");

    setPreferredSize(new Dimension(W,H));

    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        createAndShowGUI();
      }
    });
  }

  CallData getNextNumber(DataAccessManager dam,SessionData session)
  {
    CallData nextDial = null;
    if (agentDialListMap != null)
    {
      agent = session.getAgentData();
      int nEmployeeId = agent.nEmployeeId;

      if (!agentDialListMap.containsKey(nEmployeeId))
      {
        adlr = new AgentDialListRunner(nEmployeeId,dam);
        agentDialListMap.put(nEmployeeId,adlr);
        agentCount = agentDialListMap.size();
        agentPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.RAISED,Color.white,new Color(134,134,134)),agentCount + " Agent" + (agentCount > 1 ? "s" : ""),TitledBorder.CENTER,TitledBorder.TOP,new Font("Times New Roman",0,15),new Color(0,60,198)));
        addAgent(adlr.id,adlr,agent);
      }
      adlr = agentDialListMap.get(nEmployeeId);
      nextDial = adlr.getNextNumber();
    }
    return nextDial;
  }

  void createAndShowGUI()
  {
    JFrame frame = new JFrame("AgentDialListManager [  Java = " + System.getProperty("java.version") + "  |  jetty.home = "+System.getProperty("jetty.home")+"  ]   dialerServerInfo = " + dialerServerInfo+"   [ hostAddress = " + hostAddress+"   hostName = " + hostName+" ]");
    frame.add(this);

    frame.addWindowListener(new WindowAdapter()
    {
      public void windowActivated(WindowEvent e)  { }
      public void windowClosed(WindowEvent e) { }
      public void windowClosing(WindowEvent e) { if (runFromMain_B) System.exit(0); }
      public void windowDeactivated(WindowEvent e) { }
      public void windowDeiconified(WindowEvent e) { repaint(); }
      public void windowGainedFocus(WindowEvent e) { repaint(); }
      public void windowIconified(WindowEvent e) { }
      public void windowLostFocus(WindowEvent e) { }
      public void windowOpening(WindowEvent e) { repaint(); }
      public void windowOpened(WindowEvent e) { }
      public void windowResized(WindowEvent e) { repaint(); }
      public void windowStateChanged(WindowEvent e) { repaint(); }
    });

    frame.pack();
    if (runFromMain_B) frame.setLocationRelativeTo(null);
    else frame.setBounds(displayCount==3?-1728:0,displayCount==3?0:26,this.getWidth(),this.getHeight() + 43);
    frame.setVisible(true);
  }

  public void run()
  {
    try
    {
      while (!shutdown)
      {
        Thread.sleep(sleepTime);
        AgentDialListRunner.averageTimeToMoreNumbers = 0;
        for (Map.Entry<Integer,AgentDialListRunner> mapElement : agentDialListMap.entrySet())
        {
          int nEmployeeId = (int)mapElement.getKey();
          AgentDialListRunner adlr = (AgentDialListRunner)mapElement.getValue();
          AgentDialListRunner.averageTimeToMoreNumbers += adlr.averageTimeInSecondsBeforeGettingMoreNumbers;
        }
        agentCount = agentDialListMap.size();
        if (agentCount > 0)
        {
          AgentDialListRunner.averageTimeToMoreNumbers /= agentCount;
       averageTimeToMoreNumbersValueLabel.setText(AgentDialListRunner.averageTimeToMoreNumbers + " Sec.");
        }
      }
    }
    catch (Exception e)
    {
      log.error("Exception in runner thread:", e);
    }
  }

  public void start()
  {
    stop();
    if (agentDialListManagerThread == null)
    {
      agentDialListManagerThread = new Thread(this);
      agentDialListManagerThread.setPriority(Thread.NORM_PRIORITY);
      agentDialListManagerThread.start();
    }
  }

  public void stop()
  {
    if (agentDialListManagerThread != null) agentDialListManagerThread = null;
  }
...

  public static void main(String[] args)
  {
    runFromMain_B = true;
    new AgentDialListManager();
  }
}

服务器启动时的 GUI 如下所示,在左侧有一个窗口显示所有活动的呼叫者代理 [仅在我的开发 PC 上显示一个],当单击代理按钮时,另一个面板显示在右侧显示代理呼叫缓冲区中的号码,将鼠标悬停在每个号码上,该号码的客户信息将显示在按钮的工具提示中:

在此处输入图像描述

希望这些细节能让问题更清楚。

标签: javaswingservletsjava-web-start

解决方案


我试图了解您的应用程序是如何工作的。我认为您正在做的是您有一个处理 http 请求的 servlet,并且作为请求处理的一部分,您启动了一个打开 Swing 应用程序的线程。这个对吗?

如果是这样,这是一个糟糕的设计。Servlet 用于提供 Web 内容。如果您启动一个 Swing 应用程序,它在同一个 JVM 中运行,并且您实际上可以访问与 servlet 中相同的后端资源,但问题是 servlet 服务的内容是通过网络传输到客户端的。虽然这可以在您的本地机器上工作(服务器机器也是客户端机器),但它不适用于正常的客户端 - 服务器架构,其中服务器是与客户端不同的机器。此处客户端接收响应 (html) 但无法访问在服务器计算机上运行的 Swing 应用程序。

这种设计的另一个问题是如何将 swing 应用程序绑定到正确的客户端?图片 100 个用户访问 servlet,它是否打开了 100 个 Swing 应用程序实例?正如 Kayaman 所说,您需要与客户端机器建立某种其他连接才能访问 Swing 应用程序。这不是微不足道的,也不值得做。

我实际上来自 Webswing 团队,但这不是 Webswing 的正确用例。Webswing 用于独立的 Swing/JavaFX 应用程序,用户通常会从桌面启动,而不是从 servlet 启动。

我认为对您来说最好的选择是将 Swing 应用程序的逻辑实现到由 servlet 提供的 HTML 页面中,可能在按钮上使用一些 AJAX 调用等。如何从网页访问后端确实有很多可能性一种非常敏感和原生的方式。


推荐阅读