أعتقد أن العديد من مطوري Java الذين جاءوا مرة واحدة على الأقل عبر Web-
استخدموا إنشاء فئات Java
DTO
كما هو موضح في XML Schema
( XSD
) . تتعامل Jaxb مع هذا مع اثارة ضجة ، بغض النظر عن كيفية استخدامها ، عبر xjc
أو مكالمة wsimport
من سطر الأوامر ، أو الإضافات الأساسية أو المخفية.
إنها عملية سريعة وسهلة لإنشاء فصول من مخطط XSD
. ولكن هنا مشكلة واحدة - الأوصاف المتاحة في الدائرة الأصلية تختفي بالكامل تقريبًا!
في الممارسة العملية ، نظرًا لأن الفئة نفسها فقط سيكون لها وصف Javadoc
، بتنسيق ثابت (حيث لا يمكنك فصل الوصف وجزء XML
بدون العناصر النظامية ، على سبيل المثال) ، فإن وصف الحقول (الحقول) غائب تمامًا. وإذا كنت ، مثلي ، في حاجة إليها أيضًا في وقت التشغيل ( runtime
) ، فهناك مشكلة على الإطلاق .
من الغريب أن الأمر قد يبدو ، فقد كان من الضروري التغلب على هذا الأمر ، واستغرقت المهمة الكثير من الوقت ، ونتيجة لذلك كتبت مكونًا إضافيًا ، أود تقديمه على أمل أن يتمكن من إنقاذ بعض الأشخاص بضع ساعات في المستقبل.
Jaxb الميزات في لمحة
Jaxb لها تاريخ طويل ووصف رسمي جيد ، بما في ذلك إضافة السلوك إلى الطبقات التي تم إنشاؤها.
الأداة الرئيسية لاستدعاء إنشاء فئة من سطر الأوامر - xjc أيضا ليس لديها أصغر عدد من المفاتيح. ومع ذلك ، ليس واحد منهم لحالتنا.
بالطبع ، لا يمكنك إلا أن تذكر -b
، حيث يمكنك توفير رابطك الخاص. وهذا سلاح قوي جدًا ، خاصةً مع المكونات الإضافية المتعددة. منشور جيد جدًا للمدونة (باللغة الإنجليزية) - أوصي بقراءته كمقدمة مختصرة. لكن الربط يقتصر في معظمه على القيم الثابتة للتعليقات المعينة أو الأسماء المعينة ، مع الإشارة إلى العناصر التي يتم تطبيقها عليها. في مشكلتي هذا لا يساعد.
Jaxb (XJC) الإضافات
بينما كنت أبحث عن حل جاهز ، وجدت العديد من الإضافات التي توسع الجيل. أفترض أن مراجعتهم خارج نطاق هذا المنصب. ما هو مهم ، لا أجد ما يفعله بالضبط ما أحتاج إليه.
ولكن بعد ذلك ، أثناء قراءة الإجابات والأسئلة في http://stackoverflow.com/ ، وجدت عدة أسئلة من هذا النوع ، على سبيل المثال:
- استخدام JAXB للتعامل مع التعليقات التوضيحية للمخطط .
- كيفية جعل الفئات التي تم إنشاؤها تحتوي على Javadoc من وثائق مخطط XML
- كيف يمكنني إنشاء فئة يمكنني من خلالها استرداد XML لعقدة كسلسلة
وليس إجابة واحدة كاملة ، في بعض على مدى سنوات عديدة!
ولكن ، بالعودة إلى موضوع الفرص ، اتضح أن هناك API
لكتابة المكونات الإضافية! منخفض المستوى ، مربكًا في بعض الأحيان ، بدون وثائق تقريبًا ... لكن يمكنني القول أن هذا متقدم جدًا ، أي أنه يمكنك التدخل بشكل كبير في العمليات. بالمناسبة ، غالباً ما يشار إلى الإجابات عليها ، بالنسبة للعديد من الحالات غير القياسية. حسنا ، حاولت أن أكتب البرنامج المساعد.
بالنسبة لأولئك المهتمين بتفاصيل عملية كتابة الإضافات الخاصة بهم ، يمكنني أن أوصي بالمقالات:
ما أردت ولماذا
للحصول على أحد عمليات الدمج الخاصة بنا ، قدم العميل أرشيفًا يحتوي على ملفات XSD
، والتي بموجبها كان علينا إنشاء النموذج في MDM Unidata ، الذي نعمل به ، من أجل مزيد من تكوين قواعد الجودة.
ألاحظ أن نظام MDM
نفسه مملوك ، ومن غير المرجح أن يكون الكثيرون على دراية به ، لكن هذا لا يهم حقًا. خلاصة القول هي أنه كان علينا إنشاء أدلة وسجلات من أوصاف XSD
. في الوقت نفسه ، تحتوي السجلات على حقول تستخدم كلاً من المعرف (اسم الحقل) و "اسم العرض" - وهو اسم يمكن فهمه للشخص باللغة الروسية. يمكن استخلاص تشبيه بسيط (وربما يكون هذا أيضًا مثالًا مفيدًا للتطبيق) باستخدام RDBMS حيث يمكننا افتراض أننا أردنا إنشاء جداول قاعدة بيانات ، ولكن في الوقت نفسه ، قدم وصفًا ( comment
) لكل عمود لاستخدامه لاحقًا.
كانت خطتي هذه:
- توليد فئات
XSD
باستخدام XJC
- ثم نأخذ مكتبة جميلة من الانعكاسات ونكررها على كل الكائنات ، ونذهب باستمرار إلى الحقول.
عملت كل شيء بسرعة لأسماء اللاتينية ، والتي أخذت من الطبقات 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
منه (تُحذف الأحرف ، والفرامل ، وبعض التفاصيل غير الملائمة من أجل سهولة القراءة):
@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 .