Apakah ada implementasi (atau implementasi pihak ketiga untuk) validasi lintas bidang di Hibernate Validator 4.x? Jika tidak, apa cara terbersih untuk menerapkan validator lintas bidang?
Sebagai contoh, bagaimana Anda dapat menggunakan API untuk memvalidasi dua properti kacang sama (seperti memvalidasi bidang kata sandi cocok dengan bidang verifikasi kata sandi).
Dalam anotasi, saya mengharapkan sesuatu seperti:
public class MyBean {
@Size(min=6, max=50)
private String pass;
@Equals(property="pass")
private String passVerify;
}
validation
hibernate-validator
bean-validation
bradhouse
sumber
sumber
Jawaban:
Setiap kendala bidang harus ditangani oleh anotasi validator yang berbeda, atau dengan kata lain tidak disarankan untuk melakukan pemeriksaan anotasi validasi satu bidang terhadap bidang lain; validasi lintas-bidang harus dilakukan di tingkat kelas. Selain itu, JSR-303 Bagian 2.2 cara yang disukai untuk mengekspresikan beberapa validasi dari jenis yang sama adalah melalui daftar anotasi. Ini memungkinkan pesan kesalahan ditentukan per pertandingan.
Misalnya, memvalidasi bentuk umum:
Anotasi:
Validator:
sumber
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addNode(secondFieldName).addConstraintViolation().disableDefaultConstraintViolation();
Memberi kemungkinan menyoroti bidang yang benar (jika JSF mendukungnya).BeanUtils.getProperty
mengembalikan sebuah string. Contohnya mungkin dimaksudkan untuk menggunakanPropertyUtils.getProperty
yang mengembalikan objek.Saya menyarankan Anda solusi lain yang mungkin. Mungkin kurang elegan, tetapi lebih mudah!
Itu
isValid
Metode dipanggil oleh validator secara otomatis.sumber
@AssertTrue
metode seperti itu ? Beberapa konvensi penamaan berlaku?Saya terkejut ini tidak tersedia di luar kotak. Bagaimanapun, inilah solusi yang mungkin.
Saya telah membuat validator tingkat kelas, bukan level bidang seperti yang dijelaskan dalam pertanyaan awal.
Berikut adalah kode penjelasannya:
Dan validator itu sendiri:
Perhatikan bahwa saya telah menggunakan MVEL untuk memeriksa properti objek yang sedang divalidasi. Ini bisa diganti dengan API refleksi standar atau jika itu adalah kelas khusus yang Anda validasi, metode accessor itu sendiri.
Anotasi @Matches kemudian dapat digunakan digunakan pada kacang sebagai berikut:
Sebagai penafian, saya menulis ini dalam 5 menit terakhir, jadi saya mungkin belum menyelesaikan semua bug. Saya akan memperbarui jawabannya jika ada masalah.
sumber
Dengan Hibernate Validator 4.1.0. Terakhir saya sarankan menggunakan @ScriptAssert . Perkecualian dari JavaDoc-nya:
Catatan: evaluasi sedang dilakukan oleh " mesin " scripting yang berjalan di Java VM, oleh karena itu pada Java "sisi server", tidak pada "sisi klien" seperti yang dinyatakan dalam beberapa komentar.
Contoh:
atau dengan alias lebih pendek dan nol-aman:
atau dengan Java 7+ null-safe
Objects.equals()
:Meskipun demikian, tidak ada yang salah dengan solusi @Matches validator tingkat kelas kustom .
sumber
Validasi lintas bidang dapat dilakukan dengan membuat batasan khusus.
Contoh: - Bandingkan kata sandi dan bidang konfirmasiPassword instance Pengguna.
Membandingkan Strings
StringComparisonMode
CompareStringsValidator
ConstraintValidatorHelper
Pengguna
Uji
Keluaran
Message:- [Password, ConfirmPassword] must be equal.
Dengan menggunakan batasan validasi CompareStrings, kami juga dapat membandingkan lebih dari dua properti dan kami dapat mencampur salah satu dari empat metode perbandingan string.
Pilihan warna
Uji
Keluaran
Message:- Please choose three different colors.
Demikian pula, kita dapat memiliki CompareNumber, CompareDates, dll, validasi lintas-bidang lintas.
PS Saya belum menguji kode ini di bawah lingkungan produksi (meskipun saya mengujinya di bawah lingkungan dev), jadi pertimbangkan kode ini sebagai Milestone Release. Jika Anda menemukan bug, silakan tulis komentar yang bagus. :)
sumber
Saya telah mencoba contoh Alberthoven (hibernate-validator 4.0.2.GA) dan saya mendapatkan ValidationException: "Metode beranotasi harus mengikuti konvensi penamaan JavaBeans. match () tidak. "juga. Setelah saya mengganti nama metode dari "cocokkan" menjadi "isValid" itu berhasil.
sumber
Jika Anda menggunakan Spring Framework maka Anda bisa menggunakan Spring Expression Language (SpEL) untuk itu. Saya telah menulis perpustakaan kecil yang menyediakan validator JSR-303 berdasarkan SpEL - membuat validasi lintas-bidang menjadi mudah! Lihatlah https://github.com/jirutka/validator-spring .
Ini akan memvalidasi panjang dan kesetaraan bidang kata sandi.
Anda juga dapat dengan mudah memodifikasi ini untuk memvalidasi bidang kata sandi hanya ketika tidak keduanya kosong.
sumber
Saya suka ide dari Jakub Jirutka untuk menggunakan Spring Expression Language. Jika Anda tidak ingin menambahkan pustaka / dependensi lain (dengan asumsi bahwa Anda sudah menggunakan Spring), berikut ini adalah implementasi ide yang disederhanakan.
Kendala:
Validator:
Terapkan seperti ini:
sumber
Saya tidak memiliki reputasi untuk mengomentari jawaban pertama tetapi ingin menambahkan bahwa saya telah menambahkan unit test untuk jawaban yang menang dan memiliki pengamatan berikut:
sumber
Solusi bradhouse yang sangat bagus. Apakah ada cara untuk menerapkan anotasi @Matches ke lebih dari satu bidang?
EDIT: Inilah solusi yang saya buat untuk menjawab pertanyaan ini, saya memodifikasi Kendala untuk menerima array, bukan nilai tunggal:
Kode untuk anotasi:
Dan implementasinya:
sumber
Anda perlu menyebutnya secara eksplisit. Pada contoh di atas, bradhouse telah memberi Anda semua langkah untuk menulis batasan kustom.
Tambahkan kode ini di kelas pemanggil Anda.
dalam kasus di atas akan menjadi
sumber
Mengapa tidak mencoba Oval: http://oval.sourceforge.net/
Saya sepertinya mendukung OGNL jadi mungkin Anda bisa melakukannya dengan cara yang lebih alami
sumber
Kalian luar biasa. Ide yang sangat menakjubkan. Saya paling suka Alberthoven dan McGin , jadi saya memutuskan untuk menggabungkan kedua ide. Dan kembangkan beberapa solusi umum untuk memenuhi semua kasus. Inilah solusi yang saya usulkan.
sumber
Saya membuat adaptasi kecil dalam solusi Nicko sehingga tidak perlu menggunakan perpustakaan Apache Commons BeanUtils dan menggantinya dengan solusi yang sudah tersedia di musim semi, bagi mereka yang menggunakannya karena saya bisa lebih sederhana:
sumber
Solusi dikerjakan dengan pertanyaan: Cara mengakses bidang yang dijelaskan dalam properti anotasi
Dan bagaimana cara menggunakannya ...? Seperti ini:
sumber