我有一个应用程序,在后端部署轻量级HTTP服务器(Jetty) servlet基本上更新了MySQL数据库 我用Spring连接了一切。
到目前为止确定。
我有一个用于与服务器交互的UI
如果UI在本地运行,我希望它在JTree
当前登录的用户中显示。
所以我决定启动服务器,即在启动主框架时启动Spring。
最重要的是,为了更新UI的JTree以显示我认为使用Observer-Observable的所有已登录用户,并使接受连接的代码为Observable
。
ConnectionListener
会通知ArrayBlockingQueue
将DefaultMutableTreeNode
存储在Jtree
中的后台线程(对SwingUtilities
根有 public class AdminFrame extends JFrame {
public static ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("myBeans");
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
public void run() {
//Show GUI
}
}
}
根>)会更新它 - 当然是通过public class ServerThread extends Thread {
@Override
public void run() {
ClassPathXmlApplicationContext ctx = ApplicationCtx.getApplicationCtx();
}
}
在EDT主题中。
我的问题如下:
如果我这样做:
public class ApplicationCtx {
private static ClassPathXmlApplicationContext ctx;
private ApplicationCtx(){}
public static synchronized ClassPathXmlApplicationContext getApplicationCtx(){
if(ctx == null){
ctx = new ClassPathXmlApplicationContext("myBeans.xml");
}
return ctx;
}
未绘制GUI但我可以理解,因为一旦Spring启动并且服务器启动,线程就不会返回。
所以我在后端线程中启动Spring,如下所示:
public class AdminFrame extends JFrame {
public static void main(String[] args) {
ServerThread lightweightServer = new ServerThread();
lightweightServer.start();
Thread.sleep(9000);//Temporary solution to make sure the server is started up before GUI
ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler");
connectHandler.addObserver(new ConnectionListener());
EventQueue.invokeLater(new Runnable() {
public void run() {
//SHOW GUI
}
}
和
ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler");
}
GUI现在显示并且似乎正常但我错过了通知。
问题:
无法获得新连接的通知:
1)如果我按如下方式注册通知:
AdminFrame
GUI永远不会出现。如果我删除该行:
public class AdminFrame extends JFrame {
public static void main(String[] args) {
ServerThread lightweightServer = new ServerThread();
lightweightServer.start();
Thread.sleep(9000);//Temporary solution to make sure the server is started up before
EventQueue.invokeLater(new Runnable() {
public void run() {
AdminFrame frame = new AdminFrame();
//Other code
}
GUI出现。
2)如果我在EDT内部注册,即在 ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler");
的构造函数内部,GUI也不会显示。
即
ConnectHandler
如果我删除以下行,GUI会显示,但这样我无法注册以获取通知:
lazy-init="true"
这一定是线程问题,但我无法理解问题是什么 为什么第二次调用Spring应用程序上下文以使{{1}}使线程不返回? 我在这做错了什么?
更新
如果我将Spring配置文件中的属性{{1}}添加到启动Jetty服务器的bean中,问题就解决了。
但我无法理解为什么它会解决它或者问题是什么。
由于
答案 0 :(得分:1)
Serializable
或Observate
需要将GUI相关代码包装到(大多数情况下)invokeAndWait()
来自SwingWorker
的输出(因为有保证,但我看到一些不符合我预期效果的情况)或Runnable#Thread
需要强奸GUI相关代码到invokeLater()
您可以在之前准备您的GUI(然后存在EDT),并且可见性
JFrame#pack();
JFrame#setVisible(true);
对于此Container
您必须在invokeXxx();
内调用,或者最好来自javax.swing.Action()
答案 1 :(得分:0)
如果将lazy-init设置为true可以解决您的问题,我认为它没有完全解决。
默认情况下,所有bean在启动时初始化,因此如果没有正确初始化任何bean,就会出现启动问题。
如果将其设置为false,则不会调用bean,也不会遇到任何问题。所以这个问题没有解决,而是推迟了。