1 Star 1 Fork 0

艺语编程 / bean-validation-demo

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

bean-validation-demo

介绍

Bean Validation 快速开始

参数校验

参数校验是非常常见的一种应用场景,如对前端请求参数的校验,如果传入的参数不合法,则返回相应的错误信息。

如何对参数进行校验呢?可以通过代码做校验,比如使用if语句写判断逻辑校验参数,但这种方式显然很麻烦,也不好维护。

所以,Java提出了参数校验的标准,JSR 303: Bean Validation


什么是JSR303

JSR是Java Specification Requests的缩写,即 Java 规范请求,它是对 Java 平台的提议和最终规范的实际描述。任何时候都有许多 JSR 正在经历审查和批准过程。

JSR303提出了Bean Validation,即Bean 验证。通俗地说,JSR303 指的是Java制定的一套参数校验标准。大家按照这套标准去做具体的参数检验的实现逻辑,官方参考实现是hibernate-validator

后续还提出了JSR 349: Bean Validation 1.1JSR 380: Bean Validation 2.0


参考


添加依赖

<!-- Bean Validation 接口 -->
<dependency>
  <groupId>javax.validation</groupId>
  <artifactId>validation-api</artifactId>
</dependency>
<!-- hibernate 实现 -->
<dependency>
  <groupId>org.hibernate.validator</groupId>
  <artifactId>hibernate-validator</artifactId>
</dependency>

Spring Boot项目也可直接引用官方封装好的Starter。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

常用注解

注解 可使用类型 说明
@Null any type 被注释的元素必须为 null
@NotNull any type 被注释的元素必须不为 null
@AssertTrue boolean and Boolean 被注释的元素必须为 true
@AssertFalse boolean and Boolean 被注释的元素必须为 false
@Min BigDecimal
BigInteger
byte, short, int, long, and their respective wrappers
被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max BigDecimal
BigInteger
byte, short, int, long, and their respective wrappers
被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin BigDecimal
BigInteger
CharSequence
byte, short, int, long, and their respective wrappers
被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax BigDecimal
BigInteger
CharSequence
byte, short, int, long, and their respective wrappers
被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size CharSequence (length of character sequence is evaluated)
Collection (collection size is evaluated)
Map (map size is evaluated)
Array (array length is evaluated)
被注释的元素的大小必须在指定的范围内
@Digits BigDecimal
BigInteger
CharSequence
byte, short, int, long, and their respective wrapper types
被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past java.util.Date
java.util.Calendar
java.time.Instant
java.time.LocalDate
java.time.LocalDateTime
java.time.LocalTime
java.time.MonthDay
java.time.OffsetDateTime
java.time.OffsetTime
java.time.Year
java.time.YearMonth
java.time.ZonedDateTime
java.time.chrono.HijrahDate
java.time.chrono.JapaneseDate
java.time.chrono.MinguoDate
java.time.chrono.ThaiBuddhistDate
被注释的元素必须是一个过去的日期
@Future java.util.Date
java.util.Calendar
java.time.Instant
java.time.LocalDate
java.time.LocalDateTime
java.time.LocalTime
java.time.MonthDay
java.time.OffsetDateTime
java.time.OffsetTime
java.time.Year
java.time.YearMonth
java.time.ZonedDateTime
java.time.chrono.HijrahDate
java.time.chrono.JapaneseDate
java.time.chrono.MinguoDate
java.time.chrono.ThaiBuddhistDate
被注释的元素必须是一个将来的日期
@Pattern CharSequence 被注释的元素必须符合指定的正则表达式
@Email CharSequence 被注释的元素必须是电子邮箱地址
@Length String 被注释的字符串的大小必须在指定的范围内
@NotEmpty CharSequence (length of character sequence is evaluated)
Collection (collection size is evaluated)
Map (map size is evaluated)
Array (array length is evaluated)
被注释的元素的必须不能为 null 或者 empty
@Range 数值类型或者字符串形式的数值 被注释的元素必须在合适的范围内
@NotBlank CharSequence 被注释的元素必须不为 null ,并且至少包含一个非空格的字符

以上是Bean Validation的常用注解,使用时要注意注解可以被使用的参数类型。

其中,CharSequence是字符序列,比如String。

没有特殊说明的注解,一般都是允许参数为null的,具体使用时可以参考注解的注释,都有说明。

还有两个用于开启参数校验的注解:

注解 作用类型 说明
@Valid 属性、方法参数、方法返回值 在验证属性、方法参数或方法返回类型时,将验证对象及其属性上定义的约束
@Validated JSR-303的javax.validation.Valid的变体,支持验证组规范。旨在方便地使用Spring的JSR-303支持,但不特定于JSR-303。

