المصادقون + الجوانب: تخصيص التحقق من الصحة

يوم جيد يا هبر!

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

المشكلة


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

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

نحن سحب المدققون


بعد بضع ساعات من الحفر في Google ، تم العثور على اثنين من الحلول ، كان أكثرها ملاءمة هو autowire javax.validation.Validator واستدعاء طريقة التحقق من الصحة ، والتي تحتاج إلى تمرير كائن التحقق من صحتها كمعلمة.

يبدو أنه قد تم العثور على حل ، ولكن للتحقق من الصحة في كل مكان لم يكن المصدق فكرة جيدة ، أردت حلاً أكثر أناقة.

أضف AOP


دون التفكير مرتين ، قررت أن أحاول تكييف جوانبي المفضلة لهذا الحل.

كان المنطق كما يلي تقريبًا: إنشاء تعليق توضيحي وتعليقه على طريقة تحول كائنًا إلى كائن آخر. علاوة على ذلك ، نعترض جميع الطرق التي تحمل علامة هذا الشرح ونستدعي طريقة التحقق من الصحة للقيمة التي تُرجعها. الربح

تعليق توضيحي:

//      @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Validate {} 


طريقة واحدة لتحويل الاستعلامات:

 @Validate public SomeBankRequest requestToBankRequest(Request<T> request) { SomeBankRequest bankRequest = ...; ... //        ... return bankRequest; } 

حسنا ، في الواقع الجانب نفسه:

 @Aspect @Component public class ValidationAspect { private final Validator validator; //    public ValidationAspect(Validator validator) { this.validator = validator; } //       // @Validate       @AfterReturning(pointcut = "@annotation(api.annotations.Validate)", returning = "result") public void validate(JoinPoint joinPoint, Object result) { //     Set<ConstraintViolation<Object>> violations = validator.validate(result); //    ,    ,     //        if (!violations.isEmpty()) { StringBuilder builder = new StringBuilder(); //          ,   //  violations.forEach(violation -> builder .append(violation.getPropertyPath()) .append("[" + violation.getMessage() + "],")); throw new IllegalArgumentException("Invalid values for fields: " + builder.toString()); } } } 

باختصار عن جانب العمل:

نحن نعترض الكائن الذي يتم إرجاعه بواسطة الطريقة التي تم وضع علامة عليها مع التحقق من صحة التعليق التوضيحي ، ثم نمررها إلى طريقة المدقق ، والتي ستعيدنا Set<ConstraintViolation<Object>> - باختصار - مجموعة من الفئات مع معلومات مختلفة حول الحقول والأخطاء التي تم التحقق منها. إذا لم تكن هناك أخطاء ، فستكون المجموعة فارغة. ثم نذهب إلى المجموعة وننشئ رسالة خطأ ، مع عدم التحقق من صحة جميع الحقول ، ورمي التنفيذ.

 violation.getPropertyPath() -    violation.getMessage() -  ,       

الخاتمة


وبالتالي ، يمكننا استدعاء التحقق من صحة أي كائنات نحتاجها في أي وقت في التطبيق ، وإذا رغبت في ذلك ، يمكننا استكمال التعليقات التوضيحية والجانب بحيث لا يمر التحقق من الصحة فقط للطرق التي تُرجع كائنًا ، ولكن أيضًا لحقول ومعلمات الطرق.

PS


أيضًا ، إذا قمت باستدعاء طريقة تحمل علامة التحقق من الصحة من طريقة أخرى لنفس الفئة ، تذكر الاتصال بين aop والوكيل .

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


All Articles