如何在Spring Boot中优雅地进行参数校验

这篇具有很好参考价值的文章主要介绍了如何在Spring Boot中优雅地进行参数校验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 前言

在平时的开发工作中,我们通常需要对接口进行参数格式验证。当参数个数较少(个数小于3)时,可以使用if ... else ...手动进行参数验证。当参数个数大于3个时,使用if ... else ...进行参数验证就会让代码显得臃肿,这个时候推荐使用注解来进行参数验证。

在Java中,注解(Annotation)是一种代码标记,通常用于提供元数据,这些元数据可以被编译器或运行时环境使用。这些注解通常用于框架和库中,以实现更加灵活和可配置的代码。

2. 常用注解描述

  1. @NotNull

    • 描述:标记一个值不能为null。
    • 示例:
    public class User {  
        @NotNull  
        private String name;  
        // ...  
    }
    
  2. @NotEmpty

    • 描述:标记一个集合(如List、Set等)不能为空。
    • 示例:
    public class User {  
        @NotEmpty  
        private List<String> interests;  
        // ...  
    }
    
  3. @NotBlank

    • 描述:标记一个字符串不能为空白(即null、空字符串或只包含空格)。
    • 示例:
    public class User {  
        @NotBlank  
        private String username;  
        // ...  
    }
    
  4. @Size

    • 描述:标记一个字符串或集合的大小必须在指定的范围内。
    • 示例:
    public class User {  
        @Size(min = 2, max = 50)  
        private String username;  
        // ...  
    }
    
  5. @Min@Max

    • 描述:标记一个数值必须在指定的最小值和最大值之间。
    • 示例:
    public class User {  
        @Min(18)
        @Max(60)  
        private int age;  
        // ...  
    }
    
  6. @DecimalMin@DecimalMax

    • 描述:标记一个浮点数或双精度数必须在指定的最小值和最大值之间。
    • 示例:
    public class User {  
        @DecimalMin("0.01") @DecimalMax("100.00")  
        private double discount;  
        // ...  
    }
    
  7. @Digits

    • 描述:标记一个整数或浮点数必须在指定的精度和总数值范围内。
    • 示例:
    public class User {  
        @Digits(integer = 3, fraction = 2) // 总长度为5,3位整数,2位小数。例如:"123.45" 是合法的。  
        private BigDecimal amount;  
        // ...  
    }
    
  8. @Pattern

    • 描述:标记一个字符串必须匹配指定的正则表达式。通常用于验证输入格式。例如电子邮件地址、电话号码格式等。@Pattern注解在javax.validation.constraints包中。@Pattern(regexp = “^\w{5,}$”)表示长度在5-20之间,由字母、数字、下划线组成的字符串。@Pattern注解用于类字段上,例如用户密码字段。
    • 示例:
    public class User { 
        @Pattern(regexp = "^[a-zA-Z0-9]*$") 
        private String password; //... 
    } 
    
  9. @Email

    • 描述:标记一个字符串必须是一个有效的电子邮件地址。
    • 示例:
    @Email
    private String emailAddress;
    
  10. @AssertTrue@AssertFalse

    • 描述:标记一个布尔值必须为true或false。
    • 示例:
    @AssertTrue
    private boolean isValid;
    
    @AssertFalse
    private boolean isNotValid;
    
  11. @Future

    • 描述:标记一个日期必须是在未来某个时间点之后。
    • 示例:
    @Future
    private Date expiryDate;
    
  12. @Past

    • 描述:标记一个日期必须是在过去某个时间点之前。
    • 示例:
    @Past
    private Date purchaseDate;
    

这些注解通常与验证框架(如Hibernate Validator)一起使用,以在运行时验证对象的属性。

