目录
(5)@Digits(integer=,fraction=)
一.基础校验
1.数字校验
(1)@DecimalMax
- 标注的元素可定义为BigDecimal、BigInteger、String、byte、short、int、long以及他们的包装类型
- 不支持double、float类型(否则小数点会有精度丢失的可能)
- 限制必须为数字,最大值不能超过指定值
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@DecimalMax(value = "99")
private String parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
输入值必须是数字并且小于等于99
- 发送请求校验入参-99999(成功)
- 发送请求校验入参0(成功)
- 发送请求校验入参1(成功)
- 发送请求校验入参99(成功)
- 发送请求校验入参100(失败)
(2)@DecimalMin
- 标注的元素可定义为BigDecimal、BigInteger、String、byte、short、int、long以及他们的包装类型
- 不支持double、float类型(否则小数点会有精度丢失的可能)
- 限制必须为数字,最小值不能低于指定值
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@DecimalMin(value = "99")
private String parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
输入值必须是数字并且大于等于99
- 发送请求校验入参99999(成功)
- 发送请求校验入参100(成功)
- 发送请求校验入参99(成功)
- 发送请求校验入参89(失败)
- 发送请求校验入参0(失败)
- 发送请求校验入参-1(失败)
(3)@Max
- 标注的元素可定义为BigDecimal、BigInteger、String、byte、short、int、long以及他们的包装类型
- 不支持double、float类型(否则小数点会有精度丢失的可能)
- 限制必须为数字,最大值不能超过指定值
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@Max(value = 10)
private String parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
最大值不能超过10
- 发送请求校验入参10(成功)
- 发送请求校验入参9.99999999999999999999999999(成功)
- 发送请求校验入参0(成功)
- 发送请求校验入参-999999999999999999999(成功)
- 发送请求校验入参10.00000000000000000000000000001(失败)
(4)@Min
- 标注的元素可定义为BigDecimal、BigInteger、String、byte、short、int、long以及他们的包装类型
- 不支持double、float类型(否则小数点会有精度丢失的可能)
- 限制必须为数字,最小值不能低于指定值
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@Min(value = 10)
private String parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
最小值不能小于10
- 发送请求校验入参10(成功)
- 发送请求校验入参10.00000000000000000000001(成功)
- 发送请求校验入参0(失败)
- 发送请求校验入参9.999999999999999999999(失败)
- 发送请求校验入参-1(失败)
(5)@Digits(integer=,fraction=)
- 标注的元素可定义为BigDecimal、BigInteger、String、byte、short、int、long以及他们的包装类型
- 限制必须为数字类型,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@Digits(integer = 2,fraction = 2)
private String parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
输入值必须是数字并且是2位整数和2位小数
- 发送请求校验入参99.99(成功)
- 发送请求校验入参-99.99(成功)
- 发送请求校验入参0(成功)
- 发送请求校验入参999(失败)
- 发送请求校验入参-999(失败)
- 发送请求校验入参99.999(失败)
- 发送请求校验入参-99.999(失败)
- 发送请求校验入参999.999(失败)
2.字符串校验
(1)@NotBlank
- 入参不能为空,只支持String类型的校验
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@NotBlank
private String parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
入参不能为空
- 发送请求校验入参空值(失败)
- 发送请求校验入参其他值(成功)
3.时间校验
(1)@Future
- 必须为未来时间
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@Future
private Date parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
- 发送请求校验入参2050-01-01T12:12:12(成功)
- 发送请求校验入参2000-01-01T12:12:12(失败)
(2)@Past
- 必须为过去时间
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@Past
private Date parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
- 发送请求校验入参2000-01-01T12:12:12(成功)
- 发送请求校验入参2050-01-01T12:12:12(失败)
(3)@DateTimeFormat
前端传至后端规定的格式
-
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
(4)@JsonFormat
后端转换date类型格式传至前端
-
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
4.集合校验
(1)@NotEmpty
- 入参不能为空,只支持List、Set、Map集合的校验
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@NotEmpty
private List<String> parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@RequestBody @Valid DailyDTO dailyDTO){
return "ok";
}
}
入参不能为空
- 发送请求校验入参空值(失败)
- 发送请求校验入参其他值(成功)
5.布尔值校验
- 注意:包装类型的Boolean没有默认值,可以检验空
- 注意:基础类型的boolean有默认值,空即为false,无法检验空值!!!
- 所以阿里的Java开发规范也是建议我们使用包装类型定义
(1)@AssertFalse
- 标注的元素必须定义为布尔类型
- 校验必须是null值或者布尔类型的false值
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@AssertFalse(message = "一定要为false")
private Boolean parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
传递的参数如果不确定就传空,否则必须传false
- 发送请求校验入参false(成功)
- 发送请求校验入参null(成功)
- 发送请求校验入参true(失败)
(2)@AssertTrue
- 标注的元素必须定义为布尔类型
- 校验必须是null值或者布尔类型的true值
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@AssertTrue(message = "一定要为true")
private Boolean parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
传递的参数如果不确定就传空,否则必须传true
- 发送请求校验入参true(成功)
- 发送请求校验入参null(成功)
- 发送请求校验入参false(失败)
6.其他校验
(1)@NotNull
- 入参不能为空,支持定义任何类型,多数用于基础类型的校验
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@NotNull
private Long parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
入参不为空即可,且符合定义的类型
- 发送请求校验入参空值(失败)
- 发送请求校验入参其他值(成功)
(2)@Size
- 限制入参必须为字符串或者集合,不超过定义的范围
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@Size(min = 1,max = 3,message = "字符串超过该范围")
private List<String> parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@RequestBody @Valid DailyDTO dailyDTO){
return "ok";
}
}
限定该集合长度范围是1-3
- 发送请求校验入参 { "parameter": ["测试1","测试2","测试3"] }(成功)
- 发送请求校验入参 { "parameter": ["测试1"] }(成功)
- 发送请求校验入参 { "parameter": ["测试1","测试2","测试3","测试4"] }(失败)
- 发送请求校验入参其他范围值(失败)
(3)@Email
- 邮箱格式校验,必须是@后跟*.*格式拼接
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@Email
private String parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
必须为一个邮箱的格式
- 发送请求校验入参21412421@(失败)
- 发送请求校验入参21412421@qq.(失败)
- 发送请求校验入参21412421@.com(失败)
- 发送请求校验入参21412421@qq.c(成功)
- 发送请求校验入参其他非邮箱格式(失败)
(4)@Pattern(regexp=)
- 声明的字符串需要匹配定义的正则表达式,或者为null 值
举例:
@Data
public class DailyDTO implements Serializable {
private static final long serialVersionUID = -513334502940807737L;
@Pattern(regexp = "^[0-9]*$")
private List<String> parameter;
}
@RestController
public class AnnotationUser {
@PostMapping("/validator")
public Object validator(@Valid DailyDTO dailyDTO){
return "ok";
}
}
该正则表达式:必须为0-9的数字
- 发送请求校验入参45465465(成功)
- 发送请求校验入参其他非数字(失败)
下面是常用的正则表达式(注意转义符的使用,例如:“\d”要写成“\\d”):
1 匹配首尾空格的正则表达式:(^\s*)|(\s*$)
2 整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$
3 只能输入数字:"^[0-9]*$"。
4 只能输入n位的数字:"^\d{n}$"。
5 只能输入至少n位的数字:"^\d{n,}$"。
6 只能输入m~n位的数字:。"^\d{m,n}$"
7 只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
8 只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。
9 只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。
10 只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
11 只能输入非零的负整数:"^\-[1-9][]0-9"*$。
12 只能输入长度为3的字符:"^.{3}$"。
13 只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
14 只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
15 只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
16 只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。
17 只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"。
18 验证用户密码:"^[a-zA-Z]\w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
19 验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"。
20 只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
21 验证Email地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。
22 验证InternetURL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
23 验证电话号码:"^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为:"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。
24 验证身份证号(15位或18位数字):"^\d{15}|\d{18}$"。
25 验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。
26 验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。
27 匹配中文字符的正则表达式: [\u4e00-\u9fa5]
28 匹配双字节字符(包括汉字在内):[^\x00-\xff]
29 应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
30 String.prototype.len=function(){return this.replace(/[^\x00-\xff]/g,"aa").length;}
31 匹配空行的正则表达式:\n[\s| ]*\r
32 匹配html标签的正则表达式:<(.*)>(.*)<\/(.*)>|<(.*)\/>
二.高级校验
1.自定义注解校验
- 自定义注解@DailyType进行参数校验
- 参考框架内的注解编写
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE
})
@Retention(RUNTIME)
@Documented
// 指定具体的校验逻辑接口
@Constraint(validatedBy = {DailyTypeEnumValidator.class })
public @interface DailyType {
String message() default "参数不合法";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
- 实现ConstraintValidator接口,编写自定义注解的校验逻辑
- 举例:这里校验参数必须等于"hiber",否则抛出异常
public class DailyTypeEnumValidator implements ConstraintValidator<DailyType, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//这里进行参数校验,举例:值必须等于“hiber”,才符合通过
if("hiber".equals(value)){
return true;
}
return false;
}
}
2.分组校验
- 先定义两个空接口:新增和更新
public interface Insert {
}
public interface Update {
}
- 对参数进行制定分组校验
/**
要使用分组校验的话, 需要使用 @Validated 这个注解
*/
@Data
public class PersonDTO {
/**
* id, 更新时候校验
*/
@NotNull(groups = Update.class, message = "id不能为空")
private Integer id;
@NotBlank(groups =
{
Insert.class,
Update.class
},
message = "名字不能为空"
)
private String name;
@NotBlank(groups = Update.class, message = "性别不能为空")
private String gender;
/**
* 没有指定分组, 即为默认分组 Default
*/
@NotNull(message = "年龄不能为空")
private Integer age;
}
- 需使用注解@Validated进行制定分组校验
/**
* 新增分组校验测试
* @param personDTO
* @return
*/
@PostMapping("/person")
public Object groupValidationInsertDemo(@Validated(Insert.class) @RequestBody
PersonDTO personDTO){
return "ok";
}
/**
* 更新分组校验测试
* @param personDTO
* @return
*/
@PutMapping("/person")
public Object groupValidationUpdateDemo(@Validated(Update.class) @RequestBody
PersonDTO personDTO){
return "ok";
}
3.校验工具
- 自定义编写工具,一般用于service层的校验,考虑到service层不仅仅给controller层调用
public class ValidatorUtils {
private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public static <T> void validate(T object, Class... groups) {
Set<ConstraintViolation<T>> validate =
validator.validate(object, groups);
// 如果校验结果不为空
if (!CollectionUtils.isEmpty(validate)) {
StringBuilder exceptionMessage = new StringBuilder();
validate.forEach(constraintViolation -> {
exceptionMessage.append(constraintViolation.getMessage());
});
throw new IllegalArgumentException(exceptionMessage.toString());
}
}
}
4.集合校验
- 编写一个实体,这里的age属性没有标注,可为空
@Data
public class PersonDTO{
private Integer age;
}
- 使用重写的ValidatorList对实体PersonDTO进行封装,请求测试
- 传递参数空列表(失败)
- 传递参数列表中的空属性(成功)
@PostMapping("/level")
public Object levelValidation(@Validated @RequestBody ValidatorList<PersonDTO> personDTOList) {
System.err.println(personDTOList.toString());
return "ok";
}
- 这里重写List,在校验对象的属性上使用@Valid注解实现级联校验,列表List不能为空
@Data
public class ValidatorList<E> implements List<E> {
@Valid
@NotEmpty(message = "请求参数集合不能为空")
@NotNull(message = "集合不能为NULL")
private List<E> list = new ArrayList<E>();
@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<E> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> 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<? extends E> c) {
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> 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 boolean equals(Object o) {
return list.equals(o);
}
@Override
public int hashCode() {
return list.hashCode();
}
@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<E> listIterator() {
return list.listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
}
三、其他校验
1.全局异常处理
- 在基础的参数校验中所产生的异常仅服务端可见
- 把该异常抛出去到前端也可见
- 添加以下的配置类(仅针对MethodArgumentNotValidException异常处理),当 @Valid 作用的参数上,校验不通过时候,抛出该异常。
- 备注: @Validated 这个注解一样也有效
@RestControllerAdvice
@Configuration
@Slf4j
public class GlobalExceptionHandle {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Object validationExceptionHandle(MethodArgumentNotValidException mav) {
log.warn("----- handle argument not valid exception! -----");
List<FieldError> fieldErrors = mav.getBindingResult().getFieldErrors();
return fieldErrors.stream().map(item -> {
StringJoiner sj = new StringJoiner(":");
sj.add(item.getField());
sj.add(item.getDefaultMessage());
return sj.toString();
}).collect(Collectors.toList());
}
}
本文详细介绍了Java中各种注解在基础校验如数字、字符串、日期等的使用方法,以及高级校验如自定义注解、分组校验和校验工具的实践示例。掌握这些技巧有助于提升API接口的健壮性。
218

被折叠的 条评论
为什么被折叠?



