当前位置: 首页 > news >正文

武汉珞珈网站建设如何制作一个简易网站

武汉珞珈网站建设,如何制作一个简易网站,discuz可以做公司网站,最新网游排行榜2023数据校验基础 参考: Java Bean Validation 规范 Spring对Bean Validation的支持 Spring定义了一个接口org.springframework.validation.Validator,用于应用相关的对象的校验器。 这个接口完全从基础设施或者上下文中脱离的,这意味着它没有…

数据校验基础

参考: Java Bean Validation 规范

Spring对Bean Validation的支持

Spring定义了一个接口org.springframework.validation.Validator,用于应用相关的对象的校验器。

这个接口完全从基础设施或者上下文中脱离的,这意味着它没有跟web层或者数据访问层或者其余任何的某一个层次发生耦合。所以它能用于应用中的任意一个层次,能对应用中的任意一个对象进行校验。

接口定义

public interface Validator {// 此clazz是否可以被validateboolean supports(Class<?> clazz);// 执行校验,错误消息放在Errors中// 如果能执行校验,通常也意味着supports方法返回true// 可以参考ValidationUtils这个工具类void validate(Object target, Errors errors);
}

接口实现

image-20230216155742364

SmartValidator

对Validator接口进行了增强,能进行分组校验

public interface SmartValidator extends Validator {// validationHints:就是启动的校验组// target:需要校验的结果// errors:封装校验void validate(Object target, Errors errors, Object... validationHints);// 假设value将被绑定到指定对象中的指定字段上,并进行校验// @since 5.1  这个方法子类需要复写 否则不能使用default void validateValue(Class<?> targetType, String fieldName, @Nullable Object value, Errors errors, Object... validationHints) {throw new IllegalArgumentException("Cannot validate individual value for " + targetType);}
}

SpringValidatorAdapter

SpringValidatorAdapter实现了对 Bean Validation适配

// 可以看到,这个接口同时实现了Spring中的SmartValidator接口跟JSR中的Validator接口
public class SpringValidatorAdapter implements SmartValidator, javax.validation.Validator {//约束必须使用的3个属性private static final Set<String> internalAnnotationAttributes = new HashSet<>(4);static {internalAnnotationAttributes.add("message");internalAnnotationAttributes.add("groups");internalAnnotationAttributes.add("payload");}// targetValidator就是实际完成校验的对象@Nullableprivate javax.validation.Validator targetValidator;public SpringValidatorAdapter(javax.validation.Validator targetValidator) {Assert.notNull(targetValidator, "Target Validator must not be null");this.targetValidator = targetValidator;}SpringValidatorAdapter() {}void setTargetValidator(javax.validation.Validator targetValidator) {this.targetValidator = targetValidator;}// 支持对所有类型的Bean的校验@Overridepublic boolean supports(Class<?> clazz) {return (this.targetValidator != null);}// 调用targetValidator完成校验,并通过processConstraintViolations方法封装校验后的结果到Errors中@Overridepublic void validate(Object target, Errors errors) {if (this.targetValidator != null) {processConstraintViolations(this.targetValidator.validate(target), errors);}}// 完成分组校验@Overridepublic void validate(Object target, Errors errors, Object... validationHints) {if (this.targetValidator != null) {processConstraintViolations(this.targetValidator.validate(target, asValidationGroups(validationHints)), errors);}}// 完成对对象上某一个字段及给定值的校验@SuppressWarnings("unchecked")@Overridepublic void validateValue(Class<?> targetType, String fieldName, @Nullable Object value, Errors errors, Object... validationHints) {if (this.targetValidator != null) {processConstraintViolations(this.targetValidator.validateValue((Class) targetType, fieldName, value, asValidationGroups(validationHints)), errors);}}// @since 5.1// 将validationHints转换成JSR中的分组private Class<?>[] asValidationGroups(Object... validationHints) {Set<Class<?>> groups = new LinkedHashSet<>(4);for (Object hint : validationHints) {if (hint instanceof Class) {groups.add((Class<?>) hint);}}return ClassUtils.toClassArray(groups);}// 省略对校验错误的封装// .....// 省略对JSR中validator接口的实现,都是委托给targetValidator完成的// ......}

ValidatorAdapter

SpringValidatorAdapter同一级别的类,但是不同的是他没有实现JSR中的Validator接口。一般不会使用这个类。

它实现了对 SmartValidator 的适配。

public class ValidatorAdapter implements SmartValidator, ApplicationContextAware, InitializingBean, DisposableBean {private final SmartValidator target;private final boolean existingBean;ValidatorAdapter(SmartValidator target, boolean existingBean) {this.target = target;this.existingBean = existingBean;}public final Validator getTarget() {return this.target;}@Overridepublic boolean supports(Class<?> clazz) {return this.target.supports(clazz);}//... ... 
}

CustomValidatorBean

配置一个bean,暴露一个 JSR-303 Validator,使用了 JSR 的3个接口。

public class CustomValidatorBean extends SpringValidatorAdapter implements Validator, InitializingBean {@Nullableprivate ValidatorFactory validatorFactory;@Nullableprivate MessageInterpolator messageInterpolator;@Nullableprivate TraversableResolver traversableResolver;
}

LocalValidatorFactoryBean

OptionalValidatorFactoryBean

继承了LocalValidatorFactoryBean,区别在于让校验器的初始化成为可选的,即使校验器没有初始化成功也不会报错。

@Validated跟@Valid的区别

定义

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {// 校验时启动的分组Class<?>[] value() default {};
}
@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface Valid {//没有提供任何属性
}

区别