3. 注解使用

  1. 在项目的pom.xml文件中添加如下依赖:
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-validation</artifactId>
 </dependency>
  1. 在实体类中使用上述注解,代码如下:

    package com.yyqq.demo.entity;
    
    import lombok.Data;
    import javax.validation.constraints.*;
    
    @Data
    public class User {
        @NotBlank(message = "用户姓名不能为空")
        private String name;
    
        @NotBlank(message = "密码不能为空")
        @Size(min = 6, message = "密码长度不能少于6位")
        private String password;
    
        @Min(value = 0, message = "年龄不能小于0岁")
        @Max(value = 150, message = "年龄不应超过150岁")
        private Integer age;
    
        @Pattern(regexp = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-9])|(147))\d{8}$", message = "手机号格式不正确")
        private String phone;
    }
    
  2. 控制器类使用验证,代码如下:

    import com.yyqq.demo.util.Result;
    import com.yyqq.demo.entity.User;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.validation.Valid;
    
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @PostMapping("/add")
        public Result add(@Valid @RequestBody User user) {
         	return Result.success(user);
        }
    }
    
  3. Result是封装结果的一个类,用于返回统一的结果,代码如下:

    package com.yyqq.demo.util;
    
    import lombok.Data;
    import java.io.Serializable;
    
    @Data
    public class Result<T> implements Serializable {
        private int code;
        private boolean success;
        private T data;
        private String msg;
    
        private Result(int code, T data, String msg) {
            this.code = code;
            this.data = data;
            this.msg = msg;
            this.success = code == 200;
        }
    
        public static <T> Result<T> sucess(T data) {
        	return new Result<>(200, data, null);
        }
    
        public static <T> Result<T> fail(String msg) {
        	return new Result<>(500, null, msg);
        }
    }
    
  4. 定义全局异常处理类,我们在全局异常处理类中使用ExceptionHandler捕获BindException异常,获取参数验证异常信息,最后返回统一的异常结果格式,代码如下:

    package com.yyqq.demo.util;
    
    import com.yyqq.demo.util.Result;
    import org.springframework.validation.BindException;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(BindException.class)
        public Result handleError(BindException e) {
            BindingResult bindingResult = e.getBindingResult();
            return Result.fail(bindingResult.getFieldError().getDefaultMessage());
        }
    }
    

4. 使用分组验证

  1. 用于插入记录时的分组验证,代码如下:
package com.yyqq.demo.interceptor;
import javax.validation.groups.Default;

public interface Insert extends Default {
}

  1. 用于更新记录时的分组验证,代码如下:
package com.yyqq.demo.interceptor;
import javax.validation.groups.Default;

public interface Update extends Default {
}
  1. 在实体类中进行分组标记,代码如下:
package com.yyqq.demo.entity;

import lombok.Data;
import javax.validation.constraints.*;

@Data
public class User {
    @NotBlank(groups = {Insert.class, Update.class})
    @NotBlank(message = "用户姓名不能为空")
    private String name;

    @NotBlank(message = "密码不能为空")
    @Size(min = 6, message = "密码长度不能少于6位")
    private String password;

    @Min(value = 0, message = "年龄不能小于0岁")
    @Max(value = 150, message = "年龄不应超过150岁")
    private Integer age;

    @NotBlank(groups = {Insert.class, Update.class})
    @Pattern(regexp = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-9])|(147))\\d{8}$", message = "手机号格式不正确")
    private String phone;
}
  1. 控制器类使用分组验证
package com.yyqq.demo.controller;

import com.yyqq.demo.util.Result;
import com.yyqq.demo.entity.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequestMapping("/user")
public class UserController {

    @PostMapping("/add")
    public Result add(@Validated(Insert.class) @RequestBody User user) {
     	return Result.success(user);
    }
    
    @PostMapping("/update")
    public Result update(@Validated(Update.class) @RequestBody User user) {
     	return Result.success(user);
    }
}

5. 自定义验证注解

除了框架自带的注解,平时的工作中可能需要我们自定义验证注解处理特定的业务需求。

  1. 定义注解
package com.yyqq.demo.validate;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Retention(RUNTIME)
@Constraint(validatedBy = {PhoneValidator.class})
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
public @interface Phone {

    String message() default "手机号格式错误";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

  1. 定义验证器类
package com.yyqq.demo.validate;

import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintValidator;
import java.util.regex.Pattern;

public class PhoneValidator implements ConstraintValidator<Phone, String> {
    private static final String REGEX = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-9])|(147))\\d{8}$";

    @Override
    public boolean isValid(String s, ConstraintValidatorContext context) {
        boolean result = false;
        try {
            result = Pattern.matches(REGEX, s);
        } catch (Exception e) {
            System.out.println("验证手机号格式时发生异常,异常信息:" + e);
        }
        return result;
    }
}
  1. 实体类使用注解
package com.yyqq.demo.validate;

public class User {

    //其他属性...

    //  @Pattern(regexp = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-9])|(147))\\d{8}$", message = "手机号格式不正确")
    @Phone
    private String phone;
}

6. @Valid与@Validated的区别

用于参数校验的注解通常有两个:@Valid@Validated。它们的区别有如下几点:文章来源地址https://www.toymoban.com/news/detail-798225.html

