hibernate validator怎么用,hibernate校验器

  hibernate validator怎么用,hibernate校验器

  00-1010 1.前言2。常见注释说明3。支票分组4的定义。检查Bean 5的定义。validator 6的基本用法。借助BindingResult 7。全球拦截验证器8。借助于ValidatorUtils工具class 9。自定义验证器

  00-1010高效合理地使用hibernate-validator验证框架可以提高程序的可读性,减少不必要的代码逻辑。接下来,我们将介绍一些常用的方法。

  00-1010限制说明@Null限制只能为null@NotNull限制不能为null@AssertFalse限制必须为false@AssertTrue限制必须为true@DecimalMax(value)限制必须为不大于指定值的数字@DecimalMin(value)限制必须为不小于指定值的数字@Digits(整数,小数)。限制必须是小数,整数部分的位数不能超过整数。小数位数不能超过分数@未来限制必须是未来日期@最大(值)限制必须是不大于指定值的数字@最小(值)限制必须是不小于指定值的数字@过去限制必须是过去日期@模式(值)限制必须符合指定的正则表达式@Size(max, Min)限制字符长度必须在min和max之间@Past验证批注的元素值(日期类型)早于当前时间@NotEmpty验证批注的元素值不为null和空(字符串长度不为0,集合大小不为0)@NotBlank验证批注的元素值不为空(不为null,去掉第一个空格后长度为0),与@NotEmpty不同, @NotBlank只适用于字符串,比较时会去掉字符串的空格@email验证注释的元素值是Email,也可以通过正则表达式和flag指定自定义的Email格式。

  

目录

公共类验证组{公共接口第一组{ }公共接口第二组{ }公共接口第三组{ }}

 

  

一、前言

@ Validated @ group sequence({ validate group。BasemessageRequestBean。class})公共类basemessageRequestBean {//channel type @ not null(message= channel type is null ,groups=validate group . first group . class)私有字符串通道类型;//message(模板消息或普通消息)@NotNull(message=data is null ,groups=validate group . first group . class)@ validprivateobjectdata;//Business type @ not null(message= biz type is null ,groups=validate group . first group . class)私有字符串biz type;//消息推送object @ not blank(Message= to user为空,groups=validate group . first group . class)私有字符串to user;private long create time=instant . now()。getEpochSecond();}请自行参考:@Validated和@Valid的区别

 

  00-1010 @ RestControllerPublicClass TestValidatorController { @ request mapping(/test/validator )publicvidtest(@ validatedbasessagerequestbean){.}}这种用法有个缺点,不能自定义返回异常。如果spring验证失败,会直接抛出异常,一般是不可控的。

  

二、常用注解说明

@RestCo

 

  ntrollerpublic class TestValidatorController { @RequestMapping("/test/validator") public void test(@Validated BaseMessageRequestBean bean, BindingResult result){ result.getAllErrors(); ... }}如果方法中有BindingResult类型的参数,spring校验完成之后会将校验结果传给这个参数。通过BindingResult控制程序抛出自定义类型的异常或者返回不同结果。

  

 

  

七、全局拦截校验器

当然了,需要在借助BindingResult的前提下...

 

  

@Aspect@Componentpublic class ControllerValidatorAspect { @Around("execution(* com.*.controller..*.*(..)) && args(..,result)") public Object doAround(ProceedingJoinPoint pjp, result result) { result.getFieldErrors(); ... }}

这种方式可以减少controller层校验的代码,校验逻辑统一处理,更高效。

 

  

 

  

八、借助ValidatorUtils工具类

@Beanpublic Validator validator() { return new LocalValidatorFactoryBean();}

LocalValidatorFactoryBean官方示意

 

  LocalValidatorFactoryBean是Spring应用程序上下文中javax.validation(JSR-303)设置的中心类:它引导javax.validation.ValidationFactory并通过Spring Validator接口以及JSR-303 Validator接口和ValidatorFactory公开它。界面本身。通过Spring或JSR-303 Validator接口与该bean的实例进行通信时,您将与底层ValidatorFactory的默认Validator进行通信。这非常方便,因为您不必在工厂执行另一个调用,假设您几乎总是会使用默认的Validator。这也可以直接注入Validator类型的任何目标依赖项!从Spring 5.0开始,这个类需要Bean Validation 1.1+,特别支持Hibernate Validator 5.x(参见setValidationMessageSource(org.springframework.context.MessageSource))。这个类也与Bean Validation 2.0和Hibernate Validator 6.0运行时兼容,有一个特别说明:如果你想调用BV 2.0的getClockProvider()方法,通过#unwrap(ValidatorFactory.class)获取本机ValidatorFactory,在那里调用返回的本机引用上的getClockProvider()方法。Spring的MVC配置命名空间也使用此类,如果存在javax.validation API但未配置显式Validator。

  

public class ValidatorUtils implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ValidatorUtils.validator = (Validator) applicationContext.getBean("validator"); } private static Validator validator; public static Optional<String> validateResultProcess(Object obj) { Set<ConstraintViolation<Object>> results = validator.validate(obj); if (CollectionUtils.isEmpty(results)) { return Optional.empty(); } StringBuilder sb = new StringBuilder(); for (Iterator<ConstraintViolation<Object>> iterator = results.iterator(); iterator.hasNext(); ) { sb.append(iterator.next().getMessage()); if (iterator.hasNext()) { sb.append(" ,"); } } return Optional.of(sb.toString()); }}