  • 来源不同:@Valid是JSR的规范,来源于javax.validation包下,而@Validated是Spring自身定义的注解,位于org.springframework.validation.annotation包下

  • 作用范围不同:@Validated无法作用在字段上,正因为如此它就无法完成对级联属性的校验。而@Valid的没有这个限制。

  • 注解中的属性不同:@Validated注解中可以提供一个属性去指定校验时采用的分组,而@Valid没有这个功能,因为@Valid不能进行分组校验

应用

准备

待校验的类:

@Data
public class ValidatedData {@NotNullpublic String name;@Positivepublic Integer age;@NotNull@NotEmptyprivate List<@Email String> emails;/*** 定义的2个组,以接口的形式*/public interface GroupA {}public interface GroupB {}}/*** 外部验证数据,用于级联验证** @author lihz* @date 2023/2/18*/
@Data
public class OuterValidatedData {@NotNullString name;@ValidValidatedData validatedData;
}

测试Controller:

package com.jurassic.cloud.project.controller;import com.jurassic.cloud.project.dto.OuterValidatedData;
import com.jurassic.cloud.project.dto.ValidatedData;
import com.jurassic.cloud.project.service.impl.ValidationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;@RestController
@RequestMapping("/validate")
public class ValidationController {@AutowiredValidationService validationService;@PostMapping("/valid")public String testValid(@RequestBody @Valid ValidatedData data) {System.out.println(data);return "OK";}@PostMapping("/validated")public String testValidated(@RequestBody @Validated ValidatedData data) {System.out.println(data);return "OK";}@PostMapping("/valid/nest")public String testValidNest(@RequestBody @Valid OuterValidatedData data) {System.out.println(data);return "OK";}@PostMapping("/validated/nest")public String testValidatedNest(@RequestBody @Validated OuterValidatedData data) {System.out.println(data);return "OK";}@PostMapping("/valid/method")public String testValidMethod(@RequestBody ValidatedData data) {validationService.testValid(data);return "OK";}@PostMapping("/validated/method")public String testValidatedMethod(@RequestBody ValidatedData data) {validationService.testValidated(data);return "OK";}@PostMapping("/valid/nest/method")public String testValidNestMethod(@RequestBody OuterValidatedData data) {validationService.testValidNest(data);return "OK";}@PostMapping("/validated/nest/method")public String testValidatedNestMethod(@RequestBody OuterValidatedData data) {validationService.testValidatedNest(data);return "OK";}@PostMapping("/valid/simple")public String testValid(@Valid @Max(10) int age, @Valid @NotBlank String name) {System.out.println(age + "      " + name);return "OK";}@PostMapping("/validated/simple")public String testValidated(@Validated @Max(10) int age, @Validated @NotBlank String name) {System.out.println(age + "      " + name);return "OK";}@PostMapping("/non/method/simple")public String testNonMethodSimple(@Max(10) int age, @NotBlank String name) {validationService.testNon(age, name);return "OK";}@PostMapping("/valid/method/simple")public String testValidMethodSimple(@Max(10) int age, @NotBlank String name) {validationService.testValid(age, name);return "OK";}@PostMapping("/validated/method/simple")public String testValidatedMethodSimple(@Max(10) int age, @NotBlank String name) {validationService.testValidated(age, name);return "OK";}
}

测试数据:

{"name": "demon","age": -1,"emails": ["demon7552003@hotmail.com"]
}{"name": "xxxxx","data": {"name": "demon","age": -1,"emails": ["demon7552003@hotmail.com"]}
}

测试服务

package com.jurassic.cloud.project.service.impl;import com.jurassic.cloud.project.dto.OuterValidatedData;
import com.jurassic.cloud.project.dto.ValidatedData;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;/***** @author lihz* @date 2023/2/18*/
@Service
//@Validated
@Valid
public class ValidationService {public void testValid(@Valid ValidatedData data) {System.out.println(data);}public void testValidated(@Validated ValidatedData data) {System.out.println(data);}public void testValidNest(@Valid OuterValidatedData data) {System.out.println(data);}public void testValidatedNest(@Validated OuterValidatedData data) {System.out.println(data);}public void testNon(  @Max(10) int age,  @NotBlank String name) {System.out.println(age+"     "+name);}public void testValid(@Valid @Max(10) int age,@Valid @NotBlank String name) {System.out.println(age+"     "+name);}public void testValidated(@Validated   @Max(10) int age, @Validated  @NotBlank String name) {System.out.println(age+"     "+name);}}

对JavaBean的校验(Controller层)

测试结果

