java - 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 上显示一个],当单击代理按钮时,另一个面板显示在右侧显示代理呼叫缓冲区中的号码,将鼠标悬停在每个号码上,该号码的客户信息将显示在按钮的工具提示中:
希望这些细节能让问题更清楚。
解决方案
我试图了解您的应用程序是如何工作的。我认为您正在做的是您有一个处理 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 调用等。如何从网页访问后端确实有很多可能性一种非常敏感和原生的方式。
推荐阅读
- spring - 尝试创建测试时 Spring 配置和组件扫描中断
- c++ - 无法使用 GetAsyncKeyState 在 C/C++ 键盘记录器中捕获特殊键
- firebase - 应用程序暂停时如何更新用户的位置
- android - 如何使我的片段与另一个片段一起全屏显示,因为它是父片段而不是活动?
- rx-java - 使用来自另一个 observable 的数据
- python - Django 自定义用户 CustomUserManager 不会保存我的额外数据字段
- html - Unordered list inside table using FLWOR
- javascript - 如何按比例调整“div”的背景图像大小?
- python - 将现有 sqlite3 数据库添加到 Django App
- javascript - 如何表现不同在一种模式中?