【Spring 校验】
主页传送门:📀 传送
🍇 概述
Java API 规范(JSR303)定义了Bean校验的标准validation-api
,但没有提供具体的实现方法。hibernate validation
是对这个规范的实现,并增加了如@Email
、@Length
等校验注解。Spring Validation
是对hibernate validation
的二次封装,用于支持spring mvc参数的自动校验。
🍉 使用场景
Spring 校验使用场景
- Spring 常规校验(Validator)
- Spring 数据绑定(DataBinder)
- Spring Web 参数绑定(WebDataBinder)
- Spring WebMVC/WebFlux 处理方法参数校验
🍉 依赖引入
如果 spring-boot 版本小于 2.3.x,spring-boot-starter-web 会自动传入 hibernate-validator 依赖。如果 spring-boot 版本大于 2.3.x,则需要手动引入依赖:
org.hibernate.validator hibernate-validator-parent 6.2.5.Final
对于 web 服务来说,为防止非法参数对业务造成影响,在 Controller 层一定要做参数校验的!大部分情况下,请求参数分为如下两种形式:
- POST、PUT 请求,使用 requestBody 传递参数;
- GET 请求,使用 requestParam/PathVariable 传递参数。
实际上,不管是 requestBody 参数校验还是方法级别的校验,最终都是调用 Hibernate Validator 执行校验,Spring Validation 只是做了一层封装。
🍍 校验示例
🍈(1)在实体上标记校验注解
示例
@Data@NoArgsConstructor@AllArgsConstructorpublic class User implements Serializable { @NotNull private Long id; @NotBlank @Size(min = 2, max = 10) private String name; @Min(value = 1) @Max(value = 100) private Integer age;}
上述类使用了Lombok库的@Data、@NoArgsConstructor和@AllArgsConstructor注解,分别用于自动生成getter、setter、无参构造方法和全参构造方法
🍒(2)在方法参数上声明校验注解
@Slf4j@Validated@RestController@RequestMapping("validate1")public class ValidatorController { @PostMapping(value = "save") public DataResult save(@Valid @RequestBody User entity) { log.info("保存一条记录:{}", JSONUtil.toJsonStr(entity)); return DataResult.ok(true); } @GetMapping(value = "queryByName") public DataResult queryByName( @RequestParam("username") @NotBlank @Size(min = 2, max = 10) String name ) { User user = new User(1L, name, 18); return DataResult.ok(user); } @GetMapping(value = "detail/{id}") public DataResult detail(@PathVariable("id") @Min(1L) Long id) { User user = new User(id, "李四", 18); return DataResult.ok(user); }}
上述类ValidatorController,使用了Spring框架。它是一个RESTful风格的控制器,用于处理HTTP请求。这个类有三个方法:
-
save方法:使用@PostMapping注解,处理POST请求,路径为"validate1/save"。该方法接收一个User类型的参数entity,使用@Valid和@RequestBody注解进行参数校验。如果校验通过,将记录保存到数据库,并返回一个表示成功的DataResult对象。
-
queryByName方法:使用@GetMapping注解,处理GET请求,路径为"validate1/queryByName"。该方法接收一个名为username的请求参数,使用@NotBlank、@Size注解进行参数校验。如果校验通过,根据name查询用户信息,并返回一个包含用户信息的DataResult对象。
-
detail方法:使用@GetMapping注解,处理GET请求,路径为"validate1/detail/{id}"。该方法接收一个名为id的路径变量,使用@Min注解进行参数校验。如果校验通过,根据id查询用户信息,并返回一个包含用户信息的DataResult对象。
🍏(3)抛异常
如果请求参数不满足校验规则,则会抛出ConstraintViolationException
或MethodArgumentNotValidException
异常。
🥝 异常统一处理
在实际项目开发中,通常会用统一异常处理来返回一个更友好的提示。
@Slf4j@ControllerAdvicepublic class GlobalExceptionHandler { @ResponseBody @ResponseStatus(HttpStatus.OK) @ExceptionHandler(Throwable.class) public Result handleException(Throwable e) { log.error("未知异常", e); return new Result(ResultStatus.HTTP_SERVER_ERROR.getCode(), e.getMessage()); } @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler({ ConstraintViolationException.class }) public Result handleConstraintViolationException(final ConstraintViolationException e) { log.error("ConstraintViolationException", e); List errors = new ArrayList<>(); for (ConstraintViolation> violation : e.getConstraintViolations()) { Path path = violation.getPropertyPath(); List pathArr = StrUtil.split(path.toString(), ','); errors.add(pathArr.get(0) + " " + violation.getMessage()); } return new Result(ResultStatus.REQUEST_ERROR.getCode(), CollectionUtil.join(errors, ",")); } @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler({ MethodArgumentNotValidException.class }) private Result handleMethodArgumentNotValidException(final MethodArgumentNotValidException e) { log.error("MethodArgumentNotValidException", e); List errors = new ArrayList<>(); for (ObjectError error : e.getBindingResult().getAllErrors()) { errors.add(((FieldError) error).getField() + " " + error.getDefaultMessage()); } return new Result(ResultStatus.REQUEST_ERROR.getCode(), CollectionUtil.join(errors, ",")); }}
上述全局异常处理器类,用于处理控制器中抛出的异常。这个类有三个方法:
-
handleException方法:使用@ResponseBody、@ResponseStatus和@ExceptionHandler注解,处理所有不可知的异常。如果发生异常,记录错误日志,并返回一个表示服务器错误的Result对象。
-
handleConstraintViolationException方法:使用@ResponseBody、@ResponseStatus和@ExceptionHandler注解,统一处理请求参数校验异常(普通传参)。如果发生ConstraintViolationException异常,记录错误日志,将异常信息转换为字符串列表,并返回一个表示请求错误的Result对象。
-
handleMethodArgumentNotValidException方法:使用@ResponseBody、@ResponseStatus和@ExceptionHandler注解,处理参数校验异常。如果发生MethodArgumentNotValidException异常,记录错误日志,将异常信息转换为字符串列表,并返回一个表示请求错误的Result对象。
如果喜欢的话,欢迎 🤞关注 👍点赞 💬评论 🤝收藏 🙌一起讨论 你的支持就是我✍️创作的动力! 💞💞💞
来源地址:https://blog.csdn.net/wodejiaAA/article/details/132015448
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341