  • valid测试

    {"code": 1,// age 必须是正数"msg": "Validation failed for argument [0] in public java.lang.String com.jurassic.cloud.project.controller.ValidationController.testValid(com.jurassic.cloud.project.dto.ValidatedData): [Field error in object 'validatedData' on field 'age': rejected value [-1]; codes [Positive.validatedData.age,Positive.age,Positive.java.lang.Integer,Positive]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [validatedData.age,age]; arguments []; default message [age]]; default message [必须是正数]] ","data": null
    }
    
  • validated测试

{"code": 1,"msg": "Validation failed for argument [0] in public java.lang.String com.jurassic.cloud.project.controller.ValidationController.testValidated(com.jurassic.cloud.project.dto.ValidatedData): [Field error in object 'validatedData' on field 'age': rejected value [-1]; codes [Positive.validatedData.age,Positive.age,Positive.java.lang.Integer,Positive]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [validatedData.age,age]; arguments []; default message [age]]; default message [必须是正数]] ","data": null
}
  • valid测试 嵌套数据

    {"code": 1,"msg": "Validation failed for argument [0] in public java.lang.String com.jurassic.cloud.project.controller.ValidationController.testValidNest(com.jurassic.cloud.project.dto.OuterValidatedData): [Field error in object 'outerValidatedData' on field 'validatedData.age': rejected value [-1]; codes [Positive.outerValidatedData.validatedData.age,Positive.validatedData.age,Positive.age,Positive.java.lang.Integer,Positive]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [outerValidatedData.validatedData.age,validatedData.age]; arguments []; default message [validatedData.age]]; default message [必须是正数]] ","data": null
    }
    
  • validated测试 嵌套数据

    {"code": 1,"msg": "Validation failed for argument [0] in public java.lang.String com.jurassic.cloud.project.controller.ValidationController.testValidatedNest(com.jurassic.cloud.project.dto.OuterValidatedData): [Field error in object 'outerValidatedData' on field 'validatedData.age': rejected value [-1]; codes [Positive.outerValidatedData.validatedData.age,Positive.validatedData.age,Positive.age,Positive.java.lang.Integer,Positive]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [outerValidatedData.validatedData.age,validatedData.age]; arguments []; default message [validatedData.age]]; default message [必须是正数]] ","data": null
    }
    

总结

从结果上看 @Valid@Validated 都能触发级联验证。

如果要触发属性的级联验证,一定要放注解 @Valid

对普通方法的JavaBean校验

测试结果

Service类上不加注解

  • valid测试

    OK
    
  • validated测试

    ok
    
  • valid测试 嵌套数据

    OK
    
  • validated测试 嵌套数据

    OK
    

Service类上加@Valid

  • valid测试

    OK
    
  • validated测试

    ok
    
  • valid测试 嵌套数据

    OK
    
  • validated测试 嵌套数据

    OK
    

Service类上加@Validated

  • valid测试

    {"code": 1,"msg": "testValid.data.age: 必须是正数","data": null
    }
    
  • validated测试

    ok
    
  • valid测试 嵌套数据

    {"code": 1,"msg": "testValidNest.data.validatedData.age: 必须是正数","data": null
    }
    
  • validated测试 嵌套数据

