免费行情软件网站下载大全,广州建筑公司排名,物流公司图片,万网官网入口一、前言 高效、合理的使用hibernate-validator校验框架可以提高程序的可读性#xff0c;以及减少不必要的代码逻辑。接下来会介绍一下常用一些使用方式。 二、常用注解说明 限制说明Null限制只能为nullNotNull限制必须不为nullAssertFalse限制必须为falseAssertTrue限制必须为… 一、前言 高效、合理的使用hibernate-validator校验框架可以提高程序的可读性以及减少不必要的代码逻辑。接下来会介绍一下常用一些使用方式。 二、常用注解说明 限制说明Null限制只能为nullNotNull限制必须不为nullAssertFalse限制必须为falseAssertTrue限制必须为trueDecimalMax(value)限制必须为一个不大于指定值的数字DecimalMin(value)限制必须为一个不小于指定值的数字Digits(integer,fraction)限制必须为一个小数且整数部分的位数不能超过integer小数部分的位数不能超过fractionFuture限制必须是一个将来的日期Max(value)限制必须为一个不大于指定值的数字Min(value)限制必须为一个不小于指定值的数字Past限制必须是一个过去的日期Pattern(value)限制必须符合指定的正则表达式Size(max,min)限制字符长度必须在min到max之间Past验证注解的元素值日期类型比当前时间早NotEmpty验证注解的元素值不为null且不为空字符串长度不为0、集合大小不为0NotBlank验证注解的元素值不为空不为null、去除首位空格后长度为0不同于NotEmptyNotBlank只应用于字符串且在比较时会去除字符串的空格Email验证注解的元素值是Email也可以通过正则表达式和flag指定自定义的email格式三、定义校验分组 public class ValidateGroup {public interface FirstGroup {}public interface SecondeGroup {}public interface ThirdGroup {}
} 四、定义校验Bean Validated
GroupSequence({ValidateGroup.FirstGroup.class, BaseMessageRequestBean.class})
public class BaseMessageRequestBean {//渠道类型NotNull(message channelType为NULL, groups ValidateGroup.FirstGroup.class)private String channelType;//消息模板消息或者普通消息NotNull(message data为NUll, groups ValidateGroup.FirstGroup.class) Validprivate Object data;//业务类型NotNull(message bizType为NULL, groups ValidateGroup.FirstGroup.class)private String bizType;//消息推送对象NotBlank(message toUser为BLANK, groups ValidateGroup.FirstGroup.class)private String toUser;private long createTime Instant.now().getEpochSecond();......
} 请自行参考Validated和Valid区别 五、validator基本使用 RestController
public class TestValidatorController {RequestMapping(/test/validator)public void test(Validated BaseMessageRequestBean bean){ ...}
} 这种使用方式有一个弊端不能自定义返回异常。spring如果验证失败则直接抛出异常一般不可控。 六、借助BindingResult RestController
public class TestValidatorController {RequestMapping(/test/validator)public void test(Validated BaseMessageRequestBean bean, BindingResult result){result.getAllErrors();...}
} 如果方法中有BindingResult类型的参数spring校验完成之后会将校验结果传给这个参数。通过BindingResult控制程序抛出自定义类型的异常或者返回不同结果。 七、全局拦截校验器 当然了需要在借助BindingResult的前提下... Aspect
Component
public class ControllerValidatorAspect {Around(execution(* com.*.controller..*.*(..)) args(..,result))public Object doAround(ProceedingJoinPoint pjp, result result) {result.getFieldErrors();...}
} 这种方式可以减少controller层校验的代码校验逻辑统一处理更高效。 八、借助ValidatorUtils工具类 Bean
public Validator validator() {return new LocalValidatorFactoryBean();
} LocalValidatorFactoryBean官方示意 LocalValidatorFactoryBean是Spring应用程序上下文中javax.validationJSR-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参见setValidationMessageSourceorg.springframework.context.MessageSource。这个类也与Bean Validation 2.0和Hibernate Validator 6.0运行时兼容有一个特别说明如果你想调用BV 2.0的getClockProvider方法通过#unwrapValidatorFactory.class获取本机ValidatorFactory在那里调用返回的本机引用上的getClockProvider方法。Spring的MVC配置命名空间也使用此类如果存在javax.validation API但未配置显式Validator。 Component
public class ValidatorUtils implements ApplicationContextAware {Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {ValidatorUtils.validator (Validator) applicationContext.getBean(validator);}private static Validator validator;public static OptionalString validateResultProcess(Object obj) {SetConstraintViolationObject results validator.validate(obj);if (CollectionUtils.isEmpty(results)) {return Optional.empty();}StringBuilder sb new StringBuilder();for (IteratorConstraintViolationObject 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继承BaseMessageRequestBeansignature字段需要我们自定义校验逻辑。 Validated
GroupSequence({ValidateGroup.FirstGroup.class, ValidateGroup.SecondeGroup.class, MessageRequestBean.class})
LogicValidate(groups ValidateGroup.SecondeGroup.class)
public class MessageRequestBean extends BaseMessageRequestBean {//签名信息除该字段外的其他字段按照字典序排序将值顺序拼接在一起进行md5Base64签名算法NotBlank(message signature为BLANK, groups ValidateGroup.FirstGroup.class)private String signature;...
} 实现自定义校验逻辑也很简单...... 1、自定义一个带有 Constraint注解的注解LogicValidatevalidatedBy 属性指向该注解对应的自定义校验器 Target({TYPE})
Retention(RUNTIME)
//指定验证器
Constraint(validatedBy LogicValidator.class)
Documented
public interface LogicValidate {String message() default 校验异常;//分组Class?[] groups() default {};Class? extends Payload[] payload() default {};
} 2、自定义校验器LogicValidator泛型要关联上自定义的注解和需要校验bean的类型 public class LogicValidator implements ConstraintValidatorLogicValidate, MessageRequestBean {Overridepublic void initialize(LogicValidate logicValidate) {}Overridepublic 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;Beanpublic 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 ConcurrentReferenceHashMapString, ConditionOutcome cache new ConcurrentReferenceHashMapString, ConditionOutcome();Overridepublic 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 转载于:https://www.cnblogs.com/hujunzheng/p/9952563.html