最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

hibernate-validator如何使用校驗(yàn)框架

 更新時間:2022年04月13日 15:56:26   作者:胡峻崢  
高效、合理的使用hibernate-validator校驗(yàn)框架可以提高程序的可讀性,以及減少不必要的代碼邏輯,本文主要介紹了hibernate-validator如何使用校驗(yàn)框架,感興趣的可以了解一下

一、前言

高效、合理的使用hibernate-validator校驗(yàn)框架可以提高程序的可讀性,以及減少不必要的代碼邏輯。接下來會介紹一下常用一些使用方式。

二、常用注解說明

限制說明
@Null限制只能為null
@NotNull限制必須不為null
@AssertFalse限制必須為false
@AssertTrue限制必須為true
@DecimalMax(value)限制必須為一個不大于指定值的數(shù)字
@DecimalMin(value)限制必須為一個不小于指定值的數(shù)字
@Digits(integer,fraction)限制必須為一個小數(shù),且整數(shù)部分的位數(shù)不能超過integer,小數(shù)部分的位數(shù)不能超過fraction
@Future限制必須是一個將來的日期
@Max(value)限制必須為一個不大于指定值的數(shù)字
@Min(value)限制必須為一個不小于指定值的數(shù)字
@Past限制必須是一個過去的日期
@Pattern(value)限制必須符合指定的正則表達(dá)式
@Size(max,min)限制字符長度必須在min到max之間
@Past驗(yàn)證注解的元素值(日期類型)比當(dāng)前時間早
@NotEmpty驗(yàn)證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0)
@NotBlank驗(yàn)證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應(yīng)用于字符串且在比較時會去除字符串的空格
@Email驗(yàn)證注解的元素值是Email,也可以通過正則表達(dá)式和flag指定自定義的email格式

三、定義校驗(yàn)分組

public class ValidateGroup {
    public interface FirstGroup {
    }

    public interface SecondeGroup {
    }

    public interface ThirdGroup {
    }
}

四、定義校驗(yàn)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)
    @Valid
    private Object data;

    //業(yè)務(wù)類型
    @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區(qū)別

五、validator基本使用

@RestController
public class TestValidatorController {
    @RequestMapping("/test/validator")
    public void test(@Validated BaseMessageRequestBean bean){
        ...
    }
}

  這種使用方式有一個弊端,不能自定義返回異常。spring如果驗(yàn)證失敗,則直接拋出異常,一般不可控。

六、借助BindingResult

@RestController
public class TestValidatorController {
    @RequestMapping("/test/validator")
    public void test(@Validated BaseMessageRequestBean bean, BindingResult result){
        result.getAllErrors();
        ...
    }
}

  如果方法中有BindingResult類型的參數(shù),spring校驗(yàn)完成之后會將校驗(yàn)結(jié)果傳給這個參數(shù)。通過BindingResult控制程序拋出自定義類型的異?;蛘叻祷夭煌Y(jié)果。

七、全局?jǐn)r截校驗(yàn)器

  當(dāng)然了,需要在借助BindingResult的前提下...

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

  這種方式可以減少controller層校驗(yàn)的代碼,校驗(yàn)邏輯統(tǒng)一處理,更高效。

八、借助ValidatorUtils工具類

@Bean
public Validator validator() {
    return new LocalValidatorFactoryBean();
}

LocalValidatorFactoryBean官方示意

  LocalValidatorFactoryBean是Spring應(yīng)用程序上下文中javax.validation(JSR-303)設(shè)置的中心類:它引導(dǎo)javax.validation.ValidationFactory并通過Spring Validator接口以及JSR-303 Validator接口和ValidatorFactory公開它。界面本身。通過Spring或JSR-303 Validator接口與該bean的實(shí)例進(jìn)行通信時,您將與底層ValidatorFactory的默認(rèn)Validator進(jìn)行通信。這非常方便,因?yàn)槟槐卦诠S執(zhí)行另一個調(diào)用,假設(shè)您幾乎總是會使用默認(rèn)的Validator。這也可以直接注入Validator類型的任何目標(biāo)依賴項(xiàng)!從Spring 5.0開始,這個類需要Bean Validation 1.1+,特別支持Hibernate Validator 5.x(參見setValidationMessageSource(org.springframework.context.MessageSource))。這個類也與Bean Validation 2.0和Hibernate Validator 6.0運(yùn)行時兼容,有一個特別說明:如果你想調(diào)用BV 2.0的getClockProvider()方法,通過#unwrap(ValidatorFactory.class)獲取本機(jī)ValidatorFactory,在那里調(diào)用返回的本機(jī)引用上的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參數(shù)

  2、controller方法中需要校驗(yàn)的參數(shù)也不需要加入@Valid或者@Validated注解

  怎么樣是不是又省去了好多代碼,開不開心。

  具體使用,在controller方法或者全局?jǐn)r截校驗(yàn)器中調(diào)用ValidatorUtils.validateResultProcess(需要校驗(yàn)的Bean) 直接獲取校驗(yàn)的結(jié)果。

  請參考更多功能的ValidatorUtils工具類

九、自定義校驗(yàn)器

  定義一個MessageRequestBean,繼承BaseMessageRequestBean,signature字段需要我們自定義校驗(yàn)邏輯。

@Validated
@GroupSequence({ValidateGroup.FirstGroup.class, ValidateGroup.SecondeGroup.class, MessageRequestBean.class})
@LogicValidate(groups = ValidateGroup.SecondeGroup.class)
public class MessageRequestBean extends BaseMessageRequestBean {

