@Vaild注解使用及扩展
一、@Vaild注解介绍#
使用@Vaild注解可以简化入参的校验,配合统一异常实现简单快捷的入参校验,具体使用参照以下
二、@Vaild具体使用#
1、引入jar包#
如果你是springboot项目,此依赖内已经引入,无需再次引入
Copy
| <dependency> |
| <groupId>org.springframework.boot</groupId> |
| <artifactId>spring-boot-starter-web</artifactId> |
| <version>2.0.5.RELEASE</version> |
| </dependency> |
如果没有,将依赖jar包引入到自己的项目中,maven依赖如下
Copy
| <dependency> |
| <groupId>javax.validation</groupId> |
| <artifactId>validation-api</artifactId> |
| <version>1.1.0.Final</version> |
| </dependency> |
| <dependency> |
| <groupId>org.hibernate</groupId> |
| <artifactId>hibernate-validator</artifactId> |
| <version>5.3.5.Final</version> |
| </dependency> |
2、在入参请求类中添加限制注解#
Copy
| import lombok.AllArgsConstructor; |
| import lombok.Data; |
| import lombok.NoArgsConstructor; |
| import org.hibernate.validator.constraints.Length; |
| import org.hibernate.validator.constraints.NotBlank; |
| import org.hibernate.validator.constraints.Range; |
| |
| import javax.validation.constraints.NotNull; |
| import java.io.Serializable; |
| |
| @Data |
| @NoArgsConstructor |
| @AllArgsConstructor |
| public class UserReq implements Serializable { |
| |
| private Integer id; |
| |
| @NotBlank(message = "用户名不能为空") |
| @Length(message = "用户名最大为{max}个字符", max = 20) |
| private String username; |
| |
| @NotBlank(message = "密码不能为空") |
| @Length(message = "密码长度限制为{min}-{max}", min = 8, max = 16) |
| private String password; |
| |
| @NotNull(message = "性别不能为空") |
| private Byte sex; |
| |
| @Range(message = "年龄范围为{min}-{max}", min = 0, max = 120) |
| private Integer age; |
| |
| } |
3、控制器中使用@Vaild#
Copy
| import com.alibaba.fastjson.JSON; |
| import lombok.extern.slf4j.Slf4j; |
| import org.springframework.web.bind.annotation.*; |
| |
| import javax.validation.Valid; |
| |
| @Slf4j |
| @RestController |
| @RequestMapping("/user/post") |
| public class PostController { |
| |
| @PostMapping("/create") |
| public String createUser(@Valid @RequestBody UserReq req){ |
| log.info(JSON.toJSONString(req)); |
| return "成功"; |
| } |
| |
| } |
4、请求进行测试#


虽然拦截成功,但错误出参不知道所以然,一头雾水,需进行优化
三、优化出参#
1、修改控制器#
Copy
| import com.alibaba.fastjson.JSON; |
| import lombok.extern.slf4j.Slf4j; |
| import org.springframework.validation.BindingResult; |
| import org.springframework.web.bind.annotation.*; |
| |
| import javax.validation.Valid; |
| |
| @Slf4j |
| @RestController |
| @RequestMapping("/user/post") |
| public class PostController { |
| |
| @PostMapping("/create") |
| public String createUser(@Valid @RequestBody UserReq req, BindingResult result){ |
| |
| if(result.hasErrors()){ |
| String message = result.getAllErrors().get(0).getDefaultMessage(); |
| log.error(message); |
| return message; |
| } |
| log.info(JSON.toJSONString(req)); |
| return "成功"; |
| } |
| |
| } |
2、请求进行测试#

