成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從深處去掌握數(shù)據(jù)校驗(yàn)@Valid的作用(級(jí)聯(lián)校驗(yàn))

BlackFlagBin / 1338人閱讀

摘要:如果說要使用數(shù)據(jù)校驗(yàn),我十分相信小伙伴們都能夠使用,但估計(jì)大都是有個(gè)前提的環(huán)境。具體使用可參考小家讓支持對(duì)平鋪參數(shù)執(zhí)行數(shù)據(jù)校驗(yàn)?zāi)J(rèn)使用只能對(duì)進(jìn)行校驗(yàn)級(jí)聯(lián)校驗(yàn)什么叫級(jí)聯(lián)校驗(yàn),其實(shí)就是帶校驗(yàn)的成員里存在級(jí)聯(lián)對(duì)象時(shí),也要對(duì)它完成校驗(yàn)。

每篇一句
NBA里有兩大笑話:一是科比沒天賦,二是詹姆斯沒技術(shù)
相關(guān)閱讀

【小家Java】深入了解數(shù)據(jù)校驗(yàn):Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validation 6.x使用案例
【小家Spring】讓Controller支持對(duì)平鋪參數(shù)執(zhí)行數(shù)據(jù)校驗(yàn)(默認(rèn)Spring MVC使用@Valid只能對(duì)JavaBean進(jìn)行校驗(yàn))
【小家Spring】Spring方法級(jí)別數(shù)據(jù)校驗(yàn):@Validated + MethodValidationPostProcessor優(yōu)雅的完成數(shù)據(jù)校驗(yàn)動(dòng)作

對(duì)Spring感興趣可掃碼加入wx群:Java高工、架構(gòu)師3群(文末有二維碼)

前言

關(guān)于Bean Validation的基本原理篇完結(jié)之后,接下來就是小伙伴最為關(guān)心的干貨:使用篇。
如果說要使用Bean Validation數(shù)據(jù)校驗(yàn),我十分相信小伙伴們都能夠使用,但估計(jì)大都是有個(gè)前提的:Spring MVC環(huán)境。我極其簡單的調(diào)查了一下,近乎99%的人都是只把數(shù)據(jù)校驗(yàn)使用在Spring MVCController層面的,而且?guī)缀?b>90%的人都是讓它必須和@RequestBody一起來使用去校驗(yàn)JavaBean入?yún)

如果這么去理解Bean Validation的使用,那就有點(diǎn)太過于片面了,畢竟被Spring包裹起來,你其實(shí)很難去知道它真正做的事。
熟悉我文章風(fēng)格的人知道,每篇文章我都會(huì)帶你領(lǐng)略一些不一樣的風(fēng)景,本章亦不例外,會(huì)讓你知道數(shù)據(jù)校驗(yàn)在Spring框架之外的一些事~

分組校驗(yàn)

在我的前置原理篇文章,分組校驗(yàn)其實(shí)是沒太大必要說的,因?yàn)槭褂闷饋泶_實(shí)非常的簡單。此處還是給個(gè)分組校驗(yàn)的使用案例吧:

@Getter
@Setter
@ToString
public class Person {
    // 錯(cuò)誤消息message是可以自定義的
    @NotNull(message = "{message} -> 名字不能為null", groups = Simple.class)
    public String name;
    @Max(value = 10, groups = Simple.class)
    @Positive(groups = Default.class) // 內(nèi)置的分組:default
    public Integer age;

    @NotNull(groups = Complex.class)
    @NotEmpty(groups = Complex.class)
    private List<@Email String> emails;
    @Future(groups = Complex.class)
    private Date start;

    // 定義兩個(gè)組 Simple組和Complex組
    interface Simple {
    }
    interface Complex {

    }
}