为什么要使用这个工具类呢?

 

  1、controller方法中不用加入BindingResult参数

  2、controller方法中需要校验的参数也不需要加入@Valid或者@Validated注解

  怎么样是不是又省去了好多代码,开不开心。

  具体使用,在controller方法或者全局拦截校验器中调用ValidatorUtils.validateResultProcess(需要校验的Bean) 直接获取校验的结果。

  请参考更多功能的ValidatorUtils工具类。

  

 

  

九、自定义校验器

定义一个MessageRequestBean,继承BaseMessageRequestBean,signature字段需要我们自定义校验逻辑。

 

  

@Validated@GroupSequence({ValidateGroup.FirstGroup.class, ValidateGroup.SecondeGroup.class, MessageRequestBean.class})@LogicValidate(groups = ValidateGroup.SecondeGroup.class)public class MessageRequestBean extends BaseMessageRequestBean { //签名信息(除该字段外的其他字段按照字典序排序,将值顺序拼接在一起,进行md5+Base64签名算法) @NotBlank(message = "signature为BLANK", groups = ValidateGroup.FirstGroup.class) private String signature; ...}

实现自定义校验逻辑也很简单......

 

  1、自定义一个带有 @Constraint注解的注解@LogicValidate,validatedBy 属性指向该注解对应的自定义校验器

  

@Target({TYPE})@Retention(RUNTIME)//指定验证器 @Constraint(validatedBy = LogicValidator.class)@Documentedpublic @interface LogicValidate { String message() default "校验异常"; //分组 Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};}

2、自定义校验器LogicValidator,泛型要关联上自定义的注解和需要校验bean的类型

 

  

public class LogicValidator implements ConstraintValidator<LogicValidate, MessageRequestBean> { @Override public void initialize(LogicValidate logicValidate) { } @Override public boolean isValid(MessageRequestBean messageRequestBean, ConstraintValidatorContext context) { String toSignature = StringUtils.join( messageRequestBean.getBizType() , messageRequestBean.getChannelType() , messageRequestBean.getData() , messageRequestBean.getToUser()); String signature = new Base64().encodeAsString(DigestUtils.md5(toSignature)); if (!messageRequestBean.getSignature().equals(signature)) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("signature校验失败") .addConstraintViolation(); return false; } return true; }}

可以通过ConstraintValidatorContext禁用掉默认的校验配置,然后自定义校验配置,比如校验失败后返回的信息。

 

  十、springboot国际化信息配置

  

