# 参数校验
# 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
# 举例
package com.base.pre.controller;
import cn.dev33.satoken.util.SaResult;
import cn.dev33.satoken.exception.NotLoginException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* Demo 控制器,用于触发全局异常处理器
* </p>
*
* @author
*/
@RestController
@RequestMapping("/demo2")
@Tag(name = "异常演示接口")
public class DemoController {
@GetMapping("/npe")
@Operation(summary = "触发空指针异常")
public SaResult npe() {
String str = null;
str.length(); // NullPointerException
return SaResult.ok();
}
@GetMapping("/illegal")
@Operation(summary = "触发非法参数异常")
public SaResult illegal() {
throw new IllegalArgumentException("参数值不合法!");
}
@PostMapping("/duplicate")
@Operation(summary = "触发数据库唯一约束异常")
public SaResult duplicate() {
throw new org.springframework.dao.DataIntegrityViolationException("唯一约束冲突");
}
@PostMapping("/valid")
@Operation(summary = "触发 @Valid 校验异常(MethodArgumentNotValidException)")
public SaResult valid(@Valid @RequestBody UserDTO userDTO) {
return SaResult.ok("校验通过: " + userDTO.getName());
}
@GetMapping("/param")
@Operation(summary = "触发参数校验异常(ConstraintViolationException)")
public SaResult param(
@RequestParam(name = "id")
@NotNull(message = "id 不能为空")
@Min(value = 1, message = "id 必须大于 0")
Integer id) {
return SaResult.ok("收到id=" + id);
}
@GetMapping("/needLogin")
@Operation(summary = "触发未登录异常(NotLoginException)")
public SaResult needLogin() {
throw new NotLoginException("未登录","/login","请先登录");
}
// DTO 用于 @Valid 测试
public static class UserDTO {
@NotNull(message = "用户名不能为空")
private String name;
@Min(value = 18, message = "年龄必须大于等于18")
private Integer age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
}
}
全局异常处理
package com.base.exception;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.util.SaResult;
import jakarta.validation.ConstraintViolationException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.HandlerMethodValidationException;
/**
* 全局异常处理器
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
// 全局异常拦截(兜底)
@ExceptionHandler(Exception.class)
public SaResult handleException(Exception e) {
e.printStackTrace();
return SaResult.error("服务器内部错误: " + e.getMessage());
}
// 空指针异常
@ExceptionHandler(NullPointerException.class)
public SaResult handleNullPointerException(NullPointerException e) {
e.printStackTrace();
return SaResult.error("出现空指针,请检查参数或对象是否初始化");
}
// 非法参数异常
@ExceptionHandler(IllegalArgumentException.class)
public SaResult handleIllegalArgumentException(IllegalArgumentException e) {
e.printStackTrace();
return SaResult.error("参数错误: " + e.getMessage());
}
// 数据唯一性约束异常(用户名已存在等)
@ExceptionHandler(DataIntegrityViolationException.class)
public SaResult handleDataIntegrityViolationException(DataIntegrityViolationException e) {
e.printStackTrace();
return SaResult.error("用户名被占用");
}
// 登录异常(未登录)
@ExceptionHandler(NotLoginException.class)
public SaResult handleNotLoginException(NotLoginException e) {
e.printStackTrace();
return SaResult.code(401).setMsg("请先登录,再访问");
}
// 方法参数校验异常(@Valid 校验失败)
@ExceptionHandler(MethodArgumentNotValidException.class)
public SaResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
e.printStackTrace();
String msg = e.getBindingResult().getFieldError().getDefaultMessage();
return SaResult.error("参数校验失败: " + msg);
}
// 单个参数校验异常(@NotNull、@Min 等直接作用在 Controller 参数上)
@ExceptionHandler(ConstraintViolationException.class)
public SaResult handleConstraintViolationException(ConstraintViolationException e) {
e.printStackTrace();
return SaResult.error("参数校验失败: " + e.getMessage());
}
}
# 小结
spring-boot-starter-validation
= Hibernate Validator + Spring Boot 封装。
核心作用:对数据合法性进行注解式校验。
用法:
- 在 DTO/实体类上加注解。
- 在 Controller 参数上加
@Valid
或@Validated
。 - 自定义异常处理可返回友好提示。
# 常用校验注解速查
# 🔹 空值/非空校验
@NotNull
:不能为null
(但可以是空字符串、集合等)。@NotBlank
:不能为null
,且字符串必须至少包含一个非空格字符。@NotEmpty
:不能为null
,并且长度必须 > 0(适用于字符串、集合、数组)。
# 🔹 数值范围
@Min(value)
:最小值(整数/小数)。@Max(value)
:最大值。@DecimalMin(value)
:小数最小值(支持边界可控inclusive=false
)。@DecimalMax(value)
:小数最大值。@Positive
:必须 > 0。@PositiveOrZero
:必须 ≥ 0。@Negative
:必须 < 0。@NegativeOrZero
:必须 ≤ 0。@Digits(integer, fraction)
:数值位数约束(整数部分 + 小数部分)。
# 🔹 长度与大小
@Size(min, max)
:字符串、数组、集合的长度/大小范围。@Length(min, max)
:字符串长度限制(Hibernate Validator 扩展)。
# 🔹 字符串格式
@Email
:邮箱格式校验。@Pattern(regexp)
:正则表达式校验。@URL
:URL 格式校验(Hibernate Validator 扩展)。
# 🔹 时间日期
@Future
:必须是将来的时间。@FutureOrPresent
:必须是现在或将来。@Past
:必须是过去的时间。@PastOrPresent
:必须是现在或过去。
# 🔹 组合校验
@Valid
:级联校验(验证嵌套对象里的字段)。@Validated
:支持 分组校验(可以在不同场景下应用不同的校验规则)
← 常用算法封装 打包的jar启动报错问题 →