執(zhí)行分組校驗(yàn):

    public static void main(String[] args) {
        Person person = new Person();
        //person.setName("fsx");
        person.setAge(18);
        // email校驗(yàn):雖然是List都可以校驗(yàn)哦
        person.setEmails(Arrays.asList("[email protected]", "[email protected]", "aaa.com"));
        //person.setStart(new Date()); //start 需要是一個(gè)將來的時(shí)間: Sun Jul 21 10:45:03 CST 2019
        //person.setStart(new Date(System.currentTimeMillis() + 10000)); //校驗(yàn)通過

        HibernateValidatorConfiguration configure = Validation.byProvider(HibernateValidator.class).configure();
        ValidatorFactory validatorFactory = configure.failFast(false).buildValidatorFactory();
        // 根據(jù)validatorFactory拿到一個(gè)Validator
        Validator validator = validatorFactory.getValidator();


        // 分組校驗(yàn)(可以區(qū)分對(duì)待Default組、Simple組、Complex組)
        Set> result = validator.validate(person, Person.Simple.class);
        //Set> result = validator.validate(person, Person.Complex.class);

        // 對(duì)結(jié)果進(jìn)行遍歷輸出
        result.stream().map(v -> v.getPropertyPath() + " " + v.getMessage() + ": " + v.getInvalidValue())
                .forEach(System.out::println);

    }

運(yùn)行打?。?/p>

age 最大不能超過10: 18
name {message} -> 名字不能為null -> 名字不能為null: null

可以直觀的看到效果,此處的校驗(yàn)只執(zhí)行Person.Simple.class這個(gè)Group組上的約束~

分組約束在Spring MVC中的使用場景還是相對(duì)比較多的,但是需要注意的是:javax.validation.Valid沒有提供指定分組的,但是org.springframework.validation.annotation.Validated擴(kuò)展提供了直接在注解層面指定分組的能力
@Valid注解

我們知道JSR提供了一個(gè)@Valid注解供以使用,在本文之前,絕大多數(shù)小伙伴都是在Controller中并且結(jié)合@RequestBody一起來使用它,但在本文之后,你定會(huì)對(duì)它有個(gè)全新的認(rèn)識(shí)~

==該注解用于驗(yàn)證級(jí)聯(lián)的屬性、方法參數(shù)方法返回類型。==
當(dāng)驗(yàn)證屬性、方法參數(shù)或方法返回類型時(shí),將驗(yàn)證對(duì)象及其屬性上定義的約束,另外:此行為是遞歸應(yīng)用的。

:::為了理解@Valid,那就得知道處理它的時(shí)機(jī):::

MetaDataProvider

元數(shù)據(jù)提供者:約束相關(guān)元數(shù)據(jù)(如約束、默認(rèn)組序列等)的Provider。它的作用和特點(diǎn)如下:

基于不同的元數(shù)據(jù):如xml、注解。(還有個(gè)編程映射) 這三種類型。對(duì)應(yīng)的枚舉類為:

public enum ConfigurationSource {
    ANNOTATION( 0 ),
    XML( 1 ),
    API( 2 ); //programmatic API
}

MetaDataProvider只返回直接為一個(gè)類配置的元數(shù)據(jù)

