logo
Разработка Java-приложения для работы с удалённой базой данных

2. Сервер

В InteliJIDEA мы создаём проект ServerForLibrary и ServerForLibrary2. В каждом проекте мы создаём по классу Server. В классах мы создаём по методу buildGUI(), который реализует интерфейс нашего сервера. А в конце нашего метода мы вызываем метод conectBD и go().

Первый метод устанавливает соединение с базой данных MySQL. В начале нашего метода мы создаём драйвер и регистрируем его:

Driver driver = new FabricMySQLDriver();

DriverManager.registerDriver(driver);

Далее устанавливаем соединение с базой данных:

conneсtion=DriverManager.getConnection("jdbc:mysql://localhost:3306/library1", "root", "root");

Поясним параметр метода getConnection

"jdbc:mysql://localhost:3306/library1":

“jdbc” - коннектор, с помощью которого осуществляется подключение;

“mysql” - база данных,

“localhost:3306” - локальная сеть,

“library1” - первая база данных, далее указываются логин и пароль;

“root” в первом случае это логин, а во втором случае пароль.

Далее создаётся запрос.

Код метода conectBD() имеет следующий вид:

public void conectBD(){

try {

Driver driver = new FabricMySQLDriver();

DriverManager.registerDriver(driver);

connection = DriverManager.getConnection(HOST, USERNAME, PASSWORD);

statement = connection.createStatement();

textField.setText("Соединение с mysql установлено!!!");

} catch (SQLException e) {

e.printStackTrace();

textField.setText("Соединение с mysql отсутствует!!!");

JOptionPane.showMessageDialog(null,"Соединение с mysql отсутствует!!!");

}

}

Метод go() создаёт северский порт, в нашем случае это “4000”, потом использую цикл while в котором для каждого вошедшего клиента мы создаём порт для обратной связи, далее мы вызываем нить, которая считывает данные с клиентов.

Код метода go() имеет следующий вид:

private void go() {

clientOutputStreams = new ArrayList<ObjectOutputStream>();

try{

ServerSocket serverSock = new ServerSocket(4000); //создаём порт серверский

while (true){

Socket clientSocket = serverSock.accept();//клиент вошёл и созд. для него порт

ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());//поток для отправки

clientOutputStreams.add(out);

//нить, которая читает данные с вошедшего клиента

Thread t = new Thread(new ClientHandler(clientSocket));

t.start();//запускает нить

t.join();//ждёт окончания завершения нити

System.out.println("got a connection");

}

}catch (Exception ex){ex.printStackTrace();}

}

Во втором сервере создаём такие же методы go() и conectBD(), только в методе go() мы создаём серверский порт “4002”.

В интерфейс ClientHandler в конструкторе параметром является сокет клиента, а в параметре создаётся объект Socket, который состоит из IP- адреса и TCP- порта, и создаётся соединение с потоком для считывания данных отправленных клиентами.

Далее переопределяем метод run() в котором создаём цикл while, который считывает объекты, в нашем случае клиенты оправляют текстовые сообщения, содержащие sql-запросы. Потом вызывается метод tellEveryone(massege), в котором в качестве параметра является сообщение клиента.

Метод tellEveryone(Object one) состоит из шести основных if. Сначала создаём ObjectOutputStream поток для отправки.

Первый if принимает от клиента обычный запрос “Select * from books”, который выводит содержание таблицы “books”. Помещаем в объект ResultSet, переменная resultSet (объявили её в начале класса ClientHandler - это глобальная переменная), которая содержит все строки удовлетворяющие запросу. Так как объект ResultSet не сериализуемый объект, то его мы не можем отправить клиенту. Сериализация - это сохранения состояния объекта. Чтобы объект был сериализованным, он должен быть “помечен” или наследовать интерфейс Serializable. Тогда можно передавать его через потоки. Но объект ResultSet - это класс пакета java.sql, который не сериализуется. Поэтому создаём список, состоящий из объектов (ArrayList<Object> aList = new ArrayList<Object>()), в дальнейшем считываем построчно в цикле while содержимое resultSet и добавляем в список. После выхода из первого if отправлям этот список клиенту через строчку out.writeObject(aList), второй if аналогично.

В третьем if мы принимаем сообщение от клиента на добавление строки в таблицу. Четвёртый if обновляет запись, пятый - удаляет, а шестой выводит, выполняет и отправляет результаты выборки.

В самом классе Server есть четыре кнопки, каждой кнопке соответствует внутренний класс, которые наследуют интерфейсы ActionListener.

При нажатии кнопки “Показать книги” сначала очищается таблица, потом присваивается переменой resultSet результаты выборки, удовлетворяющие условию. Далее именуем столбцы и заполняем данными таблицу.

При нажатии кнопки “Показать книги”, сначала названиям столбцам даем нейтральные имена (“--”). Далее всем ячейкам таблицы присваиваю пустые значения. При нажатии кнопки “Выход” закрываем поток “connection”, далее просто выходим из программы строчкой “System.exit(0)”.

Сервер изображён на рисунке 1.

Рисунок 1- Сервер для библиотеки

На рисунке 2 изображено действие при нажатии кнопки ”Показать книги”:

Рисунок 2- Действие при нажатии кнопки

На рисунке 3 изображено действие при нажатии кнопки “Показать читателей”.

Рисунок 3- Действие при нажатии кнопки

И при нажатии кнопки очистить, таблица очистится, а при нажатии кнопки выход, приложение закроется. Для второго сервера все методы аналогичные первому серверу.