كيفية كتابة حاسبة عميل خادم بسيط (JavaFX + EJB + WildFly)

لذلك ، لنفترض أننا نريد تنفيذ تطبيق خادم عميل حيث سيتم إنشاء البيانات اللازمة من جانب العميل ، وعلى جانب الخادم ، سيتم إجراء الحساب وإعادته إلى العميل نتيجة لذلك. إذا أخذنا في الحسبان آلة حاسبة بسيطة (دعنا نجعلها أسهل ، 4 مشغلات ، معاملات بدون كسور ، والعمل وفقًا للمخطط [المعامل 1] [المشغل] [المعامل 2] [النتيجة]) ، ولنفترض تنفيذها في لغة برمجة (نوع من البرمجة) ) ، على سبيل المثال ، Java ، باستخدام خادم التطبيق (على سبيل المثال ، WildFly / JBoss) + client (يمكنك استخدام JavaFX) ، يمكنك القيام بذلك بالطريقة التالية:

يمكن حل الخيار نفسه باستخدام RMI (استدعاء الطريقة عن بُعد) بدون خادم وعميل واجهة المستخدم الرسومية و EJB في وحدة التحكم ، لكننا لن نفكر في هذا الخيار ، ولكننا ننتقل إلى تنفيذ أكثر إثارة للاهتمام.

1. سنحتاج المكونات التالية:
1.1. JDK،
1.2. IDE (بدعم Java EE) ،
1.3. WildFly (أو خادم تطبيق Java آخر) ،
1.4. SceneBuilder (لتوفير الراحة وإنشاء واجهة المستخدم الرسومية السريعة).

لتوصيل العميل بالخادم ، سنستخدم JNDI (خدمة تسمية ودليل) باستخدام EJB (إطار عمل لبناء منطق العمل).

2. إنشاء تطبيق من جانب الخادم:
2.1. الواجهة البعيدة التي يتم من خلالها الاتصال بين العملاء والخادم (نستخدم التعليق التوضيحي عن بُعد - سيستخدم مكون EJB 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. فئة تقوم بتنفيذ هذه الواجهة (نستخدم التعليق التوضيحي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. أضف فئة الاستثناء الخاصة بنا ، والتي سوف تشير إلى القسمة على صفر أو التنسيق الخاطئ.

 package com.calc.server; public class MyException extends Exception { public MyException(String message) { super(message); } } 

2.4. باستخدام IDE ، نقوم بإنشاء ملف أذني (أرشيف المؤسسة) ، وبدء تشغيل الخادم (من الممكن باستخدام منفذ قياسي) ، ونشره ، وإذا لم يتم ملاحظة أي أخطاء ، فسيتم الانتهاء من جزء الخادم.

يمكن أن يكون سجل الخادم مثل هذا:

  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. نخلق تنفيذ جزء العميل:
3.1. في SceneBuilder ، ارسم تخطيط الحاسبة التالي (main.fxml) ، لن نقوم بالالتفاف على المغلق الآن:

 <?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. نقوم بتوصيل وحدة تحكم الفصل بنموذج fxml ، لإلغاء تأمين واجهة المستخدم الرسومية (نموذج مثبت) أثناء انتظار البيانات من الخادم ، أضف سلسلة جديدة إلى الزر "=":

عرض الرمز
 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"); // props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); // props.put(Context.PROVIDER_URL, "remote+http://localhost:8080"); props.put(Context.PROVIDER_URL, "http-remoting://localhost:8080"); // props.put("jboss.naming.client.ejb.context", "true"); // props.put(Context.SECURITY_PRINCIPAL, "admin"); // props.put(Context.SECURITY_CREDENTIALS, "123"); Context ctx = new InitialContext(props); //System.out.println(ctx.getEnvironment()); CalcRemote calcRemote = (CalcRemote) ctx.lookup("Calc_ear_exploded/ejb/CalcSessionEJB!com.calc.server.CalcRemote"); //java:jboss/exported/Calc_ear_exploded/ejb/CalcSessionEJB!com.calc.server.CalcRemote String res = Integer.toString(process(calcRemote, data)); displayTextField.setText(res); System.out.println(res); } private int process(CalcRemote calcRemote, String[] resData) throws MyException { int operand1 = Integer.parseInt(resData[0]); int operand2 = Integer.parseInt(resData[1]); String operator = resData[2]; switch (operator) { case "+": return calcRemote.add(operand1, operand2); case "-": return calcRemote.sub(operand1, operand2); case "*": return calcRemote.mul(operand1, operand2); case "/": return calcRemote.div(operand1, operand2); } return 0; } @Override public void run() { displayTextField.setText("WAITING..."); try { doRequest(calculator.getResult()); } catch (NamingException ex) { ex.printStackTrace(); } catch (MyException ex) { displayTextField.setText(ex.getMessage()); } } } 



3.3. أضف منطق أبسط آلة حاسبة:

 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. أضف مكتبة العميل (في حالة WildFly فمن jboss-client.jar) ، قم بتشغيل واجهة المستخدم الرسومية.

كما يتضح من الرموز المرفقة ، يقوم المستخدم بكتابة الأرقام في المخزن المؤقت للمعاملات ، وتحديد المشغل ، عند الضغط على الزر "=" ، يتم إجراء اتصال بالخادم (عبر خدمة JNDI) ، يشير النقش على الشاشة "WAITING ..." إلى أن الخادم ينتظر استجابة.

نلاحظ أيضًا استثناءين: NumberFormatException (يتم اكتشافه عندما يقوم المستخدم بإدخال البيانات على العميل) و ArithmeticException (يتم اكتشافه عند القسمة على صفر على الخادم).

Source: https://habr.com/ru/post/ar477436/


All Articles