    //簽名信息(除該字段外的其他字段按照字典序排序,將值順序拼接在一起,進(jìn)行md5+Base64簽名算法)
    @NotBlank(message = "signature為BLANK", groups = ValidateGroup.FirstGroup.class)
    private String signature;
    ...
}

  實(shí)現(xiàn)自定義校驗(yàn)邏輯也很簡單......

  1、自定義一個帶有 @Constraint注解的注解@LogicValidate,validatedBy 屬性指向該注解對應(yīng)的自定義校驗(yàn)器

@Target({TYPE})
@Retention(RUNTIME)
//指定驗(yàn)證器  
@Constraint(validatedBy = LogicValidator.class)
@Documented
public @interface LogicValidate {
    String message() default "校驗(yàn)異常";
    //分組
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

  2、自定義校驗(yàn)器LogicValidator,泛型要關(guān)聯(lián)上自定義的注解和需要校驗(yàn)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校驗(yàn)失敗")
                    .addConstraintViolation();
            return false;
        }
        return true;
    }
}

  可以通過ConstraintValidatorContext禁用掉默認(rèn)的校驗(yàn)配置,然后自定義校驗(yàn)配置,比如校驗(yàn)失敗后返回的信息。

十、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 doesn't 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指定要配置國際化文件位置,默認(rèn)值是“message”。spring boot默認(rèn)就支持國際化的,默認(rèn)會去resouces目錄下尋找message.properties文件。

  這里就不進(jìn)行過多關(guān)于國際化相關(guān)信息的介紹了,肯定少不了區(qū)域解析器。springboot國際化相關(guān)知識請參考:Spring Boot國際化(i18n)

到此這篇關(guān)于hibernate-validator如何使用校驗(yàn)框架的文章就介紹到這了,更多相關(guān)hibernate-validator校驗(yàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java單例模式使用及注意事項(xiàng)

    java單例模式使用及注意事項(xiàng)

    這篇文章主要介紹了java單例模式使用及注意事項(xiàng),需要的朋友可以參考下
    2014-04-04
  • Java微服務(wù)間接口調(diào)用 feign

    Java微服務(wù)間接口調(diào)用 feign

    這篇文章主要介紹了微服務(wù)間的接口調(diào)用feign,F(xiàn)eign是一種聲明式、模板化的HTTP客戶端。在spring cloud中使用Feign,可以做到類似于普通的接口的請求調(diào)用,感興趣的小伙伴可以參考閱讀
    2023-03-03
  • Java使用bcrypt實(shí)現(xiàn)對密碼加密效果詳解

    Java使用bcrypt實(shí)現(xiàn)對密碼加密效果詳解

    bcrypt是一種自帶鹽值(自動加鹽)的加密方案。本文將通過示例為大家詳細(xì)介紹這一對密碼進(jìn)行加密的算法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-03-03
  • IDEA社區(qū)版創(chuàng)建spring boot項(xiàng)目的安裝插件的圖文教程

    IDEA社區(qū)版創(chuàng)建spring boot項(xiàng)目的安裝插件的圖文教程

    這篇文章主要介紹了IDEA社區(qū)版創(chuàng)建spring boot項(xiàng)目的安裝插件,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • MyBatis使用<foreach>標(biāo)簽報(bào)錯問題及解決

    MyBatis使用<foreach>標(biāo)簽報(bào)錯問題及解決

    這篇文章主要介紹了MyBatis使用<foreach>標(biāo)簽報(bào)錯問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • SpringBoot數(shù)據(jù)層處理方案精講

    SpringBoot數(shù)據(jù)層處理方案精講

    這篇文章主要介紹了SpringBoot數(shù)據(jù)層技術(shù)的解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • jar包的各種啟動方式超詳細(xì)總結(jié)

    jar包的各種啟動方式超詳細(xì)總結(jié)

    jar文件是一種軟件包文件格式,通常用于聚合大量的JAVA類文件,以jar為文件擴(kuò)展名,下面這篇文章主要給大家介紹了關(guān)于jar包的各種啟動方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • SpringBoot配置線程池的實(shí)現(xiàn)示例

    SpringBoot配置線程池的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot配置線程池的實(shí)現(xiàn)示例,主要包括在Spring Boot中創(chuàng)建和配置線程池,包括設(shè)置線程池的大小、隊(duì)列容量、線程名稱等參數(shù),感興趣的可以了解一下
    2023-09-09
  • SpringBoot創(chuàng)建Docker鏡像的方法步驟

    SpringBoot創(chuàng)建Docker鏡像的方法步驟

    這篇文章主要介紹了SpringBoot創(chuàng)建Docker鏡像的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • hibernate 中 fetch=FetchType.LAZY 懶加載失敗處理方法

    hibernate 中 fetch=FetchType.LAZY 懶加載失敗處理方法

    這篇文章主要介紹了hibernate 中 fetch=FetchType.LAZY 懶加載失敗處理方法,需要的朋友可以參考下
    2017-09-09

最新評論

清原| 精河县| 张北县| 华安县| 双牌县| 桓台县| 会理县| 沾化县| 鄂托克旗| 安图县| 巴林右旗| 岳西县| 西贡区| 揭阳市| 磐石市| 富宁县| 招远市| 崇文区| 蓝山县| 萝北县| 彭州市| 中牟县| 乐都县| 南川市| 锦州市| 永川市| 北辰区| 石台县| 广东省| 安阳市| 镇平县| 措美县| 正镶白旗| 福鼎市| 高唐县| 社会| 太仓市| 全南县| 岳池县| 息烽县| 壤塘县|