(二)JavaFx项目留言系统---登录

我前面讲过这个项目是分模块去开发的,开发完我就知道不是很符合业务逻辑。所以我还是按照业务去分解

近日,我醒悟。我觉得以后的开发生涯应该多注重一些“无用功”,比方说流程图。那么我们先画一个流程图分析一下登录的逻辑

在这里插入图片描述

普通用户与管理员登录逻辑其实是一致的,只是说登录完后的逻辑不一样。对于游客登录,我这边是提供一个按钮,点击后一键登录。另外在我v1版本开发中管理员登录是没有实现将登录的用户存在在Session中。因为初期我只设计一个管理员,显然是存在缺陷的。

我们使用Scene Builder开发页面,我这里是将后期游客登录也设计在内

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="LeaveMessageSystem.controller.LogupFrameController">
    <children>
        <VBox prefHeight="393.0" prefWidth="600.0">
            <children>
                <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label fx:id="systemLabel" text="留言管理系统">
                            <font>
                                <Font name="System Bold" size="40.0" />
                            </font>
                        </Label>
                    </children>
                   <children>
                       <HBox alignment="BASELINE_RIGHT">
                          <children>
                              <Button fx:id="touristButton"  mnemonicParsing="false" onAction="#touristButtonEvent" style="-fx-background-color: #00ffff;" text="游客登录" />
                          </children>
                       </HBox>
                   </children>
               <VBox.margin>
                  <Insets left="40.0" />
               </VBox.margin>
                </HBox>
                <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label fx:id="userNameLabel" text="用户名:" />
                        <TextField fx:id="userNameTextField" promptText="请输入您的账号" />
                    </children>
                </HBox>
                <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label fx:id="passwordLabel" text="密   码:" />
                        <PasswordField fx:id="passwordTextField" promptText="请输入您的密码" />
                    </children>
                </HBox>
                <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="80.0">
                    <children>
                        <Button fx:id="logupButton" mnemonicParsing="false" onAction="#logupButtonEvent" text=" 登 录" />
                        <Button fx:id="resetButton" mnemonicParsing="false" onAction="#resetButtonEvent" text=" 重 置" />
                    </children>
                </HBox>
            </children>
        </VBox>
    </children>
</AnchorPane>

效果如下:
在这里插入图片描述

设计beans实体层

为了区分Users,我单独设计LoginUser,其实完全可以直接使用Users

package LeaveMessageSystem.beans;

public class LoginUser {
    public int status;
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private String username;
    private String password;

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    private int roled;

    public int getRoled() {
        return roled;
    }

    public void setRoled(int roled) {
        this.roled = roled;
    }
}

在controller下新建一个java文件用于处理登录逻辑

对于管理员我们跳转到管理员后台界面,对于普通游客在跳转之前,我们需要保存Session。当然我们知道此Session非彼Session,只是为了后面普通游客的实际需求而设计。而游客我们只需要一键跳转就行。 另外在项目中我用了一些封装的轮子,如下SimpleTools

package LeaveMessageSystem.controller;
import LeaveMessageSystem.MainApp;
import LeaveMessageSystem.beans.LoginUser;
import LeaveMessageSystem.beans.Session;
import LeaveMessageSystem.dao.UserDao;
import LeaveMessageSystem.tools.SimpleTools;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.stage.Stage;

import java.sql.SQLException;


public class LogupFrameController {
    public Button touristButton;
    private SimpleTools simpleTools = new SimpleTools();
    @FXML
    private Stage stage;

    public Stage getStage() {
        return stage;
    }

    public void setStage(Stage stage) {
        this.stage = stage;
    }
    @FXML
    private TextField userNameTextField;

    @FXML
    private PasswordField passwordTextField;

    @FXML
    private Button logupButton;

    @FXML
    private Label userNameLabel;

    @FXML
    private Label systemLabel;

    @FXML
    private Button resetButton;

    @FXML
    private Label passwordLabel;

