Validator + Aspek: sesuaikan validasi

Selamat siang, Habr!

Setelah beberapa waktu, saya memutuskan untuk menulis lagi di sini dan membagikan pengalaman saya. Kali ini, artikelnya adalah tentang bagaimana menyesuaikan validator standar, dan memanggil mereka di mana pun kita perlu menggunakan aspek Spring. Yah, itu mendorong saya untuk menulis - kurangnya informasi seperti itu, terutama dalam bahasa Rusia.

Masalah


Jadi, inti dari aplikasi ini kira-kira sebagai berikut: ada gateway - api yang menerima permintaan, dan selanjutnya memodifikasi dan mengalihkannya ke bank yang sesuai. Tetapi permintaan untuk masing-masing bank berbeda - serta parameter validasi. Karena itu, tidak mungkin untuk memvalidasi permintaan awal. Ada dua cara - menggunakan anotasi dari javax.validation, atau menulis layer validasi terpisah Anda. Dalam kasus pertama, ada tangkapan - secara default, objek hanya dapat divalidasi di controller. Dalam kasus kedua, ada juga kerugian - ini adalah lapisan tambahan, sejumlah besar kode, dan bahkan jika model diubah, validator harus diubah.

Oleh karena itu, diputuskan untuk menemukan cara untuk menarik validator standar jika perlu, dan tidak hanya di controller.

Kami menarik validator


Setelah beberapa jam menggali di Google, beberapa solusi ditemukan, yang paling memadai di antaranya adalah autowire javax.validation.Validator dan panggil metode validasi di atasnya, yang Anda perlukan untuk melewatkan objek yang divalidasi sebagai parameter.

Tampaknya solusi telah ditemukan, tetapi untuk memvalidasi di mana-mana validator tidak tampak seperti ide yang bagus, saya menginginkan solusi yang lebih elegan.

Tambahkan AOP


Tanpa berpikir dua kali, saya memutuskan untuk mencoba menyesuaikan aspek favorit saya dengan solusi ini.

Logikanya kira-kira sebagai berikut: membuat anotasi, dan menggantungnya pada metode yang mengubah satu objek ke objek lain. Lebih lanjut dalam aspek ini, kami mencegat semua metode yang ditandai dengan anotasi ini dan memanggil metode validasi untuk nilai yang mereka kembalikan. Untung

Jadi penjelasan:

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


Salah satu metode untuk mengonversi kueri adalah:

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

Sebenarnya aspek itu sendiri:

 @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()); } } } 

Secara singkat tentang aspek pekerjaan:

Kami mencegat objek yang dikembalikan oleh metode yang ditandai dengan anotasi Validasi , lalu meneruskannya ke metode validator, yang akan mengembalikan kami. Set<ConstraintViolation<Object>> - singkatnya - satu set kelas dengan informasi berbeda tentang bidang dan kesalahan yang divalidasi. Jika tidak ada kesalahan, maka set akan kosong. Kemudian kita hanya melalui set dan membuat pesan kesalahan, dengan semua bidang tidak divalidasi, dan membuang eksekusi.

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

Kesimpulan


Dengan demikian, kita dapat memanggil validasi objek apa pun yang kita perlukan di titik mana saja dalam aplikasi, dan jika diinginkan, kita dapat melengkapi anotasi dan aspek sehingga validasi melewati tidak hanya untuk metode yang mengembalikan objek, tetapi juga untuk bidang dan parameter metode.

PS


Juga, jika Anda memanggil metode bertanda Validasi dari metode lain dari kelas yang sama, ingat koneksi antara aop dan proxy .

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


All Articles