Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
JavaFX.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
4.88 Mб
Скачать

3.1.5. Створення допоміжного класу для роботи з моделями

Для всіх моделей, які будуть створюватися, необхідно забезпечити мінімальну спільну кількість функціоналу. Наприклад CRUD (create, remove, update, delete). Щоб не дублювати код для кожної моделі, необхідно створити один клас, який зможе виконувати CRUD-дії зі всіма моделями.

Для цього необхідно створити новий пакет managers (javafxapp.managers), та в ньому клас GenericDAO з наступним кодом:

public class GenericDAO<T extends Serializable> {

private EntityManagerFactory emf = JavafxApp.emf;

private EntityManager em;

private Class<T> clazz;

public EntityTransaction entityTransaction;

public GenericDAO(Class<T> clazz) {

this.clazz = clazz;

em = emf.createEntityManager();

entityTransaction = em.getTransaction();

entityTransaction.begin();

}

@Override

protected void finalize() throws Throwable{

entityTransaction.commit();

em.close();

super.finalize();

}

public void create(T t) {

em.persist(t);

}

public T getByField(String fieldname, String value){

try{

Query q = em.createQuery("SELECT u FROM "+ clazz.getSimpleName() +" u WHERE u."+ fieldname +" = ?1");

return (T)q.setParameter(1, value).getSingleResult();

}catch(Exception ex){

return null;

}

}

public T read(long id) {

return em.find(clazz, id);

}

public void update(T t) {

em.merge(t);

entityTransaction.commit();

entityTransaction.begin();

}

public void delete(T t) {

t = em.merge(t);

em.remove(t);

}

public List getAll() {

return em.createQuery("SELECT u FROM "+ clazz.getSimpleName() +" u").getResultList();

}

public void updateList(){

entityTransaction.commit();

entityTransaction.begin();

}

}

Потрібна гнучкість забезпечується за допомогою generic types. При створенні менеджеру необхідно буде передати конкретну модель, з якою він буде працювати. І під час виконання програми JVM підставить цей клас на місце T.

3.1.6. Впровадження логіки авторизації користувача

Все пов’язане з авторизацією користувачів буде знаходитися в окремому пакеті. Це забезпечує легке перенесення логіки та структурує додаток. Отже створіть пакет login (javafxapp.login). До нього перенесіть Sample.fxml та Sample.java та змініть імена на Login.fxml та Login.java (або видаліть їх з проекту і створіть в пакеті javafxapp.login нові).

Вміст файлу Sample.fxml повинен бути таким:

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

<?import javafx.scene.layout.*?>

<?import javafx.scene.control.*?>

<?import javafx.scene.*?>

<BorderPane fx:controller ="javafxapp.login.Login" xmlns:fx="http://javafx.com/fxml">

<top>

<StackPane>

<Label text="Authorization" style="-fx-font: NORMAL 20 Tahoma;"/>

</StackPane>

</top>

<center>

<GridPane alignment="top_center" hgap="8" vgap="8"

style="-fx-padding: 40 0 0 0">

<children>

<Label text="Sign in:"

style="-fx-font: NORMAL 14 Tahoma;"

GridPane.columnIndex="0" GridPane.rowIndex="0"/>

<Label text="Username:"

GridPane.columnIndex="0" GridPane.rowIndex="1"

labelFor="$usernameField"/>

<TextField fx:id="usernameField" prefColumnCount="15"

GridPane.columnIndex="1" GridPane.rowIndex="1"/>

<Label text="Password:"

GridPane.columnIndex="0" GridPane.rowIndex="2"

labelFor="$passwordField"/>

<PasswordField fx:id="passwordField" prefColumnCount="15"

GridPane.columnIndex="1" GridPane.rowIndex="2"

onAction="#processLogin"/>

<Button fx:id="submitButton" text="Submit"

GridPane.columnIndex="1" GridPane.rowIndex="3"

onAction="#processLogin"/>

<Label fx:id="errorText"

GridPane.columnIndex="1" GridPane.rowIndex="4"

style="-fx-text-fill: #ff0000;"/>

</children>

</GridPane>

</center>

</BorderPane>

Отже fx:controller ="javafxapp.login.Login" вказує на клас, який буде контролером для цього fxml файлу. Hgap та vgap вказують кількість пропусків між елементами GridPane. Властивість prefColumnCount="15" у TextField та PasswordField вказує довжину цих елементів. Властивість onAction="#processLogin" вказує на метод контролера, який буде викликатися при певній події. А за допомогою fx:id (наприклад fx:id="errorText") можна звертатися до елементу з класу контролера.

Вміст файлу Login.java повинен бути таким:

package javafxapp.login;

