栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaFX 实现windows版简易的登录软件 | 整合 MyBatis 查询数据库账号 | 窗口切换 | 使用SceneBuilder进行可视化编辑页面

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaFX 实现windows版简易的登录软件 | 整合 MyBatis 查询数据库账号 | 窗口切换 | 使用SceneBuilder进行可视化编辑页面

—— 若发现文章有任何不正确的地方,敬请指出,望不吝赐教,谢谢!

文章目录

效果展示一、准备知识

相关工具:Scene Builder [点击下载](https://openjfx.cn/scene-builder/) 二、运行环境三、引入依赖四、项目结构介绍五、配置数据库交互层DAO层

5.1 连接数据库配置5.2 MyBatis配置5.3 编写MyBatis工具类 DBUtils.java5.4 DAO层 六、编写Service业务逻辑层七、JavaFX相关的类

7.1 启动类7.2 编写StageController窗口控制类7.3 公用接口ControlledStage7.4 组件的Controller类

7.4.1 登录控制层7.4.2 主页面控制层 八、核心业务逻辑

效果展示

在登录窗口进行登录,登录验证成功后跳转到另一个窗口,若失败则弹出提示框

一、准备知识

JavaFX 中文官网:点击查看

javaFX 是一个开源的下一代客户端应用平台,适用于基于Java构建的桌面、移动端和嵌入式系统。 它是许多个人和公司的共同努力的成果,目的是为开发丰富的客户端应用提供一个现代、高效、功能齐全的工具包。

JavaFX架构:

相关工具:Scene Builder 点击下载

Scene Builder 是一款创建美丽的用户界面,并将您的设计变成一个交互式原型。Scene Builder通过创建可直接用于JavaFX应用程序的用户界面,缩小了设计师和开发人员之间的差距。

JavaFX相关的资料网站:

JavaFXChina 是国内JavaFX资料最为系统全面的网站之一,他们靠业余时间维护此站点,希望能帮到大家。

二、运行环境

Windows10MySQL8JDK8Maven3.8.4IDEA 2021.3.2 Ultimate其他的版本号请查看引入的Maven依赖 三、引入依赖


pom.xml



    4.0.0

    com.uni
    cs-plugins
    1.0-SNAPSHOT
    cs-plugins

    
        UTF-8
        5.8.1
        8
    

    
        
            org.openjfx
            javafx-controls
            ${java.version}
        
        
            org.openjfx
            javafx-fxml
            ${java.version}
        
        
            org.kordamp.bootstrapfx
            bootstrapfx-core
            0.4.0
        
        
            org.junit.jupiter
            junit-jupiter-api
            ${junit.version}
            test
        
        
            org.junit.jupiter
            junit-jupiter-engine
            ${junit.version}
            test
        
        
        
            mysql
            mysql-connector-java
            8.0.25
        
	
        
            log4j
            log4j
            1.2.17
        
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    ${java.version}
                    ${java.version}
                
            
            
                org.openjfx
                javafx-maven-plugin
                0.0.8
                
                    
                        
                        default-cli
                        
                            com.uni/com.uni.App
                            app
                            app
                            app
                            true
                            true
                            true
                        
                    
                
            
        
    

四、项目结构介绍

由于工具会涉及数据库的相关交互,同时有视图的概念,这里采用类似于Web的MVC模式进行设计,其中的M表示Model模型,在这里对应于JavaFX的Stage窗口,V则表示View视图,对应于JavaFX的Scene,C表示Controller控制层,JavaFX官方API有提供getController()的方法。

其他的相关介绍:

名称描述
controller存储控制层相关的类,其中比较重要的是Stage相关的类
dao存储负责数据库交互的Mapper接口,实现则通过resources文件夹里的XML映射文件
pojo存储实体类
service存储业务层接口以及对应的Impl实现类
utils存储一些工具类,比如获取MyBatis负责数据库交互的mapper类
App.java继承于JavaFX的Application类,主要用于启动JavaFX程序以及配置相关的窗口信息
resources/com/uni/mapper/存储MyBatis里Mapper接口对应的XML映射文件
login.fxml使用SceneBuilder工具进行可视化设计的登录的页面
main.fxml使用SceneBuilder工具设计的登录成功后的主页面(这里涉及页面切换概念)
lib存储一些关键的jar包,可以忽略,Maven导入依赖就行
database.properties配置JDBC连接的一些信息,数据库连接地址、驱动类、用户、密码
mybatis-config.xml配置项目的MyBatis

五、配置数据库交互层DAO层
5.1 连接数据库配置

/resources/database.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
user=数据库用户名
password=数据库密码

这里需要注意,为方便代码里获取到配置内容,最好是将该其放在resources资源文件夹里,方便查找以及访问

JDK官方有API操作properties的配置文件,所以不需要手动进行IO流的转换,这里则通过MyBatis框架提供的API直接连接数据库

范例: 根据MySQL的配置文件创建MyBatis框架的工厂(可通过工厂取Mapper类、执行方法等)

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.session.SqlSessionFactory;

String CONFIG_PATH = "mybatis-config.xml";

InputStream config = Resources.getResourceAsStream(CONFIG_PATH);

factory = new SqlSessionFactoryBuilder().build(config);
5.2 MyBatis配置

在没有SpringBoot下配置MyBatis果然有些复杂了,不过稍微总结一下,也不难理解,它的主要配置内容如下:

引入相关的数据库配置文件(可以不引入直接写值,但这会导致耦合度提升,不利于代码修改)特殊的设置(这里可有可无,而且配置类型比较多,笔者就只改了个日志输出的类logImpl,这样就可以按照自己的日志配置来设置别名,一是简化实体类(这样可以省略包名看起来简短)二是简化Mapper类的接口类,这样在写XML时指定namespace就可以省略Mapper接口的包名)配置数据库环境最后,设置Mapper的XML映射文件地址,这样MyBatis才能找到对应的XML映射

/resources/mybatis-config.xml






    
    
    
    
        
    
    
    
        
        
        
        
    
    
        
            
            
            
            
                
                
                
                
            
        
    


    
        
    


5.3 编写MyBatis工具类 DBUtils.java

关于MyBatis的使用,之前浅学了SSM+SpringBoot,就只记住了@Repository、@Autowired这两个注解,当不使用注解的时候,有多种选择进行创建,这里则使用其中的工厂模式来创建。

DBUtils.java

package com.uni.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
public class DBUtils{
    private static final String CONFIG_PATH = "mybatis-config.xml";
    private static SqlSessionFactory factory;
    // 单例模式
    static {
        try {
            // 获取配置文件输入流
            InputStream config = Resources.getResourceAsStream(CONFIG_PATH);
            // 创建工厂
             factory = new SqlSessionFactoryBuilder().build(config);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 获取session会话
    public static SqlSession getSession(){
        return factory.openSession();
    }
    // 关闭session会话
    public static void close(){
        //..
    }
}
5.4 DAO层

在编写DAO层接口前,需先编写相应的实体类,比如笔者需要实现登录效果,这里就设计一个用户User的Pojo(简单的Java对象) 类

User.java

package com.uni.pojo;




public class User {
    private Integer id;
    private String username;
    private String password;

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    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;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + ''' +
                ", password='" + password + ''' +
                '}';
    }
}

Dao层接口类:UserMapper.java

package com.uni.dao;

import com.uni.pojo.User;


public interface UserMapper {
    User selectByPassword(User user);
}

Dao层XML映射文件:UserMapper.xml




    

六、编写Service业务逻辑层

接口类:UserService.java (实现类放在最后的部分,因为它用到了JavaFX的相关的一些类)

package com.uni.service;

import com.uni.pojo.User;


public interface UserService {
    public User login(User user);
}
七、JavaFX相关的类
7.1 启动类

App.java

package com.uni;

import com.uni.controller.StageController;
import javafx.application.Application;
import javafx.stage.Stage;


public class App extends Application {

    public static String mainViewID = "MainView";
    public static String mainViewRes = "main.fxml";

    public static String loginViewID = "LoginView";
    public static String loginViewRes = "login.fxml";

    @Override
    public void start(Stage primaryStage) {
        //新建一个StageController控制器
        StageController stageController = new StageController();
        //设置默认的主窗口
        //加载两个窗口
        stageController.loadStage(loginViewID, loginViewRes);
        stageController.loadStage(mainViewID, mainViewRes);
        //切换主窗口
        stageController.change(loginViewID);
    }

    public static void main(String[] args) {
        launch();
    }
}
7.2 编写StageController窗口控制类

该类使用HashMap结构来存储对应的窗口名称、对应的Stage窗口对象,使用双端队列进行窗口的切换控制,目前还存在一些不足,仅作参考,相关的方法以及介绍。

方法名描述
void addStage(String a, Stage b)根据名称添加Stage窗口到Map结构中
Stage getStage(String a )根据Stage窗口名称获取对应的Stage对象
change(String a)根据Stage名称切换到对应的窗口(要求Stage存在于Map中)设计双端队列的处理
loadStage(String a, String b, StageStyle …)根据Stage的名称和对应的fxml文件位置,加上可选的窗口风格加载新的Stage对象,加载完毕后会保存到Map结构
unloadStage(String a)根据Stage名称删除相应的窗口
stages静态变量,存储所有的Stage名称以及Stage信息
queue静态变量, 存储当前的窗口序列,可用于返回操作(这里暂未使用)

StageController.java

package com.uni.controller;

import com.uni.App;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.util.Deque;
import java.util.HashMap;
import java.util.linkedList;


public class StageController {

    private static HashMap stages = new HashMap();       // 存储所有Stage
    private static Deque queue = new linkedList<>();                            // 窗口双端队列(先进后出)(切换窗口有效)

    
    public void addStage(String name, Stage stage) {
        stages.put(name, stage);
    }

    
    public Stage getStage(String name) {
        return stages.get(name);
    }

    
    public void change(String stageName) {
        // 首先获取当前的state
        Stage stage = stages.get(stageName);
        if(stage == null)
            throw new NullPointerException("未获取到指定的Stage,请确保它已经使用过addStage()/loadStage()");
        else {
            // 遍历队列
            if (queue != null && !queue.isEmpty()) {
                // 将队首的传移动到队尾
                queue.push(queue.pollFirst());
                // 关闭所有窗口
                for (Stage temp : queue) {
                    // 若当前窗口是要切换的窗口,则移除(防止重复)
                    if(temp.equals(stage))
                        queue.remove(temp);
                    temp.close();
                }
            }
            // 头插法
            queue.addFirst(stage);
            // 启动队首窗口
            queue.getFirst().show();
        }
    }

    
    public boolean loadStage(String name, String resources, StageStyle... styles) {
        try {
            //加载FXML资源文件
            FXMLLoader loader = new FXMLLoader(App.class.getResource(resources));
            Pane tempPane = loader.load();
            //通过Loader获取FXML对应的ViewCtr,并将本StageController注入到ViewCtr中

            // 通过官方API获取当前Stage的Controller,利用官方提供的泛型设置将其返回为接口ControlledStage
            ControlledStage controlledStage = loader.getController();
            // 调用相应的set方法,为当前Staged设置现在的Controller列
            controlledStage.setStageController(this);

            //构造对应的Stage
            Scene tempScene = new Scene(tempPane);
            Stage tempStage = new Stage();
            tempStage.setScene(tempScene);

            //初始化窗口的风格
            for (StageStyle style : styles) {
                tempStage.initStyle(style);
            }
            //将设置好Stage添加到Map结构
            this.addStage(name, tempStage);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean unloadStage(String name) {
        if (stages.remove(name) == null) {
            System.out.println("窗口不存在,请检查名称");
            return false;
        } else {
            System.out.println("窗口移除成功");
            return true;
        }
    }
}

7.3 公用接口ControlledStage

该接口的作用是要求实现setStageController()方法,StageController则是上面那个自定义的用于处理JavaFX窗口显示的控制层类,当我们绑定一些按钮,要实现界面跳转时就得通过Controller层的逻辑代码进行处理。所以我们规定其他的Controller类都需要实现这个接口,这提示该类需要有一个StageController对象作为成员变量,方便进行窗口切换的操作。

package com.uni.controller;


public interface ControlledStage {
    public void setStageController(StageController stageController);
}
7.4 组件的Controller类 7.4.1 登录控制层

相关的fxml,通过SceneBuilder可视化工具进行设计

















  
    
      
        
          
            
          
        
      
    
    
      
          
          
            

在登录控制层中,通过@FXML获取到了fxml格式的UI配置文件里使用fx:id标记的组件,然后直接调用业务层的login方法进行登录,最后根据返回的结果是否为null则判断是否登录成功,若登录成功则需要跳转窗口,若失败则弹出提示窗口(这个功能在业务逻辑层实现)

package com.uni.controller;

import com.uni.App;
import com.uni.pojo.User;
import com.uni.service.UserService;
import com.uni.utils.ServiceUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;

import java.net.URL;
import java.util.ResourceBundle;

public class LoginController implements ControlledStage, Initializable {

    private static UserService userService = ServiceUtils.userService;

    StageController controller;

    @FXML
    private TextField username;

    @FXML
    private PasswordField password;

    @FXML
    private void btLogin(){
        User login = userService.login(new User(username.getText(), password.getText()));
        if(login != null)
            goToMain();
    }

    public void setStageController(StageController stageController) {
        this.controller = stageController;
    }

    public void initialize(URL location, ResourceBundle resources) {
    }

    public void goToMain(){
        controller.change(App.mainViewID);
    }
}
7.4.2 主页面控制层

这里还没有设计逻辑跳转,但可以参照之前的登录控制层进行添加

package com.uni.controller;


public class MainController implements ControlledStage{
    private StageController controller;

    @Override
    public void setStageController(StageController stageController) {
        this.controller = stageController;
    }
}
八、核心业务逻辑

之前声明了UserService接口,定义了login()方法,先进行补充:

这里用到了JavaFX的alert警告框,通过调用showAndWati()方法就可以弹出这个窗口,则密码验证失败后弹出提示用户输入错误,方便用户操作。

package com.uni.service.impl;

import com.uni.dao.UserMapper;
import com.uni.pojo.User;
import com.uni.service.UserService;
import com.uni.utils.DBUtils;
import javafx.scene.control.alert;


public class UserServiceImpl implements UserService {

    private static UserMapper userMapper;
    public UserServiceImpl(){
        if(userMapper == null)
            userMapper = DBUtils.getSession().getMapper(UserMapper.class);
    }
    @Override
    public User login(User user) {
        User result = userMapper.selectByPassword(user) ;
        if(result == null){
            alert alert = new alert(alert.alertType.WARNING);
            alert.setTitle("登录提示");
            alert.setContentText("输入的账号或密码有误");
            alert.showAndWait();
        }
        return result;
    }
}
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号