    // “登录”按钮的事件监听器方法
    public void logupButtonEvent(ActionEvent event) throws Exception{
        if (userNameTextField.getText().equals("") || passwordTextField.getText().equals("")) {
            SimpleTools.informationDialog(Alert.AlertType.WARNING, "提示", "警告", "请按照文本框内容提示正确填写内容!");
        } else {
            // 实例化UserDao对象
            UserDao userDao = new UserDao();
            // 登录用户
            LoginUser loginUser = null;
            try {
                loginUser = userDao.login(userNameTextField.getText(), passwordTextField.getText());
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            if(loginUser!=null) {
                // 对是否登录成功进行判断
                if (loginUser.getUsername() != null && loginUser.getPassword() != null) {
                // roled用户状态
                    int roled=loginUser.getRoled();
//                // 设置通信对象,建立登录成功通信
//                Session.setUser(loginUser);
                    // 在弹出的提示框种获取用户反馈
                    boolean b = SimpleTools.informationDialog(Alert.AlertType.INFORMATION, "提示", "信息", "恭喜登录成功,欢迎使用本系统!");
                    // 如果用户确定登录,则跳转到主界面
                    if (b) {
                        //获取当前ip
//                        InetAddress ip4 = Inet4Address.getLocalHost();
//                        String[] strs=String.valueOf(ip4).split("/");
//                        String ip=strs[1];
//                        System.err.println(ip);
                        // 跳转到主界面后,关闭登录界面
                        stage.close();
                        if(roled==1) {
                            // 打开主窗口
                            new MainApp().initMainFrame();
                        }
                        else {
                            //设置session通信对象
                            Session.setLoginUser(loginUser);
                            //普通用户主界面
                            new MainApp().initMainOrdinaryUserFrame();
                        }

                    }

                } else {
                    SimpleTools.informationDialog(Alert.AlertType.ERROR, "错误", "错误", "用户名或密码错误!");
                }
            }else {
                SimpleTools.informationDialog(Alert.AlertType.ERROR, "错误", "错误", "用户名或密码错误!");
            }
        }
    }



   // “重置”按钮的事件监听器方法
   public void resetButtonEvent(ActionEvent event) {
       userNameTextField.setText("");
       passwordTextField.setText("");
  }
    //游客登录
    public void touristButtonEvent(ActionEvent actionEvent) {
        // 跳转到主界面后,关闭登录界面
        stage.close();
        // 打开主窗口
        new MainApp().initMainTouristFrame();
    }
}

SimpleTools代码,其为一个工具类

package LeaveMessageSystem.tools;
import LeaveMessageSystem.beans.Message;
import LeaveMessageSystem.beans.UserTypeNewBeanData;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

import java.util.List;
import java.util.Optional;
public class SimpleTools {

    /**
         * 操作结果:JavaFX设置按钮、标签等组件的图标
         *
         * @param labeleds   需要设置图标的按钮
         * @param imagePaths 图标的路径
         */
    public void setLabeledImage(Labeled[] labeleds, String[] imagePaths) {
        for (int i = 0; i < labeleds.length; i++) {
            labeleds[i].setGraphic(new ImageView(new Image("file:" + imagePaths[i])));
        }
    }

      /**
    * 操作结果:清空文本框组件的内容
    *
    * @param inputControls 文本框或文本域组等
    */
    public void clearTextField(TextInputControl... inputControls) {
        for (int i = 0; i < inputControls.length; i++) {
            inputControls[i].setText("");
        }
 }

      /**
         * 操作结果:取消所有单选按钮选择
         *
         * @param toggleButtons 单选按钮组
         */
    public void clearSelectedRadioButton(ToggleButton... toggleButtons) {
        for (int i = 0; i < toggleButtons.length; i++) {
            toggleButtons[i].setSelected(false);
        }
    }

    /**
     * 操作结果:取消所有下拉列表框选择
     *
     * @param comboBoxes 下拉列表框组
     */
    public void clearSelectedComboBox(ComboBox... comboBoxes) {
        for (int i = 0; i < comboBoxes.length; i++) {
            comboBoxes[i].getSelectionModel().select(-1);// 设置选择的索引为-1,就不会选择任何选择选项了。
        }
    }

