还在用if校验参数?SpringBoot使用validation优雅实现参数校验

👩🏽‍💻个人主页:阿木木AEcru (更多精彩内容可进入主页观看)

🔥 系列专栏:《Docker容器化部署系列》 《Java每日面筋》

💹每一次技术突破,都是对自我能力的挑战和超越。

一、前言

你还在使用if else 的方式进行入参的校验吗?

能看的出来,这样的校验方式看起来很不优雅,当然也是能达到目的。如果说有非常多的参数需要校验的话,就要写非常多的if else ,就像老太婆的裹脚布一样,又臭又长,让人看起来非常的难受。话不多说,下面我就给大家推荐一个优雅校验入参的方式吧!

二、使用SpringBoot-Validation

2.1 添加依赖

   <!-- spring-boot 2.3及以上的版本需要引入包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

2.2 注解使用说明

注解说明
@NotNull验证注解的元素必须非空(即非null且非空字符串)
@NotEmpty验证注解的字符串元素必须非空且长度大于0
@NotBlank验证注解的字符串元素必须非空,并且至少包含一个非空白字符
@Null验证注解的元素必须为null
@AssertTrue验证布尔值必须为true
@AssertFalse验证布尔值必须为false
@Size验证注解的字符串或集合元素的数量是否在指定的范围内
@Length验证注解的字符串元素的长度是否在指定的范围内
@Min验证注解的数值是否大于或等于指定的最小值
@Max验证注解的数值是否小于或等于指定的最大值
@DecimalMin验证注解的数值是否大于或等于指定的十进制最小值
@DecimalMax验证注解的数值是否小于或等于指定的十进制最大值
@Email验证注解的字符串是否是有效的电子邮件地址
@Pattern验证注解的字符串是否与指定的正则表达式匹配
@Past验证注解的日期元素是否在当前日期之前
@Future验证注解的日期元素是否在当前日期之后
@Valid递归验证关联对象的属性
@Positive验证注解的数值是否大于0
@Negative验证注解的数值是否小于0
@Digits验证注解的数值是否有正确的整数位数和小数位数

2.3 注解应用到实体


@Data
public class TestOneDTO {

    @NotNull(message = "用户名不允许为空")
    @Size(min = 3, max = 50, message = "用户名长度必须在3到50个字符之间")
    private String username;

    @NotNull(message = "密码不允许为空")
    @Size(min = 6, max = 20, message = "密码长度必须在6到20个字符之间")
    private String password;

    @Email(message = "电子邮箱格式不正确")
    private String email;

    @Min(value = 18, message = "年龄必须至少为18岁")
    @Max(value = 100, message = "年龄不允许超过100岁")
    private Integer age;

    @Past(message = "生日不能大于当前时间")
    private LocalDateTime birthDate;

    @Pattern(regexp = "^((\\+86)|(0086))?(-\\d{3}-)?\\d{8}$", message = "手机号码格式不正确")
    private String phoneNumber;

    // 校验对象中的另一个对象(对象内容如下)
    @Valid
    private Address address;
    public boolean validate() {
        if (username == null || username.length() < 3 || username.length() > 50) {
            System.out.println("用户名长度必须在3到50个字符之间");
            return false;
        }
        if (password == null || password.length() < 6 || password.length() > 20) {
            System.out.println("密码长度必须在6到20个字符之间");
            return false;
        }
        if (email == null || !email.contains("@")) {
            System.out.println("电子邮箱格式不正确");
            return false;
        }
        if (age == null || age < 18 || age > 100) {
            System.out.println("年龄必须至少为18岁且不允许超过100岁");
            return false;
        }
        if (birthDate != null && birthDate.isAfter(LocalDateTime.now())) {
            System.out.println("生日必须是过去的时间");
            return false;
        }
        if (phoneNumber != null && !phoneNumber.matches("^((\\+86)|(0086))?(-\\d{3}-)?\\d{8}$")) {
            System.out.println("手机号码格式不正确");
            return false;
        }
        return true;
    }
}

@Data
class Address {
    @NotBlank(message = "地址不允许为空")
    @Size(min = 5, max = 200, message = "地址长度必须在5到200个字符之间")
    private String street;

    @NotBlank(message = "城市不允许为空")
    private String city;

}

2.4 测试是否生效

可以看出,这里没有任何请求内容依然成功了,这是因为还少了一个注解 @Valid 需要在入参前面添加上。


加上 @Valid 注解后,再次请求可以看到已经有异常信息了,这时就能使用 全局异常处理器 进行捕获处理,格式化响应的异常信息内容。

2.5 全局异常捕获

全局异常捕获类如下


@ControllerAdvice
@ResponseBody
@Component
@Slf4j
public class GlobalExceptionHandler {

    /**
     * @Valid校验异常处理
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R methodArgumentNotValidExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e){
        StringBuffer sb = new StringBuffer();
        List<ObjectError> allErrors = e.getAllErrors();
        if (CollUtil.isNotEmpty(allErrors)){
            for (ObjectError allError : allErrors) {
                sb.append(allError.getDefaultMessage()).append("|");
            }
        }
        return R.of(CommonConstants.FAIL,null,sb.toString());
    }

    @ExceptionHandler(value = Exception.class)
    public R exceptionHandler(HttpServletRequest request, Exception e){
        e.printStackTrace();
        log.info("Exception异常全局拦截:{}",e.getMessage());
        // 其余异常简单返回为服务器异常
        return R.failed("服务器繁忙,请联系管理员或稍后再试!");
    }


}

加上之后再次请求


异常信息已经被格式化了,如果需要其他格式的异常信息提示,可以自主调整相关的异常信息格式化内容来满足你的需求。
在这里需要注意的是,当在同一个字段上使用多个注解时,校验框架会按照它们在类定义中出现的顺序进行校验。如果一个字段违反了前面的校验规则,后续的校验可能不会执行。

三、结尾

感谢观看至此,希望该文章能够帮助到您提升知识和技能。如果您喜欢我的内容,请不要忘记点赞和分享哦!👍
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿木木AEcru

感谢您的阅读,赞赏请随意打赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值