跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

java参数校验使用

前言 在日常业务中参数校验是不可或缺的一部分,我们可以在业务代码中进行参数的规则校验(优雅的使用断言

Assert

),也可以在接收参数的时候直接进行校验。

由代码的执行入口顺序来看,我们最好是在入参的时候进行简单校验。

一、导入依赖 若

springboot

版本低于

2.3.x

,则

spring-boot-starter-web

则会自动引入

hibernate-validator

相关依赖,否则我们自己手动导入即可:

org.hibernate hibernate-validator 6.0.1.Final

二、常用校验注解

@NotBlank

:用于校验String类型,使得字符串不为null并且长度大于零,即.trim()的长度大于零

@NotEmpty

:一般用于校验集合不为空

@NotNull

:所校验的值不能为

null @Null

:被检验的对象要为

null @AssertTrue

:被校验的对象必须为

true

(我测试的时候怎么填都是false,不知道怎么测试。

。

。

)

@AssertFalse

:被校验的对象必须为

false @Min(value = val)

:被校验的对象必须是数字,而且大于等于

val @Max(value = val)

:被校验的对象必须是数字,而且小于等于

val @DecimalMin(value = "val")

:同

@Min(value) @DecimalMax(value = "val")

:同

@Max(value) @Size(min = min, max = max)

:验证注解的元素值的在

min

和

max

(包含)指定区间之内,如字符长度、集合大小(对于集合来说,

null

和空字符串都是算长度的)

@Past

:被校验的对象(日期类型)比当前时间早

@Future

:被校验的对象(日期类型)比当前时间晚

@Length(min=min, max=max)

:被校验字符串长度在

min

和

max

区间内,包含边界

@Range(min=min, max=max)

:验证注解的元素值在最小值和最大值之内,包含边界,如数字类型

@Email

:验证邮箱,也可以通过

regexp

自定义正则匹配

@Pattern(regexp = "")

:自定义正则匹配 三、@Validated和@Valid注意点

@Validated

: 可以用在类型、方法和方法参数上, 但是不能用在成员属性(字段)上 不能对嵌套对象进行校验 可以进行分组校验

@Valid

: 可以用在方法、方法参数、构造函数、方法参数和 成员属性(字段)上 可以进行嵌套,但是得在 需要嵌套的字段上面加上注解 不能 进行分组校验 所以大多情况下可以进行混合使用 四、实战以及问题 先写一下全局异常的处理

/**

* 方法参数校验 */ @ResponseBody @ExceptionHandler(MethodArgumentNotValidException.class) public CommonResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { log.error("MethodArgumentNotValidException=======>{}", e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","))); return CommonResult.failed(e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","))); }

/** * ConstraintViolationException */ @ResponseBody @ExceptionHandler(ConstraintViolationException.class) public CommonResult handleConstraintViolationException(ConstraintViolationException e) { log.error("ConstraintViolationException=======>{}", e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(","))); return CommonResult.failed(e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(","))); }

/** * ValidationException */ @ResponseBody @ExceptionHandler(ValidationException.class) public CommonResult handleValidationException(ValidationException e) { log.error("ValidationException=======>{}", e); return CommonResult.failed(e.getMessage()); }

@ResponseBody @ExceptionHandler(value = Exception.class) public CommonResult serviceExceptionHandler(Exception e) { log.error("GlobalExceptionHandler===========>{}", e); return CommonResult.failed(e.getMessage()); }

4.1 嵌套对象使用 入参:

// 入参

@Data public class UserVo implements Serializable { private static final long serialVersionUID = 7965030945933727065L;

@NotBlank(message = "姓名不能为空") private String name;

@NotBlank(message = "性别不能为空") private String sex;

@NotNull(message = "爱好不能为空") @Valid private HobbyVo hobbyVo; }

嵌套对象:

//嵌套对象

@Data public class HobbyVo implements Serializable { private static final long serialVersionUID = 7248588761842099248L;

@NotBlank(message = "爱好名不能为空") private String name; }

测试方法:

// 测试方法

@PostMapping("/testSingle") public String test(@Validated @RequestBody UserVo userVo) { return "ok"; }

结果: 不加内嵌对象,验证不通过:

加了内嵌对象字段,验证通过:

4.2 集合对象验证校验 测试方法:

@PostMapping("/testList")

public String test(@Validated @RequestBody List userVoList) { return "ok"; }

结果:

可以看到,我们还有几个参数没填竟然还返回

ok

了,可见我们的校验没起作用。

解决方案 先将

Spring DataBinder

配置为使用直接字段访问

@ControllerAdvice

public class CustomControllerAdvice {

@InitBinder private void activateDirectFieldAccess(DataBinder dataBinder) { dataBinder.initDirectFieldAccess(); } }

利用

@Valid

可以加在字段上面的特性重写

List public class ValidList implements List {

@Valid private List list = new ArrayList<>();

@Override public int size() { return list.size(); }

@Override public boolean isEmpty() { return list.isEmpty(); }

@Override public boolean contains(Object o) { return list.contains(o); }

@Override public Iterator iterator() { return list.iterator(); }

@Override public Object[] toArray() { return list.toArray(); }

@Override public T[] toArray(T[] a) { return list.toArray(a); }

@Override public boolean add(E e) { return list.add(e); }

@Override public boolean remove(Object o) { return list.remove(o); }

@Override public boolean containsAll(Collection c) { return list.containsAll(c); }

@Override public boolean addAll(Collection c) { return list.addAll(c); }

@Override public boolean addAll(int index, Collection c) { return list.addAll(index,c); }

@Override public boolean removeAll(Collection c) { return list.removeAll(c); }

@Override public boolean retainAll(Collection c) { return list.retainAll(c); }

@Override public void clear() { list.clear(); }

@Override public E get(int index) { return list.get(index); }

@Override public E set(int index, E element) { return list.set(index,element); }

@Override public void add(int index, E element) { list.add(index,element); }

@Override public E remove(int index) { return list.remove(index); }

@Override public int indexOf(Object o) { return list.indexOf(o); }

@Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); }

@Override public ListIterator listIterator() { return list.listIterator(); }

@Override public ListIterator listIterator(int index) { return list.listIterator(index); }

@Override public List subList(int fromIndex, int toIndex) { return list.subList(fromIndex,toIndex); } }

测试方法

@PostMapping("/testList")

public String test(@Validated @RequestBody ValidList userVoList) { return "ok"; }

测试结果

4.3分组校验 在我们平时业务中,会遇到同一个Vo进行不同的操作,但是对于Vo的检验规则是不同的,比如新增方法,对于

id

可为空,但是对于修改方法

id

不可为空,对于这种场景,就需要好好利用我们的分组校验功能了 创建分组的接口(继承

javax.validation.groups.Default

接口)

public interface Save extends Default {

}

public interface Update extends Default {

}

实体类

@Data

public class ProduceVo implements Serializable { private static final long serialVersionUID = -8921638716346141268L;

@JsonFormat(shape = JsonFormat.Shape.STRING) @NotNull(groups = {Update.class}, message = "id不能为空") private Long id;

}

测试方法 新增

@PostMapping("/testGroupInsert")

public String insert(@Validated(Save.class) @RequestBody ProduceVo produceVo) { return "ok"; }

结果:

可以看到,没传参数也能成功 修改

@PostMapping("/testGroupUpdate")

public String update(@Validated(Update.class) @RequestBody ProduceVo produceVo) { return "ok"; }

结果:

可以看到不传id校验不通过 4.4自定义校验 链接: 自定义参数校验注解的使用

相关文章