统一异常处理

使用参数校验有这么一种应用场景,在校验请求参数时,当某个请求参数不合法时,会向前端返回相应的错误信息,如下图:

image-20210702232828955

这种方式,是通过Spring MVC的两个注解(@ControllerAdvice + @ExceptionHandler)实现的统一异常处理。

@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(MethodArgumentNotValidException.class)
  public Map<String, Object> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
    ObjectError error = e.getBindingResult().getAllErrors().get(0);
    return ExceResult.build(RespStatusEnum.getCodeByName(error.getCode()), error.getDefaultMessage());
  }
}

注解:

  • @ControllerAdvice 可能和@Controller一样,返回ModelAndView,没做过验证。使用@ControllerAdvice如果想返回json,类或者方法上需要加@ResponseBody。
  • @ResrControllerAdvice 返回json。
  • @ExceptionHander 声明具体要处理异常的类型,它会最先处理粒度最小的异常。

优缺点:

  • 优点:将Controller层和数据校验的异常进行统一处理,提高开发效率;
  • 缺点:只能处理Controller层未捕获的异常,对于拦截器(Interceptor)和Spring 框架中发生的异常无法处理。

可以到Gitee仓库查看具体示例代码。


自定义校验注解

我们可以根据自己的需求来自定义参数校验注解,例如我在示例代码中实现的,校验请求参数中传入的值是否在枚举范围内。

比如User中的性别属性gender,它有两个值:1男、2女,我们一般会定义一个枚举类型:GenderEnum(1男、2女)。当前端传的gender值为3时,说明请求参数是不合法的,这时应该返回一个错误信息给前端。这种场景就可以自定义一个校验注解,专门用来校验是枚举值的参数。


具体实现方式:

  1. 定义注解。

    package com.shiguangping.beanvalidationdemo.enums.annotation;
    
    import javax.validation.Constraint;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 校验枚举值是否在参数范围内
     * 允许值为null
     *
     * @author liyan
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    // 指定约束校验器
    @Constraint(validatedBy = EnumValidator.class)
    public @interface EnumValid {
    		
      	/**
      	 * 异常信息
      	 */
        String message() default "";
    		/**
         * 要校验的枚举类
         */
        Class<?> clazz();
    
        Class[] groups() default {};
    
        Class[] payload() default {};
    }
  2. 定义约束校验器。(实现ConstraintValidator接口)

    package com.shiguangping.beanvalidationdemo.enums.annotation;
    
    import cn.hutool.core.util.ObjectUtil;
    import lombok.SneakyThrows;
    import lombok.extern.slf4j.Slf4j;
    
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    import java.lang.reflect.Method;
    
    /**
     * @author liyan
     */
    public class EnumValidator implements ConstraintValidator<EnumValid, Integer> { // 接口泛型中第一个是对应的注解,第二个是被注解的参数类型
    
        private Class<Enum> clazz;
    
        @SneakyThrows
        @Override
        public boolean isValid(Integer value, ConstraintValidatorContext context) {
            // 参数允许为null
            if (ObjectUtil.isNull(value)) {
                return true;
            }
          	// 获取枚举中所有的枚举常量
            Enum[] enums = clazz.getEnumConstants();
          	// 得到getCode()方法的Method对象
            Method getCode = clazz.getMethod("getCode");
          	// 遍历枚举中所有的枚举常量
            for (Enum anEnum : enums) {
              	// 通过getCode()方法的Method对象调用该方法,传入枚举枚举常量,得到枚举的code值
                Integer code = (Integer) getCode.invoke(anEnum);
              	// 如果校验的参数的值和当前遍历的枚举常量值相等,返回true
                if (value.equals(code)) {
                    return true;
                }
            }
          	// 如果校验的参数的值在枚举中不存在,返回false
            return false;
        }
    
        @Override
        public void initialize(EnumValid constraintAnnotation) {
            ConstraintValidator.super.initialize(constraintAnnotation);
          	// 获取注解的clazz的属性值,也就是指定的枚举的Class对象
            clazz = (Class<Enum>) constraintAnnotation.clazz();
        }
    }
  3. 参数添加自定义注解。

    /**
         * 性别 1男 2女
         */
    @EnumValid(clazz = GenderEnum.class, message = "gender: 超出枚举范围")
    private Integer gender;
  4. 测试。

    image-20210703001155225

可以到Gitee仓库查看具体示例代码。

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [2021] [liyan] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

Bean Validation 快速开始 展开 收起
Java
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/iyucode/bean-validation-demo.git
git@gitee.com:iyucode/bean-validation-demo.git
iyucode
bean-validation-demo
bean-validation-demo
master

搜索帮助