它不處理從超類、接口合并的元數(shù)據(jù)(簡單的說你@Valid放在接口處是無效的

public interface MetaDataProvider {

    // 將**注解處理選項(xiàng)**歸還給此Provider配置。  它的唯一實(shí)現(xiàn)類為:AnnotationProcessingOptionsImpl
    // 它可以配置比如:areMemberConstraintsIgnoredFor  areReturnValueConstraintsIgnoredFor
    // 也就說可以配置:讓免于被校驗(yàn)~~~~~~(開綠燈用的)
    AnnotationProcessingOptions getAnnotationProcessingOptions();
    // 返回作用在此Bean上面的`BeanConfiguration`   若沒有就返回null了
    // BeanConfiguration持有ConfigurationSource的引用~
     BeanConfiguration getBeanConfiguration(Class beanClass);
    
}

// 表示源于一個(gè)ConfigurationSource的一個(gè)Java類型的完整約束相關(guān)配置。  包含字段、方法、類級(jí)別上的元數(shù)據(jù)
// 當(dāng)然還包含有默認(rèn)組序列上的元數(shù)據(jù)(使用較少)
public class BeanConfiguration {
    // 三種來源的枚舉
    private final ConfigurationSource source;
    private final Class beanClass;
    // ConstrainedElement表示待校驗(yàn)的元素,可以知道它會(huì)如下四個(gè)子類:
    // ConstrainedField/ConstrainedType/ConstrainedParameter/ConstrainedExecutable
    
    // 注意:ConstrainedExecutable持有的是java.lang.reflect.Executable對(duì)象
    //它的兩個(gè)子類是java.lang.reflect.Method和Constructor
    private final Set constrainedElements;

    private final List> defaultGroupSequence;
    private final DefaultGroupSequenceProvider defaultGroupSequenceProvider;
    ... // 它自己并不處理什么邏輯,參數(shù)都是通過構(gòu)造器傳進(jìn)來的
}

它的繼承樹:

三個(gè)實(shí)現(xiàn)類對(duì)應(yīng)著上面所述的三種元數(shù)據(jù)類型。本文很顯然只需要關(guān)注和注解相關(guān)的:AnnotationMetaDataProvider

AnnotationMetaDataProvider

這個(gè)元數(shù)據(jù)均來自于注解的標(biāo)注,然后它是Hibernate Validation的默認(rèn)configuration source。它這里會(huì)處理標(biāo)注有@Valid的元素~

public class AnnotationMetaDataProvider implements MetaDataProvider {

    private final ConstraintHelper constraintHelper;
    private final TypeResolutionHelper typeResolutionHelper;
    private final AnnotationProcessingOptions annotationProcessingOptions;
    private final ValueExtractorManager valueExtractorManager;

    // 這是一個(gè)非常重要的屬性,它會(huì)記錄著當(dāng)前Bean  所有的待校驗(yàn)的Bean信息~~~
    private final BeanConfiguration objectBeanConfiguration;

    // 唯一構(gòu)造函數(shù)
    public AnnotationMetaDataProvider(ConstraintHelper constraintHelper,
            TypeResolutionHelper typeResolutionHelper,
            ValueExtractorManager valueExtractorManager,
            AnnotationProcessingOptions annotationProcessingOptions) {
        this.constraintHelper = constraintHelper;
        this.typeResolutionHelper = typeResolutionHelper;
        this.valueExtractorManager = valueExtractorManager;
        this.annotationProcessingOptions = annotationProcessingOptions;

        // 默認(rèn)情況下,它去把Object相關(guān)的所有的方法都retrieve:檢索出來放著  我比較費(fèi)解這件事~~~  
        // 后面才發(fā)現(xiàn):一切為了效率
        this.objectBeanConfiguration = retrieveBeanConfiguration( Object.class );
    }

    // 實(shí)現(xiàn)接口方法
    @Override
    public AnnotationProcessingOptions getAnnotationProcessingOptions() {
        return new AnnotationProcessingOptionsImpl();
    }


    // 如果你的Bean是Object  就直接返回了~~~(大多數(shù)情況下  都是Object)
    @Override
    @SuppressWarnings("unchecked")
    public  BeanConfiguration getBeanConfiguration(Class beanClass) {
        if ( Object.class.equals( beanClass ) ) {
            return (BeanConfiguration) objectBeanConfiguration;
        }
        return retrieveBeanConfiguration( beanClass );
    }
}

如上可知,核心解析邏輯在retrieveBeanConfiguration()這個(gè)私有方法上??偨Y(jié)一下調(diào)用此方法的兩個(gè)原始入口(一個(gè)構(gòu)造器,一個(gè)接口方法):

ValidatorFactory.getValidator()獲取校驗(yàn)器的時(shí)候,初始化時(shí)會(huì)自己new一個(gè),調(diào)用棧如下圖:

調(diào)用Validator.validate()方法的時(shí)候,beanMetaDataManager.getBeanMetaData( rootBeanClass )它會(huì)遍歷初始化時(shí)所有的metaDataProviders(默認(rèn)情況下兩個(gè),沒有xml方式的),拿出所有的BeanConfiguration交給BeanMetaDataBuilder,最終構(gòu)建出一個(gè)屬于此Bean的BeanMetaData。對(duì)此有一點(diǎn)注意事項(xiàng)描述如下:

    1. 處理`MetaDataProvider`時(shí)會(huì)調(diào)用`ClassHierarchyHelper.getHierarchy( beanClass ) `方法,不僅僅處理本類。拿到本類自己和所有父類后,統(tǒng)一交給`provider.getBeanConfiguration( clazz )`處理(**也就是說任何一個(gè)類都會(huì)把Object類處理一遍**)

retrieveBeanConfiguration()詳情

這個(gè)方法說白了,就是從Bean里面去檢索屬性、方法、構(gòu)造器等需要校驗(yàn)的ConstrainedElement項(xiàng)。

    private  BeanConfiguration retrieveBeanConfiguration(Class beanClass) {
        // 它檢索的范圍是:clazz.getDeclaredFields()  什么意思:就是搜集到本類所有的字段  包括private等等  但是不包括父類的所有字段
        Set constrainedElements = getFieldMetaData( beanClass );
        constrainedElements.addAll( getMethodMetaData( beanClass ) );
        constrainedElements.addAll( getConstructorMetaData( beanClass ) );

        //TODO GM: currently class level constraints are represented by a PropertyMetaData. This
        //works but seems somewhat unnatural
        // 這個(gè)TODO很有意思:當(dāng)前,類級(jí)約束由PropertyMetadata表示。這是可行的,但似乎有點(diǎn)不自然
        // ReturnValueMetaData、ExecutableMetaData、ParameterMetaData、PropertyMetaData

        // 總之吧:此處就是把類級(jí)別的校驗(yàn)器放進(jìn)來了(這個(gè)set大部分時(shí)候都是空的)
        Set> classLevelConstraints = getClassLevelConstraints( beanClass );
        if (!classLevelConstraints.isEmpty()) {
            ConstrainedType classLevelMetaData = new ConstrainedType(ConfigurationSource.ANNOTATION, beanClass, classLevelConstraints);
            constrainedElements.add(classLevelMetaData);
        }
        
        // 組裝成一個(gè)BeanConfiguration返回
        return new BeanConfiguration<>(ConfigurationSource.ANNOTATION, beanClass,
                constrainedElements, 
                getDefaultGroupSequence( beanClass ),  //此類上標(biāo)注的所有@GroupSequence注解
                getDefaultGroupSequenceProvider( beanClass ) // 此類上標(biāo)注的所有@GroupSequenceProvider注解
        );
    }

這一步驟把該Bean上的字段、方法等等需要校驗(yàn)的項(xiàng)都提取出來。就拿上例中的Demo校驗(yàn)Person類來說,最終得出的BeanConfiguration如下:(兩個(gè))


這是直觀的結(jié)論,可以看到僅僅是一個(gè)簡單的類其實(shí)所包含的項(xiàng)是挺多的。

此處說一句:項(xiàng)是有這么多,但是并不是每一個(gè)都需要走驗(yàn)證邏輯的。因?yàn)楫吘勾蠖鄶?shù)項(xiàng)上面并沒有約束(注解),大多數(shù)ConstrainedElement.getConstraints()為空嘛~

