基于MVC架构,JavaFX与Spring整合

基于MVC架构,JavaFX与Spring整合

探究了几天JavaFX,,因为它自身的一些优点,觉得JavaFX在将来的开发中会发展起来的。选择JavaFX因为自己本身Javaer,JavaFX的学习成本不高。而JavaFX跟MVC的开发有点像,同样可以将视图、模型、和控制器分开。对于JavaFX的UI表现我觉得算是Java里面自由性最好的。

JavaFX从08年到现在也差不多10年,虽然2.0版本后有很大的变化,在国内的教程更新地慢。找了几天JavaFX的资料,国内的资料真的少,而且大多是翻译官方的。

JavaFX可以整合spring,而spring可以整合数据库的操作,并且可以使用spring实现一些基础功能。现在将工程目录架构整理如下:

使用maven管理,

java文件夹的包有controller、dao、entity、service、还有一个util工具包和Main.java作为程序主入口。

基于MVC架构,JavaFX与Spring整合_第1张图片

resources文件夹中有config(spring配置文件)、css(样式文件)、fxml(场景的fxml文件)、i18n(国际化资源文件)

基于MVC架构,JavaFX与Spring整合_第2张图片

util工具包包含一些工具类,在这里主要实现的功能是FXML加载,JSR303验证和获取国际化资源。

下面来说说功能的实现,首先看看spring的配置文件spring-config.xml

 



    
    
    
    

    
    
    
    
        
        
        
        
        
        
        
        
        
        
    



    
    
    
        
        
        
        
        
        
            
        
        
        
            
                
                
                
                
                
                
            
        
        
        
            
        
        
        
            
                
                
                
                
                
                
                
                
                
                
                
                
            
        
    

    
    

    
    
        
    

    
    

    
    
        
            
                
                classpath:/i18n/validation_messages
                classpath:/i18n/ui_main
                classpath:/i18n/ui_login
                classpath:/i18n/ui_register
            
        
        
    
    
        
        
            
        
    


    
    
        
        
        
        
    

 

i18n类的实现,主要是在spring配置实现对资源文件的引用,可以通过getMessage(String s)获取资源信息

 

package com.cjx913.al.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.stereotype.Component;

import java.util.Locale;
import java.util.ResourceBundle;

@Component
public class I18n {

    @Autowired
    private ResourceBundle resourceBundle;

    public ResourceBundle getResourceBundle() {
        return resourceBundle;
    }

    public String getMessage(String s){
        return this.resourceBundle.getString(s);
    }
}

Jsr303Validation类的实现,依赖于spring配置的validator,重写了验证方法,返回字段名和错误信息映射的Map

package com.cjx913.al.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

@Component
public class Jsr303Validator {

    @Autowired
    private Validator validator;

    public Validator getValidator() {
        return validator;
    }

    /**
     * @param t   需要校检的对象
     * @param 
     * @return 错误字段和信息的映射
     */
    public  Map  validated(T t, Class ... groups) {
//        t爲空,返回null
        if (t == null) {
            return null;
        }
//        对t进行校验
        Set > violations = validator.validate(t, groups);
//        校检内有错误
        return getFieldErrorMap(violations);
    }

    public  Map  validated(T t, String propertyName, Class ... groups) {
//        t爲空,返回null
        if (propertyName == null || t == null) {
            return null;
        }
//        对t进行校验
        Set > violations = validator.validateProperty(t, propertyName, groups);

        return getFieldErrorMap(violations);
    }

    public  Map  validated(Class  beanType, String propertyName, Object value, Class ... groups) {
//        t爲空,返回null
        if (propertyName == null || value == null) {
            return null;
        }
//        对t进行校验
        Set > violations = validator.validateValue(beanType, propertyName, value, groups);

        return getFieldErrorMap(violations);
    }

    private  Map  getFieldErrorMap(Set > violations) {

        Map  map = null;
        //        校检内有错误
        if (violations.size() == 0) {
            return null;
        } else {
            map = new HashMap <>();
//        保存错误信息:Map
            Iterator > iterator = violations.iterator();
            ConstraintViolation  violation = null;
//            遍历校验信息
            while (iterator.hasNext()) {
                violation = iterator.next();
                String field = violation.getPropertyPath().toString();
                String message = violation.getMessage();
                map.put(field, message);
            }
            return map;
        }
    }
}

 

重点是SpringFXMLLoader的实现

package com.cjx913.al.util;

import com.cjx913.al.Main;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.util.BuilderFactory;
import javafx.util.Callback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

@Component
public class SpringFxmlLoader extends FXMLLoader {
    

    @Autowired
    private ResourceBundle resourceBundle;


    public  T load(String url) {
        try (InputStream fxmlStream = getClass().getResourceAsStream(url)) {
            super.setLocation(this.getClass().getClassLoader().getResource("/"));
            super.setResources(resourceBundle);
            super.setControllerFactory(new Callback , Object>() {
                @Override
                public Object call(Class  clazz) {
                    
                return Main.APPLICATION_CONTEXT.getBean(clazz);

} }); return this.load(fxmlStream); } catch (IOException ioException) { throw new RuntimeException(ioException); } }}

FXMLLoader对象的需要调用setResource()绑定资源,可以在fxml使用%实现国际化的目的,而参数可以通过spring注解注入、setLocation()设至基本路径,方便fxml中css和fxml和其他文件导入、setControllerFactory()使用spring管理的controller。

这是一个普通的Main类用于启动JavaFX程序和spring

package com.cjx913.al;

import com.cjx913.al.util.SpringFxmlLoader;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main extends Application {
    public static final ApplicationContext APPLICATION_CONTEXT
            = new ClassPathXmlApplicationContext("/config/spring-config.xml");


    public static void main(String[] args){
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        SpringFxmlLoader springFxmlLoader = Main.APPLICATION_CONTEXT.getBean(SpringFxmlLoader.class);
        BorderPane root = springFxmlLoader.load("/fxml/main.fxml");
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}
public static final ApplicationContext APPLICATION_CONTEXT
            = new ClassPathXmlApplicationContext("/config/spring-config.xml");


    public static void main(String[] args){
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        SpringFxmlLoader springFxmlLoader = Main.APPLICATION_CONTEXT.getBean(SpringFxmlLoader.class);
        BorderPane root = springFxmlLoader.load("/fxml/main.fxml");
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

 

BaseController的实现,用于被其他controller类继承,获取一些公共的方法,在controller类中使用@Controller注解

 

package com.cjx913.al.controller;

import com.cjx913.al.util.I18n;
import com.cjx913.al.util.Jsr303Validator;
import com.cjx913.al.util.SpringFxmlLoader;
import javafx.fxml.Initializable;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class BaseController implements Initializable {
    @Autowired
    private SpringFxmlLoader springFxmlLoader;
    @Autowired
    private I18n i18n;
    @Autowired
    private Jsr303Validator jsr303Validator;

    public SpringFxmlLoader getSpringFxmlLoader() {
        return springFxmlLoader;
    }

    public I18n getI18n() {
        return i18n;
    }

    public Jsr303Validator getJsr303Validator() {
        return jsr303Validator;
    }
}

 

尽可能减少java代码创建容器、控件等,应该使用fxml创建用户界面

关于fxml的使用,还有数据绑定下次再写

 

 

你可能感兴趣的:(JavaFX)