التحقق من صحة البيانات - التحقق من صحة جافا والربيع

التحقق من بيانات الصف (الفول) في جافا ليس موضوعًا جديدًا ، ولكنه أيضًا ذو صلة هنا وسأجمع بين جوانب مختلفة: التحقق من صحة البيانات في JSR-303 ، وسأوضح كيفية القيام بذلك بحتة في Java واستخدام Spring ، وكيفية القيام بذلك في تطبيق قياسي وعلى الويب.

المحتويات: التحقق من صحة البيانات (JSR-303) في

  • تطبيق جافا القياسي
  • باستخدام الربيع
  • جمعية جافا + الربيع
  • mvc الربيع

التحقق في تطبيق Java قياسي


للتحقق من الكائن ، يتم استخدام التعليقات التوضيحية في حقول الصف ، أي نموذج تعريفي. التعليقات التوضيحية جاهزة بالفعل:
Null ،DecimalMin ،Digits ، Pattern ، Email ، etc.
، ويمكنك أيضًا أن تصنع بنفسك. وهكذا هناك فئة (حبة)

import javax.validation.constraints.Digits; import javax.validation.constraints.Size; public class Person { @Size(min=2, max=50) private String Name; @Digits(integer=3, fraction=0, message = "  3- ") @PersonAgeConstraint private Integer age; public Person(String name, Integer age) { Name = name; this.age = age; } } 

هنا في المثال الحجم وDigits التعليقات التوضيحية الجاهزة ، وPersonAgeConstraint الخاصة. كيف تصنع بنفسك:

- تحضير الشرح

 @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=PersonAgeConstraintValidator.class) public @interface PersonAgeConstraint { String message() default "{value.negative}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } 

في الرسالة () ، حدد المفتاح (value.negative) من ملف المورد (ValidationMessages.properties) للرسالة
value.negative = قيمة سالبة
وتنفيذ فئة التحقق - PersonAgeConstraintValidator.class

 public class PersonAgeConstraintValidator implements ConstraintValidator<PersonAgeConstraint, Integer> { @Override public boolean isValid(Integer age, ConstraintValidatorContext constraintValidatorContext) { return age > 0; } } 

التعليق التوضيحي الخاص بي جاهز ، نضيفه إلى الحقل ومن الممكن بالفعل التحقق منه ، وسيتم التحقق من جميع الحقول التي توجد بها تعليقات توضيحية وفقًا للقواعد المقابلة.

 import javax.validation.Validator; /** * Test Validation */ public class DemoJValidationApplicationTests { //  Validator private static Validator validator; static { ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); validator = validatorFactory.usingContext().getValidator(); } @Test public void testValidators() { final Person person = new Person(" ", -4500); Set<ConstraintViolation<Person>> validates = validator.validate(person); Assert.assertTrue(validates.size() > 0); validates.stream().map(v -> v.getMessage()) .forEach(System.out::println); } } 

النتيجة في وحدة التحكم

3-



يمكن تحديد رسائل التعليقات التوضيحية القياسية في ملف الرسائل ، كقاعدة:

AnnotationName.entity.fieldname=

هيكل المشروع

الصورة

ملف بوم
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>DemoJSRvalidation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>DemoJSRvalidation</name> <description>Demo project for Spring Boot JSR-303 validation</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 


التحقق المرحلي. بالنسبة للفئة <؟> [] المجموعات () ، يمكنك تحديد أنواع الفصول التي يمكنك من خلالها تجميعها ، وتحديد قائمة الشيكات ، أي استخدم كمرشح. وبالتالي ، يمكن إجراء التحقق على مراحل ، 1) على سبيل المثال ، نقسم فحص الشخص لأسباب صحية ، 2) ثم البيانات المهنية. سنقوم بإعداد شروحين
HealthConstraint و ProfessionalConstraint وتنفيذها. نتحقق أولاً من الامتثال للصحة ، ثم إذا مرت الصحة ، نتحقق من البيانات المهنية.

