يقوم Jaxb (XJC) بإنشاء فئات من مخطط XML (XSD) مع وصف الفئة والحقل كتعليقات توضيحية. XJC المساعد

أعتقد أن العديد من مطوري Java الذين جاءوا مرة واحدة على الأقل عبر Web- استخدموا إنشاء فئات Java DTO كما هو موضح في XML Schema ( XSD ) . تتعامل Jaxb مع هذا مع اثارة ضجة ، بغض النظر عن كيفية استخدامها ، عبر xjc أو مكالمة wsimport من سطر الأوامر ، أو الإضافات الأساسية أو المخفية.


إنها عملية سريعة وسهلة لإنشاء فصول من مخطط XSD . ولكن هنا مشكلة واحدة - الأوصاف المتاحة في الدائرة الأصلية تختفي بالكامل تقريبًا!


في الممارسة العملية ، نظرًا لأن الفئة نفسها فقط سيكون لها وصف Javadoc ، بتنسيق ثابت (حيث لا يمكنك فصل الوصف وجزء XML بدون العناصر النظامية ، على سبيل المثال) ، فإن وصف الحقول (الحقول) غائب تمامًا. وإذا كنت ، مثلي ، في حاجة إليها أيضًا في وقت التشغيل ( runtime ) ، فهناك مشكلة على الإطلاق .


من الغريب أن الأمر قد يبدو ، فقد كان من الضروري التغلب على هذا الأمر ، واستغرقت المهمة الكثير من الوقت ، ونتيجة لذلك كتبت مكونًا إضافيًا ، أود تقديمه على أمل أن يتمكن من إنقاذ بعض الأشخاص بضع ساعات في المستقبل.


Jaxb الميزات في لمحة


Jaxb لها تاريخ طويل ووصف رسمي جيد ، بما في ذلك إضافة السلوك إلى الطبقات التي تم إنشاؤها.


الأداة الرئيسية لاستدعاء إنشاء فئة من سطر الأوامر - xjc أيضا ليس لديها أصغر عدد من المفاتيح. ومع ذلك ، ليس واحد منهم لحالتنا.


بالطبع ، لا يمكنك إلا أن تذكر -b ، حيث يمكنك توفير رابطك الخاص. وهذا سلاح قوي جدًا ، خاصةً مع المكونات الإضافية المتعددة. منشور جيد جدًا للمدونة (باللغة الإنجليزية) - أوصي بقراءته كمقدمة مختصرة. لكن الربط يقتصر في معظمه على القيم الثابتة للتعليقات المعينة أو الأسماء المعينة ، مع الإشارة إلى العناصر التي يتم تطبيقها عليها. في مشكلتي هذا لا يساعد.


Jaxb (XJC) الإضافات


بينما كنت أبحث عن حل جاهز ، وجدت العديد من الإضافات التي توسع الجيل. أفترض أن مراجعتهم خارج نطاق هذا المنصب. ما هو مهم ، لا أجد ما يفعله بالضبط ما أحتاج إليه.


ولكن بعد ذلك ، أثناء قراءة الإجابات والأسئلة في http://stackoverflow.com/ ، وجدت عدة أسئلة من هذا النوع ، على سبيل المثال:


  1. استخدام JAXB للتعامل مع التعليقات التوضيحية للمخطط .
  2. كيفية جعل الفئات التي تم إنشاؤها تحتوي على Javadoc من وثائق مخطط XML
  3. كيف يمكنني إنشاء فئة يمكنني من خلالها استرداد XML لعقدة كسلسلة

وليس إجابة واحدة كاملة ، في بعض على مدى سنوات عديدة!


ولكن ، بالعودة إلى موضوع الفرص ، اتضح أن هناك API لكتابة المكونات الإضافية! منخفض المستوى ، مربكًا في بعض الأحيان ، بدون وثائق تقريبًا ... لكن يمكنني القول أن هذا متقدم جدًا ، أي أنه يمكنك التدخل بشكل كبير في العمليات. بالمناسبة ، غالباً ما يشار إلى الإجابات عليها ، بالنسبة للعديد من الحالات غير القياسية. حسنا ، حاولت أن أكتب البرنامج المساعد.


بالنسبة لأولئك المهتمين بتفاصيل عملية كتابة الإضافات الخاصة بهم ، يمكنني أن أوصي بالمقالات:



ما أردت ولماذا


للحصول على أحد عمليات الدمج الخاصة بنا ، قدم العميل أرشيفًا يحتوي على ملفات XSD ، والتي بموجبها كان علينا إنشاء النموذج في MDM Unidata ، الذي نعمل به ، من أجل مزيد من تكوين قواعد الجودة.


