广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >Java中Validated、Valid 、Validator区别详解
  • 644
分享到

Java中Validated、Valid 、Validator区别详解

ValidatedValidValidator 2014-09-01 08:09:17 644人浏览 绘本
摘要

目录1. 结论先出jsR 380Valid VS Validated 不同点?Validator2. @Valid和​​​​​​​@Validated 注解

目录
  • 1. 结论先出
    • jsR 380
    • Valid VS Validated 不同点?
    • Validator
  • 2. @Valid和​​​​​​​@Validated 注解
    • 3. 例子
      • 4.使用@Valid嵌套校验
        • 5. 组合使用@Valid和@Validated 进行集合校验
          • 6. 自定义校验
            • 自定义约束注解
              • 工作原理
                • 结论
                  • 参考链接:

                    1. 结论先出

                    Valid VS Validated 相同点
                    都可以对方法和参数进行校验
                    @Valid和@Validated
                    两种注释都会导致应用标准Bean验证。

                    如果验证不通过会抛出BindException异常,并变成400(BAD_REQUEST)响应;或者可以通过Errors或BindingResult参数在控制器内本地处理验证错误。另外,如果参数前有@RequestBody注解,验证错误会抛出MethodArgumentNotValidException异常。

                    JSR 380

                    JSR 380 是用于 bean 验证的 Java api 规范,是 Jakarta EE 和 JavaSE 的一部分。这确保 bean 的属性满足特定条件,使用诸如@NotNull、@Min和@Max 之类的注释。

                    此版本需要 Java 8 或更高版本,并利用 Java 8 中添加的新功能,例如类型注释和对Optional和LocalDate等新类型的支持。

                    有关规范的完整信息,请继续阅读JSR 380。

                    Valid VS Validated 不同点?

                    javax.validation.Valid

                    • 是JSR-303规范标准注解支持,是一个标记注解。
                    • 注解支持ElementType#METHOD,ElementType#FIELD, ElementType#CONSTRUCTOR,
                    • ElementType#PARAMETER, ElementType#TYPE_USE

                    org.springframework.validation.annotation.Validated

                    • 是Spring 做得一个自定义注解,增强了分组功能。
                    • 注解支持 ElementType#TYPE,ElementType#METHOD,ElementType#PARAMETER

                    @Valid和@Validated区别

                    区别 @Valid @Validated
                    提供者 JSR-303规范 Spring
                    是否支持分组 不支持 支持
                    标注位置 METHOD, FIELD, CONSTRUCTOR, PARAMETER, TYPE_USE TYPE, METHOD, PARAMETER
                    嵌套校验 支持 不支持

                    Validator

                    Bean Validation 2.0(JSR 380)定义了用于实体和方法验证的元数据模型和API,Hibernate Validator是目前最好的实现

                    Validator接口有三个方法,可用于验证整个实体或仅验证实体的单个属性

                    • Validator#validate() 验证所有bean的所有约束
                    • Validator#validateProperty() 验证单个属性
                    • Validator#validateValue() 检查给定类的单个属性是否可以成功验证

                    不管是requestBody参数校验还是方法级别的校验,最终都是调用Hibernate Validator执行校验,Spring Validation只是做了一层封装。

                    验证用户的输入是我们大多数应用程序中的常见功能。在 Java 生态系统中,我们专门使用Java Standard Bean Validation API来支持这一点。此外,从 4.0 版本开始,这也与 Spring 很好地集成在一起.

                    在接下来的部分中,让我们详细了解它们。

                    2. @Valid和​​​​​​​@Validated 注解

                    在 Spring 中,我们使用 JSR-303 的@Valid注释进行方法级别验证。此外,我们还使用它来标记成员属性以进行验证。但是,此注释不支持组验证

                    组有助于限制验证期间应用的约束。一个特殊的用例是 UI 界面(UI wizards)。在这里,在第一步中,我们可能有某个字段子组。在后续步骤中,可能有另一个组属于同一个 bean。因此我们需要在每一步中对这些有限的字段应用约束,但@Valid不支持这一点。

                    在这种情况下,对于组级别,我们必须使用 Spring 的@Validated,它是 JSR-303 的@Valid的变体。这是在方法级别使用的。对于标记成员属性,我们继续使用@Valid注释。

                    现在,让我们直接进入并通过一个例子来看看这些注解的用法。

                    3. 例子

                    让我们考虑一个使用 Spring Boot 开发的简单用户注册。首先,我们将只有名称和密码属性:

                    
                    public class UserAccount {
                     
                        @NotNull
                        @Size(min = 4, max = 15)
                        private String passWord;
                     
                        @NotBlank
                        private String name;
                     
                        // standard constructors / setters / getters / toString   
                    }

                    接下来,让我们看看控制器。在这里,我们将使用带有@Valid注释的saveBasicInfo方法来验证用户输入:

                    
                    @RequestMapping(value = "/saveBasicInfo", method = RequestMethod.POST)
                    public String saveBasicInfo(
                      @Valid @ModelAttribute("useraccount") UserAccount useraccount, 
                      BindingResult result, 
                      ModelMap model) {
                        if (result.hasErrors()) {
                            return "error";
                        }
                        return "success";
                    }
                    

                    现在让我们测试这个方法:

                    
                    @Test
                    public void givenSaveBasicInfo_whenCorrectInput_thenSuccess() throws Exception {
                        this.mockmvc.perfORM(MockMvcRequestBuilders.post("/saveBasicInfo")
                          .accept(MediaType.TEXT_html)
                          .param("name", "test123")
                          .param("password", "pass"))
                          .andExpect(view().name("success"))
                          .andExpect(status().isOk())
                          .andDo(print());
                    }
                    

                    确认测试运行成功后,我们现在扩展功能。下一个合乎逻辑的步骤是将其转换为复杂用户注册。第一步,名称和密码保持不变。在第二步中,我们将获取诸如年龄 和 电话之类的附加信息。因此,我们将使用这些附加字段更新我们的域对象: 

                    
                    public class UserAccount {
                        
                        @NotNull
                        @Size(min = 4, max = 15)
                        private String password;
                     
                        @NotBlank
                        private String name;
                     
                        @Min(value = 18, message = "Age should not be less than 18")
                        private int age;
                     
                        @NotBlank
                        private String phone;
                        
                        // standard constructors / setters / getters / toString   
                    }

                    但是,这一次我们会注意到之前的测试失败了。这是因为我们没有传入age和phone字段。为了支持这种行为,我们需要组验证和@Validated注释。

                    为此,我们需要对字段进行分组,创建两个不同的组。首先,我们需要创建两个标记接口。每个组或每个步骤单独一个。我们可以参考我们关于组验证的文章以了解具体的实现方式。在这里,让我们关注注释的差异。

                    我们将有第一步的BasicInfo接口和第二步的 AdvanceInfo  。此外,我们将更新UserAccount类以使用这些标记接口,如下所示:

                    
                    public class UserAccount {
                        
                        @NotNull(groups = BasicInfo.class)
                        @Size(min = 4, max = 15, groups = BasicInfo.class)
                        private String password;
                     
                        @NotBlank(groups = BasicInfo.class)
                        private String name;
                     
                        @Min(value = 18, message = "Age should not be less than 18", groups = AdvanceInfo.class)
                        private int age;
                     
                        @NotBlank(groups = AdvanceInfo.class)
                        private String phone;
                        
                        // standard constructors / setters / getters / toString   
                        
                    }
                    

                    此外,我们现在将更新我们的控制器以使用@Validated批注而不是@Valid:

                    
                    @RequestMapping(value = "/saveBasicInfoStep1", method = RequestMethod.POST)
                    public String saveBasicInfoStep1(
                      @Validated(BasicInfo.class) 
                      @ModelAttribute("useraccount") UserAccount useraccount, 
                      BindingResult result, ModelMap model) {
                        if (result.hasErrors()) {
                            return "error";
                        }
                        return "success";
                    }
                    

                    由于此更新,我们的测试现在成功运行。现在让我们也测试一下这个新方法:

                    
                    @Test
                    public void givenSaveBasicInfoStep1_whenCorrectInput_thenSuccess() throws Exception {
                        this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfoStep1")
                          .accept(MediaType.TEXT_HTML)
                          .param("name", "test123")
                          .param("password", "pass"))
                          .andExpect(view().name("success"))
                          .andExpect(status().isOk())
                          .andDo(print());
                    }
                    

                    这也运行成功。因此,我们可以看到@Validated的使用 对于组验证至关重要。

                    接下来,让我们看看@Valid如何触发嵌套属性的验证。

                    4.使用@Valid嵌套校验

                    @Valid注释用于校验嵌套属性。这会触发嵌套对象的验证。例如,在我们当前的场景中,让我们创建一个 UserAddress 对象:

                    
                    public class UserAddress {
                     
                        @NotBlank
                        private String countryCode;
                     
                        // standard constructors / setters / getters / toString
                    }
                    

                    为了确保此嵌套对象的验证,我们将使用@Valid注释来装饰该属性:

                    
                    public class UserAccount {
                        
                        //...
                        
                        @Valid
                        @NotNull(groups = AdvanceInfo.class)
                        private UserAddress useraddress;
                        
                        // standard constructors / setters / getters / toString 
                    }
                    

                    5. 组合使用@Valid和@Validated 进行集合校验

                    如果请求体直接传递了JSON数组给后台,并希望对数组中的每一项都进行参数校验。此时,如果我们直接使用java.util.Collection下的list或者set来接收数据,参数校验并不会生效!我们可以使用自定义list集合来接收参数:

                    包装List类型,并声明@Valid注解​​​​​​​​​​​​​​

                    
                    package com.devicemag.core.BO;
                     
                    import javax.validation.Valid;
                    import java.util.*;
                     
                    
                    public class ValidList<E> implements List<E> {
                     
                        @Valid
                        private List<E> list = new ArrayList<>();
                     
                        @Override
                        public int size() {
                            return list.size();
                        }
                     
                        @Override
                        public boolean isEmpty() {
                            return list.isEmpty();
                        }
                     
                        @Override
                        public boolean contains(Object o) {
                            return list.contains(o);
                        }
                     
                        @Override
                        public Iterator<E> iterator() {
                            return list.iterator();
                        }
                     
                        @Override
                        public Object[] toArray() {
                            return list.toArray();
                        }
                     
                        @Override
                        public <T> T[] toArray(T[] a) {
                            return list.toArray(a);
                        }
                     
                        @Override
                        public boolean add(E e) {
                            return list.add(e);
                        }
                     
                        @Override
                        public boolean remove(Object o) {
                            return list.remove(o);
                        }
                     
                        @Override
                        public boolean containsAll(Collection<?> c) {
                            return list.containsAll(c);
                        }
                     
                        @Override
                        public boolean addAll(Collection<? extends E> c) {
                            return list.addAll(c);
                        }
                     
                        @Override
                        public boolean addAll(int index, Collection<? extends E> c) {
                            return list.addAll(index, c);
                        }
                     
                        @Override
                        public boolean removeAll(Collection<?> c) {
                            return list.removeAll(c);
                        }
                     
                        @Override
                        public boolean retainAll(Collection<?> c) {
                            return list.retainAll(c);
                        }
                     
                        @Override
                        public void clear() {
                            list.clear();
                        }
                     
                        @Override
                        public E get(int index) {
                            return list.get(index);
                        }
                     
                        @Override
                        public E set(int index, E element) {
                            return list.set(index, element);
                        }
                     
                        @Override
                        public void add(int index, E element) {
                            list.add(index, element);
                        }
                     
                        @Override
                        public E remove(int index) {
                            return list.remove(index);
                        }
                     
                        @Override
                        public int indexOf(Object o) {
                            return list.indexOf(o);
                        }
                     
                        @Override
                        public int lastIndexOf(Object o) {
                            return list.lastIndexOf(o);
                        }
                     
                        @Override
                        public ListIterator<E> listIterator() {
                            return list.listIterator();
                        }
                     
                        @Override
                        public ListIterator<E> listIterator(int index) {
                            return list.listIterator(index);
                        }
                     
                        @Override
                        public List<E> subList(int fromIndex, int toIndex) {
                            return list.subList(fromIndex, toIndex);
                        }
                     
                        public List<E> getList() {
                            return list;
                        }
                     
                        public void setList(List<E> list) {
                            this.list = list;
                        }
                         // 一定要记得重写toString方法
                     
                        @Override
                        public String toString() {
                            return "ValidList{" +
                                    "list=" + list +
                                    '}';
                        }
                    }

                    比如,我们需要一次性保存多个UserAccount 对象,Controller层的方法可以这么写:​​​​​​​

                    
                    @PostMapping("/saveList")
                     
                    public Result saveList(@RequestBody @Validated(UserAccount.class) ValidationList<UserAccount > userList) {
                     
                    // 校验通过,才会执行业务逻辑处理
                     
                    return Result.ok();
                     
                    }

                    6. 自定义校验

                    validator-api-2.0的约束注解有22个,具体我们看下面表格

                    空与非空检查

                    注解 支持Java类型 说明
                    @Null Object 为null
                    @NotNull Object 不为null
                    @NotBlank CharSequence 不为null,且必须有一个非空格字符
                    @NotEmpty CharSequence、Collection、Map、Array 不为null,且不为空(length/size>0)

                    Boolean值检查

                    注解 支持Java类型 说明 备注
                    @AssertTrue boolean、Boolean 为true 为null有效
                    @AssertFalse boolean、Boolean 为false 为null有效

                    日期检查

                    注解 支持Java类型 说明 备注
                    @Future Date、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate 验证日期为当前时间之后 为null有效
                    @FutureOrPresent Date、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate 验证日期为当前时间或之后 为null有效
                    @Past Date、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate 验证日期为当前时间之前 为null有效
                    @PastOrPresent Date、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate 验证日期为当前时间或之前 为null有效

                    数值检查

                    注解 支持Java类型 说明 备注
                    @Max BigDecimal、BigInteger,byte、short、int、long以及包装类 小于或等于 为null有效
                    @Min BigDecimal、BigInteger,byte、short、int、long以及包装类 大于或等于 为null有效
                    @DecimalMax BigDecimal、BigInteger、CharSequence,byte、short、int、long以及包装类 小于或等于 为null有效
                    @DecimalMin BigDecimal、BigInteger、CharSequence,byte、short、int、long以及包装类 大于或等于 为null有效
                    @Negative BigDecimal、BigInteger,byte、short、int、long、float、double以及包装类 负数 为null有效,0无效
                    @NegativeOrZero BigDecimal、BigInteger,byte、short、int、long、float、double以及包装类 负数或零 为null有效
                    @Positive BigDecimal、BigInteger,byte、short、int、long、float、double以及包装类 正数 为null有效,0无效
                    @PositiveOrZero BigDecimal、BigInteger,byte、short、int、long、float、double以及包装类 正数或零 为null有效
                    @Digits(integer = 3, fraction = 2) BigDecimal、BigInteger、CharSequence,byte、short、int、long以及包装类 整数位数和小数位数上限 为null有效

                    其他

                    注解 支持Java类型 说明 备注
                    @Pattern CharSequence 匹配指定的正则表达式 为null有效
                    @Email CharSequence 邮箱地址 为null有效,默认正则 '.*'
                    @Size CharSequence、Collection、Map、Array 大小范围(length/size>0) 为null有效

                    hibernate-validator扩展约束(部分)

                    注解 支持Java类型 说明
                    @Length String 字符串长度范围
                    @Range 数值类型和String 指定范围
                    @URL URL地址验证

                    自定义约束注解

                    除了以上提供的约束注解(大部分情况都是能够满足的),我们还可以根据自己的需求自定义自己的约束注解

                    定义自定义约束,有三个步骤

                    • 创建约束注解
                    • 实现一个验证器
                    • 定义默认的错误信息

                    那么下面就直接来定义一个简单的验证手机号码的注解

                    
                    @Documented
                    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
                    @Constraint(validatedBy = {MobileValidator.class})
                    @Retention(RUNTIME)
                    @Repeatable(Mobile.List.class)
                    public @interface Mobile {
                     
                        
                        String message() default "手机号码不正确";
                     
                        Class<?>[] groups() default {};
                        
                        Class<? extends Payload>[] payload() default {};
                     
                        String regexp() default "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$";
                        @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
                        @Retention(RUNTIME)
                        @Documented
                        @interface List {
                            Mobile[] value();
                        }
                    }
                    

                    关于注解的配置这里不说了,自定义约束需要下面3个属性

                    • message 错误提示信息,可以写死,也可以填写国际化的key
                    • groups 分组信息,允许指定此约束所属的验证组(下面会说到分组约束)
                    • payload 有效负载,可以通过payload来标记一些需要特殊处理的操作

                    @Repeatable注解和List定义可以让该注解在同一个位置重复多次,通常是不同的配置(比如不同的分组和消息)
                    @Constraint(validatedBy = {MobileValidator.class})该注解是指明我们的自定义约束的验证器,那下面就看一下验证器的写法,需要实现javax.validation.ConstraintValidator接口

                    
                    public class MobileValidator implements ConstraintValidator<Mobile, String> {
                     
                        
                        private Pattern pattern;
                     
                        @Override
                        public void initialize(Mobile mobile) {
                            pattern = Pattern.compile(mobile.regexp());
                        }
                     
                        @Override
                        public boolean isValid(String value, ConstraintValidatorContext context) {
                            if (value == null) {
                                return true;
                            }
                     
                            return pattern.matcher(value).matches();
                        }
                    }
                    

                    ConstraintValidator接口定义了在实现中设置的两个类型参数。

                    • 第一个指定要验证的注解类(如Mobile),
                    • 第二个指定验证器可以处理的元素类型(如String);initialize()方法可以访问约束注解的属性值;isValid()方法用于验证,返回true表示验证通过

                    Bean验证规范建议将空值视为有效。如果null不是元素的有效值,则应使用@NotNull 显式注释

                    到这里我们自定义的约束就写好了,可以用个例子来测试一下

                    
                    public class MobileTest {
                     
                        public void setMobile(@Mobile String mobile){
                            // to do
                        }
                     
                        private static ExecutableValidator executableValidator;
                     
                        @BeforeAll
                        public static void setUpValidator() {
                            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
                            executableValidator = factory.getValidator().forExecutables();
                        }
                     
                        @Test
                        public void manufacturerIsNull() throws NoSuchMethodException {
                            MobileTest mobileTest = new MobileTest();
                     
                            Method method = MobileTest.class.getMethod("setMobile", String.class);
                            Object[] parameterValues = {"1111111"};
                            Set<ConstraintViolation<MobileTest>> violations = executableValidator.validateParameters(
                                    mobileTest, method, parameterValues);
                            violations.forEach(violation -> System.out.println(violation.getMessage()));
                        }
                    }
                    

                    手机号码不正确

                    工作原理

                    @Validated的工作原理

                    方法级别参数校验

                    在每个参数前面声明约束注解,然后通过解析参数注解完成校验,这就是方法级别的参数校验。 这种方式可以用于任何的Spring Bean的方法上,一般来说,这种方式一般会采用aop的Around增强完成 在Spring中,是通过以下步骤完成

                    • MethodValidationPostProcessor在Bean的初始化完成之后,判断是否要进行AOP代理(类是否被@Validated标记)
                    • MethodValidationInterceptor拦截所有方法,执行校验逻辑
                    • 委派Validator执行参数校验和返回值校验,得到ConstraintViolation
                    • 处理ConstraintViolation

                    结论

                    总之,对于任何基本验证,我们将在方法调用中使用 JSR @Valid注释。另一方面,对于任何组验证,包括组序列,我们需要 在我们的方法调用中使用 Spring 的@Validated注释。所述@Valid 还需要注释来触发嵌套属性的验证。

                    • @Validated的原理本质还是AOP。在方法校验上,利用AOP动态拦截方法,利用JSR303 Validator实现完成校验。在Bean的属性校验上,则是基于Bean的生命周期,在其初始化前后完成校验
                    • Spring Validator本质实现还是JSR303 Validaotr,只是能让其更好的适配Spring Context
                    • @javax.validation.Valid是JSR303的核心标记注解,但是在Spring Framework中被@Validated取代,但是Spring Validator的实现可以支持兼容@javax.validation.Valid

                    例如,在MethodValidationPostProcessor提供了setValidatedAnnotationType方法,替换默认的@Validated

                    在Spring MVC中,RequestResponseBodyMethodProcessor对@RequestBody和@ResponseBody的校验处理,就兼容了@javax.validation.Valid和@Validated

                    
                    public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
                        @Override
                        protected void validateIfApplicable(WEBDataBinder binder, MethodParameter parameter) {
                            Annotation[] annotations = parameter.getParameterAnnotations();
                            for (Annotation ann : annotations) {
                                Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
                                if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
                                    Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann));
                                    Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
                                    binder.validate(validationHints);
                                    break;
                                }
                            }
                        }
                    }
                    

                    参考链接:

                    https://www.baeldung.com/spring-valid-vs-validated

                    Https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/annotation/Validated.html

                    https://docs.oracle.com/javaee/7/api/javax/validation/Valid.html

                    https://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api/javax/validation/Validator.html

                    https://reflectoring.io/bean-validation-with-spring-boot/

                    https://jcp.org/en/jsr/detail?id=380

                    https://www.baeldung.com/javax-validation

                    到此这篇关于Java中Validated、Valid 、Validator区别详解的文章就介绍到这了,更多相关Validated、Valid 、Validator区别内容请搜索编程界以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程界!

                    --结束END--

                    本文标题: Java中Validated、Valid 、Validator区别详解

                    本文链接: https://www.lsjlt.com/news/102.html(转载时请注明来源链接)

                    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

                    本篇文章演示代码以及资料文档资料下载

                    下载Word文档到电脑,方便收藏和打印~

                    下载Word文档
                    猜你喜欢
                    • Java中Validated、Valid 、Validator区别详解
                      目录1. 结论先出JSR 380Valid VS Validated 不同点?Validator2. @Valid和​​​​​​​@Validated 注解...
                      99+
                      2014-09-01
                      Validated Valid Validator
                    • Spring中@Validated和@Valid区别浅析
                      目录基本概念@Valid和@Validated 批注主要区别什么是嵌套验证?总结基本概念 Spring Validation 验证框架对参数的验证机制提供了@Validated(Sp...
                      99+
                      2022-11-13
                    • @Valid注解的作用及@Valid注解与@Validated的区别
                      目录1.@Valid注解2.@Valid与@Validated的区别注解位置分组校验组序列嵌套校验1.@Valid注解 用于验证注解是否符合要求,直接加在变量user之前,在变量中添...
                      99+
                      2022-11-13
                    • Spring中@Validated和@Valid区别是什么
                      这篇文章主要介绍“Spring中@Validated和@Valid区别是什么”,在日常操作中,相信很多人在Spring中@Validated和@Valid区别是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答...
                      99+
                      2023-06-30
                    • 详解Spring中@Valid和@Validated注解用法
                      目录案例引入@Valid 详解@Validated 详解@Valid 和 @Validated 比较案例引入 下面我们以新增一个员工为功能切入点,以常规写法为背景,慢慢烘托出 @Va...
                      99+
                      2022-11-13
                    • Java中的三种校验注解的使用(@Valid,@Validated和@PathVariable)
                      目录@Valid和@Validated@Valid和@Validated比较@Valid高级使用@Valid级联校验@Validated高级使用@Validated分组校验@Vali...
                      99+
                      2022-11-13
                    • Java中equals和==的区别详解
                      目录1.java中的数据类型,可分为两类: 2.再稍微改动一下程序,会有更奇怪的发现: 3. 字符串缓冲池 4.再次更改程序: 总结1.java中的数据类型,可分为两类: 1.基本...
                      99+
                      2022-11-12
                    • 详解Java中==和equals()的区别
                      目录1. ==1.1 基本数据类型1.2 引用数据类型1.3 小结2. equals3. 总结1. == == 是运算符,用来判断两个值是否相等,==可以使用在基本数据类型变量和引用...
                      99+
                      2022-11-12
                    • Java中Exception和Error的区别详解
                      世界上存在永远不会出错的程序吗?也许这只会出现在程序员的梦中。随着编程语言和软件的诞生,异常情况就如影随形地纠缠着我们,只有正确的处理好意外情况,才能保证程序的可靠性。 java语...
                      99+
                      2022-11-12
                    • java中StringStringBuffer和StringBuilder的区别详解
                      目录从声明定义上来谈从结构上来谈从线程安全来谈总结从声明定义上来谈 只有String 可以 直接声明创建 而 StringBuffer 与 StringBuilder 必须去new...
                      99+
                      2022-11-13
                    • Kotlin与Java的区别详解
                      什么是Kotlin? Kotlin是一种可以在 Java 虚拟机 (JVM) 上运行的开源编程语言。该语言可以在许多平台上运行。 它是一种将面向对象编程 (OOP) 和函数式编程结合...
                      99+
                      2022-11-12
                    • Java 中泛型 T 和 ? 的区别详解
                      目录泛型中 T 类型变量 和 通配符 区别Generic Types 类型变量用法2.声明通用的方法 – 泛型方法:有界类型参数Wildcards 通配符1.上界通配符...
                      99+
                      2022-11-12
                    • java compare compareTo方法区别详解
                      1,compareTo(Object o)方法是java.lang.Comparable<T>接口中的方法,当需要对某个类的对象进行排序时,该类需要实现Comparabl...
                      99+
                      2022-11-12
                    • Java Thread.currentThread().getName() 和 this.getName()区别详解
                      目录currentThread的详解为什么为main呢?创建一个新的线程如何理解上述的情况呢?为什么新线程的名字为thread0呢?再看一种带this的情况创建的线程setName的...
                      99+
                      2022-11-13
                    • Java中class和Class的区别示例详解
                      目录一.class与Class区别二.Class介绍三.如何得到Class对象1.通过getClass()方法获取到Class对象2.通过forName()方法获取到Class对象3...
                      99+
                      2022-11-13
                    • Java中Cookie和Session详解及区别总结
                      目录会话技术Cookie概念快速入门实现原理cookie的细节Cookie的特点和作用案例:记住上一次访问时间分析代码实现Session概念快速入门原理细节Session的特点Ses...
                      99+
                      2022-11-13
                    • Java中BufferedReader与Scanner读入的区别详解
                      java.util.Scanner类是一个简单的文本扫描类,它可以解析基本数据类型和字符串。它本质上是使用正则表达式去读取不同的数据类型。 Java.io.BufferedReade...
                      99+
                      2022-11-12
                    • 基于Java中throw和throws的区别(详解)
                      系统自动抛出的异常所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,并且 Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示,或者修正后使程序继续执行。语句抛出的异常用户程序自定义的异常和应用程序特定的异常,必须...
                      99+
                      2023-05-31
                      java throw throws
                    • java中 String和StringBuffer的区别实例详解
                      java中 String和StringBuffer的区别实例详解String:           是对象不是原始类型.  &nb...
                      99+
                      2023-05-31
                      string stringbuffer buf
                    • Java中Stream流中map和forEach的区别详解
                      目录什么是 stream 流MapforEach使用场景不是很难的知识,但是今天犯错了,记录一下 什么是 stream 流 我们在使用集合或数组对元素进行操作时往往会遇到这种情况:通...
                      99+
                      2022-11-13
                    软考高级职称资格查询
                    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
                    • 官方手机版

                    • 微信公众号

                    • 商务合作