Jadi, katakanlah kita ingin mengimplementasikan aplikasi client-server di mana data yang diperlukan akan dihasilkan di sisi klien, dan di sisi server, perhitungan akan dilakukan dan dikembalikan ke klien sebagai hasilnya. Jika kita memperhitungkan kalkulator sederhana (mari kita membuatnya lebih sederhana, 4 operator, operan tanpa fraksi dan bekerja sesuai dengan skema [operand1] [operator] [operand2] [hasil]) dan, katakanlah, implementasikan dalam beberapa jenis bahasa pemrograman (bahasa pemrograman) ), misalnya, Java, menggunakan server aplikasi (misalnya, WildFly / JBoss) + klien (Anda dapat menggunakan JavaFX), Anda dapat melakukan ini dengan cara berikut:
Opsi yang sama dapat diselesaikan menggunakan RMI (Remote Method Invocation) tanpa server, klien GUI, dan EJB di konsol, tetapi kami tidak akan mempertimbangkan opsi ini, tetapi melanjutkan ke implementasi yang lebih menarik.1. Kami membutuhkan bahan-bahan berikut:
1.1. JDK,
1.2. IDE (dengan dukungan Java EE),
1.3. WildFly (atau server aplikasi Java lainnya),
1.4. SceneBuilder (untuk kenyamanan dan pembuatan GUI cepat).
Untuk menghubungkan klien ke server, kami akan menggunakan JNDI (layanan penamaan dan direktori) menggunakan EJB (kerangka kerja untuk membangun logika bisnis).
2. Buat implementasi dari sisi server:
2.1. Antarmuka jarak jauh di mana komunikasi antara klien dan server akan terjadi (gunakan anotasi
Remote - komponen EJB akan menggunakan RMI).
package com.calc.server; import javax.ejb.Remote; @Remote public interface CalcRemote { int add(int a, int b); int sub(int a, int b); int mul(int a, int b); int div(int a, int b) throws MyException; }
2.2. Kelas yang mengimplementasikan antarmuka ini (kami menggunakan penjelasan @Stateless - komponen sesi stateless).
package com.calc.server; import javax.ejb.Stateless; @Stateless(name = "CalcSessionEJB") public class CalcSessionBean implements CalcRemote { public CalcSessionBean() { } @Override public int add(int a, int b) { return a + b; } @Override public int sub(int a, int b) { return a - b; } @Override public int mul(int a, int b) { return a * b; } @Override public int div(int a, int b) throws MyException { try { return a / b; } catch (ArithmeticException ex) { throw new MyException("Divide by Zero!!!"); } } }
2.3. Tambahkan kelas pengecualian kami, yang akan menandakan pembagian dengan nol atau format yang salah.
package com.calc.server; public class MyException extends Exception { public MyException(String message) { super(message); } }
2.4. Dengan menggunakan IDE, kami membuat file-telinga (Enterprise Archive), memulai server (dimungkinkan dengan port standar), menyebar ke sana, dan jika tidak ada kesalahan yang diketahui, maka bagian server selesai.
Log server bisa seperti ini:
java:global/Calc_ear_exploded/ejb/CalcSessionEJB!com.calc.server.CalcRemote java:app/ejb/CalcSessionEJB!com.calc.server.CalcRemote java:module/CalcSessionEJB!com.calc.server.CalcRemote java:jboss/exported/Calc_ear_exploded/ejb/CalcSessionEJB!com.calc.server.CalcRemote ejb:Calc_ear_exploded/ejb/CalcSessionEJB!com.calc.server.CalcRemote java:global/Calc_ear_exploded/ejb/CalcSessionEJB java:app/ejb/CalcSessionEJB java:module/CalcSessionEJB
3. Kami membuat implementasi bagian klien:
3.1. Di SceneBuilder, buat sketsa tata letak kalkulator berikut (main.fxml), kami tidak akan membungkus css untuk saat ini:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="321.0" prefWidth="231.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.calc.client.impl2.controller.Controller"> <children> <Label disable="false" layoutX="24.0" layoutY="15.0" prefHeight="28.0" prefWidth="189.0" text="EJB Calculator" /> <TextField fx:id="displayTextField" layoutX="24.0" layoutY="43.0" prefHeight="56.0" prefWidth="182.0" /> <Button fx:id="num7Button" layoutX="24.0" layoutY="110.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="7" /> <Button fx:id="num8Button" layoutX="72.0" layoutY="110.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="8" /> <Button fx:id="num9Button" layoutX="119.0" layoutY="110.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="9" /> <Button fx:id="divButton" layoutX="166.0" layoutY="110.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="/" /> <Button fx:id="num4Button" layoutX="24.0" layoutY="161.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="4" /> <Button fx:id="num5Button" layoutX="72.0" layoutY="161.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="5" /> <Button fx:id="num6Button" layoutX="119.0" layoutY="161.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="6" /> <Button fx:id="mulButton" layoutX="166.0" layoutY="161.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="*" /> <Button fx:id="num1Button" layoutX="24.0" layoutY="209.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="1" /> <Button fx:id="num2Button" layoutX="72.0" layoutY="209.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="2" /> <Button fx:id="num3Button" layoutX="119.0" layoutY="209.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="3" /> <Button fx:id="subButton" layoutX="166.0" layoutY="209.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="-" /> <Button fx:id="num0Button" layoutX="24.0" layoutY="259.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="0" /> <Button fx:id="clrButton" layoutX="72.0" layoutY="259.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="C" /> <Button fx:id="resButton" layoutX="119.0" layoutY="259.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="=" /> <Button fx:id="addButton" layoutX="166.0" layoutY="259.0" mnemonicParsing="false" prefHeight="39.0" prefWidth="40.0" text="+" /> </children> </AnchorPane>
3.2. Kami menghubungkan pengontrol kelas ke formulir fxml, untuk membuka kunci GUI (formulir tempel) sambil menunggu data dari server, tambahkan utas baru ke tombol "=":
Tampilan kode package com.calc.client.impl2.controller; import com.calc.server.CalcRemote; import com.calc.server.MyException; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import java.util.Properties; public class Controller implements Runnable { private Calculator calculator; @FXML private TextField displayTextField; @FXML private Button num1Button; @FXML private Button num2Button; @FXML private Button num3Button; @FXML private Button num4Button; @FXML private Button num5Button; @FXML private Button num6Button; @FXML private Button num7Button; @FXML private Button num8Button; @FXML private Button num9Button; @FXML private Button num0Button; @FXML private Button addButton; @FXML private Button subButton; @FXML private Button mulButton; @FXML private Button divButton; @FXML private Button clrButton; @FXML private Button resButton; @FXML private void initialize() { System.out.println("initialize()"); calculator = new Calculator(); displayTextField.setText("0"); num1Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("1"))); num2Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("2"))); num3Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("3"))); num4Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("4"))); num5Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("5"))); num6Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("6"))); num7Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("7"))); num8Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("8"))); num9Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("9"))); num0Button.setOnAction(event -> displayTextField.setText(calculator.addNumber("0"))); addButton.setOnAction(event -> { calculator.addOperator("+"); displayTextField.setText(""); }); subButton.setOnAction(event -> { calculator.addOperator("-"); displayTextField.setText(""); }); mulButton.setOnAction(event -> { calculator.addOperator("*"); displayTextField.setText(""); }); divButton.setOnAction(event -> { calculator.addOperator("/"); displayTextField.setText(""); }); resButton.setOnAction(event -> new Thread(this).start()); clrButton.setOnAction(event -> displayTextField.setText("")); } private void doRequest(String[] data) throws NamingException, MyException { Properties props = new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
3.3. Tambahkan logika kalkulator paling sederhana:
package com.calc.client.impl2.controller; import com.calc.server.MyException; public class Calculator { private String buffer = "", operator, operand1, operand2; private boolean isOperator = false; public String addNumber(String value) { buffer += value; if (!isOperator) { operand1 = buffer; } else { operand2 = buffer; } return buffer; } public void addOperator(String value) { operator = value; buffer = ""; isOperator = true; } public String[] getResult() throws MyException { isOperator = false; buffer = ""; int check; try { check = Integer.parseInt(operand1); check = Integer.parseInt(operand2); } catch (NumberFormatException ex) { throw new MyException("Wrong format!!!"); } return new String[]{operand1, operand2, operator}; } }
3.5. Tambahkan perpustakaan klien (dalam kasus WildFly itu adalah jboss-client.jar), jalankan GUI.
Seperti dapat dilihat dari kode terlampir, pengguna mengetik angka dalam buffer untuk operan, memilih operator, ketika tombol "=" ditekan, koneksi dilakukan ke server (melalui layanan JNDI), tulisan pada layar "WAITING ..." akan menunjukkan bahwa server sedang menunggu jawaban.
Kami juga mencatat beberapa pengecualian: NumberFormatException (ditangkap ketika pengguna memasukkan data pada klien) dan ArithmeticException (ditangkap ketika dibagi dengan nol di server).