    /**
     * 操作结果:JavaFX设置菜单项组件的图标
     *
     * @param menuItems  菜单项
      * @param imagePaths 图标的路径
    */
    public void setMenuItemImage(MenuItem[] menuItems, String[] imagePaths) {
        for (int i = 0; i < menuItems.length; i++) {
            menuItems[i].setGraphic(new ImageView(new Image("file:" + imagePaths[i])));
        }
    }

      /**
     * 操作结果:JavaFX判断是否为空
     *
     * @param str 文本
     * @return boolean 如果不为空返回true,否则返回false
     */
    public boolean isEmpty(String str) {
        if (str == null || "".equals(str.trim())) {
            return true;
          } else {
            return false;
        }
        }

    /**
    * 操作结果:自定义一个JavaFX的对话框
    *
    * @param alterType 对话框类型
    * @param title     对话框标题
    * @param header    对话框头信息
    * @param message   对话框显示内容
    * @return boolean 如果点击了”确定“那么就返回true,否则返回false
    */
    public static boolean informationDialog(Alert.AlertType alterType, String title, String header, String message) {
        // 按钮部分可以使用预设的也可以像这样自己 new 一个
        Alert alert = new Alert(alterType, message, new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE), new ButtonType("确定", ButtonBar.ButtonData.YES));
        // 设置对话框的标题
        alert.setTitle(title);
        alert.setHeaderText(header);
        // showAndWait() 将在对话框消失以前不会执行之后的代码
        Optional<ButtonType> buttonType = alert.showAndWait();
        // 根据点击结果返回
        if (buttonType.get().getButtonData().equals(ButtonBar.ButtonData.YES)) {
            return true;// 如果点击了“确定”就返回true
          } else {
            return false;
              }
        }

            /**
     * 操作结果:JavaFX判断是否登录成功
      *
     * @param userNameTextField 用户名文本框
     * @param passwordTextField 密码文本框
     * @param userName   正确用户名
     * @param password   正确密码
     * @return boolean 如果登录成功返回true,否则返回false
      */
            public boolean isLogIn(TextInputControl userNameTextField, TextInputControl passwordTextField, String userName, String password) {
                SimpleTools simpleTools = new SimpleTools();
                if (simpleTools.isEmpty(userNameTextField.getText())) {
                    simpleTools.informationDialog(Alert.AlertType.WARNING, "提示", "警告", "用户名不能为空!");
                    return false;
                }
                if (simpleTools.isEmpty(passwordTextField.getText())) {
                    simpleTools.informationDialog(Alert.AlertType.WARNING, "提示", "警告", "密码不能为空!");
                    return false;
                }
                if (!userNameTextField.getText().equals(userName)) {
                    simpleTools.informationDialog(Alert.AlertType.WARNING, "提示", "警告", "用户名不正确!");
                    return false;
                }
                if (!passwordTextField.getText().equals(password)) {
                    simpleTools.informationDialog(Alert.AlertType.WARNING, "提示", "警告", "密码不正确!");
                    return false;
                }
                if (!userNameTextField.getText().equals(userName) && !passwordTextField.getText().equals(password)) {
                    simpleTools.informationDialog(Alert.AlertType.ERROR, "提示", "错误", "用户名和密码均不正确!");
                     return false;
                }
                if (userNameTextField.getText().equals(userName) && passwordTextField.getText().equals(password)) {
                    boolean isOK = simpleTools.informationDialog(Alert.AlertType.INFORMATION, "提示", "信息", "登录成功!");
                    return isOK;
                }
            return false;
  }

        /**
         * 操作结果:向下拉列表框中添加列表项
         *
         * @param comboBox 下拉列表框
         * @param items    列表项
          */
        public void addComboBoxItems(ComboBox comboBox, Object[] items) {
            comboBox.getItems().clear();// 清除下列列表框中的所有选项
            ObservableList options = FXCollections.observableArrayList(items);
            comboBox.setItems(options);// 添加下拉列表项
   }