@Configuration@ConditionalOnMissingBean(value = MessageSource.class, search = SearchStrategy.CURRENT)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)@Conditional(ResourceBundleCondition.class)@EnableConfigurationProperties@ConfigurationProperties(prefix = "spring.messages")public class MessageSourceAutoConfiguration { private static final Resource[] NO_RESOURCES = {}; /** * Comma-separated list of basenames, each following the ResourceBundle convention. * Essentially a fully-qualified classpath location. If it doesnt contain a package * qualifier (such as "org.mypackage"), it will be resolved from the classpath root. */ private String basename = "messages"; /** * Message bundles encoding. */ private Charset encoding = Charset.forName("UTF-8"); /** * Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles * are cached forever. */ private int cacheSeconds = -1; /** * Set whether to fall back to the system Locale if no files for a specific Locale * have been found. if this is turned off, the only fallback will be the default file * (e.g. "messages.properties" for basename "messages"). */ private boolean fallbackToSystemLocale = true; /** * Set whether to always apply the MessageFormat rules, parsing even messages without * arguments. */ private boolean alwaysUseMessageFormat = false; @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); if (StringUtils.hasText(this.basename)) { messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray( StringUtils.trimAllWhitespace(this.basename))); } if (this.encoding != null) { messageSource.setDefaultEncoding(this.encoding.name()); } messageSource.setFallbackToSystemLocale(this.fallbackToSystemLocale); messageSource.setCacheSeconds(this.cacheSeconds); messageSource.setAlwaysUseMessageFormat(this.alwaysUseMessageFormat); return messageSource; } public String getBasename() { return this.basename; } public void setBasename(String basename) { this.basename = basename; } public Charset getEncoding() { return this.encoding; } public void setEncoding(Charset encoding) { this.encoding = encoding; } public int getCacheSeconds() { return this.cacheSeconds; } public void setCacheSeconds(int cacheSeconds) { this.cacheSeconds = cacheSeconds; } public boolean isFallbackToSystemLocale() { return this.fallbackToSystemLocale; } public void setFallbackToSystemLocale(boolean fallbackToSystemLocale) { this.fallbackToSystemLocale = fallbackToSystemLocale; } public boolean isAlwaysUseMessageFormat() { return this.alwaysUseMessageFormat; } public void setAlwaysUseMessageFormat(boolean alwaysUseMessageFormat) { this.alwaysUseMessageFormat = alwaysUseMessageFormat; } protected static class ResourceBundleCondition extends SpringBootCondition { private static ConcurrentReferenceHashMap<String, ConditionOutcome> cache = new ConcurrentReferenceHashMap<String, ConditionOutcome>(); @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { String basename = context.getEnvironment() .getProperty("spring.messages.basename", "messages"); ConditionOutcome outcome = cache.get(basename); if (outcome == null) { outcome = getMatchOutcomeForBasename(context, basename); cache.put(basename, outcome); } return outcome; } private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context, String basename) { ConditionMessage.Builder message = ConditionMessage .forCondition("ResourceBundle"); for (String name : StringUtils.commaDelimitedListToStringArray( StringUtils.trimAllWhitespace(basename))) { for (Resource resource : getResources(context.getClassLoader(), name)) { if (resource.exists()) { return ConditionOutcome .match(message.found("bundle").items(resource)); } } } return ConditionOutcome.noMatch( message.didNotFind("bundle with basename " + basename).atAll()); } private Resource[] getResources(ClassLoader classLoader, String name) { try { return new PathMatchingResourcePatternResolver(classLoader) .getResources("classpath*:" + name + ".properties"); } catch (Exception ex) { return NO_RESOURCES; } } }}

从上面的MessageSource自动配置可以看出,可以通过spring.message.basename指定要配置国际化文件位置,默认值是message。spring boot默认就支持国际化的,默认会去resouces目录下寻找message.properties文件。

 

  这里就不进行过多关于国际化相关信息的介绍了,肯定少不了区域解析器。springboot国际化相关知识请参考:Spring Boot国际化(i18n)

  到此这篇关于hibernate-validator如何使用校验框架的文章就介绍到这了,更多相关hibernate-validator校验内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: