javascript
JSR 310新日期/时间API的自定义JSR 303 Bean验证约束
借助JSR 310,Java 8終于為我們帶來了不錯(cuò)的日期和時(shí)間API。 對于仍在使用Java 7的那些人(例如我目前在我的當(dāng)前項(xiàng)目中),有很好的反向移植,請?jiān)L問www.threeten.org了解更多詳細(xì)信息。 但是,由于有關(guān)該主題的博客已經(jīng)很多,因此我將不涉及使用新API的任何細(xì)節(jié)。 在本文中,我將向您展示的是如何通過編寫自己的自定義批注將Date / Time API與JSR 303 Bean驗(yàn)證API結(jié)合使用。
如果您同時(shí)使用bean驗(yàn)證和新的日期/時(shí)間API,則可能需要結(jié)合使用它們。 API和Hibernate Validator之類的實(shí)現(xiàn)僅提供少數(shù)約束,例如NotEmpty或@Pattern 。 但是,到目前為止,JSR 310還沒有現(xiàn)成的約束。幸運(yùn)的是,創(chuàng)建自己的約束非常容易。 作為示例,我將演示如何編寫自己的@Past批注以驗(yàn)證java.time.LocalDate字段。
為了進(jìn)行測試,我們將從一個(gè)非常簡單的類開始,該類包含一個(gè)日期和一個(gè)dateTime。 這些字段應(yīng)該代表過去的日期。 因此,它們使用@Past注釋進(jìn)行注釋:
ClassWithPastDates
package it.jdev.example.jsr310.validator;import java.time.LocalDate; import java.time.LocalDateTime;public class ClassWithPastDates {@Pastprivate LocalDate date;@Pastprivate LocalDateTime dateTime;public LocalDate getDate() {return date;}public void setDate(LocalDate date) {this.date = date;}public LocalDateTime getDateTime() {return dateTime;}public void setDateTime(LocalDateTime dateTime) {this.dateTime = dateTime;}}接下來,我們將為@Past約束編寫一個(gè)非?;镜膯卧獪y試,以證明我們的意圖:顯然,除了過去的日期之外,我們還希望null引用有效,但將來的日期無效,甚至今天也算作無效。
過去測試
package it.jdev.example.jsr310.validator;import static org.junit.Assert.assertEquals;import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Set;import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory;import org.junit.Before; import org.junit.Test;public class PastTest {private ClassWithPastDates classUnderTest;@Beforepublic void setup() {classUnderTest = new ClassWithPastDates();}@Testpublic void thatNullIsValid() {Set<ConstraintViolation<ClassWithPastDates>> violations = validateClass(classUnderTest);assertEquals(violations.size(), 0);}@Testpublic void thatYesterdayIsValid() throws Exception {classUnderTest.setDate(LocalDate.now().minusDays(1));classUnderTest.setDateTime(LocalDateTime.now().minusDays(1));Set<ConstraintViolation<ClassWithPastDates>> violations = validateClass(classUnderTest);assertEquals(violations.size(), 0);}@Testpublic void thatTodayIsInvalid() throws Exception {classUnderTest.setDate(LocalDate.now());classUnderTest.setDateTime(LocalDateTime.now());Set<ConstraintViolation<ClassWithPastDates>> violations = validateClass(classUnderTest);assertEquals(violations.size(), 2);}@Testpublic void thatTomorrowIsInvalid() throws Exception {classUnderTest.setDate(LocalDate.now().plusDays(1));classUnderTest.setDateTime(LocalDateTime.now().plusDays(1));Set<ConstraintViolation<ClassWithPastDates>> violations = validateClass(classUnderTest);assertEquals(violations.size(), 2);}private Set<ConstraintViolation<ClassWithPastDates>> validateClass(ClassWithPastDates myClass) {ValidatorFactory factory = Validation.buildDefaultValidatorFactory();Validator validator = factory.getValidator();Set<ConstraintViolation<ClassWithPastDates>> violations = validator.validate(myClass);return violations;}}現(xiàn)在我們已經(jīng)建立了基本測試,我們可以實(shí)現(xiàn)約束本身。 這包括兩個(gè)步驟。 首先,我們必須編寫注釋,然后必須實(shí)現(xiàn)ConstraintValidator 。 從注釋開始:
@interface過去
package it.jdev.example.jsr310.validator;import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;import javax.validation.Constraint; import javax.validation.Payload;@Target({ ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = PastValidator.class) @Documented public @interface Past {String message() default "it.jdev.example.jsr310.validator.Past.message";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};}如您所見, @Past注釋不是很壯觀。 要注意的主要事情是@Constraint批注,在其中我們指定將使用哪個(gè)類執(zhí)行實(shí)際驗(yàn)證。
PastValidator
package it.jdev.example.jsr310.validator;import java.time.LocalDate; import java.time.temporal.Temporal;import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext;public class PastValidator implements ConstraintValidator<Past, Temporal> {@Overridepublic void initialize(Past constraintAnnotation) {}@Overridepublic boolean isValid(Temporal value, ConstraintValidatorContext context) {if (value == null) {return true;}LocalDate ld = LocalDate.from(value);if (ld.isBefore(LocalDate.now())) {return true;}return false;}}PastValidator是所有魔術(shù)發(fā)生的地方。 通過實(shí)現(xiàn)ConstraintValidator接口,我們不得不提供兩種方法,但對于我們的示例,僅使用isValid()方法,這是我們執(zhí)行實(shí)際驗(yàn)證的地方。
請注意,我們使用java.time.temporal.Temporal作為類型,因?yàn)樗荓ocalDate和LocalDateTime類共同擁有的接口。 這使我們可以對LocalDate和LocalDateTime字段使用相同的@Past 。
真正的全部就是它。 在這個(gè)非?;镜氖纠?#xff0c;我展示了創(chuàng)建自己的定制JSR 303 bean驗(yàn)證約束是多么容易。
翻譯自: https://www.javacodegeeks.com/2014/09/custom-jsr-303-bean-validation-constraints-for-the-jsr-310-new-datetime-api.html
總結(jié)
以上是生活随笔為你收集整理的JSR 310新日期/时间API的自定义JSR 303 Bean验证约束的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电视棒安卓下载英文(电视棒安卓)
- 下一篇: Spring WebApplicatio