    OK
    

总结

只有类上添加了@Vlidated注解,并且待校验的**JavaBean上添加了@Valid**的情况下校验才会生效。

返回的异常信息包含了 进行验证的方法的名称,以及验证的属性

对简单参数的校验(Controller层)

测试结果

1、测试:http://127.0.0.1:8073/validate/valid/simple?age=20&name=demon

结果:OK

2、测试:http://127.0.0.1:8073/validate/validated/simple?age=20&name=demon

结果:OK

结论

参数上,不论加 @Valid 还是 @Validated ,都不会触发验证。

对简单参数的校验(Service层)

测试结果

1、测试:http://127.0.0.1:8073/validate/valid/simple?age=20&name=demon

结果:OK

2、测试:http://127.0.0.1:8073/validate/validated/simple?age=20&name=demon

结果:OK

结论

参数上,不论加 @Valid 还是 @Validated ,都不会触发验证。

对普通方法上的简单参数的校验(Service层)

1、参数不加注解: http://127.0.0.1:8073/validate/non/method/simple?age=20

2、参数加@Valid: http://127.0.0.1:8073/validate/valid/simple?age=20

3、参数加@Validated:http://127.0.0.1:8073/validate/validated/simple?age=20

测试结果

Service类上不加注解

1、OK

2、OK

3、OK

Service类上加@Valid

1、OK

2、OK

3、OK

Service类上加@Validated

1、

{"code": 1,"msg": "testNon.age: 最大不能超过10, testNon.name: 不能为空","data": null
}

2、

{"code": 1,"msg": "testValid.name: 不能为空, testValid.age: 最大不能超过10","data": null
}

3、

{"code": 1,"msg": "testValidated.age: 最大不能超过10, testValidated.name: 不能为空","data": null
}

结论

参数上,不论加 @Valid 还是 @Validated,或者不加 ,都不会影响结果。

仅在类上加 @Validated 时,才会触发简单参数的验证。

普通方法验证的总结

仅在类上加@Validated 时,才会触发参数的验证。对于非简单类的验证,必须加 @Valid 触发级联验证。

Controller层验证的总结

仅能验证非简单类型

从结果上看 @Valid@Validated 都能触发级联验证。

如果要触发属性的级联验证,一定要放注解 @Valid

Spring对JSR的适配

在普通方法上的验证,抛出异常ConstraintViolationException,在Controller层抛出的异常是MethodArgumentNotValidException。Spring对参数绑定做了封装,错误信息被封装为BindingResult,在方法RequestResponseBodyMethodProcessor#resolveArgument中做处理。

全局异常处理

通过@RestControllerAdvice 做AOP。

@RestControllerAdvice
public class MethodArgumentNotValidExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public Result handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {BindingResult bindingResult = ex.getBindingResult();StringBuilder stringBuilder = new StringBuilder();for (FieldError error : bindingResult.getFieldErrors()) {String field = error.getField();Object value = error.getRejectedValue();String msg = error.getDefaultMessage();String message = String.format("错误字段:%s,错误值:%s,原因:%s;", field, value, msg);stringBuilder.append(message).append("\r\n");}return Result.error(MsgDefinition.ILLEGAL_ARGUMENTS.codeOf(), stringBuilder.toString());}
}

附录

参考

官网:https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/spring-framework-reference/core.html#validation-beanvalidation

http://www.tj-hxxt.cn/news/59952.html

相关文章:

  • 深圳金鼎网站建设搜狗站长
  • dede美女图片网站模板网址导航下载到桌面
  • 成都做公司网站推广百度指数的数值代表什么
  • 46设计网站官网电商培训课程
  • 赶集网站建设多少钱网络营销包括
  • 兴宁电子商务网站建设优化设计五年级下册数学答案
  • 做旅游宣传网站的流程网站多久被百度收录
  • wordpress中文cms主题武汉seo诊断
  • 汉中做网站的公司百度怎么发帖做推广
  • 潍坊网站建设建站关键词优化排名网站
  • 世界经理人网站手机版网站推广要点
  • 中午网站做google广告好吗营销推广方式
  • 集团网站开发宁波网站建设网站排名优化
  • 金华哪里有做网站的公司4000-262-合肥seo优化
  • 网站建设的报价为什么不同软文什么意思
  • 成品网站是什么意思百度商家入驻
  • 惠州网站建设服务google search
  • 郑州做网站推广地链接交换
  • 微网站自己怎么做的吗福建网络seo关键词优化教程
  • 网站config配置教程seo 优化一般包括哪些内容
  • 商务咨询网站源码软文营销案例文章
  • 服装网都有哪些网站营销平台
  • 做网站可以抄袭别人吗淘宝搜索排名
  • 长沙优化网站哪家公司好网球排名即时最新排名
  • 本地做网站百度收录排名
  • 学做家常菜的网站怎么推广自己的微信
  • 杭州做企业网站公司爱站小工具圣经
  • 六安做网站多少钱seo好学吗入门怎么学
  • 百度页面推广东莞有限公司seo
  • 销售平台是什么意思东莞seo网站排名优化公司