    /**
     * 将查询的用户状态结果,放到表中
     * @param userTypeManageView
     * @param data
     * @param idTableColumn
     * @param userTypeNameColumn
     * @param userTypeStatus
     */
    public void setUserTypeTableViewData(TableView<UserTypeNewBeanData> userTypeManageView,ObservableList data, TableColumn<UserTypeNewBeanData , String> idTableColumn, TableColumn<UserTypeNewBeanData, String> userTypeNameColumn, TableColumn<UserTypeNewBeanData, String> userTypeStatus) {
        //设置id列数据
        idTableColumn.setCellValueFactory(cellData -> cellData.getValue().idProperty());

        //设置name列数据
        userTypeNameColumn.setCellValueFactory(cellData -> cellData.getValue().usernameProperty());
        //设置status列数据
        userTypeStatus.setCellValueFactory(cellData ->  cellData.getValue().statusProperty());
        userTypeManageView.setItems(data);
    }
    /**
     * 把数据放到表中
     * @param messageTypeManageView
     * @param data
     * @param messageIdColumn
     * @param messageNameColumn
     * @param messageTitleColumn
     * @param messageContentColumn
     * @param messageTimeColumn
     */
    public void setMessageTableViewData(TableView<Message> messageTypeManageView, ObservableList<Message> data, TableColumn<Message, String> messageIdColumn, TableColumn<Message, String> messageNameColumn, TableColumn<Message, String> messageTitleColumn, TableColumn<Message, String> messageContentColumn, TableColumn<Message, String> messageTimeColumn) {
        //id列数据
        messageIdColumn.setCellValueFactory(cellData -> cellData.getValue().midProperty());
        //name列数据
        messageNameColumn.setCellValueFactory(cellData -> cellData.getValue().mnameProperty());
        //title列数据
        messageTitleColumn.setCellValueFactory(cellData -> cellData.getValue().mtitleProperty());
        //content列数据
        messageContentColumn.setCellValueFactory(cellData -> cellData.getValue().mcontentProperty());
        //time列数据
        messageTimeColumn.setCellValueFactory(cellData -> cellData.getValue().mtimeProperty());
        messageTypeManageView.setItems(data);
    }
    /**
     * 将数据库拿到data数据封装转换成javafx中 ObservableList<BookTypeBeanTableData>类型的数据
     */
    public ObservableList<UserTypeNewBeanData> getUserTypeTableViewData(List<UserTypeNewBeanData> tableDataList) {

        // 创建ObservableList<BookTypeBeanTableData>对象
        ObservableList<UserTypeNewBeanData> data = FXCollections.observableArrayList();
        // 循环遍历集合中的数据
        for (int i = 0; i < tableDataList.size(); i++) {
            UserTypeNewBeanData r = (UserTypeNewBeanData) tableDataList.get(i);
            // 将数据封装到BookTypeBeanTableData中
            UserTypeNewBeanData td = new UserTypeNewBeanData(r.getId(), r.getUsername(), r.getStatus());
            // 将BookTypeBeanTableData对象添加到data中
            data.add(td);
        }
        // 返回数据
        return data;
    }
    /**
     * 将数据库拿到data数据封装转换成javafx中 ObservableList<Message>类型的数据
     * @param messageDataList
     * @return
     */
    public ObservableList<Message> getMessageTableViewData(List<Message> messageDataList) {
        // 创建ObservableList<BookTypeBeanTableData>对象
        ObservableList<Message> data = FXCollections.observableArrayList();
        // 循环遍历集合中的数据
        for (int i = 0; i < messageDataList.size(); i++) {
            Message r = (Message) messageDataList.get(i);
            // 将BookTypeBeanTableData对象添加到data中
            data.add(r);
        }
        // 返回数据
        return data;
    }
    /**
     *  这是自己定义一个提示框
     * @param alterType
     * @param title
     * @param header
     * @param message
     * @return
     */
    public boolean informationDalog(Alert.AlertType alterType, String title, String header, String message) {
        // 按钮部分可以使用预设的也可以像这样自己 new 一个
        Alert alert = new Alert(alterType, message, new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE), new ButtonType("确定", ButtonBar.ButtonData.YES));
        // 设置对话框的标题
        alert.setTitle(title);
        alert.setHeaderText(header);
        // showAndWait() 将在对话框消失以前不会执行之后的代码
        Optional<ButtonType> buttonType = alert.showAndWait();
        // 根据点击结果返回
        if (buttonType.get().getButtonData().equals(ButtonBar.ButtonData.YES)) {
            return true;// 如果点击了“确定”就返回true
          } else {
            return false;
         }
    }
}

