Java参数校验框架Validation的使用和踩坑

Java使用validation注解

一、JSR303规范

使用javax.validation注解族

常用注解说明 来自csdn

//JSR303标准提供的注解
@AssertFalse	被注释的元素只能为false
@AssertTrue	被注释的元素只能为true
@DecimalMax	被注释的元素必须小于或等于{value}
@DecimalMin	被注释的元素必须大于或等于{value}
@Digits	被注释的元素数字的值超出了允许范围(只允许在{integer}位整数和{fraction}位小数范围内)
@Email	被注释的元素不是一个合法的电子邮件地址
@Future	被注释的元素需要是一个将来的时间
@FutureOrPresent	被注释的元素需要是一个将来或现在的时间
@Max	被注释的元素最大不能超过{value}
@Min	被注释的元素最小不能小于{value}
@Negative	被注释的元素必须是负数
@NegativeOrZero	被注释的元素必须是负数或零
@NotBlank	被注释的元素不能为空
@NotEmpty	被注释的元素不能为空
@NotNull	被注释的元素不能为null
@Null	被注释的元素必须为null
@Past	被注释的元素需要是一个过去的时间
@PastOrPresent	被注释的元素需要是一个过去或现在的时间
@Pattern	被注释的元素需要匹配正则表达式"{regexp}"
@Positive	被注释的元素必须是正数
@PositiveOrZero	被注释的元素必须是正数或零
@Size	被注释的元素个数必须在{min}和{max}之间

// Hibernate Validator提供的校验注解
@CreditCardNumber	被注释的元素不合法的信用卡号码
@Currency	被注释的元素不合法的货币 (必须是{value}其中之一)
@EAN	被注释的元素不合法的{type}条形码
@Email	被注释的元素不是一个合法的电子邮件地址 (已过期)
@Length	被注释的元素长度需要在{min}和{max}之间
@CodePointLength	被注释的元素长度需要在{min}和{max}之间
@LuhnCheck	被注释的元素${validatedValue}的校验码不合法, Luhn模10校验和不匹配
@Mod10Check	被注释的元素${validatedValue}的校验码不合法, 模10校验和不匹配
@Mod11Check	被注释的元素${validatedValue}的校验码不合法, 模11校验和不匹配
@ModCheck	被注释的元素${validatedValue}的校验码不合法, ${modType}校验和不匹配 (已过期)
@NotBlank	被注释的元素不能为空 (已过期)
@NotEmpty	被注释的元素不能为空 (已过期)
@ParametersScriptAssert	被注释的元素执行脚本表达式"{script}"没有返回期望结果
@Range	被注释的元素需要在{min}和{max}之间
@SafeHtml	被注释的元素可能有不安全的HTML内容
@ScriptAssert	被注释的元素执行脚本表达式"{script}"没有返回期望结果
@URL	被注释的元素需要是一个合法的URL
@DurationMax 被注释的元素必须小于${inclusive == true ? '或等于' : ''}${days == 0 ? '' : days += '天'}${hours == 0 ? '' : hours += '小时'}${minutes == 0 ? '' : minutes += '分钟'}${seconds == 0 ? '' : seconds += '秒'}${millis == 0 ? '' : millis += '毫秒'}${nanos == 0 ? '' : nanos += '纳秒'}
@DurationMin	被注释的元素必须大于${inclusive == true ? '或等于' : ''}${days == 0 ? '' : days += '天'}${hours == 0 ? '' : hours += '小时'}${minutes == 0 ? '' : minutes += '分钟'}${seconds == 0 ? '' : seconds += '秒'}${millis == 0 ? '' : millis += '毫秒'}${nanos == 0 ? '' : nanos += '纳秒'}

二、依赖

<!--
引入validation注解
-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
 </dependency>
<!--
hibernate-validation 扩展
-->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

三、使用

1.对dto 实体类等进行校验

例子

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import javax.validation.constraints.Size;


@Data
public class CommentDTO {
    
    @NotNull(message = "被回复人id不能为空")
    private Integer replyUserId;
    
    @NotNull(message = "被评论的文章id不能为空")
    private Integer articleId;
    
    @NotBlank(message = "评论内容不能为空!")
    @Size(max = 3000,min = 6,message = "评论内容不能小于6字符!")
    private String commentContent;
    
    //todo 判断是否为空并且给默认值
    @NotNull(message = "父评论id不能为空")
    private Integer parentId;
    
    @Null
    private Integer userId;
}

2.在controller中使用

//使用@Valid注解 或者@Validated注解
    @PostMapping("/addComment")
    public R addComment(@RequestBody @Valid CommentDTO commentDTO){
        return commentService.addComment(commentDTO);
    }

3.全局异常处理拦截校验异常

@RestControllerAdvice
@Slf4j
public class GlobalExceptionAdvice {
    
    //    参数校验异常
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R validationException(MethodArgumentNotValidException e) {
    
String msg = e.getBindingResult().getFieldErrors()
                .stream()
                .map(n -> String.format("%s: %s", n.getField(), 		      n.getDefaultMessage()))
                .reduce((x, y) -> String.format("%s; %s", x, y))
                .orElse("参数输入有误");
        log.error("BindException异常,参数校验异常:{}", msg);
        return R.error(msg);
    }
    
    
}

踩坑:异常被SpringMVC的DefaultHandlerExceptionResolver吞掉

如果在同一包内,不用配置@RestControllerAdvice的 basepackage属性,如果配置了,异常会交给mvc默认的
defaultHandlerExceptionResolVer拦截,导致返回400

图示

1.Controller方法
image

2.DTO

image

3.全局异常处理方法
image

4.加了basePackage

image

5.400错误
image

6.控制台:被mvc DefaultHandlerExceptionResolver吞掉
image

7.同包内 不指定basePackage
image

8.正常拦截异常
image

解决方式

  • 使用其它的异常处理方式,下面有

四、其它的异常处理方式

  • 继承mvc父类的异常拦截 重写方法 见参考链接
  • 在controller层手动拦截BindingResult
  • 继承DefaultHandlerExceptionResolver并重写他的方法

等等

五、自定义校验注解和自定义校验器

见参考链接
https://blog.csdn.net/en_joker/article/details/113244667

posted @   YURainnn  阅读(5053)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示