Donc, disons que nous voulons implémenter une application client-serveur où les données nécessaires seront générées côté client, et côté serveur, le calcul sera effectué et renvoyé au client en conséquence. Si nous prenons en compte une simple calculatrice (simplifions encore plus, 4 opérateurs, opérandes sans fractions et travaillons selon le schéma [opérande1] [opérateur] [opérande2] [résultat]) et, disons, implémentons-le dans une sorte de langage de programmation (langage de programmation ), par exemple, Java, en utilisant le serveur d'applications (par exemple, WildFly / JBoss) + client (vous pouvez utiliser JavaFX), vous pouvez le faire de la manière suivante:
La même option peut être résolue en utilisant RMI (Remote Method Invocation) sans serveur, client GUI et EJB dans la console, mais nous ne considérerons pas cette option, mais procédons à une implémentation plus intéressante.1. Nous aurons besoin des ingrédients suivants:
1.1. JDK,
1.2. IDE (avec support Java EE),
1.3. WildFly (ou un autre serveur d'applications Java),
1.4. SceneBuilder (pour plus de commodité et de création graphique rapide).
Pour connecter le client au serveur, nous utiliserons JNDI (un service de nommage et d'annuaire) en utilisant EJB (un cadre pour la construction de la logique métier).
2. Créez une implémentation côté serveur:
2.1. L'interface distante à travers laquelle la communication entre les clients et le serveur aura lieu (nous utilisons l'annotation
distante - le composant EJB utilisera 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. Une classe qui implémente cette interface (nous utilisons l'annotation @Stateless - un composant de session sans état).
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. Ajoutez notre classe d'exception, qui signalera la division par zéro ou le mauvais format.
package com.calc.server; public class MyException extends Exception { public MyException(String message) { super(message); } }
2.4. À l'aide de l'IDE, nous créons un fichier d'oreille (Enterprise Archive), démarrons le serveur (c'est possible avec un port standard), déployons-y et si aucune erreur n'a été remarquée, alors la partie serveur est terminée.
Le journal du serveur peut être comme ceci:
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. Nous créons l'implémentation de la partie client:
3.1. Dans SceneBuilder, esquissez la disposition de la calculatrice suivante (main.fxml), nous n'allons pas envelopper CSS pour l'instant:
<?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. Nous connectons le contrôleur de classe au formulaire fxml, pour déverrouiller l'interface graphique (formulaire collant) en attendant les données du serveur, ajoutez un nouveau thread au bouton "=":
Vue de code 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. Ajoutez la logique de la calculatrice la plus simple:
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. Ajoutez la bibliothèque client (dans le cas de WildFly, c'est jboss-client.jar), exécutez l'interface graphique.
Comme le montrent les codes joints, l'utilisateur saisit des chiffres dans la mémoire tampon des opérandes, sélectionne l'opérateur, lorsque le bouton "=" est enfoncé, une connexion est établie avec le serveur (via le service JNDI), l'inscription sur l'affichage "WAITING ..." indiquera que le serveur attend une réponse.
Nous notons également quelques exceptions: NumberFormatException (interceptées lorsque l'utilisateur entre des données sur le client) et ArithmeticException (interceptées lorsqu'elles sont divisées par zéro sur le serveur).