مثال:

 public class Person { @HealthConstraint(groups = Health.class) private Documents healthDocuments; @ProfessionalConstraint(groups = Professional.class) private Documents ProfessionalDocuments; //... } 

مثال على التعليق التوضيحي HealthConstraint

 @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=HealthConstraintValidator.class) public @interface HealthConstraint { String message() default "{health.documents}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } 

مثال على تطبيق HealthConstraintValidator

 public class HealthConstraintValidator implements ConstraintValidator<HealthConstraint, Documents> { @Override public boolean isValid(Documents documents, ConstraintValidatorContext constraintValidatorContext) { return documents.contains(" 1"); } } 

كل شيء عن ProfessionalConstraint هو نفسه

الاختيار التالي مثل هذا:

  @Test public void healthAndProfessionalValidators() { final Person person = new Person(" ", 45); person.setHealthDocuments(new Documents(Arrays.asList(" 1", " 3"))); person.setProfessionalDocuments(new Documents(Arrays.asList(" 1", " 4"))); //    Set<ConstraintViolation<Person>> validates = validator.validate(person, Health.class); Assert.assertTrue(validates.size() == 0); //    ,  .  validates = validator.validate(person, Professional.class); Assert.assertTrue(validates.size() == 0); } 

هذه الفحوصات ، على سبيل المثال ، مطلوبة عندما نقوم بتحميل البيانات من ملف وخدمة ويب ومصادر أخرى.

وثائق الفصل
 public class Documents { private List<String> tests = new ArrayList(); public Documents(List<String> tests) { this.tests.addAll(tests); } public boolean contains(String test) { return this.tests.contains(test); } } 


التحقق باستخدام Spring


يحتوي Spring أيضًا على واجهة Validator الخاصة به.
(org.springframework.validation.Validator)
كما في جافا
(javax.validation.Validator)
وينفذ تنفيذه بالتحديد البيانات. لم يعد هذا نهجًا إعلانيًا ، ولكنه يتمتع بمرونته وقابليته للتوسع. بالنسبة إلى السلة نفسها ، سأفحص نفس العمر.

من خلال تجاوز الطريقتين ، فإننا التحقق من الصحة

 @Service public class PersonValidator implements Validator { @Override public boolean supports(Class<?> aClass) { return Person.class.equals(aClass); } @Override public void validate(Object obj, Errors errors) { Person p = (Person) obj; if (p.getAge() < 0) { errors.rejectValue("age", "value.negative"); } } } 

value.negative - هو أيضًا المفتاح في ملف الرسالة ، public boolean supports نوع الفئة المدعومة.

يتم إطلاق التحقق من خلال DataBinder

مثال:

 @RunWith(SpringRunner.class) @SpringBootTest public class DemoJValidationApplicationTests { //    private static final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); static { messageSource.setBasename("message"); } @Autowired private PersonValidator personValidator; @Test public void testValidators() { final Person person = new Person(" ", -4500); final DataBinder dataBinder = new DataBinder(person); dataBinder.addValidators(personValidator); dataBinder.validate(); Assert.assertTrue(dataBinder.getBindingResult().hasErrors()); if (dataBinder.getBindingResult().hasErrors()) { dataBinder.getBindingResult().getAllErrors().stream(). forEach(e -> System.out.println(messageSource .getMessage(e, Locale.getDefault()))); } } } 

سيتم تنفيذ جميع عمليات التحقق التي نفذت org.springframework.validation.Validator لفئة الشخص.

يمكنك أيضًا إضافة العديد من أدوات التحقق ، dataBinder.addValidators ، يمكنك إنشاء تركيبة القواعد (استدعاء من قاعدة ، قاعدة أخرى) ، على سبيل المثال:

 public class OtherValidator implements Validator { @Override public boolean supports(Class<?> aClass) { return Person.class.equals(aClass); } @Override public void validate(Object obj, Errors errors) { // ... } } //--------- @Service public class PersonValidator implements Validator { /** *   */ @Autowired private OtherValidator otherValidator; @Override public void validate(Object obj, Errors errors) { Person p = (Person) obj; if (p.getAge() < 0) { errors.rejectValue("age", "value.negative"); } //   ,   otherValidator.validate(obj, errors); } } 

لسبب ما توقعت أن يقوم الربيع أيضًا بإجراء الفحوصات الموضحة في التعليقات التوضيحية ، ولكن لا ، يجب إجراء هذه المكالمة بشكل مستقل.

هيكل المشروع

الصورة

ملف بوم
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>DemoJSRvalidation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>DemoJSRvalidation</name> <description>Demo project for Spring Boot JSR-303 validation</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 


جافا والربيع


من الواضح أنني أريد استخدام طريقتين في التحقق من البيانات - Java و Spring ، يمكنك الجمع بينهما ، وهما إضافة javax.validation.Validator لاستدعاء Spring Validator.

مثال

 import javax.validation.Validator; @Service public class PersonValidator implements org.springframework.validation.Validator { // javax.validation.Validator @Autowired private Validator validator; @Override public boolean supports(Class<?> aClass) { return Person.class.equals(aClass); } @Override public void validate(Object obj, Errors errors) { Set<ConstraintViolation<Object>> validates = validator.validate(obj); for (ConstraintViolation<Object> constraintViolation : validates) { String propertyPath = constraintViolation.getPropertyPath().toString(); String message = constraintViolation.getMessage(); errors.rejectValue(propertyPath, "", message); } Person p = (Person) obj; if (p.getAge() < 0) { errors.rejectValue("age", "only.positive.numbers"); } } } 

باستخدام الربيع ، نقوم بحقن javax.validation.Validator

@Autowired
private Validator validator;


مزيد من المعلومات عن طريقة public void validate(Object obj, Errors errors)
قم بإجراء الفحوصات التصريحية على جافا ثم قم بإجراء جميع الفحوصات لفئة الشخص في الربيع org.springframework.validation.Validator.

نقوم أيضًا بإجراء التحقق خلال فصل الربيع

  @Test public void testValidators() { final Person person = new Person("", -4500); final DataBinder dataBinder = new DataBinder(person); dataBinder.addValidators(personValidator); dataBinder.validate(); if (dataBinder.getBindingResult().hasErrors()) { dataBinder.getBindingResult().getAllErrors() // .... 

الآن في المجموعة ، ستكون هناك فحوصات ضد جافا سكريبت والتعليقات التوضيحية الربيعية (org.springframework.validation.Validator) للشخص

إخراج وحدة التحكم

()
3- ()
(spring)


هيكل المشروع

الصورة

mvc الربيع


بالطبع ، الآن يمكن تطبيق كل هذا في تطبيق ويب.

نضيف وحدة التحكم ، صفحة jsp إلى المشروع (هنا ، بالمناسبة ، قد تكون هناك خيارات أخرى ، على سبيل المثال ، إنشاء صفحات باستخدام freeMarker ، وما إلى ذلك) ، نمط css ، تبعية pom. وهكذا بالترتيب

1) تحكم MVC

 import org.springframework.validation.Validator; @Controller public class DemoJValidationController { @Autowired @Qualifier("personValidator") // spring validator private Validator personValidator; @InitBinder protected void initBinder(WebDataBinder binder) { binder.setValidator(personValidator); } @GetMapping("/") public String savePersonAction(ModelMap model) { model.addAttribute("person", new Person(null, null)); return "personEdit"; } @RequestMapping(value = "/save", method = RequestMethod.POST) public String savePersonAction( @Valid @ModelAttribute("person") Person person, BindingResult bindingResult, Model model) { if (bindingResult.hasErrors()) { return "personEdit"; // to person.jsp page } model.addAttribute("name", person.getName()); model.addAttribute("age", person.getAge()); return "saveSuccess"; // to saveSuccess.jsp page } @RequestMapping(value = "/edit", method = RequestMethod.POST) public String editPersonAction(ModelMap model) { model.addAttribute("person", new Person(null, null)); return "personEdit"; // to personEdit.jsp page; } } 

هنا مع حقن شخص متصل بالزنبرك

@Autowired
@Qualifier("personValidator") // spring validator
private Validator personValidator;


قم بتعيين PersonValidator على initBinder

@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(personValidator);
}


تم التحقق من الصحة بواسطة تعليق توضيحي @Valid
في هذه الحالة ، سيتم إجراء فحص الربيع فقط ، وسيتم تجاهل عمليات الفحص التقريرية.

إذا تمت إزالته من التعليمات البرمجية

@InitBinder
protected void initBinder(WebDataBinder binder)


على العكس من ذلك ، سيتم تنفيذ جميع الشيكات التقريرية ، وسيتم تجاهل الربيع.
لإكمال جميع الشيكات ، التصريح والربيع ، يمكنك القيام بذلك:

إزالةInitBinder ، وترك الحقن

@Autowired
@Qualifier("personValidator") // spring validator
private Validator personValidator;


وإضافة مكالمة شيك الربيع يدويًا

// spring validate
personValidator.validate(person, bindingResult);


هذا هو الرمز:

 @Controller public class DemoJValidationController { @Autowired @Qualifier("personValidator") // spring validator private Validator personValidator; //... @RequestMapping(value = "/save", method = RequestMethod.POST) public String savePersonAction( @Valid @ModelAttribute("person") Person person, BindingResult bindingResult, Model model) { // spring validate personValidator.validate(person, bindingResult); if (bindingResult.hasErrors()) { return "personEdit"; // to person.jsp page } model.addAttribute("name", person.getName()); model.addAttribute("age", person.getAge()); return "saveSuccess"; // to saveSuccess.jsp page } } 

أي ستضاف الشيكات الإضافية من الربيع إلى ملزمResult :-) ، وهو ما أردت!

يتم تنفيذ ربط البيانات في jsp والنموذج بواسطة السمة - modelAttribute="person" في المثال ، مكتبة علامات نماذج SpringMVC متصلة.

الموارد المتبقية من هذا المثال هي:

DemoJValidationApplication
 @SpringBootApplication @ImportResource("classpath:configuration.xml") public class DemoJValidationApplication { public static void main(String[] args) { SpringApplication.run(DemoJValidationApplication.class, args); } } 


تكوين الربيع
config.xml
 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/c" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="classpath:message"/> <property name="defaultEncoding" value="UTF-8"/> </bean> <mvc:annotation-driven/> <mvc:resources mapping="/resources/**" location="classpath:/META-INF/resources/"/> </beans> 


personEdit.jsp
 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <link href="<c:url value="/resources/my.css" />" rel="stylesheet"> <title>Person</title> </head> <body> <h3> Enter Person. </h3> <form:form method="POST" modelAttribute="person" action="save"> <div> Name: <form:input path="name"/> <form:errors path="name" cssClass="error"/> </div> <div> Age: <form:input path="age"/> <form:errors path="age" cssClass="error"/> </div> <button type="submit">Registration</button> </form:form> </body> </html> 


saveSuccess.jsp
 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <link href="<c:url value="/resources/my.css" />" rel="stylesheet"> <title>Person Saved Successfully</title> </head> <body> <h3> Person Saved Successfully. </h3> <form:form method="POST" modelAttribute="person" action="edit"> <div> ${name} </div> <div> ${age} </div> <button type="submit">Edit</button> </form:form> </body> </html> 


my.css
 span.error { color: red; } form div{ margin: 5px; } 


ملف بوم
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>DemoJSRvalidation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>DemoJSRvalidation</name> <description>Demo project for Spring Boot JSR-303 validation</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.1.0.Final</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 


هيكل المشروع

الصورة

عمل التطبيق

الصورة

المواد

مواصفات التحقق من الفول

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


All Articles