👩🏽💻个人主页:阿木木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("服务器繁忙,请联系管理员或稍后再试!");
}
}
加上之后再次请求
异常信息已经被格式化了,如果需要其他格式的异常信息提示,可以自主调整相关的异常信息格式化内容来满足你的需求。
在这里需要注意的是,当在同一个字段上使用多个注解时,校验框架会按照它们在类定义中出现的顺序进行校验。如果一个字段违反了前面的校验规则,后续的校验可能不会执行。
三、结尾
感谢观看至此,希望该文章能够帮助到您提升知识和技能。如果您喜欢我的内容,请不要忘记点赞和分享哦!👍