在持久层UserDao添加登录方法

在v2版本中,我大量使用了面向接口的思想。很遗憾的是v1版本为了赶进度,并没有这么去处理。

 /**
     * 实现登录
     * @param username
     * @param password
     * @return
     * @throws SQLException
     */
    public LoginUser login(String username, String password) throws SQLException{
        MyDataSource dataSource=new MyDataSource();
        QueryRunner runner=new QueryRunner(dataSource);
        String sql="select * from users where username =? and password =?";
//        return runner.query(sql,new BeanHandler<User>(User.class),username,password);
        return runner.query(sql,new BeanHandler<LoginUser>(LoginUser.class),username,password);
    }

连接数据库用的是dbUtils以及连接池技术,dbUtils这个半自动化工具是不提供类型转换,这里为我后面埋了一个坑。
两个工具类 MyDataSource和JDBCUtil_V3
JDBCUtil_V3代码

package LeaveMessageSystem.tools;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

//提供获取连接和资源释放的方法
public class JDBCUtil_V3 {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    /**
     * 静态代码块加载配置文件信息
     */
    static {
        try {
            // 1.通过当前类获取类加载器
            ClassLoader classLoader =  JDBCUtil_V3 .class.getClassLoader();
            // 2.通过类加载器的方法获得一个输入流
            InputStream is = classLoader.getResourceAsStream("db.properties");
            // 3.创建一个properties对象
            Properties props = new Properties();
            // 4.加载输入流
            props.load(is);
            // 5.获取相关参数的值
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            username = props.getProperty("username");
            password = props.getProperty("password");
            System.out.println(driver+"---"+url+"--"+username+"---"+password);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取连接方法
     *
     * @return
     */
    public static Connection getConnection() {
        Connection conn = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, username, password);
            System.out.println("连接成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 释放资源方法
     *
     * @param conn
     * @param pstmt
     * @param rs
     */
    public static void release(Connection conn, PreparedStatement pstmt, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (pstmt != null) {
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

MyDataSource代码

package LeaveMessageSystem.tools;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

public class MyDataSource implements DataSource{
//    1.创建一个容器用于存放Connection对象
    private static LinkedList<Connection> pool=new LinkedList<Connection>();
//    2.创建5个连接放到容器中
    static {
        for (int i=0;i<5;i++){
            Connection conn= JDBCUtil_V3.getConnection();
            pool.add(conn);
        }
}
/**
 *获取重新连接的方法
 */
    @Override
    public Connection getConnection() throws SQLException {
        Connection conn=null;
//        3.使用前的预处理
        if (pool.size() == 0) {
            for (int i = 0; i < 5; i++) {
                conn = JDBCUtil_V3.getConnection();
                pool.add(conn);
//                System.out.println("执行了");
            }

        }
        //            4.从池子里面获取一个连接对象
        conn = pool.remove();
        return conn;

    }
    /**
     *归还对象到连接池
     */
    public void backPoll(Connection conn){
        pool.add(conn);
    }
    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

另外需要db.properties文件去配置连接数据库


代码已经放入GitHub,需要的同学自取。别忘了给一个star!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值