Spring Boot中@Valid注解未生效,是否需额外启用验证?
Spring Boot @Valid与@Email注解不生效问题解决
问题描述
在接口参数上添加@Valid与@Email注解后未生效,任意字符串都可调用该API。相关代码如下:
控制器代码
import javax.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor @RestController @RequestMapping("/account") @Transactional(rollbackFor = Exception.class) @Slf4j public class AccountController { private final AccountService accountService; @GetMapping @ResponseBody public Account getAccountDetails(@Valid @Email @RequestParam final String email) { return accountService.getAccount(email); } }
启动类代码
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableScheduling @EnableCaching @EnableAsync public class AccountApplication { public static void main(String[] args) { SpringApplication.run(AccountApplication.class, args); } }
Maven依赖配置
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.8</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> ... </dependencies>
解决办法
1. 替换@Valid为@Validated激活方法级验证
@Valid仅适用于JavaBean对象的验证,单个请求参数的验证需要用Spring提供的@Validated注解:
- 在控制器类上添加
@Validated(导入org.springframework.validation.annotation.Validated) - 参数上保留
@Email注解,移除无效的@Valid
修改后的控制器代码:
import javax.validation.constraints.Email; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor @RestController @RequestMapping("/account") @Transactional(rollbackFor = Exception.class) @Slf4j @Validated // 添加此注解激活参数验证 public class AccountController { private final AccountService accountService; @GetMapping @ResponseBody public Account getAccountDetails(@Email @RequestParam final String email) { return accountService.getAccount(email); } }
2. 全局处理验证失败异常
验证不通过时会抛出ConstraintViolationException,可以添加全局异常处理器返回友好响应:
import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.validation.ConstraintViolationException; import java.util.HashMap; import java.util.Map; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Map<String, String> handleValidationExceptions(ConstraintViolationException ex) { Map<String, String> errorMap = new HashMap<>(); ex.getConstraintViolations().forEach(violation -> { String paramName = violation.getPropertyPath().toString(); errorMap.put(paramName, violation.getMessage()); }); return errorMap; } }
3. 无需额外启用验证功能
你已经引入了spring-boot-starter-validation依赖,Spring Boot会自动配置验证相关组件,启动类不需要添加额外注解。
内容的提问来源于stack exchange,提问作者Datz
相关产品推荐
相关产品推荐