總得來說,我個(gè)人建議不能光只記憶結(jié)論,因?yàn)槟呛苋菀淄?,所以還是得稍微深入一點(diǎn),讓記憶更深刻吧。那就從下面四個(gè)方面深入:

檢索Field:getFieldMetaData( beanClass )

拿到本類所有字段Fieldclazz.getDeclaredFields()

把每個(gè)Field都包裝成ConstrainedElement存放起來~~~

    1.  注意:此步驟完成了對(duì)每個(gè)`Field`上標(biāo)注的注解進(jìn)行了保存

檢索Method:getMethodMetaData( beanClass )

拿到本類所有的方法Methodclazz.getDeclaredMethods()

排除掉靜態(tài)方法和合成(isSynthetic)方法

把每個(gè)Method都轉(zhuǎn)換成一個(gè)ConstrainedExecutable裝著~~(ConstrainedExecutable也是個(gè)ConstrainedElement)。在此期間它完成了如下事(方法和構(gòu)造器都復(fù)雜點(diǎn),因?yàn)榘雲(yún)⒑头祷刂?/strong>):

    1. 找到方法上所有的注解保存起來
    2. 處理入?yún)ⅰ⒎祷刂担òㄗ詣?dòng)判斷是作用在入?yún)⑦€是返回值上)

