0

我有一个需要让用户登录的应用程序。数据存储在 Derby DB 中。下面的表单根据用户名和密码字段对其进行查询,并设置一个用户会话,该会话应填充用户数据。

但是,即使数据库正在对用户进行身份验证,会话也会返回 null。我如何将 system.out.println 放在此类的 main 方法中,该方法将根据 db 查询返回会话数据,而不是立即执行代码并返回 null?

注意:数据库工作正常。我可以根据 sql 语句中的用户名和密码字段获得结果。

public class LoginForm{

    private static JTextField userName;
    private static JTextField password;
    private static JButton submit;
    private static int attempts;
    private static JFrame main;

    private Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();

    final int MAX_ATTEMPTS = 5;

    private UserSession session;

    public LoginForm(){

        Handler handle = new Handler();                             //inner class
        LoginFormFocusListener fl = new LoginFormFocusListener();   //inner class

        main = new JFrame();

        main.setUndecorated(true);
        main.setBounds((dim.width/2) - (500/2),(dim.height/2) - (150/2),500, 75);
        main.setVisible(true);
        main.setAlwaysOnTop(true);
        main.setResizable(false);
        main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        userName = new JTextField(10);
        password = new JTextField(10);
        main.setLayout(new GridLayout(0,1));

        JPanel panel = new JPanel();
        main.add(panel);

        panel.add(new JLabel("Username: "));
        panel.add(userName);
        panel.add(new JLabel("Password: "));
        panel.add(password);
        panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(4), "Please Login"));

        submit = new JButton("Submit");
        panel.add(submit);

        if(attempts > 0){
            panel.add(new JLabel("" + (MAX_ATTEMPTS - attempts) + " attempts remaining..."));
        }

        main.addWindowFocusListener(fl);
        submit.addActionListener(handle);
    }



    public UserSession getSession(){
        return this.session;
    }

    /**
     * creates the session that's returned to main/POSsystem via getSession
     * @author Matt
     *
     */
    private class Handler implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e) {
            String user = userName.getText();
            String pass = password.getText();

            session = new UserSession();
            if(session.authenticate(user,  pass)){
                System.out.println("User has been authenticated");
                JOptionPane.showMessageDialog(null,"Login Successful! ","",JOptionPane.PLAIN_MESSAGE);
            }else{
                System.out.println("Login Failed!");
                JOptionPane.showMessageDialog(null,"Login Failed!","", JOptionPane.WARNING_MESSAGE);
                attempts++;
                if(attempts < MAX_ATTEMPTS){
                    new LoginForm();
                }else{
                    JOptionPane.showMessageDialog(null, "Max attempts reached.  " +
                                                        "Please Contact the administrator of this system. ",
                                                        "User Locked",
                                                        JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }

    /**
     * Inner Class
     * custom focus events for the login form
     * the user may click away from this pop-up to close it.
     * @author Matt
     *
     */
    public class LoginFormFocusListener implements WindowFocusListener{

        @Override
        public void windowGainedFocus(WindowEvent wEvt) {}

        @Override
        public void windowLostFocus(WindowEvent wEvt) {
            ((JFrame) wEvt.getSource()).dispose();
        } 
    }    

    //test
    public static void main(String args[]){

        SwingUtilities.invokeLater(new Runnable(){  
              public void run(){  
                LoginForm lf = new LoginForm();  
                System.out.println("Session: " + lf.getSession());    <---NULL!!!
              }  
            });  


    }

}
4

2 回答 2

2

如果您真正想要的是将输出输出到控制台,那么您应该将其放在 actionPerformed 方法的最后一行,而不是将 System.out.println 代码放在 main 方法中。

如果您真的,真的,真的想在 main 方法中包含该代码,那么您应该创建一个实现 Runnable 接口的类,该接口允许获取创建的 LoginForm

像这样:

final class InitThread implements Runnable {
LoginForm lf;

public LoginForm getLfForSystemOut() {
    while (lf == null) {
        try {
            Thread.sleep(500);
        } catch (final InterruptedException e) {
            return null;
        }
    }
    synchronized (lf) {
        try {
            lf.wait();
            return lf;
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }
    return null;
}

@Override
public void run() {
    lf = new LoginForm();
}
}

然后将主要方法更改为:

public static void main(final String args[]) {

    final InitThread init = new InitThread();
    SwingUtilities.invokeLater(init);

    System.out.println("Session: " + init.getLfForSystemOut().getSession());

}

最后在此块的 actionPerformed 方法的末尾:

synchronized (LoginForm.this) {
    LoginForm.this.notifyAll();
}
于 2012-09-03T22:41:28.740 回答
1

您遇到的问题是因为您试图在用户有机会填写表单并按下提交按钮之前获取会话。

按下提交按钮时会异步调用handler,创建表单后会直接调用main中的println。您要么必须等到会话不再为空,要么在处理程序中使用经过身份验证的会话。

于 2012-09-03T22:29:04.883 回答