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方法
2.DTO
3.全局异常处理方法
4.加了basePackage
5.400错误
6.控制台:被mvc DefaultHandlerExceptionResolver吞掉
7.同包内 不指定basePackage
8.正常拦截异常
解决方式
- 使用其它的异常处理方式,下面有
四、其它的异常处理方式
- 继承mvc父类的异常拦截 重写方法 见参考链接
- 在controller层手动拦截BindingResult
- 继承DefaultHandlerExceptionResolver并重写他的方法
等等
五、自定义校验注解和自定义校验器
见参考链接
https://blog.csdn.net/en_joker/article/details/113244667
分类:
Java学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?