檢索Constructor:getConstructorMetaData( beanClass )

完全同處理Method,略

檢索Type:getClassLevelConstraints( beanClass )

找打標(biāo)注在此類上的所有的注解,轉(zhuǎn)換成ConstraintDescriptor

對(duì)已經(jīng)找到每個(gè)ConstraintDescriptor進(jìn)行處理,最終都轉(zhuǎn)換Set>這個(gè)類型

    1. 

Set>用一個(gè)ConstrainedType包裝起來(ConstrainedType是個(gè)ConstrainedElement

==關(guān)于級(jí)聯(lián)校驗(yàn)此處補(bǔ)充說明一點(diǎn),處理Type,都會(huì)處理級(jí)聯(lián)校驗(yàn)情況,并且還是遞歸處理:==
也就是這個(gè)方法(課件@Valid在此處生效):

    // type解釋:分如下N中情況
    // Field為:.getGenericType() // 字段的類型
    // Method為:.getGenericReturnType() // 返回值類型
    // Constructor:.getDeclaringClass() // 構(gòu)造器所在類

    // annotatedElement:可不一定說一定要有注解才能進(jìn)來(每個(gè)字段、方法、構(gòu)造器等都能傳進(jìn)來)
    private CascadingMetaDataBuilder getCascadingMetaData(Type type, AnnotatedElement annotatedElement, Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData) {
        return CascadingMetaDataBuilder.annotatedObject( type, annotatedElement.isAnnotationPresent( Valid.class ), containerElementTypesCascadingMetaData, getGroupConversions( annotatedElement ) );
    }

這里對(duì)我們理解級(jí)聯(lián)校驗(yàn)最重要的一句是:annotatedElement.isAnnotationPresent(Valid.class)。也就是說:若元素被此注解標(biāo)注了,那就證明需要對(duì)它進(jìn)行級(jí)聯(lián)校驗(yàn),這就是JSR定位@Valid的作用~

Spring提升了它???請(qǐng)關(guān)注后文Spring對(duì)它的應(yīng)用吧~
ConstraintValidator.isValid()調(diào)用處

我們知道,每個(gè)約束注解都是交給約束校驗(yàn)器ConstraintValidator.isValid()這個(gè)方法來處理的,它被調(diào)用(生效)的地方在此(唯一處):

public abstract class ConstraintTree {
    ...
    protected final  Set> validateSingleConstraint(ValidationContext executionContext,
            ValueContext valueContext,
            ConstraintValidatorContextImpl constraintValidatorContext,
            ConstraintValidator validator) {
        ...
        V validatedValue = (V) valueContext.getCurrentValidatedValue();
        isValid = validator.isValid( validatedValue, constraintValidatorContext );
        ...
        // 顯然校驗(yàn)不通過就返回錯(cuò)誤消息  否則返回空集合
        if ( !isValid ) {
            return executionContext.createConstraintViolations(valueContext, constraintValidatorContext);
        }
        return Collections.emptySet();
    }
    ...
}

這個(gè)方法的調(diào)用,會(huì)在執(zhí)行每個(gè)Group的時(shí)候

success = metaConstraint.validateConstraint( validationContext, valueContext );

MetaConstraint在上面檢索的時(shí)候就已經(jīng)準(zhǔn)備好了,最后通過ConstrainedElement.getConstraints就拿到了每個(gè)元素的校驗(yàn)器們,繼續(xù)調(diào)用

// ConstraintTree
boolean validationResult = constraintTree.validateConstraints( executionContext, valueContext );

so,最終就調(diào)用到了isValid這個(gè)真正做事的方法上了。

==說了這么多,你可能還云里霧里,那么就show一把吧:==

Demo Show

上面用一個(gè)示例校驗(yàn)Person這個(gè)JavaBean了,但是你會(huì)發(fā)現(xiàn)示例中我們?nèi)际切r?yàn)的Field屬性。從理論里我們知道了Bean Validation它是有校驗(yàn)方法、構(gòu)造器、入?yún)⑸踔吝f歸校驗(yàn)級(jí)聯(lián)屬性的能力的