ألاحظ أن نظام MDM نفسه مملوك ، ومن غير المرجح أن يكون الكثيرون على دراية به ، لكن هذا لا يهم حقًا. خلاصة القول هي أنه كان علينا إنشاء أدلة وسجلات من أوصاف XSD . في الوقت نفسه ، تحتوي السجلات على حقول تستخدم كلاً من المعرف (اسم الحقل) و "اسم العرض" - وهو اسم يمكن فهمه للشخص باللغة الروسية. يمكن استخلاص تشبيه بسيط (وربما يكون هذا أيضًا مثالًا مفيدًا للتطبيق) باستخدام RDBMS حيث يمكننا افتراض أننا أردنا إنشاء جداول قاعدة بيانات ، ولكن في الوقت نفسه ، قدم وصفًا ( comment ) لكل عمود لاستخدامه لاحقًا.

كانت خطتي هذه:


  1. توليد فئات XSD باستخدام XJC
  2. ثم نأخذ مكتبة جميلة من الانعكاسات ونكررها على كل الكائنات ، ونذهب باستمرار إلى الحقول.

عملت كل شيء بسرعة لأسماء اللاتينية ، والتي أخذت من الطبقات field . لكن الوصف الروسي الذي يمكن قراءته من قبل الإنسان لم يكن في أي مكان!


لا يعد تحرير الأوصاف يدويًا خيارًا ، نظرًا لوجود عشرات الآلاف من الحقول المتداخلة.


كانت المحاولة الأولى لكتابة محلل مماثل على Groovy بنفسك ، وتمزيق أوصاف XSD . وبشكل عام ، تم تنفيذه. ولكن سرعان ما أصبح من الواضح أن هناك العديد من الحالات التي تتطلب معالجة إضافية - مكالمات متكررة ، ودعم ملحقات XSD 1.1 في شكل restriction / extension (مع دعم الميراث والتجاوز) ، والتي أنواع مختلفة من إنشاء حقول فئة مثل <element> و <attribute> ، <sequence> ، <choose> والعديد من الأشياء الصغيرة الأخرى. كان التنفيذ ممتلئًا بالإضافات ، لكنها لم تزيد الانسجام.


كنتيجة لذلك ، عدت إلى فكرة كتابة البرنامج المساعد xjc-documentation-annotation-plugin ، الذي أقدمه لك ، على أمل أن يكون مفيدًا لشخص ما باستثناءي!


XJC - وثائق الشرح البرنامج المساعد


وضعت كل شيء على جيثب: https://github.com/Hubbitus/xjc-documentation-annotation-plugin
هناك تعليمات واختبارات - gradle منفصل - gradle مع مثال للاستخدام.


أعتقد أنه من غير المنطقي نسخ الوصف هنا من هناك ، فقط عرض بإيجاز ما الذي يفعله.


دعنا نقول أن هناك جزء XSD :


  <xs:complexType name="Customer"> <xs:annotation> <xs:documentation></xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="name" type="xs:string"> <xs:annotation> <xs:documentation>  </xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType> 

بشكل افتراضي ، XJC فئة XJC منه (تُحذف الأحرف ، والفرامل ، وبعض التفاصيل غير الملائمة من أجل سهولة القراءة):


 /** *  * * <p>Java class for Customer complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * &lt;complexType name="Customer"&gt; * &lt;complexContent&gt; * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt; * &lt;sequence&gt; * &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/&gt; * &lt;element name="age" type="{http://www.w3.org/2001/XMLSchema}positiveInteger"/&gt; * &lt;/sequence&gt; * &lt;/restriction&gt; * &lt;/complexContent&gt; * &lt;/complexType&gt; * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Customer", propOrder = { "name", "age" }) public class Customer { @XmlElement(required = true) protected String name; @XmlElement(required = true) @XmlSchemaType(name = "positiveInteger") protected BigInteger age; } 

باستخدام المكوّن الإضافي ، ستحصل على (يظل Javadoc هو ، محذوفًا للبساطة):


 @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Customer", propOrder = { "name", "age" }) @XsdInfo(name = "", xsdElementPart = "<complexType name=\"Customer\">\n <complexContent>\n <restriction base=\"{http://www.w3.org/2001/XMLSchema}anyType\">\n <sequence>\n <element name=\"name\" type=\"{http://www.w3.org/2001/XMLSchema}string\"/>\n <element name=\"age\" type=\"{http://www.w3.org/2001/XMLSchema}positiveInteger\"/>\n </sequence>\n </restriction>\n </complexContent>\n</complexType>") public class Customer { @XmlElement(required = true) @XsdInfo(name = "  ") protected String name; @XmlElement(required = true) @XmlSchemaType(name = "positiveInteger") @XsdInfo(name = "") protected BigInteger age; } 

تحقق من التعليقات التوضيحية @XmlType المضافة.


عندئذٍ يكون استخدام هذا الأمر بسيطًا مثل أي تعليق توضيحي آخر:


  XsdInfo xsdAnnotation = CadastralBlock.class.getDeclaredAnnotation(XsdInfo.class); System.out.println("XSD description: " + xsdAnnotation.name()); 

مثال عملي في الاختبارات: 1 ، 2 .

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


All Articles