区别 @Valid @Validated
来源 @Valid是Java标准注解 @Validated是Spring框架定义的注解。
是否支持分组验证 不支持 支持
使用位置 构造函数、方法、方法参数、成员属性 类、方法、方法参数,不能用于成员属性
是否支持嵌套校验 支持 不支持

到了这里,关于如何在Spring Boot中优雅地进行参数校验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot 使用validation校验参数

    在看公司代码的时候,发现是用了 Spring Boot Validation 去检验参数的,但是后面又在代码里去检验参数去了,而且这个 Spring Boot Validation 校验好像并不生效。于是自己摸索研究了一下。 虽然项目使用的校验都是 javax.validation ,但是不引入这个依赖他是真的不生效。 gradle如下:

    2024年01月25日
    浏览(32)
  • 优雅地处理参数传递:Spring Boot中的技巧

    目录 一:四种传参方式 1.1:在 URL 中传递参数 1.2:PathVariable 传递参数(Restful 风格) 1.3:在请求体中传递参数 1.4:在请求头中传递参数  二:文件上传接口测试  2.1 : test.java  三、@RequestParam 3.1 多个参数  3.2 单个参数  四、@PathVariable 4.1  单个参数  4.2  多个参数 五、@

    2024年02月05日
    浏览(37)
  • spring boot3参数校验基本用法

    ⛰️个人主页:      蒾酒 🔥系列专栏: 《spring boot实战》 🌊山高路远,行路漫漫,终有归途。 目录 前置条件 前言 导入依赖 使用介绍 配置检验规则 开启校验 使用注意 全局异常捕获返回友好提示信息 常用的校验规则注解 使用技巧 已经初始化好一个spring boot项目且版本为

    2024年02月21日
    浏览(33)
  • spring boot实现实体类参数自定义校验

    安装依赖项 1、新建实体类 2、新建验证类 3、在控制器中 3.1 首先写入方法 @InitBinder注解的作用是在控制器方法执行之前,先执行有 @InitBinder注解的方法,使用WebDataBinder 把新建的验证规则绑定 3.2 在控制器接口参数中

    2024年02月12日
    浏览(28)
  • spring-boot 请求参数校验:注解 @Validated 的使用、手动校验、自定义校验

    spring-boot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。 spring-boot已经引入了基础包,所以直接使用就可以。 在属性上添加校验注解: 在Controller上添加 @Validated 注解 校验未通过时,可能看到: 在 @Validated 后面紧跟着追加BindingResult,

    2023年04月16日
    浏览(88)
  • 参数校验: spring-boot-starter-validation

    2024年01月21日
    浏览(37)
  • Spring Boot使用 Hibernate-Validator校验参数时的长度校验

    今天在使用Validator框架数据验证的时候碰到了三个类似的注解,都是用来限制长度,但是用法上有区别:  @Size是一个Bean验证注释,用于验证关联的String具有的长度受最小值和最大值限制的值.  @Length是一个Hibernate特定的注释,与@Size具有相同的含义; 两者的区别: ​ 用@length限

    2024年02月14日
    浏览(32)
  • Spring Boot中使用JSR-303实现请求参数校验

    JSR-303是Java中的一个规范,用于实现请求参数校验。它定义了一组注解,可以应用于JavaBean的字段上,用于验证输入参数的合法性。下面是一些常用的JSR-303注解及其介绍: @NotNull :用于验证字段值不能为null。 @NotEmpty :用于验证字符串字段不能为空。 @NotBlank :用于验证字符

    2024年02月08日
    浏览(25)
  • Spring Boot中如何编写优雅的单元测试

    单元测试是指对软件中的最小可测试单元进行检查和验证。在Java中,单元测试的最小单元是类。通过编写针对类或方法的小段代码,来检验被测代码是否符合预期结果或行为。执行单元测试可以帮助开发者验证代码是否正确实现了功能需求,以及是否能够适应应用环境或需求

    2024年02月11日
    浏览(32)
  • Spring Boot进阶(45): Spring Boot 开发必备技能:如何优雅地返回统一结果包装!

            在实际的开发中,我们常常需要对 API 接口的返回结果进行统一的包装,以方便客户端的处理和异常情况的统一处理。例如,我们可能需要对 API 接口返回结果进行统一的格式处理,将所有的异常情况都转化为统一的错误类型,同时也可能需要对返回结果进行统一的加

    2024年02月07日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包