校驗(yàn)屬性Field

校驗(yàn)Method入?yún)ⅰ⒎祷刂?/b> 校驗(yàn)Constructor入?yún)?、返回?/b> 既校驗(yàn)入?yún)ⅲ瑫r(shí)也校驗(yàn)返回值

這些是不能直接使用的,需要在運(yùn)行時(shí)進(jìn)行校驗(yàn)。具體使用可參考:【小家Spring】讓Controller支持對(duì)平鋪參數(shù)執(zhí)行數(shù)據(jù)校驗(yàn)(默認(rèn)Spring MVC使用@Valid只能對(duì)JavaBean進(jìn)行校驗(yàn))

級(jí)聯(lián)校驗(yàn)

什么叫級(jí)聯(lián)校驗(yàn),其實(shí)就是帶校驗(yàn)的成員里存在級(jí)聯(lián)對(duì)象時(shí),也要對(duì)它完成校驗(yàn)。這個(gè)在實(shí)際應(yīng)用場景中是比較常見的,比如入?yún)?b>Person對(duì)象中,還持有Child對(duì)象,我們不僅僅要完成Person的校驗(yàn),也依舊還要對(duì)Child內(nèi)的屬性校驗(yàn):

@Getter
@Setter
@ToString
public class Person {

    @NotNull
    private String name;
    @NotNull
    @Positive
    private Integer age;
    @Valid
    @NotNull
    private InnerChild child;

    @Getter
    @Setter
    @ToString
    public static class InnerChild {
        @NotNull
        private String name;
        @NotNull
        @Positive
        private Integer age;
    }

}

校驗(yàn)邏輯如下:

    public static void main(String[] args) {
        Person person = new Person();
        person.setName("fsx");
        Person.InnerChild child = new Person.InnerChild();
        child.setName("fsx-son");
        child.setAge(-1);
        person.setChild(child); // 放進(jìn)去

        Validator validator = Validation.byProvider(HibernateValidator.class).configure().failFast(false)
                .buildValidatorFactory().getValidator();
        Set> result = validator.validate(person);

        // 輸出錯(cuò)誤消息
        result.stream().map(v -> v.getPropertyPath() + " " + v.getMessage() + ": " + v.getInvalidValue())
                .forEach(System.out::println);
    }

運(yùn)行:

child.age 必須是正數(shù): -1
age 不能為null: null

對(duì)child.age這個(gè)級(jí)聯(lián)屬性校驗(yàn)成功~

總結(jié)

本文值得說是深入了解數(shù)據(jù)校驗(yàn)(Bean Validation)了,對(duì)于數(shù)據(jù)校驗(yàn)的基本使用一直都不是難事,特別是在Spring環(huán)境下使用就更簡單了~

知識(shí)交流
若文章格式混亂,可點(diǎn)擊:原文鏈接-原文鏈接-原文鏈接-原文鏈接-原文鏈接

==The last:如果覺得本文對(duì)你有幫助,不妨點(diǎn)個(gè)贊唄。當(dāng)然分享到你的朋友圈讓更多小伙伴看到也是被作者本人許可的~==

**若對(duì)技術(shù)內(nèi)容感興趣可以加入wx群交流:Java高工、架構(gòu)師3群
若群二維碼失效,請(qǐng)加wx號(hào):fsx641385712(或者掃描下方wx二維碼)。并且備注:"java入群" 字樣,會(huì)手動(dòng)邀請(qǐng)入群**

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75698.html