import javafx.event.ActionEvent;

import javafx.fxml.FXML;

import javafx.scene.control.Label;

import javafx.scene.control.PasswordField;

import javafx.scene.control.TextField;

import javafxapp.JavafxApp;

public class Login {

@FXML private Label errorText;

@FXML private TextField usernameField;

@FXML private PasswordField passwordField;

@FXML protected void processLogin(ActionEvent event) {

errorText.setText("Hello!");

}

}

Отже в контролері поки що буде знаходитися заглушка. Наступні зміни потрібно зробити у класі JavafxApp:

package javafxapp;

import java.util.logging.FileHandler;

import java.util.logging.Level;

import java.util.logging.Logger;

import javafx.application.Application;

import javafx.event.EventHandler;

import javafx.fxml.FXMLLoader;

import javafx.scene.Parent;

import javafx.scene.Scene;

import javafx.stage.Stage;

import javafx.stage.WindowEvent;

import javafxapp.models.UserFx;

import javafxapp.login.Auth;

import javax.persistence.EntityManagerFactory;

import javax.persistence.Persistence;

public class JavafxApp extends Application {

private static JavafxApp instance;

public static EntityManagerFactory emf = Persistence.createEntityManagerFactory("JavafxAppPU");

public Logger logger;

public UserFx loggedUser = null;

public JavafxApp(){

try{

FileHandler hand = new FileHandler("log_info.log");

logger = Logger.getLogger("log_file");

logger.addHandler(hand);

}catch(Exception ex){

ex.printStackTrace();

}

instance = this;

}

public static JavafxApp getInstance() {

return instance;

}

public static void main(String[] args) {

Application.launch(JavafxApp.class, args);

}

@Override

public void start(Stage stage) throws Exception {

stage.setTitle("Login");

Parent root = FXMLLoader.load(this.getClass().getResource("login/Login.fxml"));

stage.setScene(new Scene(root, 500, 200));

stage.show();

}

public boolean userLogging(String username, String password){

//TODO

}

public void userLogout(){

this.loggedUser = null;

}

}

В класі поле public static EntityManagerFactory emf зберігає фабрику, через яку в GenericDAO отримуємо EntityManager для роботи з базою даних. public UserFx loggedUser — буде зберігати активного користувача (той, що зайшов в систему). В конструкторі класу ініціалізується logger для запису помилок та виняткових ситуацій у файл. В цьому файлі метод userLogging поки що теж потрібно зробити заглушкою. На цьому етапі можна запустити додаток та подивитись на те, що вже зроблено (рис. 3.5).

Тепер потрібно в пакеті javafxapp.login створити файл Auth.java, який буде зберігати логіку аутентефікації користувача.

import javafxapp.managers.GenericDAO;

import javafxapp.models.UserFx;

public class Auth {

public static UserFx validate(String username, String password){

GenericDAO<UserFx> userManager = new GenericDAO(UserFx.class);

UserFx ufx = userManager.getByField("username", username);

if (ufx != null && ufx.getPassword().equals(password))

return ufx;

else

return null;

}

}

Рис. 3.5. Вигляд додатку після натиснутої кнопки Submit

За допомогою GenericDAO виконується пошук по базі даних. Якщо логін і пароль співпадають — повертається юзер, якщо ні — null.

Тепер потрібно позбавитися заглушок. В класі JavafxApp потрібно написати:

public boolean userLogging(String username, String password){

this.loggedUser = Auth.validate(username, password);

return loggedUser != null;

}

В класі Login потрібно написати:

@FXML protected void processLogin(ActionEvent event) {

if(!JavafxApp.getInstance().userLogging(usernameField.getText(), passwordField.getText()))

errorText.setText("Invalid username or password.");

else{

errorText.setText("It's ok!");

}

}

Тепер потрібно переконатися, що все працює вірно. Запускаємо додаток та вводимо валідні дані, які є у базі даних, а потім дані, яких немає. Це зображено на рис. 3.6 та 3.7 відповідно.

Рис. 3.6. Вигляд додатка з введеними валідними даними

Рис. 3.7. Вигляд додатка з введеними не валідними даними

Практичне завдання

  1. Зробити на формі авторизації перевірку на пусті значення полів та вивести відповідне повідомлення.

  2. Добавити в модель UserFx поле banned і якщо banned = true, то не пускати користувача в систему і написати відповідне повідомлення. (Якщо змінюється модель, то необхідно видалити змінені таблиці з бази даних, щоб JPA створив нові).

Контрольні питання

  1. Що таке FXML?

  2. Для чого використовують JavaFx?

  3. Що таке JPA? Чому розробники використовують JPA?

  4. Для чого використовують IDE?