四、使用统一异常#
1、创建统一异常捕获类#
Copy
| import lombok.extern.slf4j.Slf4j; |
| import org.springframework.web.bind.MethodArgumentNotValidException; |
| import org.springframework.web.bind.annotation.ControllerAdvice; |
| import org.springframework.web.bind.annotation.ExceptionHandler; |
| import org.springframework.web.bind.annotation.ResponseBody; |
| |
| @Slf4j |
| @ControllerAdvice |
| public class MyExceptionHandler { |
| |
| @ResponseBody |
| @ExceptionHandler(Exception.class) |
| public ResultData exceptionHandler(Exception exception){ |
| log.error("统一异常", exception); |
| |
| if(exception instanceof MethodArgumentNotValidException){ |
| MethodArgumentNotValidException ex = (MethodArgumentNotValidException) exception; |
| String message = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage(); |
| return ResultData.getFailResult(message); |
| } |
| return ResultData.getFailResult("服务器繁忙,请稍后再试!"); |
| } |
| |
| } |
2、此时控制器不需要做额外处理#
Copy
| import com.alibaba.fastjson.JSON; |
| import lombok.extern.slf4j.Slf4j; |
| import org.springframework.web.bind.annotation.*; |
| |
| import javax.validation.Valid; |
| |
| @Slf4j |
| @RestController |
| @RequestMapping("/user/post") |
| public class PostController { |
| |
| @PostMapping("/create") |
| public String createUser(@Valid @RequestBody UserReq req){ |
| log.info(JSON.toJSONString(req)); |
| return "成功"; |
| } |
| |
| } |
3、请求进行测试#


五、验证注解#
1、官方的验证注解#
验证注解 |
说明 |
@Null |
只能为null |
@NotNull |
不能为null |
@NotEmpty |
不为null、不能为空字符串(字符串长度不为0、集合大小不为0) |
@NotBlank |
不为null、不能为空字符串,不同于@NotEmpty,@NotBlank会去掉空格再判断 |
@AssertFalse |
必须为false |
@AssertTrue |
必须为true |
@DecimalMax(value) |
必须为一个不大于指定值的数字 |
@DecimalMin(value) |
必须为一个不小于指定值的数字 |
@Max(value) |
必须为一个不大于指定值的数字 |
@Min(value) |
必须为一个不小于指定值的数字 |
@Digits(integer,fraction) |
必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction |
@Future |
必须是一个将来的日期 |
@Past |
必须是一个过去的日期 |
@Pattern(value) |
必须符合指定的正则表达式 |
@Length(max,min) |
字符长度必须在min到max之间 |
@Email |
验证注解的元素值是Email |
2、自定义验证注解#
1)定义注解#
Copy
| import javax.validation.Constraint; |
| import javax.validation.Payload; |
| import java.lang.annotation.ElementType; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.annotation.Target; |
| |
| @Constraint(validatedBy = {SexConstraintValidator.class}) |
| @Target({ElementType.METHOD, ElementType.FIELD}) |
| @Retention(RetentionPolicy.RUNTIME) |
| public @interface SexConstraint { |
| |
| String message() default "性别有误,请确认"; |
| |
| Class<?>[] groups() default {}; |
| |
| Class<? extends Payload>[] payload() default {}; |
| |
| } |
2)定义校验器#
Copy
| import javax.validation.ConstraintValidator; |
| import javax.validation.ConstraintValidatorContext; |
| |
| public class SexConstraintValidator implements ConstraintValidator<SexConstraint, Byte> { |
| |
| @Override |
| public void initialize(SexConstraint sexConstraint) { |
| System.out.println("初始化信息"); |
| } |
| |
| @Override |
| public boolean isValid(Byte sex, ConstraintValidatorContext constraintValidatorContext) { |
| if(sex==null) |
| return false; |
| if(sex!=0 && sex!=1 && sex!=2) |
| return false; |
| return true; |
| } |
| |
| } |
3)使用注解#
Copy
| import com.banmoon.lol.config.annotation.SexConstraint; |
| import lombok.AllArgsConstructor; |
| import lombok.Data; |
| import lombok.NoArgsConstructor; |
| import org.hibernate.validator.constraints.Length; |
| import org.hibernate.validator.constraints.NotBlank; |
| import org.hibernate.validator.constraints.Range; |
| |
| import java.io.Serializable; |
| |
| @Data |
| @NoArgsConstructor |
| @AllArgsConstructor |
| public class UserReq implements Serializable { |
| |
| private Integer id; |
| |
| @NotBlank(message = "用户名不能为空") |
| @Length(message = "用户名最大为{max}个字符", max = 20) |
| private String username; |
| |
| @NotBlank(message = "密码不能为空") |
| @Length(message = "密码长度限制为{min}-{max}", min = 8, max = 16) |
| private String password; |
| |
| @SexConstraint |
| private Byte sex; |
| |
| @Range(message = "年龄范围为{min}-{max}", min = 0, max = 120) |
| private Integer age; |
| |
| } |
4)请求进行测试#


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!