相關(guān)文章

  • Bean Validation完結(jié)篇:你必須關(guān)注邊邊角角(約束級(jí)聯(lián)、自定義約束、自定義驗(yàn)器、國際

    摘要:和上標(biāo)注的約束都會(huì)被執(zhí)行注意如果子類覆蓋了父類的方法,那么子類和父類的約束都會(huì)被校驗(yàn)。 每篇一句 沒有任何技術(shù)方案會(huì)是一種銀彈,任何東西都是有利弊的 相關(guān)閱讀 【小家Java】深入了解數(shù)據(jù)校驗(yàn):Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validation 6.x使用案例【小家Spring】Spring方法級(jí)別數(shù)據(jù)校...

    niuxiaowei111 評(píng)論0 收藏0
  • @Validated和@Valid區(qū)別?驗(yàn)級(jí)聯(lián)屬性(內(nèi)部類)

    摘要:畢竟永遠(yuǎn)相信本文能給你帶來意想不到的收獲使用示例關(guān)于數(shù)據(jù)校驗(yàn)這一塊在中的使用案例,我相信但凡有點(diǎn)經(jīng)驗(yàn)的程序員應(yīng)該沒有不會(huì)使用的,并且還不乏熟練的選手。 每篇一句 NBA里有兩大笑話:一是科比沒天賦,二是詹姆斯沒技術(shù) 相關(guān)閱讀 【小家Java】深入了解數(shù)據(jù)校驗(yàn):Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validati...

    Winer 評(píng)論0 收藏0
  • Hibernate-Validator 驗(yàn)證參數(shù)

    摘要:添加依賴,如果使用了,則不需要引用任何依賴,因?yàn)榘幸呀?jīng)包含了依賴在類的屬性上加上對(duì)應(yīng)的注解核查結(jié)果中文不能為空檢查結(jié)果中文級(jí)聯(lián)校驗(yàn)不能超過個(gè)嫌疑人集合被注釋的元素必須為被注釋的元素必須不為被注釋的元素必須為被注釋的元素必須為被 1.添加 Hibernate-Validator 依賴,如果使用了springboot,則不需要引用任何依賴,因?yàn)閟pring-boot-starter-we...

    myeveryheart 評(píng)論0 收藏0
  • Spring方法級(jí)數(shù)據(jù)驗(yàn):@Validated + MethodValidationPostPr

    摘要:就這樣借助相關(guān)約束注解,就非常簡單明了,語義清晰的優(yōu)雅的完成了方法級(jí)別入?yún)⑿r?yàn)返回值校驗(yàn)的校驗(yàn)。但倘若是返回值校驗(yàn)執(zhí)行了即使是失敗了,方法體也肯定被執(zhí)行了只能哪些類型上提出這個(gè)細(xì)節(jié)的目的是約束注解并不是能用在所有類型上的。 每篇一句 在《深度工作》中作者提出這么一個(gè)公式:高質(zhì)量產(chǎn)出=時(shí)間*專注度。所以高質(zhì)量的產(chǎn)出不是靠時(shí)間熬出來的,而是效率為王 相關(guān)閱讀 【小家Java】深入了解數(shù)據(jù)校...

    孫吉亮 評(píng)論0 收藏0
  • 原理層面掌握@ModelAttribute使用(使用篇)【一起學(xué)Spring MVC】

    摘要:和一起使用參照博文從原理層面掌握的使用一起學(xué)。至于具體原因,可以移步這里輔助理解從原理層面掌握的使用核心原理篇一起學(xué)再看下面的變種例子重要訪問。 每篇一句 每個(gè)人都應(yīng)該想清楚這個(gè)問題:你是祖師爺賞飯吃的,還是靠老天爺賞飯吃的 前言 上篇文章 描繪了@ModelAttribute的核心原理,這篇聚焦在場景使用上,演示@ModelAttribute在不同場景下的使用,以及注意事項(xiàng)(當(dāng)然有些...

    BenCHou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<